Repository navigation
feat(ai, ai-harness, ai-mcp, ai-acp, ai-harness-cli): durable waits in the log, at the boundary, in background runs, and on every transport - #1817
Conversation
…itFor, settled({ inputId, signal }), and operator answers to human waits
… background-waits (stopped mid-way, not checked)
…stion tool, step.ask), live MCP and sign-in waits, and background runs that suspend and resume
…e on boundary approvals through SubagentBinding.interrupts, and every transport uses one wait shape
…d an unanswered wait expires
…on, step.ask, approvals at the boundary, background waits, and waits on every transport
…and interrupts other hosts write
🦋 Changeset detectedLatest commit: eb3279e The changes in this PR will be included in the next version bump. This PR includes changesets to release 53 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
View your CI Pipeline Execution ↗ for commit eb3279e
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-byteplus
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-cloudflare
@tanstack/ai-code-mode
@tanstack/ai-code-mode-snippets
@tanstack/ai-codex
@tanstack/ai-cohere
@tanstack/ai-compaction
@tanstack/ai-devtools-core
@tanstack/ai-durable-stream
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-grok-build
@tanstack/ai-groq
@tanstack/ai-harness
@tanstack/ai-harness-cli
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-daytona
@tanstack/ai-isolate-e2b
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-isolate-quickjs-bun
@tanstack/ai-llmgateway
@tanstack/ai-lovable
@tanstack/ai-mcp
@tanstack/ai-memory
@tanstack/ai-mistral
@tanstack/ai-octane
@tanstack/ai-ollama
@tanstack/ai-ollaya
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@tanstack/ai-perplexity
@tanstack/ai-persistence
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-reactor
@tanstack/ai-remix
@tanstack/ai-sandbox
@tanstack/ai-sandbox-blaxel
@tanstack/ai-sandbox-boxd
@tanstack/ai-sandbox-cloudflare
@tanstack/ai-sandbox-daytona
@tanstack/ai-sandbox-docker
@tanstack/ai-sandbox-e2b
@tanstack/ai-sandbox-local-process
@tanstack/ai-sandbox-railway
@tanstack/ai-sandbox-sprites
@tanstack/ai-sandbox-upstash-box
@tanstack/ai-sandbox-vercel
@tanstack/ai-skills
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-typesafe
@tanstack/ai-utils
@tanstack/ai-vercel-gateway
@tanstack/ai-vertex
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/ai-worldlabs
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
@tanstack/svelte-ai-devtools
commit: |
…h resolve, and the device code carries expiresAt
…s formatter, and a reject writes nothing
Coverage✅ Coverage held across 68 compared package(s). Each package is measured twice in this job — on this PR and on its merge-base with
|
A run that waits for a person now waits in the log. Any server can answer the wait, a server that restarts picks it up again, and a wait can expire. Approvals, questions, sign-ins, client tools, and human waits share one
Waitshape on every transport. This is PR 7 of the harness redesign stack for #1755. It targets #1815 (feat/harness-redaction).🎯 Changes
Waittype.Wait,WaitKind(approval | question | sign-in | client-tool | human),waitKind,isApproval,waitOfInterrupt, andwaitOfQuestion.harness.waitrecords in the log.SessionSnapshot.pendingWaitslists them.expiresAt. Onlysign-inhas a default (15 minutes). An expired wait endsexpired, also on a worker.session.waitFor({ runId?, signal? })resolves with the next open wait.session.settled({ inputId, signal? })now takes one object.operatoraccess action answershumanwaits.permissions()decides before the calls run and opens one approval wait per call. An answer can betrue/false,'once' | 'always' | 'reject', or{ answer, message? }.questiontool is its own wait.step.ask(question)in durable tools, durable agent runs, and commands is a wait that only the log holds. It survives a restart, is checked against its JSON Schema, and can be secret.ctx.session.askwithoutlivethrows, and its error names the places that can wait (D9). Commands that calledstep.askrun again from the top after a host stop.expiresAtend on time.waiting) and resumes after the answer, also after a restart, on any host.permissions()approval through the new coreSubagentBinding.interruptsfield.pendingWaitsand background waits.resolveanswers turn interrupts and background-run waits.answeranswersstep.askand live questions.waitsper operation (E9). ACP maps every kind.--printexits 3 on any wait.host.submitpasses the wait, so an operator answer works.Docs: a new
docs/harness/waits.md, and updates topermissions,inputs,acp,cli,mcp-server,durable-tools,custom-ui,subagents,access,plugins,coding-tools,chat/subagents, and others. Changesets for@tanstack/ai,@tanstack/ai-harness,@tanstack/ai-mcp,@tanstack/ai-acp, and@tanstack/ai-harness-cli.Decisions made while building:
SubagentBinding.interrupts(approved by Alem). An agent's own interrupt wins on an id clash. Subagents that the model calls as tools inside a turn still cannot ask: they are refused, because their resume would ask again.questiontool stays a lead-turn tool. Agents do not get plugin tools, so a background agent has noquestiontool. The docs say so.--printused to hang.permissions()approval was refused, because the answer schema took only an object.✅ Checklist
pnpm run test:pr, or these tests do not apply to this pull request.docs/for this change, or this change is not user-facing.pnpm changeset), or this PR does not change a published package.🚀 Release Impact
Testing
Commands run:
ai,ai-persistence,ai-harness, andai-mcp.test:typesof those plusai-acp,ai-harness-cli,ai-code-mode,ai-skills, andai-sandbox. All pass.--maxWorkers=2. Examples:waits,wait-records,step-ask,json-schema,permissions,question,workspace-tools,live-waits,background-waits,remote-waits,view,client,protocol,access,input-lane, and the ai-mcp, ai-acp, and CLI tests. All pass.test:oxlintofai-harness,pnpm test:docs,kiira checkon the changed pages, andoxfmt --checkon every changed file.Not run locally: the full suites, knip, E2E (including the new
harness-waits.spec.ts), and coverage. CI runs them.Manual test:
pnpm --dir packages/ai-harness exec vitest run tests/step-ask.test.ts tests/background-waits.test.ts tests/remote-waits.test.ts.tests/step-ask.test.ts: a durable tool asks, the host stops, and the answer reaches the run on another host.tests/remote-waits.test.ts: host B sees and answers an approval that host A opened.How this PR makes testing easy: the new test files pin each part:
waits,wait-records,step-ask,live-waits,background-waits, andremote-waits.testing/e2e/tests/harness-waits.spec.tsanswers an approval on a second server and lets a wait expire.Risk / rollback
High. Every approval and question now goes through the wait records,
ctx.session.askthrows withoutlive, andsettledtakes an object. The harness is not released yet, and all callers in this repo are moved. To undo, revert this PR.Public API change
Before
After