Skip to content

feat(sandbox): thread backend.interactions through stream prompt options#166

Merged
vutuanlinh2k2 merged 2 commits into
mainfrom
feat/sandbox-interactions-passthrough
Jul 2, 2026
Merged

feat(sandbox): thread backend.interactions through stream prompt options#166
vutuanlinh2k2 merged 2 commits into
mainfrom
feat/sandbox-interactions-passthrough

Conversation

@vutuanlinh2k2

Copy link
Copy Markdown
Contributor

Closes #165.

Summary

The sandbox question channel — where an agent pauses mid-turn to ask the user a clarifying question — is off unless the session's backend.interactions is set. agent-app builds the backend object but hardcoded it to { type, profile, ...model } with no interactions, so consumers like gtm-agent could not enable it. agent-app was the missing link between the published SDK surface (@tangle-network/sandbox@0.9.7) and consumers.

This threads an opt-in interactions passthrough through the streaming/interactive prompt path and deliberately withholds it from the detached path (which has no consumer to answer a question). The field is forwarded verbatim — agent-app does not duplicate the per-harness support matrix; the sidecar rejects unsupported kinds loudly at session init, and a local matrix would drift.

Changes

  • package.json — bump @tangle-network/sandbox devDep ^0.9.5^0.9.7 and raise the peerDependency floor >=0.9.4>=0.9.7. Older SDKs strip the field client-side (normalizeRuntimeBackendConfig), so the floor makes the requirement explicit.
  • StreamSandboxPromptOptions — new inline-typed interactions?: { question?; permission?; plan? } option (no BackendConfig import; typechecks independent of SDK version via the existing cast).
  • streamSandboxPrompt — spreads interactions verbatim into the backend, mirroring the model spread.
  • driveSandboxTurn — left untouched, with a comment documenting the policy (detached cron/mission-step turns have no consumer to answer a question). Box-create payload also untouched.
  • detectInteractiveQuestion — extended to recognize the generic interaction/kind:"question" event shape (the SDK docstring confirms enabled kinds surface exactly as interaction stream events), strengthening the disallowQuestions backstop.
  • Tests — verbatim forwarding on the streaming path, undefined by default, driveSandboxTurn never sets it, and the detector recognizing/ignoring interaction events.

Note on the issue's file reference

The issue points at runSandboxPrompt / :1784 as the autonomous path to avoid. In the actual code, runSandboxPrompt builds no backend (it delegates to streamSandboxPrompt); the function at :1784 is driveSandboxTurn, the detached box.prompt path — that is the one left untouched.

Acceptance criteria

  • StreamSandboxPromptOptions.interactions exists and reaches box.streamPrompt's backend config verbatim (test)
  • Autonomous/non-streaming path (driveSandboxTurn) never sets it (test)
  • @tangle-network/sandbox bumped to ≥ 0.9.7
  • New agent-app version published for gtm-agent to consume (release flow after merge)

Verification

  • pnpm typecheck — clean
  • pnpm test src/sandbox/index.test.ts — interaction/sandbox tests pass (6 targeted, 110 total)
  • pnpm build — ESM + DTS both succeed

Two pre-existing, environment-specific failures are unrelated to this change: the deferred profile files suite shells out to a real bash that breaks on the local .bash_profile (confirmed failing identically on clean main), and the DTS build needs NODE_OPTIONS=--max-old-space-size=8192 on this machine due to the existing type-surface size.

Brings BackendConfig.interactions and the SDK-internal wire allowlist
(normalizeRuntimeBackendConfig) that forwards the field; older SDK
versions silently strip it. Raises the peerDependency floor to >=0.9.7
so consumers get a version that actually forwards interactions.
The sandbox question channel (agent pauses mid-turn to ask the user) is
off unless backend.interactions is set. agent-app builds the backend
object but hardcoded it without the field, so consumers could not enable
it — the missing link between the SDK surface and products like gtm-agent.

Add an opt-in interactions?: { question?, permission?, plan? } option to
StreamSandboxPromptOptions and forward it VERBATIM into the streaming
backend config. No per-harness matrix here: the sidecar rejects
unsupported kinds loudly at session init; a local matrix would drift.

The detached box.prompt path (driveSandboxTurn) deliberately never sets
it — cron/mission-step turns have no consumer to answer a question.
detectInteractiveQuestion also learns the generic interaction/kind:
"question" event shape, strengthening the disallowQuestions backstop.
@vutuanlinh2k2 vutuanlinh2k2 requested a review from tangletools July 2, 2026 14:15
@vutuanlinh2k2 vutuanlinh2k2 merged commit 6914103 into main Jul 2, 2026
1 check passed
drewstone added a commit that referenced this pull request Jul 8, 2026
…t-stream primitive (#176)

* feat(chat): add shared ChatInteraction contract to web-react

Lift the framework-agnostic interaction contract (ChatInteraction type,
wire<->persisted codecs, dedupe/transition/compose-answer helpers) into
web-react so every agent-app consumer imports one source of truth instead
of hand-rolling it. Pure module (no React), re-exported from the web-react
barrel alongside the chat-stream primitives.

* feat(chat): surface sidecar interaction line via onInteraction callback

dispatchChatStreamLine silently dropped the sidecar 'interaction' NDJSON
line — the backend already threads it into the stream (#166), but the
client parser had no seam for it. Add an optional onInteraction callback
to ChatStreamCallbacks and a case in the switch that validates the ask
with the shared wire codec and surfaces the parsed ChatInteraction; a
malformed ask is logged and skipped. Optional callback keeps every
existing consumer unchanged. Covers dispatch, the {kind:'event'} envelope,
and consumeChatStream drain, plus a non-breaking (no callback) path.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] Thread backend.interactions through sandbox prompt options (question-channel passthrough)

1 participant