Pi-style ack-and-steer sub-agent protocol: dispatch mid-turn, steer via server wake turn
The job tools (research/demo/visual) switch from client-side turn-breaking calls to pi's model: execute resolves IMMEDIATELY with a fire-and-forget ack, the teacher's turn continues, and the result arrives later as an injected user-role steer message that wakes the teacher in a new server-side turn. - contracts.ts: THE ASYNC PROTOCOL rewritten (ack now, steer later); steer types (SubagentSteerMessage, metadata.subagentResult + data-subagent- artifact part), pure buildSubagentSteer/steerDelivered/isSubagentFailure - tools/jobs.ts: jobTools(ctx) factory — server-side execute creates the job (deduped by toolCallId), fires spawn with the dispatch-time input (the part isn't persisted yet at execute — a transcript scan would race) - runner.ts: runJob(jobId, input?) builds the steer and hands it to the injected deliver seam; pipeline owns the done/error flip (a polling client re-syncs once, at the end); failures still steer - server/jobs.ts (new pipeline): per-chat serialized queues on globalThis, idle gates (turn liveness + pending question, 1.5s grace), 409 retry with backoff, idempotent per jobId, stale-job recovery sweep (re-deliver or re-spawn); wake turns run through the same handleChatRequest composition via setTurnRunner injection - chat-handler.ts: wires runner+deliver+tools ctx; drops spawnTurnJobs from onFinish; teacher default registry = question tools only - plan.ts: PlanToolContext split out (plan tools need no job wiring) - visual-maker: edit_svg added (pi parity — exact-match single replacement, fuzzy context on a miss); researcher: pi's kept/dropped source accounting restored - prompts 20-jobs/40-demos: async discipline rewritten (announce and keep teaching, no waiting/polling/fabricating, parallel dispatch, teach with the artifact when it arrives) - tests: jobs.test.ts rewritten (dispatch ack mid-turn, runner steers, wake pipeline: deferral/409/idempotency/failure), demos.test.tsx runner tests ported to runJob + fake deliver; 222 green FLAGGED surgical touches outside the stream's owned files, for master review at merge: src/core/contracts.ts (protocol doc + steer types), src/core/ui-message.ts (job tool + data-part types), src/server/ chat-handler.ts (wiring), src/server/turn-service.ts (spawnTurnJobs retirement), src/agent/teacher-agent.ts (default tools), src/agent/tools/ plan.ts (context type split). Verified live on PORT=3003 with real models: teacher dispatched research mid-turn, researcher ran real searches/fetches, steer injected on quiz answer, wake turn wove the brief in citing its sources, job flipped done; a client/wake race correctly 409'd.
This commit is contained in:
@@ -9,19 +9,21 @@ outsource what you cannot reliably know yourself:
|
||||
- **Never use it for:** anything you know cold, internal reasoning, or math. Do not offload
|
||||
thinking — only facts you genuinely need verified.
|
||||
|
||||
**The call is asynchronous and your turn ends at it.** The discipline:
|
||||
**The call is fire-and-forget: it resolves immediately with an ack and your turn
|
||||
continues.** The discipline:
|
||||
|
||||
1. **Say your piece first.** Explain the concept, set up what you're doing and why, and tell
|
||||
the learner roughly what you're checking — the research brief arrives later as the tool's
|
||||
output, and the lesson resumes from there. A bare tool call with no surrounding text is a
|
||||
failed turn.
|
||||
1. **Announce it, then keep teaching.** Say what you're checking and why ("let me verify the
|
||||
current version while we continue"), make the call, and carry the lesson forward — do NOT
|
||||
wait, do NOT poll, do NOT say "hold on until it's back". Never fabricate the result.
|
||||
2. **Call with a single, specific question.** The researcher sees nothing else of the lesson —
|
||||
give it the question plus one or two sentences of context about what you need it for.
|
||||
3. **Resume from the brief.** When the result returns, weave it into the lesson. If it
|
||||
contradicted what you said, correct yourself openly — that's a teaching moment.
|
||||
3. **The brief arrives as a new message** when the research is done, and the lesson resumes
|
||||
from it. Weave it into the lesson then. If it contradicted what you said, correct yourself
|
||||
openly — that's a teaching moment.
|
||||
4. **Cite the brief's sources** when you use its findings (a short "source: …" or inline link).
|
||||
Never present researched facts as your own certainty.
|
||||
|
||||
At most one research call per turn — don't fan out; the researcher searches multiple angles on
|
||||
its own. If research fails or is unconfigured, you'll get a failure brief: say so plainly and
|
||||
continue with what you can establish, flagging the uncertainty.
|
||||
Dispatch as many research jobs as you genuinely need — in one turn or across turns, in
|
||||
parallel when the questions are independent — but don't fan out on one question; the
|
||||
researcher searches multiple angles on its own. If research fails, you'll get a failure
|
||||
message: say so plainly and continue with what you can establish, flagging the uncertainty.
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
If the concept is DYNAMIC — a parameter to sweep, a process to animate, a distribution to sample, a
|
||||
system to simulate — build the learner the instrument rather than describing its behavior in prose.
|
||||
A paragraph about how frequency response changes with damping teaches less than ten seconds of
|
||||
dragging a slider. You have two artifact tools for this, both asynchronous (same discipline as
|
||||
research):
|
||||
dragging a slider. You have two artifact tools for this, both fire-and-forget (same async
|
||||
discipline as research).
|
||||
|
||||
### `demo` — interactive teaching instruments
|
||||
|
||||
@@ -31,15 +31,19 @@ for geometry mermaid's auto-layout cannot express.
|
||||
|
||||
### The async discipline
|
||||
|
||||
The call is asynchronous and **your turn ends at it**, exactly like research:
|
||||
Both calls resolve immediately with an ack and your turn continues:
|
||||
|
||||
1. **Say your piece first.** Set up the concept, explain what the learner is about to see and what to
|
||||
watch for — the artifact arrives later as the tool's output and the lesson resumes from there. A
|
||||
bare tool call with no surrounding text is a failed turn.
|
||||
2. **At most one demo or visual per turn.**
|
||||
3. **When the artifact arrives, TEACH WITH IT.** Reference its controls and elements by name: "drag
|
||||
the damping slider all the way left and watch the overshoot", "notice the vector at t=2s". An
|
||||
1. **Announce it, then keep teaching.** Set up the concept and tell the learner what's coming
|
||||
("I'm having an interactive demo built for this — meanwhile, the idea itself…"), make the call,
|
||||
and carry on — do NOT wait, do NOT poll, do NOT say "hold on until it's back". Never fabricate
|
||||
the result. A bare tool call with no surrounding text is a failed turn.
|
||||
2. **Dispatch freely.** Parallel jobs are encouraged when they're genuinely independent — a demo
|
||||
and a figure for the same concept, several figures for a multi-step construction. Keep each
|
||||
brief self-contained.
|
||||
3. **The artifact arrives as a new message** when it's built, verified, and rendered in the
|
||||
lesson — **TEACH WITH IT then.** Reference its controls and elements by name: "drag the
|
||||
damping slider all the way left and watch the overshoot", "notice the vector at t=2s". An
|
||||
artifact you never point at is decoration.
|
||||
4. **Failures arrive as notes** ("FAILED: …") with no artifact — say so plainly, fall back to
|
||||
explaining in prose, and if the brief was the problem, re-call with a tighter one. Re-calling a
|
||||
tool produces a new version of the artifact; use that to fix a demo that misbehaves in the field.
|
||||
4. **Failures arrive as messages** with no artifact — say so plainly, fall back to explaining
|
||||
in prose, and if the brief was the problem, re-call with a tighter one. Re-calling a tool
|
||||
produces a new version of the artifact; use that to fix a demo that misbehaves in the field.
|
||||
|
||||
Reference in New Issue
Block a user