zidane 5.7.7 → 5.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/{agent-BSPhByzT.d.ts → agent-DYghZGC8.d.ts} +135 -2
- package/dist/agent-DYghZGC8.d.ts.map +1 -0
- package/dist/chat/pure.d.ts +3 -3
- package/dist/chat.d.ts +6 -6
- package/dist/chat.js +2 -2
- package/dist/headless-DnjYDckH.js +502 -0
- package/dist/headless-DnjYDckH.js.map +1 -0
- package/dist/headless.d.ts +2 -0
- package/dist/headless.js +2 -0
- package/dist/{index-B6h9C_JE.d.ts → index-B2cMuK6S.d.ts} +1285 -1124
- package/dist/index-B2cMuK6S.d.ts.map +1 -0
- package/dist/{index-DmbrQjOk.d.ts → index-CVzpMtdq.d.ts} +2 -2
- package/dist/{index-DmbrQjOk.d.ts.map → index-CVzpMtdq.d.ts.map} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +6 -241
- package/dist/index.js.map +1 -1
- package/dist/{login-C8Kc4gH0.js → login-D-3A5CK7.js} +2 -2
- package/dist/{login-C8Kc4gH0.js.map → login-D-3A5CK7.js.map} +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/{presets-DTxFbEZ5.js → presets-B1gWui0v.js} +2 -2
- package/dist/{presets-DTxFbEZ5.js.map → presets-B1gWui0v.js.map} +1 -1
- package/dist/presets.d.ts +2 -2
- package/dist/presets.js +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/restate.d.ts +1 -1
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/skills.d.ts +2 -2
- package/dist/{tool-formatters-fUAp2Nr4.d.ts → tool-formatters-0FEGRd6w.d.ts} +2 -2
- package/dist/{tool-formatters-fUAp2Nr4.d.ts.map → tool-formatters-0FEGRd6w.d.ts.map} +1 -1
- package/dist/tools/fetch-url.d.ts +1 -1
- package/dist/tools/web-search.d.ts +1 -1
- package/dist/{tools-dkB_jARJ.js → tools-BmPeBGU1.js} +196 -5
- package/dist/tools-BmPeBGU1.js.map +1 -0
- package/dist/tools.d.ts +2 -2
- package/dist/tools.js +1 -1
- package/dist/{transcript-anchors-Cl7lbbeP.js → transcript-anchors-Bp5bV0Bv.js} +31 -4
- package/dist/transcript-anchors-Bp5bV0Bv.js.map +1 -0
- package/dist/{transcript-anchors-qxevvEwT.d.ts → transcript-anchors-D2erm5iS.d.ts} +4 -4
- package/dist/transcript-anchors-D2erm5iS.d.ts.map +1 -0
- package/dist/tui.d.ts +3 -3
- package/dist/tui.js +5 -5
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-CE1prnuP.d.ts → turn-operations-CeUrtsaM.d.ts} +3 -3
- package/dist/{turn-operations-CE1prnuP.d.ts.map → turn-operations-CeUrtsaM.d.ts.map} +1 -1
- package/dist/types-BPw_i5vb.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/docs/ARCHITECTURE.md +2 -1
- package/docs/CHAT.md +19 -1
- package/docs/HEADLESS.md +138 -0
- package/docs/SKILL.md +1 -0
- package/package.json +8 -2
- package/dist/agent-BSPhByzT.d.ts.map +0 -1
- package/dist/index-B6h9C_JE.d.ts.map +0 -1
- package/dist/tools-dkB_jARJ.js.map +0 -1
- package/dist/transcript-anchors-Cl7lbbeP.js.map +0 -1
- package/dist/transcript-anchors-qxevvEwT.d.ts.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as SkillConfig, Gt as AgentStats,
|
|
1
|
+
import { D as SkillConfig, Gt as AgentStats, I as SessionStore, Kt as ChildRunStats, N as Session, Sn as TurnUsage, Zt as McpServerConfig, ft as StreamOptions, gn as ThinkingLevel, i as AgentOptions, l as SkillActivationState, lt as Provider, pn as SessionTurn, r as AgentHooks, rn as PromptPart, s as ActiveSkill, v as ToolContext, vn as ToolResultContent, xn as TurnFinishReason, y as ToolDef } from "./agent-DYghZGC8.js";
|
|
2
2
|
import { a as ExecutionContext, o as ExecutionHandle } from "./types-CEAMIUXw.js";
|
|
3
3
|
import { Hookable } from "hookable";
|
|
4
4
|
import { OAuthClientProvider, OAuthDiscoveryState } from "@modelcontextprotocol/sdk/client/auth.js";
|
|
@@ -618,1348 +618,1509 @@ declare const BYTES_PER_TOKEN = 4;
|
|
|
618
618
|
*/
|
|
619
619
|
declare function estimateTokens(text: string): number;
|
|
620
620
|
//#endregion
|
|
621
|
-
//#region src/
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
621
|
+
//#region src/run-summary.d.ts
|
|
622
|
+
interface RunSummaryTokens {
|
|
623
|
+
input: number;
|
|
624
|
+
output: number;
|
|
625
|
+
cacheRead: number;
|
|
626
|
+
cacheCreation: number;
|
|
627
|
+
cost?: number;
|
|
628
|
+
/** First observable byte from the provider, ms from run start. */
|
|
629
|
+
ttftMs?: number;
|
|
630
|
+
}
|
|
631
|
+
interface RunSummaryByModel {
|
|
632
|
+
modelId: string;
|
|
633
|
+
input: number;
|
|
634
|
+
output: number;
|
|
635
|
+
cacheRead: number;
|
|
636
|
+
cacheCreation: number;
|
|
637
|
+
cost: number;
|
|
638
|
+
turns: number;
|
|
639
|
+
}
|
|
640
|
+
interface RunSummaryError {
|
|
641
|
+
kind: 'stream' | 'tool' | 'mcp-tool' | 'mcp' | 'spawn';
|
|
628
642
|
message: string;
|
|
629
|
-
|
|
630
|
-
|
|
643
|
+
errorType?: string;
|
|
644
|
+
turnId?: string;
|
|
645
|
+
callId?: string;
|
|
646
|
+
server?: string;
|
|
647
|
+
toolName?: string;
|
|
648
|
+
childId?: string;
|
|
649
|
+
statusCode?: number;
|
|
650
|
+
requestId?: string;
|
|
631
651
|
}
|
|
632
|
-
interface
|
|
633
|
-
|
|
652
|
+
interface RunSummaryBlock {
|
|
653
|
+
callId: string;
|
|
654
|
+
toolName: string;
|
|
655
|
+
outcome: 'gate-block' | 'unknown' | 'invalid-input';
|
|
656
|
+
reason?: string;
|
|
634
657
|
}
|
|
635
|
-
interface
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
658
|
+
interface RunSummaryValidation {
|
|
659
|
+
callId: string;
|
|
660
|
+
toolName: string;
|
|
661
|
+
reason: string;
|
|
662
|
+
}
|
|
663
|
+
interface RunSummaryBudget {
|
|
664
|
+
kind: 'bytes' | 'tool-count';
|
|
665
|
+
/** Tool name (for `'tool-count'`); absent for byte budgets. */
|
|
666
|
+
toolName?: string;
|
|
667
|
+
/** `mode` for `'tool-count'`; absent for byte budgets. */
|
|
668
|
+
mode?: 'steer' | 'block';
|
|
669
|
+
observed: number;
|
|
670
|
+
limit: number;
|
|
671
|
+
turnId?: string;
|
|
672
|
+
}
|
|
673
|
+
interface RunSummaryRepeatGuard {
|
|
674
|
+
toolName: string;
|
|
675
|
+
/** Consecutive identical calls including the one that tripped the guard. */
|
|
676
|
+
count: number;
|
|
677
|
+
threshold: number;
|
|
678
|
+
action: 'block' | 'abort';
|
|
679
|
+
turnId?: string;
|
|
651
680
|
}
|
|
652
681
|
/**
|
|
653
|
-
*
|
|
654
|
-
*
|
|
682
|
+
* Postmortem snapshot of one `agent.run()`. Strictly serializable — every
|
|
683
|
+
* field round-trips through `JSON.stringify` / `JSON.parse` without loss
|
|
684
|
+
* so a log aggregator can ingest it as-is.
|
|
655
685
|
*/
|
|
656
|
-
|
|
657
|
-
|
|
686
|
+
interface RunSummary {
|
|
687
|
+
runId?: string;
|
|
688
|
+
parentRunId?: string;
|
|
689
|
+
depth: number;
|
|
690
|
+
agentName?: string;
|
|
691
|
+
startedAt: number;
|
|
692
|
+
endedAt: number;
|
|
693
|
+
durationMs: number;
|
|
694
|
+
status: 'completed' | 'aborted';
|
|
695
|
+
turns: number;
|
|
696
|
+
totals: RunSummaryTokens;
|
|
697
|
+
byModel: RunSummaryByModel[];
|
|
698
|
+
errors: RunSummaryError[];
|
|
699
|
+
blocks: RunSummaryBlock[];
|
|
700
|
+
validationRejects: RunSummaryValidation[];
|
|
701
|
+
budgetEvents: RunSummaryBudget[];
|
|
658
702
|
/**
|
|
659
|
-
*
|
|
660
|
-
*
|
|
661
|
-
* `
|
|
703
|
+
* Consecutive-identical repeat-guard escalations. An `action: 'abort'`
|
|
704
|
+
* entry means the guard terminated the run via the agent's
|
|
705
|
+
* `AbortController` (the run finalizes as `'aborted'`).
|
|
662
706
|
*/
|
|
663
|
-
|
|
664
|
-
/**
|
|
665
|
-
|
|
666
|
-
write: (chunk: string) => void;
|
|
667
|
-
};
|
|
668
|
-
}
|
|
669
|
-
/**
|
|
670
|
-
* Human-readable terminal sink. Renders each record as
|
|
671
|
-
* `<ISO timestamp> <LEVEL> <message> <attrs as kv pairs>`.
|
|
672
|
-
*
|
|
673
|
-
* Honors `process.stderr` by default so log lines don't interleave with
|
|
674
|
-
* the agent's stdout-bound output (chat responses, JSON results).
|
|
675
|
-
*/
|
|
676
|
-
declare function consoleSink(options?: ConsoleSinkOptions): LogSink;
|
|
677
|
-
/**
|
|
678
|
-
* One-JSON-object-per-line sink. Suitable for piping into log aggregators
|
|
679
|
-
* (Datadog Agent, Fluent Bit, Loki, Vector) that expect JSONL.
|
|
680
|
-
*/
|
|
681
|
-
declare function jsonSink(options?: ConsoleSinkOptions): LogSink;
|
|
682
|
-
interface LoggingHooksOptions {
|
|
683
|
-
logger: Logger;
|
|
707
|
+
repeatGuardEvents: RunSummaryRepeatGuard[];
|
|
708
|
+
/** Counts of pairing repairs, keyed by repair mode. */
|
|
709
|
+
pairingRepairs: Record<string, number>;
|
|
684
710
|
/**
|
|
685
|
-
*
|
|
686
|
-
*
|
|
687
|
-
* `'warn'` to mute the chatty ones and only see failures + budgets.
|
|
711
|
+
* Postmortem snapshots of child runs that bubbled their stats up via
|
|
712
|
+
* `spawn:complete`. Only present when the run actually spawned.
|
|
688
713
|
*/
|
|
689
|
-
|
|
714
|
+
children?: RunSummary[];
|
|
715
|
+
}
|
|
716
|
+
interface RunSummaryCollectorOptions {
|
|
690
717
|
/**
|
|
691
|
-
*
|
|
692
|
-
*
|
|
693
|
-
* stay quiet by default. Set false to mute them entirely regardless of
|
|
694
|
-
* the configured minimum level — useful when piping into a tracer
|
|
695
|
-
* that already captures lifecycle.
|
|
718
|
+
* Called with the assembled {@link RunSummary} on every `agent:done`.
|
|
719
|
+
* Synchronous — heavy I/O should be deferred (e.g. via `setImmediate`).
|
|
696
720
|
*/
|
|
697
|
-
|
|
721
|
+
onSummary?: (summary: RunSummary) => void;
|
|
698
722
|
}
|
|
699
|
-
interface
|
|
723
|
+
interface RunSummaryCollector {
|
|
724
|
+
/** Install the collector's hook handlers. Returns an uninstall fn. */
|
|
700
725
|
install: (hooks: Hookable<AgentHooks>) => () => void;
|
|
726
|
+
/** Most-recent summary; `undefined` until the first `agent:done` fires. */
|
|
727
|
+
latest: () => RunSummary | undefined;
|
|
701
728
|
}
|
|
702
729
|
/**
|
|
703
|
-
*
|
|
704
|
-
*
|
|
705
|
-
*
|
|
730
|
+
* Build a run-summary collector. State is created fresh inside each
|
|
731
|
+
* `install()` call, so a single collector instance can be installed
|
|
732
|
+
* across multiple agents without attribution cross-talk. `latest()`
|
|
733
|
+
* returns the most-recent summary across **any** install — install
|
|
734
|
+
* per-agent collectors if you need separate post-run snapshots.
|
|
706
735
|
*
|
|
707
736
|
* @example
|
|
708
737
|
* ```ts
|
|
709
|
-
* const
|
|
710
|
-
*
|
|
711
|
-
*
|
|
738
|
+
* const collector = createRunSummaryCollector({
|
|
739
|
+
* onSummary: s => console.log(JSON.stringify(s)),
|
|
740
|
+
* })
|
|
741
|
+
* const uninstall = collector.install(agent.hooks)
|
|
712
742
|
* try { await agent.run({ prompt }) }
|
|
713
743
|
* finally { uninstall() }
|
|
714
744
|
* ```
|
|
715
745
|
*/
|
|
716
|
-
declare function
|
|
746
|
+
declare function createRunSummaryCollector(options?: RunSummaryCollectorOptions): RunSummaryCollector;
|
|
717
747
|
//#endregion
|
|
718
|
-
//#region src/
|
|
719
|
-
/**
|
|
720
|
-
* Canonical tool_result text emitted when a tool call is interrupted by the
|
|
721
|
-
* user mid-flight (Esc / Ctrl-C / external `AbortSignal`). Mirrors Claude
|
|
722
|
-
* Code's `INTERRUPT_MESSAGE_FOR_TOOL_USE` so downstream consumers can pattern
|
|
723
|
-
* match a single string across both harnesses. Always paired with
|
|
724
|
-
* `isError: true` on the wire — the model treats it as a failed call rather
|
|
725
|
-
* than a successful tool response.
|
|
726
|
-
*/
|
|
727
|
-
declare const INTERRUPT_MESSAGE_FOR_TOOL_USE = "[Request interrupted by user for tool use]";
|
|
728
|
-
/**
|
|
729
|
-
* Canonical tool_result text emitted when a tool call is skipped because a
|
|
730
|
-
* steering message arrived between dispatches inside
|
|
731
|
-
* {@link executeToolBatch}. Distinguished from
|
|
732
|
-
* {@link INTERRUPT_MESSAGE_FOR_TOOL_USE} so consumers can split "user
|
|
733
|
-
* cancelled" from "framework superseded".
|
|
734
|
-
*/
|
|
735
|
-
declare const TOOL_USE_SKIPPED_MESSAGE = "[Tool use skipped \u2014 superseded by user message]";
|
|
748
|
+
//#region src/tools/edit.d.ts
|
|
736
749
|
/**
|
|
737
|
-
*
|
|
738
|
-
* mid-flight via `agent.cancelTool(callId)` (typically the TUI's
|
|
739
|
-
* "cancel this tool" affordance). Distinguished from
|
|
740
|
-
* {@link INTERRUPT_MESSAGE_FOR_TOOL_USE} (run-wide user abort) and
|
|
741
|
-
* {@link TOOL_USE_SKIPPED_MESSAGE} (steered) so the model — and downstream
|
|
742
|
-
* consumers — can tell the three apart by string match.
|
|
750
|
+
* Surgical edit — replace `old_string` with `new_string` in a single file.
|
|
743
751
|
*
|
|
744
|
-
*
|
|
745
|
-
*
|
|
746
|
-
*
|
|
747
|
-
|
|
748
|
-
declare const TOOL_USE_CANCELLED_MESSAGE = "[Tool call cancelled by user]";
|
|
749
|
-
/**
|
|
750
|
-
* Canonical `tool_result.content` text emitted to siblings that were
|
|
751
|
-
* cancelled by a `shell` error in the same batch. Distinct from
|
|
752
|
-
* {@link INTERRUPT_MESSAGE_FOR_TOOL_USE} (user-issued abort) and
|
|
753
|
-
* {@link TOOL_USE_SKIPPED_MESSAGE} (steered) so consumers can split
|
|
754
|
-
* the three causes by string-match.
|
|
752
|
+
* Mirrors Claude Code's `Edit` semantics so models post-trained on Anthropic's
|
|
753
|
+
* tool surface need no relearning. Fails clearly when `old_string` isn't unique
|
|
754
|
+
* (unless `replace_all: true`) and when not found, with a nearest-match preview
|
|
755
|
+
* so the model can recover without a separate `read_file` round-trip.
|
|
755
756
|
*/
|
|
756
|
-
declare const
|
|
757
|
+
declare const edit: ToolDef;
|
|
757
758
|
//#endregion
|
|
758
|
-
//#region src/
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
759
|
+
//#region src/tools/glob.d.ts
|
|
760
|
+
declare const glob: ToolDef;
|
|
761
|
+
//#endregion
|
|
762
|
+
//#region src/tools/grep.d.ts
|
|
763
|
+
declare const grep: ToolDef;
|
|
764
|
+
//#endregion
|
|
765
|
+
//#region src/tools/interaction.d.ts
|
|
766
|
+
interface InteractionToolOptions {
|
|
767
|
+
/** JSON Schema for the request payload the model sends */
|
|
768
|
+
schema: Record<string, unknown>;
|
|
769
|
+
/** Tool name (default: 'interaction') */
|
|
770
|
+
name?: string;
|
|
771
|
+
/** Tool description shown to the model */
|
|
772
|
+
description?: string;
|
|
773
|
+
/** Called when the model invokes this tool. Receives the validated payload and tool context, returns data for the model. */
|
|
774
|
+
onRequest: (payload: Record<string, unknown>, ctx: ToolContext) => Promise<Record<string, unknown> | string>;
|
|
775
|
+
}
|
|
771
776
|
/**
|
|
772
|
-
*
|
|
773
|
-
* Exported so wire-level passes (tail compaction, future stale-output
|
|
774
|
-
* elision) can recognize a persisted stub and preserve its path attribute
|
|
775
|
-
* rather than replacing the stub with their own — losing the pointer to
|
|
776
|
-
* the on-disk blob.
|
|
777
|
+
* Create an interaction tool that lets the agent request structured input.
|
|
777
778
|
*
|
|
778
|
-
*
|
|
779
|
-
*
|
|
780
|
-
*
|
|
779
|
+
* The model calls this tool with a payload matching the schema.
|
|
780
|
+
* `onRequest` is called with the payload and should return the response
|
|
781
|
+
* (string or object) that gets sent back to the model as the tool result.
|
|
781
782
|
*/
|
|
782
|
-
declare
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
* Resolve the per-session background-tasks directory under
|
|
796
|
-
* `<userDir>/<sessionId>/tasks/`.
|
|
797
|
-
*
|
|
798
|
-
* The chat layer calls this at session activation and forwards the result
|
|
799
|
-
* via `behavior.tasksDir`. Same shape as {@link resolvePersistDir}: hosts
|
|
800
|
-
* get a single source of truth for "where do task log files live".
|
|
801
|
-
* Created on first write; cleanup is the session-delete path's job.
|
|
802
|
-
*/
|
|
803
|
-
declare function resolveTasksDir(opts: {
|
|
804
|
-
userDir: string;
|
|
805
|
-
sessionId: string;
|
|
806
|
-
}): string;
|
|
807
|
-
/**
|
|
808
|
-
* Inputs to {@link maybePersistToolResult}. Kept as a struct so the loop's
|
|
809
|
-
* call site stays readable and additional optional knobs (compression,
|
|
810
|
-
* mime detection, …) land without re-threading every call site.
|
|
811
|
-
*/
|
|
812
|
-
interface PersistInput {
|
|
813
|
-
/** Canonical tool name — checked against `excludeTools`. */
|
|
814
|
-
toolName: string;
|
|
815
|
-
/** `tool_use` id from the assistant turn. Used as the filename. */
|
|
816
|
-
callId: string;
|
|
817
|
-
/** Result returned by the tool (post-`tool:transform`). */
|
|
818
|
-
output: string | ToolResultContent[];
|
|
819
|
-
/** Byte threshold; outputs at or below stay inline. */
|
|
820
|
-
threshold: number;
|
|
821
|
-
/** Canonical tool names that bypass persistence. */
|
|
822
|
-
excludeTools?: readonly string[];
|
|
823
|
-
/** Persistence root directory. Created on first write. */
|
|
824
|
-
persistDir: string;
|
|
783
|
+
declare function createInteractionTool(options: InteractionToolOptions): ToolDef;
|
|
784
|
+
//#endregion
|
|
785
|
+
//#region src/tools/list-files.d.ts
|
|
786
|
+
declare const listFiles: ToolDef;
|
|
787
|
+
//#endregion
|
|
788
|
+
//#region src/tools/multi-edit.d.ts
|
|
789
|
+
declare const multiEdit: ToolDef;
|
|
790
|
+
//#endregion
|
|
791
|
+
//#region src/tools/read-file.d.ts
|
|
792
|
+
declare const readFile: ToolDef;
|
|
793
|
+
//#endregion
|
|
794
|
+
//#region src/tools/shell.d.ts
|
|
795
|
+
interface CreateShellToolOptions {
|
|
825
796
|
/**
|
|
826
|
-
*
|
|
827
|
-
*
|
|
828
|
-
*
|
|
829
|
-
*
|
|
797
|
+
* Whether to expose the `run_in_background` flag in the input schema +
|
|
798
|
+
* the background-mode paragraphs in the description. When `false`, the
|
|
799
|
+
* model never sees the flag and won't try to use it. The execute path
|
|
800
|
+
* still has a defensive fallback: an explicit `run_in_background: true`
|
|
801
|
+
* call (e.g. from a hand-crafted message) returns a clean error rather
|
|
802
|
+
* than silently running foreground.
|
|
830
803
|
*
|
|
831
|
-
*
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
804
|
+
* Default: `true`.
|
|
805
|
+
*/
|
|
806
|
+
allowBackground?: boolean;
|
|
807
|
+
/**
|
|
808
|
+
* Canonical names of tools registered alongside `shell` on the same
|
|
809
|
+
* agent. When non-empty, the description gains a "prefer the dedicated
|
|
810
|
+
* tool" block for each known sibling (`read_file`, `glob`, `grep`,
|
|
811
|
+
* `list_files`, `edit`, `write_file`) — useful against the
|
|
812
|
+
* `ls`/`cat`-to-re-verify loop some models fall into when both a
|
|
813
|
+
* dedicated tool AND `shell` are visible. Unknown / unrecognized names
|
|
814
|
+
* are ignored.
|
|
835
815
|
*
|
|
836
|
-
*
|
|
837
|
-
*
|
|
838
|
-
*
|
|
839
|
-
*
|
|
816
|
+
* Set by `createAgent` per-run from the tool registry; hosts that
|
|
817
|
+
* construct a `shell` directly can pass it explicitly. Omit to suppress
|
|
818
|
+
* the block entirely (no nudge for shell-only agents, no nudge for
|
|
819
|
+
* hosts that prefer to author their own anti-loop prose).
|
|
840
820
|
*/
|
|
841
|
-
|
|
821
|
+
registeredCanonicals?: ReadonlySet<string>;
|
|
822
|
+
/**
|
|
823
|
+
* The agent's `toolAliases` map, used to render the wire-level name of
|
|
824
|
+
* each sibling in the swap block. Without this, the block always prints
|
|
825
|
+
* canonical names — fine for the default preset, wrong for hosts that
|
|
826
|
+
* alias-rename (the model would be told to call a name it doesn't see
|
|
827
|
+
* in the tool spec).
|
|
828
|
+
*/
|
|
829
|
+
toolAliases?: Record<string, string>;
|
|
842
830
|
}
|
|
843
|
-
type PersistOutcome = {
|
|
844
|
-
kind: 'skip';
|
|
845
|
-
reason: 'disabled' | 'excluded' | 'under-threshold' | 'unsupported-shape' | 'unsafe-call-id' | 'invalid-persist-dir';
|
|
846
|
-
} | {
|
|
847
|
-
kind: 'persisted';
|
|
848
|
-
output: string;
|
|
849
|
-
originalBytes: number;
|
|
850
|
-
persistedPath: string;
|
|
851
|
-
evicted?: {
|
|
852
|
-
files: number;
|
|
853
|
-
bytes: number;
|
|
854
|
-
};
|
|
855
|
-
} | {
|
|
856
|
-
kind: 'error';
|
|
857
|
-
reason: 'write-failed';
|
|
858
|
-
error: Error;
|
|
859
|
-
};
|
|
860
831
|
/**
|
|
861
|
-
*
|
|
862
|
-
*
|
|
863
|
-
*
|
|
864
|
-
*
|
|
865
|
-
*
|
|
866
|
-
* read (or a crash mid-write) never sees a half-written blob.
|
|
832
|
+
* Factory for the `shell` tool. The default exported `shell` is
|
|
833
|
+
* equivalent to `createShellTool({ allowBackground: true })`. The
|
|
834
|
+
* factory is the entry point hosts use when they want to override the
|
|
835
|
+
* default — e.g. to ship a preset that always disables background mode
|
|
836
|
+
* regardless of `behavior.tasksDir`.
|
|
867
837
|
*
|
|
868
|
-
* `
|
|
869
|
-
*
|
|
870
|
-
*
|
|
871
|
-
*
|
|
838
|
+
* Hosts that use the framework's `createAgent` typically don't need to
|
|
839
|
+
* call this directly: when `behavior.tasksDir` is unset or
|
|
840
|
+
* `behavior.disableBackgroundTasks: true` is set, the agent
|
|
841
|
+
* automatically rewrites the registered `shell` (if it's the
|
|
842
|
+
* framework's built-in) using this factory.
|
|
872
843
|
*/
|
|
873
|
-
declare function
|
|
874
|
-
interface BuildStubInput {
|
|
875
|
-
toolName: string;
|
|
876
|
-
originalBytes: number;
|
|
877
|
-
persistedPath: string;
|
|
878
|
-
output: string;
|
|
879
|
-
}
|
|
844
|
+
declare function createShellTool(opts?: CreateShellToolOptions): ToolDef;
|
|
880
845
|
/**
|
|
881
|
-
*
|
|
882
|
-
* of the original `tool_result`.
|
|
883
|
-
*
|
|
884
|
-
* Format choices:
|
|
885
|
-
* - XML wrapper because models reliably parse it as structural.
|
|
886
|
-
* - Byte count + path in attributes so the model can decide whether to
|
|
887
|
-
* `read_file` the persisted blob without scanning the preview.
|
|
888
|
-
* - Preview always shows the head — `shell`'s tail-priority truncation is
|
|
889
|
-
* irrelevant here because the model has the full path if it needs the
|
|
890
|
-
* tail.
|
|
891
|
-
* - No timestamps, no random UUIDs inside the stub: every byte must be
|
|
892
|
-
* reproducible from the inputs, otherwise re-emission on subsequent
|
|
893
|
-
* turns would bust the prompt cache.
|
|
846
|
+
* Default `shell` tool with background mode enabled.
|
|
894
847
|
*
|
|
895
|
-
*
|
|
896
|
-
*
|
|
897
|
-
*
|
|
848
|
+
* Most hosts use this directly via `basicTools`. When the agent's
|
|
849
|
+
* `behavior.tasksDir` is unset OR `behavior.disableBackgroundTasks:
|
|
850
|
+
* true` is set, `createAgent` auto-rewrites this identity to a
|
|
851
|
+
* `createShellTool({ allowBackground: false })` variant so the model
|
|
852
|
+
* never sees a flag it can't use. Hosts who want to bypass that
|
|
853
|
+
* auto-rewrite can register a `createShellTool({ allowBackground })`
|
|
854
|
+
* directly — the rewrite only fires on identity-equal references to
|
|
855
|
+
* this constant.
|
|
898
856
|
*/
|
|
899
|
-
declare
|
|
857
|
+
declare const shell: ToolDef;
|
|
858
|
+
//#endregion
|
|
859
|
+
//#region src/tools/shell-kill.d.ts
|
|
860
|
+
declare const shellKill: ToolDef;
|
|
861
|
+
//#endregion
|
|
862
|
+
//#region src/tools/skills-read.d.ts
|
|
863
|
+
interface SkillsReadToolOptions {
|
|
864
|
+
catalog: readonly SkillConfig[];
|
|
865
|
+
state: SkillActivationState;
|
|
866
|
+
}
|
|
867
|
+
declare function createSkillsReadTool(options: SkillsReadToolOptions): ToolDef;
|
|
868
|
+
//#endregion
|
|
869
|
+
//#region src/tools/skills-run-script.d.ts
|
|
870
|
+
interface SkillsRunScriptToolOptions {
|
|
871
|
+
catalog: readonly SkillConfig[];
|
|
872
|
+
state: SkillActivationState;
|
|
873
|
+
/** Script timeout in milliseconds. Default 60000. */
|
|
874
|
+
scriptTimeoutMs?: number;
|
|
875
|
+
}
|
|
876
|
+
declare function createSkillsRunScriptTool(options: SkillsRunScriptToolOptions): ToolDef;
|
|
877
|
+
//#endregion
|
|
878
|
+
//#region src/tools/skills-use.d.ts
|
|
879
|
+
interface SkillsUseToolOptions {
|
|
880
|
+
/** Resolved skills catalog for this run. */
|
|
881
|
+
catalog: readonly SkillConfig[];
|
|
882
|
+
/** Per-agent activation state the tool mutates. */
|
|
883
|
+
state: SkillActivationState;
|
|
884
|
+
/** Agent hooks — used to fire `skills:activate` on first activation. */
|
|
885
|
+
hooks: Hookable<AgentHooks>;
|
|
886
|
+
}
|
|
900
887
|
/**
|
|
901
|
-
*
|
|
902
|
-
*
|
|
903
|
-
*
|
|
888
|
+
* Factory for `skills_use`. Auto-injected into the agent's tool set by the
|
|
889
|
+
* agent runtime when a non-empty skills catalog is available (unless
|
|
890
|
+
* `SkillsConfig.tool === false`).
|
|
904
891
|
*
|
|
905
|
-
*
|
|
906
|
-
*
|
|
907
|
-
* blob doesn't propagate to the caller; the chat layer can't usefully
|
|
908
|
-
* recover from "couldn't unlink a result file" mid-delete.
|
|
892
|
+
* The tool schema's `name` property is `enum`-constrained to the resolved
|
|
893
|
+
* catalog so the LLM cannot hallucinate a skill that doesn't exist.
|
|
909
894
|
*/
|
|
910
|
-
declare function
|
|
895
|
+
declare function createSkillsUseTool(options: SkillsUseToolOptions): ToolDef;
|
|
911
896
|
//#endregion
|
|
912
|
-
//#region src/
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
*/
|
|
918
|
-
|
|
919
|
-
tokens?: OAuthTokens;
|
|
920
|
-
clientInformation?: OAuthClientInformationMixed;
|
|
921
|
-
discoveryState?: OAuthDiscoveryState;
|
|
897
|
+
//#region src/tools/spawn.d.ts
|
|
898
|
+
interface ChildAgent {
|
|
899
|
+
id: string;
|
|
900
|
+
task: string;
|
|
901
|
+
startedAt: number;
|
|
902
|
+
/** Subagent depth — 1 for a direct child of a top-level agent. */
|
|
903
|
+
depth: number;
|
|
922
904
|
}
|
|
923
|
-
interface
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
905
|
+
interface SpawnToolState {
|
|
906
|
+
/** Currently running children. */
|
|
907
|
+
readonly children: ReadonlyMap<string, ChildAgent>;
|
|
908
|
+
/**
|
|
909
|
+
* Cumulative stats across every completed direct child of this spawn-tool
|
|
910
|
+
* instance (returns a copy). Each child's contribution is the cumulative
|
|
911
|
+
* `AgentStats` returned by its `agent.run()` — so
|
|
912
|
+
* `totalIn`/`totalOut`/`totalCacheRead`/`totalCacheCreation` cover the
|
|
913
|
+
* entire subtree (children + grandchildren + …), while `turns` and
|
|
914
|
+
* `elapsed` stay parent-loop-only per child and are summed across direct
|
|
915
|
+
* children. `elapsed` over-counts when children ran in parallel.
|
|
916
|
+
*
|
|
917
|
+
* Lives across multiple parent runs that share this instance.
|
|
918
|
+
*/
|
|
919
|
+
readonly totalChildStats: Readonly<AgentStats>;
|
|
927
920
|
}
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
*/
|
|
932
|
-
declare function createMemoryMcpCredentialStore(seed?: Record<string, McpCredentialEntry>): McpCredentialStore;
|
|
933
|
-
interface McpOAuthProviderOptions {
|
|
934
|
-
/** Server name — used as the storage key. */
|
|
935
|
-
name: string;
|
|
936
|
-
/** Persistence backend. */
|
|
937
|
-
store: McpCredentialStore;
|
|
921
|
+
interface SpawnToolOptions {
|
|
922
|
+
/** Maximum concurrent sub-agents (default: 3). */
|
|
923
|
+
maxConcurrent?: number;
|
|
938
924
|
/**
|
|
939
|
-
*
|
|
940
|
-
*
|
|
925
|
+
* Maximum subagent depth. 0 disables spawning entirely; 1 allows top-level
|
|
926
|
+
* spawns but forbids grandchildren; 3 (default) allows three levels of
|
|
927
|
+
* recursion — enough for most orchestration patterns, a sharp ceiling
|
|
928
|
+
* against runaway loops.
|
|
941
929
|
*/
|
|
942
|
-
|
|
930
|
+
maxDepth?: number;
|
|
931
|
+
/** Child model override. */
|
|
932
|
+
model?: string;
|
|
933
|
+
/** Child system prompt override. Per-spawn `input.system` takes precedence. */
|
|
934
|
+
system?: string;
|
|
935
|
+
/** Child thinking level. */
|
|
936
|
+
thinking?: 'off' | 'minimal' | 'low' | 'medium' | 'high';
|
|
937
|
+
/** Preset override for children. Shallow-merged over the parent's preset (parent fields still win for anything left unset). */
|
|
938
|
+
preset?: Preset;
|
|
943
939
|
/**
|
|
944
|
-
*
|
|
945
|
-
*
|
|
946
|
-
*
|
|
947
|
-
* still calls this before throwing `UnauthorizedError` from connect).
|
|
940
|
+
* Per-child timeout, in milliseconds. When the child exceeds it the spawn
|
|
941
|
+
* tool returns a timeout marker, fires `spawn:error`, and destroys the
|
|
942
|
+
* child agent. Default: none.
|
|
948
943
|
*/
|
|
949
|
-
|
|
944
|
+
timeoutMs?: number;
|
|
950
945
|
/**
|
|
951
|
-
* `
|
|
952
|
-
*
|
|
946
|
+
* When `true` and the parent has a session, the child reuses the parent's
|
|
947
|
+
* session — child turns are appended with the child's own `runId`, and the
|
|
948
|
+
* resulting `SessionRun` carries `parentRunId` so the tree is
|
|
949
|
+
* reconstructible. Default: `false` (child is in-memory only).
|
|
950
|
+
*
|
|
951
|
+
* **Read-state isolation.** Sharing the session also shares the
|
|
952
|
+
* `read_file` / `requireReadBeforeEdit` tracking map (it's keyed
|
|
953
|
+
* by `Session`). With `persist: false` the child gets no session,
|
|
954
|
+
* so reads inside the subagent populate nothing the parent can see —
|
|
955
|
+
* a follow-up `edit` / `multi_edit` in the parent will trip the
|
|
956
|
+
* gate with `"has not been read"` even though the model just
|
|
957
|
+
* read the file in the child. Use {@link shareReadState} when
|
|
958
|
+
* you want the parent's gate to honor the child's reads WITHOUT
|
|
959
|
+
* also persisting child turns to the parent's session.
|
|
953
960
|
*/
|
|
954
|
-
|
|
961
|
+
persist?: boolean;
|
|
955
962
|
/**
|
|
956
|
-
*
|
|
957
|
-
*
|
|
963
|
+
* Forward the parent's read-state map to the child agent so the
|
|
964
|
+
* `requireReadBeforeEdit` gate and `dedupReads` cache see reads
|
|
965
|
+
* across the parent/child boundary. Orthogonal to {@link persist} —
|
|
966
|
+
* use this when you want shared read tracking without sharing the
|
|
967
|
+
* session's turn history. Default: `false`.
|
|
968
|
+
*
|
|
969
|
+
* Has no effect when the parent has no read-state to share (no
|
|
970
|
+
* session and no explicit `readState` on the parent agent's
|
|
971
|
+
* options). Implementation: passes the parent's resolved
|
|
972
|
+
* `ReadStateMap` to the child via `AgentOptions.readState`, which
|
|
973
|
+
* tools resolve via `ctx.readState ?? getReadState(ctx.session)`.
|
|
958
974
|
*/
|
|
959
|
-
|
|
960
|
-
}
|
|
961
|
-
declare class McpOAuthProvider implements OAuthClientProvider {
|
|
962
|
-
private readonly name;
|
|
963
|
-
private readonly store;
|
|
964
|
-
private readonly _redirectUri?;
|
|
965
|
-
private readonly onAuthorizationUrl?;
|
|
966
|
-
private readonly clientName;
|
|
967
|
-
private readonly _scope?;
|
|
968
|
-
private codeVerifierValue;
|
|
969
|
-
constructor(opts: McpOAuthProviderOptions);
|
|
970
|
-
get redirectUrl(): string | URL | undefined;
|
|
971
|
-
get clientMetadata(): OAuthClientMetadata;
|
|
972
|
-
tokens(): OAuthTokens | undefined;
|
|
973
|
-
saveTokens(tokens: OAuthTokens): void;
|
|
974
|
-
clientInformation(): OAuthClientInformationMixed | undefined;
|
|
975
|
-
saveClientInformation(info: OAuthClientInformationMixed): void;
|
|
976
|
-
discoveryState(): OAuthDiscoveryState | undefined;
|
|
977
|
-
saveDiscoveryState(state: OAuthDiscoveryState): void;
|
|
978
|
-
saveCodeVerifier(verifier: string): void;
|
|
979
|
-
codeVerifier(): string;
|
|
980
|
-
redirectToAuthorization(url: URL): Promise<void>;
|
|
975
|
+
shareReadState?: boolean;
|
|
981
976
|
/**
|
|
982
|
-
*
|
|
983
|
-
*
|
|
984
|
-
*
|
|
985
|
-
* - `'client'` → client registration invalidated, reset everything
|
|
986
|
-
* - `'verifier'`→ PKCE state stale (e.g. mismatched state param)
|
|
987
|
-
* - `'discovery'` → discovery metadata stale (servers re-keyed)
|
|
988
|
-
* - `'all'` → full reset
|
|
977
|
+
* Forward a curated subset of child hook events (`stream:*`, `tool:*`,
|
|
978
|
+
* `turn:after`) onto the parent's hook bus as `child:*` events. Default:
|
|
979
|
+
* `true`. Grandchildren bubble through their child transparently.
|
|
989
980
|
*/
|
|
990
|
-
|
|
991
|
-
|
|
981
|
+
forwardHooks?: boolean;
|
|
982
|
+
/** Called when a child agent starts. */
|
|
983
|
+
onSpawn?: (child: ChildAgent) => void;
|
|
984
|
+
/** Called when a child agent completes (success, abort, timeout, or error). */
|
|
985
|
+
onComplete?: (child: ChildAgent, stats: AgentStats, status: NonNullable<ChildRunStats['status']>) => void;
|
|
986
|
+
/**
|
|
987
|
+
* Named subagent presets the model can select via the `subagent_type`
|
|
988
|
+
* input field. Mirrors the Claude Code SDK's surface — models trained
|
|
989
|
+
* on it routinely emit `subagent_type: 'Explore' | 'Plan' |
|
|
990
|
+
* 'Verification' | 'general-purpose'`, and without a registry the
|
|
991
|
+
* field is silently dropped, so hosts wanting type-specialized
|
|
992
|
+
* subagents have to invent their own dispatch layer.
|
|
993
|
+
*
|
|
994
|
+
* Each entry overlays the base spawn config for that particular
|
|
995
|
+
* dispatch. Per-call `input.system` still wins over `subagents[type].system`
|
|
996
|
+
* so the model can always specialize further.
|
|
997
|
+
*
|
|
998
|
+
* When the registry is non-empty:
|
|
999
|
+
* - `subagent_type` appears in the spawn input schema as a `string`
|
|
1000
|
+
* enum of the registered keys (plus the always-available
|
|
1001
|
+
* `'general-purpose'` fallback).
|
|
1002
|
+
* - Models that pass an unregistered type are routed to
|
|
1003
|
+
* `'general-purpose'` (no error — degrade gracefully so trained
|
|
1004
|
+
* models keep working even on hosts that haven't wired every
|
|
1005
|
+
* type Claude Code uses).
|
|
1006
|
+
*
|
|
1007
|
+
* When the registry is empty / unset, the field is omitted entirely
|
|
1008
|
+
* (preserves the historical schema for hosts that never use this).
|
|
1009
|
+
*
|
|
1010
|
+
* Default: `undefined` (no subagent types; `subagent_type` schema
|
|
1011
|
+
* field hidden).
|
|
1012
|
+
*/
|
|
1013
|
+
subagents?: SubagentRegistry;
|
|
992
1014
|
}
|
|
993
1015
|
/**
|
|
994
|
-
*
|
|
995
|
-
*
|
|
996
|
-
*
|
|
997
|
-
*
|
|
998
|
-
* Case-insensitive — Node normalizes outgoing headers to lowercase but
|
|
999
|
-
* users hand-write `Authorization` in configs.
|
|
1016
|
+
* Per-type subagent override applied when the model calls
|
|
1017
|
+
* `spawn({ subagent_type: '…' })`. All fields are optional; absent
|
|
1018
|
+
* fields fall back to the parent's resolved configuration (see
|
|
1019
|
+
* {@link SpawnToolOptions} comments for the merge order).
|
|
1000
1020
|
*/
|
|
1001
|
-
|
|
1002
|
-
//#endregion
|
|
1003
|
-
//#region src/mcp/login.d.ts
|
|
1004
|
-
interface LoginMcpServerOptions {
|
|
1005
|
-
/** Persistence — same store the bootstrap path reads from. */
|
|
1006
|
-
store: McpCredentialStore;
|
|
1021
|
+
interface SubagentDef {
|
|
1007
1022
|
/**
|
|
1008
|
-
*
|
|
1009
|
-
*
|
|
1010
|
-
*
|
|
1011
|
-
* fired automatically — this callback is a synchronous hook for callers
|
|
1012
|
-
* that don't want to wire the agent hook machinery.
|
|
1023
|
+
* System prompt override for this subagent type. Per-call
|
|
1024
|
+
* `input.system` still wins — model-supplied specialization beats
|
|
1025
|
+
* preset defaults.
|
|
1013
1026
|
*/
|
|
1014
|
-
|
|
1015
|
-
/** Cancels the flow (esc / close modal / SIGINT). */
|
|
1016
|
-
signal?: AbortSignal;
|
|
1017
|
-
/** Agent hooks. The flow emits `mcp:auth:url`/`success`/`error` when wired. */
|
|
1018
|
-
hooks?: Hookable<AgentHooks>;
|
|
1019
|
-
/** Override `client_name` shown on consent screens. Default: 'zidane'. */
|
|
1020
|
-
clientName?: string;
|
|
1021
|
-
/** Override the requested OAuth scope. */
|
|
1022
|
-
scope?: string;
|
|
1027
|
+
system?: string;
|
|
1023
1028
|
/**
|
|
1024
|
-
*
|
|
1025
|
-
*
|
|
1029
|
+
* Restrict the child agent's tool registry to this list of canonical
|
|
1030
|
+
* tool names. Operates as a filter over the parent's tools (the
|
|
1031
|
+
* parent's selection is the upper bound — a subagent can never gain
|
|
1032
|
+
* tools the parent doesn't have). When unset, the child inherits the
|
|
1033
|
+
* parent's full tool list.
|
|
1034
|
+
*
|
|
1035
|
+
* Tool names are canonical (registry-key) not wire/alias names — the
|
|
1036
|
+
* filter runs before aliases are applied. Names that don't match a
|
|
1037
|
+
* parent tool are silently dropped (matches the lenient behaviour of
|
|
1038
|
+
* `enabledTools` on MCP configs).
|
|
1026
1039
|
*/
|
|
1027
|
-
|
|
1040
|
+
tools?: readonly string[];
|
|
1028
1041
|
/**
|
|
1029
|
-
*
|
|
1030
|
-
*
|
|
1042
|
+
* Mark this subagent as read-only — equivalent to listing only
|
|
1043
|
+
* obviously-non-mutating tools (`read_file`, `grep`, `glob`,
|
|
1044
|
+
* `list_files`) in {@link SubagentDef.tools}. Convenience for the
|
|
1045
|
+
* common "Plan" / "Explore" subagent shape Claude Code ships.
|
|
1046
|
+
*
|
|
1047
|
+
* When both `readonly: true` and `tools` are set, `tools` wins
|
|
1048
|
+
* (explicit beats implicit).
|
|
1031
1049
|
*/
|
|
1032
|
-
|
|
1033
|
-
}
|
|
1034
|
-
interface LoginMcpServerResult {
|
|
1035
|
-
/** Stored OAuth tokens after a successful exchange. */
|
|
1036
|
-
tokens: NonNullable<ReturnType<McpOAuthProvider['tokens']>>;
|
|
1050
|
+
readonly?: boolean;
|
|
1037
1051
|
/**
|
|
1038
|
-
*
|
|
1039
|
-
*
|
|
1040
|
-
*
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
/**
|
|
1051
|
-
* Run the full interactive OAuth flow for `config`. Only supports `sse` and
|
|
1052
|
-
* `streamable-http` transports — `stdio` MCP servers don't speak OAuth.
|
|
1053
|
-
*
|
|
1054
|
-
* Throws on:
|
|
1055
|
-
* - Wrong transport.
|
|
1056
|
-
* - Abort signal.
|
|
1057
|
-
* - Browser-side error (user denied, server rejected, etc.).
|
|
1058
|
-
* - Code exchange failure.
|
|
1059
|
-
* - Post-exchange connect failure.
|
|
1060
|
-
*
|
|
1061
|
-
* Always closes the loopback callback server before returning, success or
|
|
1062
|
-
* failure.
|
|
1063
|
-
*/
|
|
1064
|
-
declare function loginMcpServer(config: McpServerConfig, options: LoginMcpServerOptions): Promise<LoginMcpServerResult>;
|
|
1065
|
-
//#endregion
|
|
1066
|
-
//#region src/mcp/oauth-callback.d.ts
|
|
1067
|
-
/**
|
|
1068
|
-
* Local loopback HTTP callback for OAuth 2.0 authorization code flows.
|
|
1069
|
-
*
|
|
1070
|
-
* Stands up a one-shot server on `127.0.0.1:<random>` that captures the
|
|
1071
|
-
* `?code=...` redirect from a browser-driven OAuth flow and resolves a
|
|
1072
|
-
* promise with the code. Used as the `redirectUrl` half of the MCP SDK's
|
|
1073
|
-
* `OAuthClientProvider` (the persistence half lives separately).
|
|
1074
|
-
*
|
|
1075
|
-
* Design:
|
|
1076
|
-
* - Loopback-only (`127.0.0.1`) — the OAuth spec treats `http://127.0.0.1:<port>`
|
|
1077
|
-
* as a public-client redirect URI per RFC 8252 §7.3. Browsers do NOT block it,
|
|
1078
|
-
* and Anthropic / OpenAI / Linear / GitHub all accept it.
|
|
1079
|
-
* - Random port (`port = 0`) — the OS picks an unused one. We read the actual
|
|
1080
|
-
* port back from `server.address()` after `listen()`.
|
|
1081
|
-
* - Single-shot — the first GET to `path` with a `code` (or `error`) wins;
|
|
1082
|
-
* subsequent requests get 404. The server keeps listening (in case the user
|
|
1083
|
-
* hits "back" and re-authorizes), so callers must `close()` once they have
|
|
1084
|
-
* the code or have given up.
|
|
1085
|
-
* - Abort-aware — wiring an external `AbortSignal` rejects the promise and
|
|
1086
|
-
* closes the server immediately. Required for the TUI's "esc cancels login"
|
|
1087
|
-
* UX.
|
|
1088
|
-
* - No HTML framework — a single inline `<html>` string keeps this isolated
|
|
1089
|
-
* from any UI dependency.
|
|
1052
|
+
* Short description rendered into the spawn tool's schema (the
|
|
1053
|
+
* `subagent_type` field's description) so the model can pick a type
|
|
1054
|
+
* that matches the task without round-tripping through docs.
|
|
1055
|
+
*/
|
|
1056
|
+
description?: string;
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* Map of subagent-type key → preset. Keys are case-sensitive and
|
|
1060
|
+
* appear verbatim in the spawn input schema's enum so the model emits
|
|
1061
|
+
* them with the same casing. Common conventions: `'Explore'`,
|
|
1062
|
+
* `'Plan'`, `'Verification'`, `'general-purpose'` (Claude Code SDK's
|
|
1063
|
+
* built-in set).
|
|
1090
1064
|
*/
|
|
1065
|
+
type SubagentRegistry = Record<string, SubagentDef>;
|
|
1091
1066
|
/**
|
|
1092
|
-
*
|
|
1093
|
-
*
|
|
1094
|
-
*
|
|
1067
|
+
* Create a configured spawn tool.
|
|
1068
|
+
*
|
|
1069
|
+
* State (`children`, `totalChildStats`, counters, active count) is scoped to
|
|
1070
|
+
* the returned instance. Multiple parent agents using the same instance will
|
|
1071
|
+
* share counters + stats + concurrency slots — call `createSpawnTool()` per
|
|
1072
|
+
* agent (or use the stateless default `spawn`) to keep them isolated.
|
|
1095
1073
|
*/
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
interface OAuthCallbackHandle {
|
|
1101
|
-
/**
|
|
1102
|
-
* Full URI to register with the authorization server, e.g.
|
|
1103
|
-
* `http://127.0.0.1:51823/callback`. Stable for the lifetime of the
|
|
1104
|
-
* handle.
|
|
1105
|
-
*/
|
|
1106
|
-
redirectUri: string;
|
|
1074
|
+
declare function createSpawnTool(options?: SpawnToolOptions): ToolDef & SpawnToolState;
|
|
1075
|
+
//#endregion
|
|
1076
|
+
//#region src/tools/tool-search.d.ts
|
|
1077
|
+
interface LazyToolEntry {
|
|
1107
1078
|
/**
|
|
1108
|
-
*
|
|
1109
|
-
*
|
|
1110
|
-
*
|
|
1111
|
-
* - `'OAuth callback aborted'` when the external `AbortSignal` fires.
|
|
1112
|
-
* - `'OAuth callback server closed'` when `close()` is called before any
|
|
1113
|
-
* callback arrives.
|
|
1114
|
-
*
|
|
1115
|
-
* Single-shot — only the first matching request resolves the promise.
|
|
1079
|
+
* Wire name (after `toolAliases` rewrite). What the model sees in the
|
|
1080
|
+
* catalog, what `tool_search` matches against, and what the provider's
|
|
1081
|
+
* tool list will carry once the entry is unlocked.
|
|
1116
1082
|
*/
|
|
1117
|
-
|
|
1083
|
+
name: string;
|
|
1118
1084
|
/**
|
|
1119
|
-
*
|
|
1120
|
-
*
|
|
1121
|
-
*
|
|
1085
|
+
* Canonical (registry-key) name used for unlock-set membership and for the
|
|
1086
|
+
* loop's `ctx.tools[name]` dispatch lookup. Equal to `name` when no alias
|
|
1087
|
+
* is configured for this tool.
|
|
1122
1088
|
*/
|
|
1123
|
-
|
|
1089
|
+
canonicalName: string;
|
|
1090
|
+
description: string;
|
|
1091
|
+
inputSchema: Record<string, unknown>;
|
|
1092
|
+
/** Source MCP server, when applicable. Used for `server`-bulk unlock. */
|
|
1093
|
+
server?: string;
|
|
1124
1094
|
}
|
|
1125
|
-
interface
|
|
1126
|
-
/** Cancels the flow — rejects `promise` and closes the server. */
|
|
1127
|
-
signal?: AbortSignal;
|
|
1095
|
+
interface ToolSearchToolOptions {
|
|
1128
1096
|
/**
|
|
1129
|
-
*
|
|
1130
|
-
*
|
|
1131
|
-
* different path.
|
|
1097
|
+
* Snapshot of every lazy tool the model can discover. Built once per run by
|
|
1098
|
+
* the agent — the tool closes over this array and never mutates it.
|
|
1132
1099
|
*/
|
|
1133
|
-
|
|
1100
|
+
catalog: readonly LazyToolEntry[];
|
|
1134
1101
|
/**
|
|
1135
|
-
*
|
|
1136
|
-
*
|
|
1137
|
-
*
|
|
1102
|
+
* Mutable per-run set of unlocked **canonical** tool names. The tool adds
|
|
1103
|
+
* matches in place; the loop reads the set when rebuilding the wire-level
|
|
1104
|
+
* tool list. Keyed by canonical (not wire) so dispatch lookups stay
|
|
1105
|
+
* alias-stable.
|
|
1106
|
+
*
|
|
1107
|
+
* Prefer `addUnlock` for cache-stable wire-tool ordering: writes through a
|
|
1108
|
+
* Set lose unlock order, so the wire-level rebuild that filters by `unlocked`
|
|
1109
|
+
* has to fall back to registry iteration order — which moves entries every
|
|
1110
|
+
* time a lazy tool earlier in the registry is unlocked, breaking provider
|
|
1111
|
+
* prompt-cache breakpoints. The agent passes both when it owns the unlock
|
|
1112
|
+
* tracker, with `addUnlock` mirroring writes into an ordered log.
|
|
1138
1113
|
*/
|
|
1139
|
-
|
|
1114
|
+
unlocked: Set<string>;
|
|
1140
1115
|
/**
|
|
1141
|
-
*
|
|
1142
|
-
*
|
|
1143
|
-
*
|
|
1116
|
+
* Optional callback fired for every canonical name the tool unlocks. When
|
|
1117
|
+
* set, the agent uses this to maintain an append-only `dynamicUnlockOrder`
|
|
1118
|
+
* so the wire-level tool list emits new unlocks at the tail and keeps the
|
|
1119
|
+
* provider prefix cache warm. Idempotent on repeat unlocks of the same
|
|
1120
|
+
* name — callers may dedupe internally.
|
|
1121
|
+
*
|
|
1122
|
+
* Invoked **in addition to** the `unlocked.add` (which still happens for
|
|
1123
|
+
* back-compat with callers that only watch the Set).
|
|
1144
1124
|
*/
|
|
1145
|
-
|
|
1125
|
+
addUnlock?: (canonical: string) => void;
|
|
1126
|
+
/** Default cap on returned matches when the model omits `limit`. */
|
|
1127
|
+
defaultLimit?: number;
|
|
1146
1128
|
}
|
|
1147
1129
|
/**
|
|
1148
|
-
*
|
|
1149
|
-
*
|
|
1150
|
-
*
|
|
1151
|
-
*
|
|
1152
|
-
* Always `await handle.close()` in a `finally` block — even on success, the
|
|
1153
|
-
* server stays open until told to shut down (so it can serve the
|
|
1154
|
-
* "you can close this tab" page).
|
|
1130
|
+
* Factory for `tool_search`. Auto-injected by the agent when
|
|
1131
|
+
* `behavior.toolDisclosure === 'lazy'` and at least one MCP tool is in the
|
|
1132
|
+
* registry. Opt out via `behavior.toolSearch.tool === false`.
|
|
1155
1133
|
*/
|
|
1156
|
-
declare function
|
|
1134
|
+
declare function createToolSearchTool(options: ToolSearchToolOptions): ToolDef;
|
|
1157
1135
|
//#endregion
|
|
1158
|
-
//#region src/
|
|
1159
|
-
type MetricAttributes = Record<string, string | number | boolean | undefined>;
|
|
1160
|
-
interface Counter {
|
|
1161
|
-
add: (value: number, attributes?: MetricAttributes) => void;
|
|
1162
|
-
}
|
|
1163
|
-
interface Histogram {
|
|
1164
|
-
record: (value: number, attributes?: MetricAttributes) => void;
|
|
1165
|
-
}
|
|
1166
|
-
interface UpDownCounter {
|
|
1167
|
-
add: (value: number, attributes?: MetricAttributes) => void;
|
|
1168
|
-
}
|
|
1169
|
-
interface InstrumentOptions {
|
|
1170
|
-
description?: string;
|
|
1171
|
-
unit?: string;
|
|
1172
|
-
}
|
|
1136
|
+
//#region src/tools/validation.d.ts
|
|
1173
1137
|
/**
|
|
1174
|
-
*
|
|
1175
|
-
*
|
|
1176
|
-
*
|
|
1138
|
+
* Tool argument validation against JSON Schema-style inputSchema.
|
|
1139
|
+
*
|
|
1140
|
+
* Two passes:
|
|
1141
|
+
* 1. Required-field presence. Missing or null/undefined required fields fail.
|
|
1142
|
+
* 2. Per-property type checks with **best-effort coercion**. Small/OSS models
|
|
1143
|
+
* routinely send `"true"` for a `boolean` field or `"42"` for a `number`,
|
|
1144
|
+
* and rejecting outright forces a confusing retry. Instead, we auto-heal
|
|
1145
|
+
* coerce when the conversion is unambiguous, fail only when the value
|
|
1146
|
+
* cannot be reasonably normalized to any of the declared types.
|
|
1147
|
+
*
|
|
1148
|
+
* Recursion: when a property declares `type: 'array'` with an `items` schema,
|
|
1149
|
+
* each item is validated against `items`. Object items are walked one level
|
|
1150
|
+
* deep (their declared `properties` get the same coercion + enum checks the
|
|
1151
|
+
* top level does). Items that can't be coerced are dropped rather than
|
|
1152
|
+
* rejecting the whole call — the model rarely benefits from an
|
|
1153
|
+
* all-or-nothing failure on a 20-item list because one entry was malformed.
|
|
1154
|
+
* Dropped items are reported back via `droppedItems` so the tool's `execute`
|
|
1155
|
+
* can surface a hint to the model if it wants to.
|
|
1177
1156
|
*/
|
|
1178
|
-
interface
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
}
|
|
1183
|
-
interface MetricsHooksOptions {
|
|
1184
|
-
meter: Meter;
|
|
1157
|
+
interface ValidationResult {
|
|
1158
|
+
valid: boolean;
|
|
1159
|
+
/** Human-readable reason. Present on failure only. */
|
|
1160
|
+
error?: string;
|
|
1185
1161
|
/**
|
|
1186
|
-
*
|
|
1187
|
-
* (
|
|
1188
|
-
*
|
|
1189
|
-
* namespace inside a shared meter registry.
|
|
1162
|
+
* Possibly-coerced input. Present iff `valid: true`. Tools should call
|
|
1163
|
+
* `execute(coercedInput, ctx)` so auto-healed values reach the tool body.
|
|
1164
|
+
* When no coercion was applied, this is reference-equal to the input.
|
|
1190
1165
|
*/
|
|
1191
|
-
|
|
1166
|
+
coercedInput?: Record<string, unknown>;
|
|
1192
1167
|
/**
|
|
1193
|
-
*
|
|
1194
|
-
*
|
|
1195
|
-
*
|
|
1168
|
+
* Names of fields whose values were coerced. Empty when nothing changed.
|
|
1169
|
+
* Useful for telemetry (`validation:reject` on failure already carries the
|
|
1170
|
+
* reason; this is the success-path equivalent).
|
|
1196
1171
|
*/
|
|
1197
|
-
|
|
1172
|
+
coercions?: readonly string[];
|
|
1198
1173
|
/**
|
|
1199
|
-
*
|
|
1200
|
-
*
|
|
1201
|
-
*
|
|
1174
|
+
* Indexes of array items dropped during recursive validation, keyed by
|
|
1175
|
+
* the property name. Empty / absent when nothing was dropped. Tools that
|
|
1176
|
+
* care about the discrepancy (e.g. `todowrite` wanting to surface
|
|
1177
|
+
* "ignored 2 malformed items") can inspect this.
|
|
1202
1178
|
*/
|
|
1203
|
-
|
|
1204
|
-
}
|
|
1205
|
-
interface MetricsHookSet {
|
|
1206
|
-
install: (hooks: Hookable<AgentHooks>) => () => void;
|
|
1179
|
+
droppedItems?: Readonly<Record<string, readonly number[]>>;
|
|
1207
1180
|
}
|
|
1181
|
+
declare function validateToolArgs(input: Record<string, unknown>, schema: Record<string, unknown>): ValidationResult;
|
|
1182
|
+
//#endregion
|
|
1183
|
+
//#region src/tools/write-file.d.ts
|
|
1208
1184
|
/**
|
|
1209
|
-
*
|
|
1185
|
+
* Write a file, with an idempotency signal when the content is unchanged.
|
|
1210
1186
|
*
|
|
1211
|
-
*
|
|
1212
|
-
*
|
|
1213
|
-
*
|
|
1214
|
-
*
|
|
1215
|
-
*
|
|
1216
|
-
*
|
|
1217
|
-
*
|
|
1218
|
-
*
|
|
1219
|
-
*
|
|
1187
|
+
* Three return shapes — chosen so the model can recognize a no-op without a
|
|
1188
|
+
* separate read:
|
|
1189
|
+
* - `Created path (N bytes)` — file did not exist
|
|
1190
|
+
* - `Updated path (N bytes)` — content differed from on-disk
|
|
1191
|
+
* - `No change needed: path already at target state (N bytes)` — equal
|
|
1192
|
+
*
|
|
1193
|
+
* Race window: in non-process execution contexts (docker, sandbox) shared by
|
|
1194
|
+
* multiple agents, another writer can mutate the file between our read and
|
|
1195
|
+
* our write. Local process context is single-writer per agent so the race is
|
|
1196
|
+
* a non-issue there. Documented rather than locked because the cost of
|
|
1197
|
+
* cross-context locking outweighs the cost of a stale "No change" message.
|
|
1220
1198
|
*/
|
|
1221
|
-
declare
|
|
1199
|
+
declare const writeFile: ToolDef;
|
|
1222
1200
|
//#endregion
|
|
1223
|
-
//#region src/
|
|
1224
|
-
|
|
1201
|
+
//#region src/headless.d.ts
|
|
1202
|
+
type HeadlessStatus = 'completed' | 'aborted' | 'error' | 'timeout';
|
|
1203
|
+
interface HeadlessUsage {
|
|
1225
1204
|
input: number;
|
|
1226
1205
|
output: number;
|
|
1227
1206
|
cacheRead: number;
|
|
1228
1207
|
cacheCreation: number;
|
|
1208
|
+
/** Cumulative USD cost when the provider/registry could price the run. */
|
|
1229
1209
|
cost?: number;
|
|
1230
|
-
/** First observable byte from the provider, ms from run start. */
|
|
1231
|
-
ttftMs?: number;
|
|
1232
1210
|
}
|
|
1233
|
-
interface
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1211
|
+
interface HeadlessErrorInfo {
|
|
1212
|
+
message: string;
|
|
1213
|
+
/** Typed-error class name (`AgentAbortedError`, `AgentContextExceededError`, …). */
|
|
1214
|
+
type: string;
|
|
1215
|
+
}
|
|
1216
|
+
/**
|
|
1217
|
+
* Strictly JSON-serializable postmortem of one headless run. Everything an RL
|
|
1218
|
+
* reward function needs: the final answer (`finalText`), the verifiable
|
|
1219
|
+
* structured output (`output`, present iff a `schema` was set), usage/turns,
|
|
1220
|
+
* and the lossless `transcript` (the SFT training data).
|
|
1221
|
+
*/
|
|
1222
|
+
interface HeadlessResult {
|
|
1223
|
+
status: HeadlessStatus;
|
|
1224
|
+
/** Concatenated text of the last assistant turn that produced any text. */
|
|
1225
|
+
finalText: string;
|
|
1226
|
+
/** Schema-enforced structured output (only when `opts.schema` is set). */
|
|
1227
|
+
output?: Record<string, unknown>;
|
|
1228
|
+
usage: HeadlessUsage;
|
|
1240
1229
|
turns: number;
|
|
1230
|
+
durationMs: number;
|
|
1231
|
+
/** Total `tool_call` blocks across the whole transcript. */
|
|
1232
|
+
numToolCalls: number;
|
|
1233
|
+
/** Finish reason of the final turn that reported one. */
|
|
1234
|
+
finishReason?: TurnFinishReason;
|
|
1235
|
+
error?: HeadlessErrorInfo;
|
|
1236
|
+
sessionId: string;
|
|
1237
|
+
/** Incident postmortem (errors, gate blocks, budget events) via run-summary. */
|
|
1238
|
+
summary?: RunSummary;
|
|
1239
|
+
/** Lossless transcript — raw `session.turns`. Thinking stripped when `includeThinking: false`. */
|
|
1240
|
+
transcript: SessionTurn[];
|
|
1241
|
+
}
|
|
1242
|
+
/**
|
|
1243
|
+
* Live event union — the in-process equivalent of a `stream-json` line. Every
|
|
1244
|
+
* member is JSON-serializable; render to JSONL with {@link headlessEventToJsonl}.
|
|
1245
|
+
*/
|
|
1246
|
+
type HeadlessEvent = {
|
|
1247
|
+
type: 'start';
|
|
1248
|
+
runId: string;
|
|
1249
|
+
provider?: string;
|
|
1250
|
+
} | {
|
|
1251
|
+
type: 'text';
|
|
1252
|
+
delta: string;
|
|
1253
|
+
} | {
|
|
1254
|
+
type: 'thinking';
|
|
1255
|
+
delta: string;
|
|
1256
|
+
} | {
|
|
1257
|
+
type: 'tool_call';
|
|
1258
|
+
callId: string;
|
|
1259
|
+
name: string;
|
|
1260
|
+
input: Record<string, unknown>;
|
|
1261
|
+
} | {
|
|
1262
|
+
type: 'tool_result';
|
|
1263
|
+
callId: string;
|
|
1264
|
+
name: string;
|
|
1265
|
+
output: string;
|
|
1266
|
+
isError: boolean;
|
|
1267
|
+
} | {
|
|
1268
|
+
type: 'turn';
|
|
1269
|
+
index: number;
|
|
1270
|
+
usage: TurnUsage;
|
|
1271
|
+
} | {
|
|
1272
|
+
type: 'spawn';
|
|
1273
|
+
event: 'before' | 'complete' | 'error';
|
|
1274
|
+
id: string;
|
|
1275
|
+
info?: Record<string, unknown>;
|
|
1276
|
+
} | {
|
|
1277
|
+
type: 'error';
|
|
1278
|
+
message: string;
|
|
1279
|
+
errorType?: string;
|
|
1280
|
+
} | {
|
|
1281
|
+
type: 'result';
|
|
1282
|
+
result: HeadlessResult;
|
|
1283
|
+
};
|
|
1284
|
+
/** Serialize one event as a newline-terminated JSON line (stream-json). */
|
|
1285
|
+
declare function headlessEventToJsonl(event: HeadlessEvent): string;
|
|
1286
|
+
interface HeadlessOptions {
|
|
1287
|
+
/** User prompt — plain string or multimodal `PromptPart[]`. */
|
|
1288
|
+
prompt: string | PromptPart[];
|
|
1289
|
+
/** Built provider (e.g. `local()`, `openaiCompat(...)`, `anthropic(...)`). */
|
|
1290
|
+
provider: Provider;
|
|
1291
|
+
model?: string;
|
|
1292
|
+
/** Override the preset system prompt for this run. */
|
|
1293
|
+
system?: string;
|
|
1294
|
+
thinking?: ThinkingLevel;
|
|
1295
|
+
maxTurns?: number;
|
|
1296
|
+
maxTokens?: number;
|
|
1297
|
+
/** Wall-clock cap; on expiry the run is aborted and `status` becomes `'timeout'`. */
|
|
1298
|
+
timeoutMs?: number;
|
|
1299
|
+
/** External abort signal — chained with the internal timeout controller. */
|
|
1300
|
+
signal?: AbortSignal;
|
|
1301
|
+
/** JSON Schema for structured-output enforcement → populates `result.output`. */
|
|
1302
|
+
schema?: Record<string, unknown>;
|
|
1303
|
+
/** Tool overrides. Omit to use the basic preset's tools. */
|
|
1304
|
+
tools?: Record<string, ToolDef>;
|
|
1305
|
+
mcpServers?: McpServerConfig[];
|
|
1306
|
+
skills?: AgentOptions['skills'];
|
|
1307
|
+
/** Execution context. Defaults to a process context rooted at `cwd`. */
|
|
1308
|
+
execution?: ExecutionContext;
|
|
1309
|
+
/** Working directory for the default process context (ignored if `execution` is set). */
|
|
1310
|
+
cwd?: string;
|
|
1311
|
+
/** Reuse / resume an existing session. */
|
|
1312
|
+
session?: Session;
|
|
1313
|
+
/** Session store for a fresh session (defaults to an in-memory store). */
|
|
1314
|
+
store?: SessionStore;
|
|
1315
|
+
/** Keep `thinking` blocks in `result.transcript` (default true). */
|
|
1316
|
+
includeThinking?: boolean;
|
|
1317
|
+
/** Live event callback — the in-process stream-json equivalent. */
|
|
1318
|
+
onEvent?: (event: HeadlessEvent) => void;
|
|
1241
1319
|
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1320
|
+
/**
|
|
1321
|
+
* Run a prompt to completion, headless, and return a single serializable
|
|
1322
|
+
* {@link HeadlessResult}. Safe to call concurrently for parallel rollouts —
|
|
1323
|
+
* each call builds its own agent + session and tears them down in `finally`.
|
|
1324
|
+
*/
|
|
1325
|
+
declare function runHeadless(opts: HeadlessOptions): Promise<HeadlessResult>;
|
|
1326
|
+
interface OpenAIChatMessage {
|
|
1327
|
+
role: 'system' | 'user' | 'assistant' | 'tool';
|
|
1328
|
+
content: string | null;
|
|
1329
|
+
tool_calls?: Array<{
|
|
1330
|
+
id: string;
|
|
1331
|
+
type: 'function';
|
|
1332
|
+
function: {
|
|
1333
|
+
name: string;
|
|
1334
|
+
arguments: string;
|
|
1335
|
+
};
|
|
1336
|
+
}>;
|
|
1337
|
+
tool_call_id?: string;
|
|
1253
1338
|
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1339
|
+
/**
|
|
1340
|
+
* Convert raw `session.turns` into standard OpenAI chat-completion messages:
|
|
1341
|
+
* assistant turns carry `tool_calls`, and each `tool_result` becomes its own
|
|
1342
|
+
* `role: 'tool'` message. This is the drop-in shape for an SFT renderer —
|
|
1343
|
+
* unlike `toOpenAI` (session/messages.ts), which emits an internal `_tag`
|
|
1344
|
+
* envelope meant for re-sending to a provider, not for training data.
|
|
1345
|
+
*/
|
|
1346
|
+
declare function transcriptToOpenAIMessages(turns: SessionTurn[]): OpenAIChatMessage[];
|
|
1347
|
+
//#endregion
|
|
1348
|
+
//#region src/logger.d.ts
|
|
1349
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
1350
|
+
interface LogRecord {
|
|
1351
|
+
level: LogLevel;
|
|
1352
|
+
/** Unix ms — set by `Logger` at emit time. */
|
|
1353
|
+
timestamp: number;
|
|
1354
|
+
/** Free-form message. Sinks render this as the human-facing line. */
|
|
1355
|
+
message: string;
|
|
1356
|
+
/** Structured fields. Correlation ids land here automatically. */
|
|
1357
|
+
attrs: Record<string, unknown>;
|
|
1259
1358
|
}
|
|
1260
|
-
interface
|
|
1261
|
-
|
|
1262
|
-
toolName: string;
|
|
1263
|
-
reason: string;
|
|
1359
|
+
interface LogSink {
|
|
1360
|
+
emit: (record: LogRecord) => void;
|
|
1264
1361
|
}
|
|
1265
|
-
interface
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1362
|
+
interface Logger {
|
|
1363
|
+
debug: (message: string, attrs?: Record<string, unknown>) => void;
|
|
1364
|
+
info: (message: string, attrs?: Record<string, unknown>) => void;
|
|
1365
|
+
warn: (message: string, attrs?: Record<string, unknown>) => void;
|
|
1366
|
+
error: (message: string, attrs?: Record<string, unknown>) => void;
|
|
1367
|
+
/**
|
|
1368
|
+
* Returns a child logger that prepends the given attributes onto every
|
|
1369
|
+
* subsequent emit. Equivalent to `pino.child` / `winston.child`. The
|
|
1370
|
+
* parent and child share the same sink — children are zero-cost.
|
|
1371
|
+
*/
|
|
1372
|
+
with: (extra: Record<string, unknown>) => Logger;
|
|
1373
|
+
/**
|
|
1374
|
+
* Inspectable baseline attributes — handy for tests and for hook
|
|
1375
|
+
* handlers that want to clone-with-extra without recursing.
|
|
1376
|
+
*/
|
|
1377
|
+
readonly baseAttributes: Readonly<Record<string, unknown>>;
|
|
1274
1378
|
}
|
|
1275
1379
|
/**
|
|
1276
|
-
*
|
|
1277
|
-
*
|
|
1278
|
-
* so a log aggregator can ingest it as-is.
|
|
1380
|
+
* Build a Logger from a sink. Stateless and cheap; create one per agent
|
|
1381
|
+
* (or per app) and use `.with()` to attach correlation ids per-call.
|
|
1279
1382
|
*/
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
parentRunId?: string;
|
|
1283
|
-
depth: number;
|
|
1284
|
-
agentName?: string;
|
|
1285
|
-
startedAt: number;
|
|
1286
|
-
endedAt: number;
|
|
1287
|
-
durationMs: number;
|
|
1288
|
-
status: 'completed' | 'aborted';
|
|
1289
|
-
turns: number;
|
|
1290
|
-
totals: RunSummaryTokens;
|
|
1291
|
-
byModel: RunSummaryByModel[];
|
|
1292
|
-
errors: RunSummaryError[];
|
|
1293
|
-
blocks: RunSummaryBlock[];
|
|
1294
|
-
validationRejects: RunSummaryValidation[];
|
|
1295
|
-
budgetEvents: RunSummaryBudget[];
|
|
1296
|
-
/** Counts of pairing repairs, keyed by repair mode. */
|
|
1297
|
-
pairingRepairs: Record<string, number>;
|
|
1383
|
+
declare function createLogger(sink: LogSink, baseAttributes?: Readonly<Record<string, unknown>>): Logger;
|
|
1384
|
+
interface ConsoleSinkOptions {
|
|
1298
1385
|
/**
|
|
1299
|
-
*
|
|
1300
|
-
*
|
|
1386
|
+
* Minimum level to emit. Defaults to `'info'` — `debug` is dropped so
|
|
1387
|
+
* the harness's lifecycle logging is not noisy by default. Set to
|
|
1388
|
+
* `'debug'` to see every event.
|
|
1301
1389
|
*/
|
|
1302
|
-
|
|
1390
|
+
minLevel?: LogLevel;
|
|
1391
|
+
/** Custom output stream. Defaults to `process.stderr` so logs don't pollute stdout. */
|
|
1392
|
+
stream?: {
|
|
1393
|
+
write: (chunk: string) => void;
|
|
1394
|
+
};
|
|
1303
1395
|
}
|
|
1304
|
-
|
|
1396
|
+
/**
|
|
1397
|
+
* Human-readable terminal sink. Renders each record as
|
|
1398
|
+
* `<ISO timestamp> <LEVEL> <message> <attrs as kv pairs>`.
|
|
1399
|
+
*
|
|
1400
|
+
* Honors `process.stderr` by default so log lines don't interleave with
|
|
1401
|
+
* the agent's stdout-bound output (chat responses, JSON results).
|
|
1402
|
+
*/
|
|
1403
|
+
declare function consoleSink(options?: ConsoleSinkOptions): LogSink;
|
|
1404
|
+
/**
|
|
1405
|
+
* One-JSON-object-per-line sink. Suitable for piping into log aggregators
|
|
1406
|
+
* (Datadog Agent, Fluent Bit, Loki, Vector) that expect JSONL.
|
|
1407
|
+
*/
|
|
1408
|
+
declare function jsonSink(options?: ConsoleSinkOptions): LogSink;
|
|
1409
|
+
interface LoggingHooksOptions {
|
|
1410
|
+
logger: Logger;
|
|
1305
1411
|
/**
|
|
1306
|
-
*
|
|
1307
|
-
*
|
|
1412
|
+
* Minimum interesting level for harness-emitted lines. Default `'info'`.
|
|
1413
|
+
* Set to `'debug'` to see every tool dispatch / stream event. Set to
|
|
1414
|
+
* `'warn'` to mute the chatty ones and only see failures + budgets.
|
|
1308
1415
|
*/
|
|
1309
|
-
|
|
1416
|
+
level?: LogLevel;
|
|
1417
|
+
/**
|
|
1418
|
+
* When true (default), lifecycle events (`agent:start`, `turn:before`,
|
|
1419
|
+
* `tool:before`, `mcp:bootstrap:start`) emit at `debug` level so they
|
|
1420
|
+
* stay quiet by default. Set false to mute them entirely regardless of
|
|
1421
|
+
* the configured minimum level — useful when piping into a tracer
|
|
1422
|
+
* that already captures lifecycle.
|
|
1423
|
+
*/
|
|
1424
|
+
includeLifecycle?: boolean;
|
|
1310
1425
|
}
|
|
1311
|
-
interface
|
|
1312
|
-
/** Install the collector's hook handlers. Returns an uninstall fn. */
|
|
1426
|
+
interface LoggingHookSet {
|
|
1313
1427
|
install: (hooks: Hookable<AgentHooks>) => () => void;
|
|
1314
|
-
/** Most-recent summary; `undefined` until the first `agent:done` fires. */
|
|
1315
|
-
latest: () => RunSummary | undefined;
|
|
1316
1428
|
}
|
|
1317
1429
|
/**
|
|
1318
|
-
*
|
|
1319
|
-
*
|
|
1320
|
-
*
|
|
1321
|
-
* returns the most-recent summary across **any** install — install
|
|
1322
|
-
* per-agent collectors if you need separate post-run snapshots.
|
|
1430
|
+
* Install a bundle of hook handlers that emit a structured line per
|
|
1431
|
+
* relevant lifecycle event, automatically attaching correlation ids
|
|
1432
|
+
* (`runId`, `turnId`, `callId`, `childId`, `depth`, `agentName`).
|
|
1323
1433
|
*
|
|
1324
1434
|
* @example
|
|
1325
1435
|
* ```ts
|
|
1326
|
-
* const
|
|
1327
|
-
*
|
|
1328
|
-
*
|
|
1329
|
-
* const uninstall = collector.install(agent.hooks)
|
|
1436
|
+
* const logger = createLogger(consoleSink({ minLevel: 'debug' }), { service: 'tui' })
|
|
1437
|
+
* const lh = createLoggingHooks({ logger })
|
|
1438
|
+
* const uninstall = lh.install(agent.hooks)
|
|
1330
1439
|
* try { await agent.run({ prompt }) }
|
|
1331
1440
|
* finally { uninstall() }
|
|
1332
1441
|
* ```
|
|
1333
1442
|
*/
|
|
1334
|
-
declare function
|
|
1443
|
+
declare function createLoggingHooks(options: LoggingHooksOptions): LoggingHookSet;
|
|
1335
1444
|
//#endregion
|
|
1336
|
-
//#region src/
|
|
1445
|
+
//#region src/loop.d.ts
|
|
1337
1446
|
/**
|
|
1338
|
-
*
|
|
1339
|
-
*
|
|
1340
|
-
*
|
|
1341
|
-
*
|
|
1342
|
-
*
|
|
1447
|
+
* Canonical tool_result text emitted when a tool call is interrupted by the
|
|
1448
|
+
* user mid-flight (Esc / Ctrl-C / external `AbortSignal`). Mirrors Claude
|
|
1449
|
+
* Code's `INTERRUPT_MESSAGE_FOR_TOOL_USE` so downstream consumers can pattern
|
|
1450
|
+
* match a single string across both harnesses. Always paired with
|
|
1451
|
+
* `isError: true` on the wire — the model treats it as a failed call rather
|
|
1452
|
+
* than a successful tool response.
|
|
1343
1453
|
*/
|
|
1344
|
-
|
|
1345
|
-
input: number;
|
|
1346
|
-
output: number;
|
|
1347
|
-
cost: number;
|
|
1348
|
-
cacheRead: number;
|
|
1349
|
-
cacheCreation: number;
|
|
1350
|
-
turns: number;
|
|
1351
|
-
}
|
|
1454
|
+
declare const INTERRUPT_MESSAGE_FOR_TOOL_USE = "[Request interrupted by user for tool use]";
|
|
1352
1455
|
/**
|
|
1353
|
-
*
|
|
1354
|
-
*
|
|
1355
|
-
*
|
|
1356
|
-
*
|
|
1357
|
-
*
|
|
1358
|
-
* `AgentStats` deliberately doesn't carry cumulative forms (one source of
|
|
1359
|
-
* truth, no risk of drift). Anything that needs a tree-wide sum walks
|
|
1360
|
-
* through this.
|
|
1456
|
+
* Canonical tool_result text emitted when a tool call is skipped because a
|
|
1457
|
+
* steering message arrived between dispatches inside
|
|
1458
|
+
* {@link executeToolBatch}. Distinguished from
|
|
1459
|
+
* {@link INTERRUPT_MESSAGE_FOR_TOOL_USE} so consumers can split "user
|
|
1460
|
+
* cancelled" from "framework superseded".
|
|
1361
1461
|
*/
|
|
1362
|
-
declare
|
|
1462
|
+
declare const TOOL_USE_SKIPPED_MESSAGE = "[Tool use skipped \u2014 superseded by user message]";
|
|
1363
1463
|
/**
|
|
1364
|
-
*
|
|
1365
|
-
*
|
|
1366
|
-
*
|
|
1367
|
-
*
|
|
1464
|
+
* Canonical tool_result text emitted when a single tool call is cancelled
|
|
1465
|
+
* mid-flight via `agent.cancelTool(callId)` (typically the TUI's
|
|
1466
|
+
* "cancel this tool" affordance). Distinguished from
|
|
1467
|
+
* {@link INTERRUPT_MESSAGE_FOR_TOOL_USE} (run-wide user abort) and
|
|
1468
|
+
* {@link TOOL_USE_SKIPPED_MESSAGE} (steered) so the model — and downstream
|
|
1469
|
+
* consumers — can tell the three apart by string match.
|
|
1368
1470
|
*
|
|
1369
|
-
*
|
|
1370
|
-
*
|
|
1471
|
+
* Always paired with `isError: true` on the wire so the model treats the
|
|
1472
|
+
* call as failed rather than as a successful response. The remaining tool
|
|
1473
|
+
* calls in the batch continue running, in contrast with a full-run abort.
|
|
1371
1474
|
*/
|
|
1372
|
-
declare
|
|
1475
|
+
declare const TOOL_USE_CANCELLED_MESSAGE = "[Tool call cancelled by user]";
|
|
1476
|
+
/**
|
|
1477
|
+
* Canonical `tool_result.content` text emitted to siblings that were
|
|
1478
|
+
* cancelled by a `shell` error in the same batch. Distinct from
|
|
1479
|
+
* {@link INTERRUPT_MESSAGE_FOR_TOOL_USE} (user-issued abort) and
|
|
1480
|
+
* {@link TOOL_USE_SKIPPED_MESSAGE} (steered) so consumers can split
|
|
1481
|
+
* the three causes by string-match.
|
|
1482
|
+
*/
|
|
1483
|
+
declare const SHELL_CASCADE_CANCEL_MESSAGE = "Cancelled: a sibling `shell` call in the same batch errored; re-run independently if still needed.";
|
|
1373
1484
|
//#endregion
|
|
1374
|
-
//#region src/
|
|
1485
|
+
//#region src/loop-persistence.d.ts
|
|
1375
1486
|
/**
|
|
1376
|
-
*
|
|
1377
|
-
*
|
|
1378
|
-
*
|
|
1379
|
-
*
|
|
1380
|
-
* of the system prompt, so the cached prefix covers the entire system text.
|
|
1381
|
-
* Any byte change anywhere — including a per-turn `<env>` rewrite — busts the
|
|
1382
|
-
* cache for the doctrine that sits below. A literal marker in the system
|
|
1383
|
-
* string lets providers split it into:
|
|
1384
|
-
*
|
|
1385
|
-
* ┌──────────────┐ cache_control: ephemeral
|
|
1386
|
-
* │ STATIC half │ — doctrine, skills catalog, tool catalog,
|
|
1387
|
-
* │ │ user instructions
|
|
1388
|
-
* ├──────────────┤ ← SYSTEM_PROMPT_BOUNDARY
|
|
1389
|
-
* │ DYNAMIC half │ — env, cwd, mtimes, anything per-turn
|
|
1390
|
-
* └──────────────┘ (no cache_control)
|
|
1391
|
-
*
|
|
1392
|
-
* The static prefix rides the prompt cache across turns/sessions; the dynamic
|
|
1393
|
-
* suffix re-bills per turn. Net effect: a cwd change between turns no longer
|
|
1394
|
-
* invalidates 4 KB of doctrine.
|
|
1395
|
-
*
|
|
1396
|
-
* Wire contract:
|
|
1487
|
+
* Bytes of head content included in the inline preview block. 2 KiB matches
|
|
1488
|
+
* Claude Code's `PREVIEW_SIZE_BYTES` — enough for the model to identify the
|
|
1489
|
+
* content class (error output / structured data / log shape) and decide
|
|
1490
|
+
* whether to call `read_file` on the persisted path for the full payload.
|
|
1397
1491
|
*
|
|
1398
|
-
* - `
|
|
1399
|
-
*
|
|
1400
|
-
*
|
|
1401
|
-
*
|
|
1402
|
-
* cache-disabled path on providers that DO support `cache_control`.
|
|
1403
|
-
* - The marker uses underscores rather than XML/punctuation so it's
|
|
1404
|
-
* unambiguous when scanning prompts manually and unlikely to collide with
|
|
1405
|
-
* model-written content.
|
|
1406
|
-
* - Providers handle the split internally (Anthropic emits a 2-block array;
|
|
1407
|
-
* OpenAI-compat splits the leading `system` message into multi-part text).
|
|
1408
|
-
* Callers always pass a single `string` — no API break.
|
|
1492
|
+
* Tail-priority preview (matching `shell`'s truncation strategy) was
|
|
1493
|
+
* considered but rejected: most "what is this?" decisions get made from
|
|
1494
|
+
* the head, and the path is in the stub for the rare case where the tail
|
|
1495
|
+
* matters.
|
|
1409
1496
|
*/
|
|
1497
|
+
declare const PERSISTENCE_PREVIEW_BYTES: number;
|
|
1410
1498
|
/**
|
|
1411
|
-
*
|
|
1412
|
-
*
|
|
1499
|
+
* Byte-stable prefix every {@link buildPersistedStub} output starts with.
|
|
1500
|
+
* Exported so wire-level passes (tail compaction, future stale-output
|
|
1501
|
+
* elision) can recognize a persisted stub and preserve its path attribute
|
|
1502
|
+
* rather than replacing the stub with their own — losing the pointer to
|
|
1503
|
+
* the on-disk blob.
|
|
1413
1504
|
*
|
|
1414
|
-
*
|
|
1415
|
-
*
|
|
1416
|
-
*
|
|
1417
|
-
* prompts.
|
|
1505
|
+
* Bound to the literal opening of the XML tag; changing the stub format
|
|
1506
|
+
* requires updating this constant in lockstep (and shipping a migration
|
|
1507
|
+
* for in-flight sessions).
|
|
1418
1508
|
*/
|
|
1419
|
-
declare const
|
|
1420
|
-
/** Result of {@link splitSystemPrompt} — both halves stripped of the marker. */
|
|
1421
|
-
interface SystemPromptParts {
|
|
1422
|
-
/** Bytes BEFORE the marker (or the entire string when no marker present). Cacheable. */
|
|
1423
|
-
static: string;
|
|
1424
|
-
/** Bytes AFTER the marker. Empty when no marker present. NOT cached. */
|
|
1425
|
-
dynamic: string;
|
|
1426
|
-
}
|
|
1509
|
+
declare const PERSISTED_STUB_PREFIX = "<persisted-output tool=\"";
|
|
1427
1510
|
/**
|
|
1428
|
-
*
|
|
1429
|
-
*
|
|
1430
|
-
* Splits on the FIRST occurrence — subsequent markers are folded into the
|
|
1431
|
-
* dynamic half. This way callers can append additional `<env>` style blocks
|
|
1432
|
-
* with extra markers without each one creating a new cache layer (Anthropic
|
|
1433
|
-
* caps breakpoints; we use the budget elsewhere). The marker itself is
|
|
1434
|
-
* stripped from both sides — providers attach `cache_control` directly to
|
|
1435
|
-
* the static half's text content.
|
|
1436
|
-
*
|
|
1437
|
-
* A single blank line (`\n\n`) immediately adjacent to the marker on each
|
|
1438
|
-
* side is trimmed — callers conventionally write
|
|
1439
|
-
* `<doctrine>\n\n<MARKER>\n\n<env>` and expect the rendered wire bytes to
|
|
1440
|
-
* read as one logical paragraph. Blank lines beyond that immediate pair
|
|
1441
|
-
* (e.g. `\n\n\n<env>`) are preserved verbatim so callers composing their
|
|
1442
|
-
* own spacing don't lose intentional gaps.
|
|
1511
|
+
* Resolve the per-session persistence directory under `<userDir>/tool-results/<sessionId>/`.
|
|
1443
1512
|
*
|
|
1444
|
-
*
|
|
1445
|
-
*
|
|
1513
|
+
* The chat layer calls this at session activation and forwards the result
|
|
1514
|
+
* via `behavior.persistDir`. Exposed as a public helper so SDK consumers
|
|
1515
|
+
* pick the same layout — single source of truth for "where do blobs live".
|
|
1446
1516
|
*/
|
|
1447
|
-
declare function
|
|
1517
|
+
declare function resolvePersistDir(opts: {
|
|
1518
|
+
userDir: string;
|
|
1519
|
+
sessionId: string;
|
|
1520
|
+
}): string;
|
|
1448
1521
|
/**
|
|
1449
|
-
*
|
|
1450
|
-
*
|
|
1451
|
-
* dynamic side is non-empty — single-block prompts stay marker-free, so
|
|
1452
|
-
* callers that never opt in pay zero overhead and providers fall back to the
|
|
1453
|
-
* existing whole-string caching path.
|
|
1522
|
+
* Resolve the per-session background-tasks directory under
|
|
1523
|
+
* `<userDir>/<sessionId>/tasks/`.
|
|
1454
1524
|
*
|
|
1455
|
-
*
|
|
1456
|
-
*
|
|
1457
|
-
*
|
|
1525
|
+
* The chat layer calls this at session activation and forwards the result
|
|
1526
|
+
* via `behavior.tasksDir`. Same shape as {@link resolvePersistDir}: hosts
|
|
1527
|
+
* get a single source of truth for "where do task log files live".
|
|
1528
|
+
* Created on first write; cleanup is the session-delete path's job.
|
|
1458
1529
|
*/
|
|
1459
|
-
declare function
|
|
1530
|
+
declare function resolveTasksDir(opts: {
|
|
1531
|
+
userDir: string;
|
|
1532
|
+
sessionId: string;
|
|
1533
|
+
}): string;
|
|
1460
1534
|
/**
|
|
1461
|
-
*
|
|
1462
|
-
*
|
|
1463
|
-
*
|
|
1464
|
-
* Used by the agent to fold in run-stable content (skills catalog, lazy tool
|
|
1465
|
-
* catalog) without bumping it into the dynamic half — both catalogs are
|
|
1466
|
-
* built once per run and remain byte-stable for the duration, so they
|
|
1467
|
-
* belong in the cached prefix.
|
|
1468
|
-
*
|
|
1469
|
-
* Returns a new string; the input is not mutated. When `extra` is empty,
|
|
1470
|
-
* returns the input verbatim.
|
|
1535
|
+
* Inputs to {@link maybePersistToolResult}. Kept as a struct so the loop's
|
|
1536
|
+
* call site stays readable and additional optional knobs (compression,
|
|
1537
|
+
* mime detection, …) land without re-threading every call site.
|
|
1471
1538
|
*/
|
|
1472
|
-
|
|
1539
|
+
interface PersistInput {
|
|
1540
|
+
/** Canonical tool name — checked against `excludeTools`. */
|
|
1541
|
+
toolName: string;
|
|
1542
|
+
/** `tool_use` id from the assistant turn. Used as the filename. */
|
|
1543
|
+
callId: string;
|
|
1544
|
+
/** Result returned by the tool (post-`tool:transform`). */
|
|
1545
|
+
output: string | ToolResultContent[];
|
|
1546
|
+
/** Byte threshold; outputs at or below stay inline. */
|
|
1547
|
+
threshold: number;
|
|
1548
|
+
/** Canonical tool names that bypass persistence. */
|
|
1549
|
+
excludeTools?: readonly string[];
|
|
1550
|
+
/** Persistence root directory. Created on first write. */
|
|
1551
|
+
persistDir: string;
|
|
1552
|
+
/**
|
|
1553
|
+
* Optional cap on the total bytes of persisted blobs under `persistDir`.
|
|
1554
|
+
* When set (and > 0), after a successful write the helper sweeps the
|
|
1555
|
+
* directory and removes the oldest `*.txt` blobs (by mtime) until the
|
|
1556
|
+
* sum of remaining sizes is at or below the cap.
|
|
1557
|
+
*
|
|
1558
|
+
* Bound to the **current session** because `persistDir` is per-session
|
|
1559
|
+
* (see {@link resolvePersistDir}); eviction never crosses session
|
|
1560
|
+
* boundaries. The new blob is always preserved — its mtime is the
|
|
1561
|
+
* latest, so the LRU sort guarantees older blobs go first.
|
|
1562
|
+
*
|
|
1563
|
+
* Skipped when the value isn't a positive finite number. Eviction
|
|
1564
|
+
* failures (permissions, races) are surfaced through `ZIDANE_DEBUG`
|
|
1565
|
+
* but never block the calling tool result; an over-cap dir is a
|
|
1566
|
+
* housekeeping concern, not a correctness one.
|
|
1567
|
+
*/
|
|
1568
|
+
maxBytes?: number;
|
|
1569
|
+
}
|
|
1570
|
+
type PersistOutcome = {
|
|
1571
|
+
kind: 'skip';
|
|
1572
|
+
reason: 'disabled' | 'excluded' | 'under-threshold' | 'unsupported-shape' | 'unsafe-call-id' | 'invalid-persist-dir';
|
|
1573
|
+
} | {
|
|
1574
|
+
kind: 'persisted';
|
|
1575
|
+
output: string;
|
|
1576
|
+
originalBytes: number;
|
|
1577
|
+
persistedPath: string;
|
|
1578
|
+
evicted?: {
|
|
1579
|
+
files: number;
|
|
1580
|
+
bytes: number;
|
|
1581
|
+
};
|
|
1582
|
+
} | {
|
|
1583
|
+
kind: 'error';
|
|
1584
|
+
reason: 'write-failed';
|
|
1585
|
+
error: Error;
|
|
1586
|
+
};
|
|
1473
1587
|
/**
|
|
1474
|
-
*
|
|
1475
|
-
*
|
|
1588
|
+
* Decide-and-persist for a single tool result. Pure decision + filesystem
|
|
1589
|
+
* side-effect; returns the new wire-level `output` string when substitution
|
|
1590
|
+
* happened, otherwise tells the caller to leave the result alone.
|
|
1476
1591
|
*
|
|
1477
|
-
*
|
|
1478
|
-
*
|
|
1479
|
-
* marker format. The host's `system:transform` hook rewrites the dynamic
|
|
1480
|
-
* half each turn; the static doctrine above stays byte-stable and rides the
|
|
1481
|
-
* cache.
|
|
1592
|
+
* Atomicity: writes go through `<path>.tmp` + `rename` so a concurrent
|
|
1593
|
+
* read (or a crash mid-write) never sees a half-written blob.
|
|
1482
1594
|
*
|
|
1483
|
-
*
|
|
1484
|
-
*
|
|
1595
|
+
* `ToolResultContent[]` results (images, structured blocks) currently bypass
|
|
1596
|
+
* persistence — the inline image bytes are the point of the call, and a
|
|
1597
|
+
* mixed text/image array isn't representable as a single `.txt` file. We
|
|
1598
|
+
* may revisit if a tool starts returning very large text-only arrays.
|
|
1485
1599
|
*/
|
|
1486
|
-
declare function
|
|
1600
|
+
declare function maybePersistToolResult(input: PersistInput): Promise<PersistOutcome>;
|
|
1601
|
+
interface BuildStubInput {
|
|
1602
|
+
toolName: string;
|
|
1603
|
+
originalBytes: number;
|
|
1604
|
+
persistedPath: string;
|
|
1605
|
+
output: string;
|
|
1606
|
+
}
|
|
1487
1607
|
/**
|
|
1488
|
-
*
|
|
1489
|
-
*
|
|
1490
|
-
* each turn rather than appended to.
|
|
1608
|
+
* Render the byte-stable `<persisted-output>` stub the model sees in place
|
|
1609
|
+
* of the original `tool_result`.
|
|
1491
1610
|
*
|
|
1492
|
-
*
|
|
1611
|
+
* Format choices:
|
|
1612
|
+
* - XML wrapper because models reliably parse it as structural.
|
|
1613
|
+
* - Byte count + path in attributes so the model can decide whether to
|
|
1614
|
+
* `read_file` the persisted blob without scanning the preview.
|
|
1615
|
+
* - Preview always shows the head — `shell`'s tail-priority truncation is
|
|
1616
|
+
* irrelevant here because the model has the full path if it needs the
|
|
1617
|
+
* tail.
|
|
1618
|
+
* - No timestamps, no random UUIDs inside the stub: every byte must be
|
|
1619
|
+
* reproducible from the inputs, otherwise re-emission on subsequent
|
|
1620
|
+
* turns would bust the prompt cache.
|
|
1621
|
+
*
|
|
1622
|
+
* Exported for tests (asserting the byte-stable contract) and for SDK
|
|
1623
|
+
* consumers wiring their own persistence middleware against the same
|
|
1624
|
+
* surface.
|
|
1493
1625
|
*/
|
|
1494
|
-
declare function
|
|
1626
|
+
declare function buildPersistedStub(input: BuildStubInput): string;
|
|
1495
1627
|
/**
|
|
1496
|
-
*
|
|
1497
|
-
*
|
|
1498
|
-
*
|
|
1499
|
-
* Cerebras, ...) or for the cache-disabled path on any provider.
|
|
1500
|
-
*
|
|
1501
|
-
* Cache-aware providers re-derive the split from the original (un-rendered)
|
|
1502
|
-
* system string via `splitSystemPrompt` — `renderSystemForWire` is the
|
|
1503
|
-
* marker-free counterpart used to build the actual wire bytes.
|
|
1628
|
+
* Remove every persisted blob belonging to a session. Called by the chat
|
|
1629
|
+
* layer from its session-delete path so closing a session frees the disk
|
|
1630
|
+
* footprint alongside the SQLite row.
|
|
1504
1631
|
*
|
|
1505
|
-
*
|
|
1632
|
+
* Idempotent — missing directory (session never persisted anything) is a
|
|
1633
|
+
* no-op, not an error. Wraps the `rm -rf` so a permissions blip on one
|
|
1634
|
+
* blob doesn't propagate to the caller; the chat layer can't usefully
|
|
1635
|
+
* recover from "couldn't unlink a result file" mid-delete.
|
|
1506
1636
|
*/
|
|
1507
|
-
declare function
|
|
1508
|
-
/** True when `system` contains the boundary marker. */
|
|
1509
|
-
declare function hasSystemPromptBoundary(system: string): boolean;
|
|
1637
|
+
declare function cleanupPersistedSession(persistRoot: string): Promise<void>;
|
|
1510
1638
|
//#endregion
|
|
1511
|
-
//#region src/
|
|
1639
|
+
//#region src/mcp/oauth-provider.d.ts
|
|
1512
1640
|
/**
|
|
1513
|
-
*
|
|
1514
|
-
*
|
|
1515
|
-
*
|
|
1516
|
-
* tool surface need no relearning. Fails clearly when `old_string` isn't unique
|
|
1517
|
-
* (unless `replace_all: true`) and when not found, with a nearest-match preview
|
|
1518
|
-
* so the model can recover without a separate `read_file` round-trip.
|
|
1641
|
+
* Per-server persisted state. Subfields are optional so a partial save
|
|
1642
|
+
* (e.g. `saveCodeVerifier` arriving before `saveTokens`) doesn't blow away
|
|
1643
|
+
* earlier subfields — the provider always patches, never replaces.
|
|
1519
1644
|
*/
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
/**
|
|
1537
|
-
|
|
1645
|
+
interface McpCredentialEntry {
|
|
1646
|
+
tokens?: OAuthTokens;
|
|
1647
|
+
clientInformation?: OAuthClientInformationMixed;
|
|
1648
|
+
discoveryState?: OAuthDiscoveryState;
|
|
1649
|
+
}
|
|
1650
|
+
interface McpCredentialStore {
|
|
1651
|
+
load: (name: string) => McpCredentialEntry | undefined;
|
|
1652
|
+
save: (name: string, entry: McpCredentialEntry) => void;
|
|
1653
|
+
delete: (name: string) => void;
|
|
1654
|
+
}
|
|
1655
|
+
/**
|
|
1656
|
+
* In-memory store — primarily for tests, but valid as a no-persistence option
|
|
1657
|
+
* (tokens evaporate on process exit, the user re-auths every cold start).
|
|
1658
|
+
*/
|
|
1659
|
+
declare function createMemoryMcpCredentialStore(seed?: Record<string, McpCredentialEntry>): McpCredentialStore;
|
|
1660
|
+
interface McpOAuthProviderOptions {
|
|
1661
|
+
/** Server name — used as the storage key. */
|
|
1662
|
+
name: string;
|
|
1663
|
+
/** Persistence backend. */
|
|
1664
|
+
store: McpCredentialStore;
|
|
1665
|
+
/**
|
|
1666
|
+
* Loopback callback URI. Pass `undefined` for bootstrap (non-interactive
|
|
1667
|
+
* mode — stored tokens + refresh only, never opens a browser).
|
|
1668
|
+
*/
|
|
1669
|
+
redirectUri?: string;
|
|
1670
|
+
/**
|
|
1671
|
+
* Invoked when the SDK wants the user agent to navigate to the authorization
|
|
1672
|
+
* URL. Typically the host opens the browser AND emits a hook so the TUI can
|
|
1673
|
+
* render the URL in a status row. No-op in non-interactive mode (the SDK
|
|
1674
|
+
* still calls this before throwing `UnauthorizedError` from connect).
|
|
1675
|
+
*/
|
|
1676
|
+
onAuthorizationUrl?: (url: URL) => void | Promise<void>;
|
|
1677
|
+
/**
|
|
1678
|
+
* `client_name` used in dynamic client registration. Defaults to `'zidane'`.
|
|
1679
|
+
* Some servers display this string to the user on the consent screen.
|
|
1680
|
+
*/
|
|
1681
|
+
clientName?: string;
|
|
1682
|
+
/**
|
|
1683
|
+
* Override the requested OAuth scope. Default: unset (the SDK negotiates
|
|
1684
|
+
* via the server's metadata).
|
|
1685
|
+
*/
|
|
1686
|
+
scope?: string;
|
|
1687
|
+
}
|
|
1688
|
+
declare class McpOAuthProvider implements OAuthClientProvider {
|
|
1689
|
+
private readonly name;
|
|
1690
|
+
private readonly store;
|
|
1691
|
+
private readonly _redirectUri?;
|
|
1692
|
+
private readonly onAuthorizationUrl?;
|
|
1693
|
+
private readonly clientName;
|
|
1694
|
+
private readonly _scope?;
|
|
1695
|
+
private codeVerifierValue;
|
|
1696
|
+
constructor(opts: McpOAuthProviderOptions);
|
|
1697
|
+
get redirectUrl(): string | URL | undefined;
|
|
1698
|
+
get clientMetadata(): OAuthClientMetadata;
|
|
1699
|
+
tokens(): OAuthTokens | undefined;
|
|
1700
|
+
saveTokens(tokens: OAuthTokens): void;
|
|
1701
|
+
clientInformation(): OAuthClientInformationMixed | undefined;
|
|
1702
|
+
saveClientInformation(info: OAuthClientInformationMixed): void;
|
|
1703
|
+
discoveryState(): OAuthDiscoveryState | undefined;
|
|
1704
|
+
saveDiscoveryState(state: OAuthDiscoveryState): void;
|
|
1705
|
+
saveCodeVerifier(verifier: string): void;
|
|
1706
|
+
codeVerifier(): string;
|
|
1707
|
+
redirectToAuthorization(url: URL): Promise<void>;
|
|
1708
|
+
/**
|
|
1709
|
+
* Wipe stored credentials when the server reports the cached state is no
|
|
1710
|
+
* longer valid. The SDK calls this with a scope hint:
|
|
1711
|
+
* - `'tokens'` → access/refresh revoked, keep client registration
|
|
1712
|
+
* - `'client'` → client registration invalidated, reset everything
|
|
1713
|
+
* - `'verifier'`→ PKCE state stale (e.g. mismatched state param)
|
|
1714
|
+
* - `'discovery'` → discovery metadata stale (servers re-keyed)
|
|
1715
|
+
* - `'all'` → full reset
|
|
1716
|
+
*/
|
|
1717
|
+
invalidateCredentials(scope: 'all' | 'client' | 'tokens' | 'verifier' | 'discovery'): Promise<void>;
|
|
1718
|
+
private patch;
|
|
1538
1719
|
}
|
|
1539
1720
|
/**
|
|
1540
|
-
*
|
|
1721
|
+
* True when an HTTP transport's auth headers already include an explicit
|
|
1722
|
+
* Authorization. Used by the bootstrap escape-hatch: a user who provided
|
|
1723
|
+
* their own bearer token shouldn't be auto-promoted to OAuth on a 401.
|
|
1541
1724
|
*
|
|
1542
|
-
*
|
|
1543
|
-
* `
|
|
1544
|
-
* (string or object) that gets sent back to the model as the tool result.
|
|
1725
|
+
* Case-insensitive — Node normalizes outgoing headers to lowercase but
|
|
1726
|
+
* users hand-write `Authorization` in configs.
|
|
1545
1727
|
*/
|
|
1546
|
-
declare function
|
|
1547
|
-
//#endregion
|
|
1548
|
-
//#region src/tools/list-files.d.ts
|
|
1549
|
-
declare const listFiles: ToolDef;
|
|
1550
|
-
//#endregion
|
|
1551
|
-
//#region src/tools/multi-edit.d.ts
|
|
1552
|
-
declare const multiEdit: ToolDef;
|
|
1553
|
-
//#endregion
|
|
1554
|
-
//#region src/tools/read-file.d.ts
|
|
1555
|
-
declare const readFile: ToolDef;
|
|
1728
|
+
declare function hasAuthorizationHeader(headers: Record<string, string> | undefined): boolean;
|
|
1556
1729
|
//#endregion
|
|
1557
|
-
//#region src/
|
|
1558
|
-
interface
|
|
1730
|
+
//#region src/mcp/login.d.ts
|
|
1731
|
+
interface LoginMcpServerOptions {
|
|
1732
|
+
/** Persistence — same store the bootstrap path reads from. */
|
|
1733
|
+
store: McpCredentialStore;
|
|
1559
1734
|
/**
|
|
1560
|
-
*
|
|
1561
|
-
*
|
|
1562
|
-
*
|
|
1563
|
-
*
|
|
1564
|
-
*
|
|
1565
|
-
* than silently running foreground.
|
|
1566
|
-
*
|
|
1567
|
-
* Default: `true`.
|
|
1735
|
+
* Invoked with the authorization URL once it's ready. Hosts typically
|
|
1736
|
+
* (a) emit `mcp:auth:url` for the TUI, and (b) call `tryOpenBrowser`.
|
|
1737
|
+
* The URL is identical to the one passed to the `mcp:auth:url` hook
|
|
1738
|
+
* fired automatically — this callback is a synchronous hook for callers
|
|
1739
|
+
* that don't want to wire the agent hook machinery.
|
|
1568
1740
|
*/
|
|
1569
|
-
|
|
1741
|
+
onAuthorizationUrl?: (url: URL) => void | Promise<void>;
|
|
1742
|
+
/** Cancels the flow (esc / close modal / SIGINT). */
|
|
1743
|
+
signal?: AbortSignal;
|
|
1744
|
+
/** Agent hooks. The flow emits `mcp:auth:url`/`success`/`error` when wired. */
|
|
1745
|
+
hooks?: Hookable<AgentHooks>;
|
|
1746
|
+
/** Override `client_name` shown on consent screens. Default: 'zidane'. */
|
|
1747
|
+
clientName?: string;
|
|
1748
|
+
/** Override the requested OAuth scope. */
|
|
1749
|
+
scope?: string;
|
|
1570
1750
|
/**
|
|
1571
|
-
*
|
|
1572
|
-
*
|
|
1573
|
-
* tool" block for each known sibling (`read_file`, `glob`, `grep`,
|
|
1574
|
-
* `list_files`, `edit`, `write_file`) — useful against the
|
|
1575
|
-
* `ls`/`cat`-to-re-verify loop some models fall into when both a
|
|
1576
|
-
* dedicated tool AND `shell` are visible. Unknown / unrecognized names
|
|
1577
|
-
* are ignored.
|
|
1578
|
-
*
|
|
1579
|
-
* Set by `createAgent` per-run from the tool registry; hosts that
|
|
1580
|
-
* construct a `shell` directly can pass it explicitly. Omit to suppress
|
|
1581
|
-
* the block entirely (no nudge for shell-only agents, no nudge for
|
|
1582
|
-
* hosts that prefer to author their own anti-loop prose).
|
|
1751
|
+
* Override the loopback callback path. Default: `/callback`. Useful only
|
|
1752
|
+
* for servers that pinned a different path during registration.
|
|
1583
1753
|
*/
|
|
1584
|
-
|
|
1754
|
+
callbackPath?: string;
|
|
1585
1755
|
/**
|
|
1586
|
-
*
|
|
1587
|
-
*
|
|
1588
|
-
* canonical names — fine for the default preset, wrong for hosts that
|
|
1589
|
-
* alias-rename (the model would be told to call a name it doesn't see
|
|
1590
|
-
* in the tool spec).
|
|
1756
|
+
* Maximum time to wait for the user to complete the browser flow, in ms.
|
|
1757
|
+
* The user can also cancel via `signal`. Default: 5 minutes.
|
|
1591
1758
|
*/
|
|
1592
|
-
|
|
1759
|
+
timeoutMs?: number;
|
|
1760
|
+
}
|
|
1761
|
+
interface LoginMcpServerResult {
|
|
1762
|
+
/** Stored OAuth tokens after a successful exchange. */
|
|
1763
|
+
tokens: NonNullable<ReturnType<McpOAuthProvider['tokens']>>;
|
|
1764
|
+
/**
|
|
1765
|
+
* Upstream tool descriptors discovered after re-connecting with the new
|
|
1766
|
+
* tokens. Already filtered by the server's `enabledTools` / `disabledTools`
|
|
1767
|
+
* is NOT applied here — that's a bootstrap concern. Hosts that want filtering
|
|
1768
|
+
* should pass the result through `connectMcpServers` rebuild on the next
|
|
1769
|
+
* session activation rather than reusing this list verbatim.
|
|
1770
|
+
*/
|
|
1771
|
+
tools: Array<{
|
|
1772
|
+
name: string;
|
|
1773
|
+
description?: string | null;
|
|
1774
|
+
inputSchema?: unknown;
|
|
1775
|
+
}>;
|
|
1593
1776
|
}
|
|
1594
1777
|
/**
|
|
1595
|
-
*
|
|
1596
|
-
*
|
|
1597
|
-
* factory is the entry point hosts use when they want to override the
|
|
1598
|
-
* default — e.g. to ship a preset that always disables background mode
|
|
1599
|
-
* regardless of `behavior.tasksDir`.
|
|
1778
|
+
* Run the full interactive OAuth flow for `config`. Only supports `sse` and
|
|
1779
|
+
* `streamable-http` transports — `stdio` MCP servers don't speak OAuth.
|
|
1600
1780
|
*
|
|
1601
|
-
*
|
|
1602
|
-
*
|
|
1603
|
-
*
|
|
1604
|
-
*
|
|
1605
|
-
*
|
|
1606
|
-
|
|
1607
|
-
declare function createShellTool(opts?: CreateShellToolOptions): ToolDef;
|
|
1608
|
-
/**
|
|
1609
|
-
* Default `shell` tool with background mode enabled.
|
|
1781
|
+
* Throws on:
|
|
1782
|
+
* - Wrong transport.
|
|
1783
|
+
* - Abort signal.
|
|
1784
|
+
* - Browser-side error (user denied, server rejected, etc.).
|
|
1785
|
+
* - Code exchange failure.
|
|
1786
|
+
* - Post-exchange connect failure.
|
|
1610
1787
|
*
|
|
1611
|
-
*
|
|
1612
|
-
*
|
|
1613
|
-
* true` is set, `createAgent` auto-rewrites this identity to a
|
|
1614
|
-
* `createShellTool({ allowBackground: false })` variant so the model
|
|
1615
|
-
* never sees a flag it can't use. Hosts who want to bypass that
|
|
1616
|
-
* auto-rewrite can register a `createShellTool({ allowBackground })`
|
|
1617
|
-
* directly — the rewrite only fires on identity-equal references to
|
|
1618
|
-
* this constant.
|
|
1788
|
+
* Always closes the loopback callback server before returning, success or
|
|
1789
|
+
* failure.
|
|
1619
1790
|
*/
|
|
1620
|
-
declare
|
|
1621
|
-
//#endregion
|
|
1622
|
-
//#region src/tools/shell-kill.d.ts
|
|
1623
|
-
declare const shellKill: ToolDef;
|
|
1624
|
-
//#endregion
|
|
1625
|
-
//#region src/tools/skills-read.d.ts
|
|
1626
|
-
interface SkillsReadToolOptions {
|
|
1627
|
-
catalog: readonly SkillConfig[];
|
|
1628
|
-
state: SkillActivationState;
|
|
1629
|
-
}
|
|
1630
|
-
declare function createSkillsReadTool(options: SkillsReadToolOptions): ToolDef;
|
|
1631
|
-
//#endregion
|
|
1632
|
-
//#region src/tools/skills-run-script.d.ts
|
|
1633
|
-
interface SkillsRunScriptToolOptions {
|
|
1634
|
-
catalog: readonly SkillConfig[];
|
|
1635
|
-
state: SkillActivationState;
|
|
1636
|
-
/** Script timeout in milliseconds. Default 60000. */
|
|
1637
|
-
scriptTimeoutMs?: number;
|
|
1638
|
-
}
|
|
1639
|
-
declare function createSkillsRunScriptTool(options: SkillsRunScriptToolOptions): ToolDef;
|
|
1791
|
+
declare function loginMcpServer(config: McpServerConfig, options: LoginMcpServerOptions): Promise<LoginMcpServerResult>;
|
|
1640
1792
|
//#endregion
|
|
1641
|
-
//#region src/
|
|
1642
|
-
interface SkillsUseToolOptions {
|
|
1643
|
-
/** Resolved skills catalog for this run. */
|
|
1644
|
-
catalog: readonly SkillConfig[];
|
|
1645
|
-
/** Per-agent activation state the tool mutates. */
|
|
1646
|
-
state: SkillActivationState;
|
|
1647
|
-
/** Agent hooks — used to fire `skills:activate` on first activation. */
|
|
1648
|
-
hooks: Hookable<AgentHooks>;
|
|
1649
|
-
}
|
|
1793
|
+
//#region src/mcp/oauth-callback.d.ts
|
|
1650
1794
|
/**
|
|
1651
|
-
*
|
|
1652
|
-
* agent runtime when a non-empty skills catalog is available (unless
|
|
1653
|
-
* `SkillsConfig.tool === false`).
|
|
1795
|
+
* Local loopback HTTP callback for OAuth 2.0 authorization code flows.
|
|
1654
1796
|
*
|
|
1655
|
-
*
|
|
1656
|
-
*
|
|
1797
|
+
* Stands up a one-shot server on `127.0.0.1:<random>` that captures the
|
|
1798
|
+
* `?code=...` redirect from a browser-driven OAuth flow and resolves a
|
|
1799
|
+
* promise with the code. Used as the `redirectUrl` half of the MCP SDK's
|
|
1800
|
+
* `OAuthClientProvider` (the persistence half lives separately).
|
|
1801
|
+
*
|
|
1802
|
+
* Design:
|
|
1803
|
+
* - Loopback-only (`127.0.0.1`) — the OAuth spec treats `http://127.0.0.1:<port>`
|
|
1804
|
+
* as a public-client redirect URI per RFC 8252 §7.3. Browsers do NOT block it,
|
|
1805
|
+
* and Anthropic / OpenAI / Linear / GitHub all accept it.
|
|
1806
|
+
* - Random port (`port = 0`) — the OS picks an unused one. We read the actual
|
|
1807
|
+
* port back from `server.address()` after `listen()`.
|
|
1808
|
+
* - Single-shot — the first GET to `path` with a `code` (or `error`) wins;
|
|
1809
|
+
* subsequent requests get 404. The server keeps listening (in case the user
|
|
1810
|
+
* hits "back" and re-authorizes), so callers must `close()` once they have
|
|
1811
|
+
* the code or have given up.
|
|
1812
|
+
* - Abort-aware — wiring an external `AbortSignal` rejects the promise and
|
|
1813
|
+
* closes the server immediately. Required for the TUI's "esc cancels login"
|
|
1814
|
+
* UX.
|
|
1815
|
+
* - No HTML framework — a single inline `<html>` string keeps this isolated
|
|
1816
|
+
* from any UI dependency.
|
|
1657
1817
|
*/
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
depth: number;
|
|
1818
|
+
/**
|
|
1819
|
+
* Result of a successful callback. `state` is forwarded verbatim from the
|
|
1820
|
+
* query string — callers verify it against their pre-flight value to defend
|
|
1821
|
+
* against CSRF (the MCP SDK does this internally when it controls `state`).
|
|
1822
|
+
*/
|
|
1823
|
+
interface OAuthCallbackResult {
|
|
1824
|
+
code: string;
|
|
1825
|
+
state?: string;
|
|
1667
1826
|
}
|
|
1668
|
-
interface
|
|
1669
|
-
/**
|
|
1670
|
-
|
|
1827
|
+
interface OAuthCallbackHandle {
|
|
1828
|
+
/**
|
|
1829
|
+
* Full URI to register with the authorization server, e.g.
|
|
1830
|
+
* `http://127.0.0.1:51823/callback`. Stable for the lifetime of the
|
|
1831
|
+
* handle.
|
|
1832
|
+
*/
|
|
1833
|
+
redirectUri: string;
|
|
1671
1834
|
/**
|
|
1672
|
-
*
|
|
1673
|
-
*
|
|
1674
|
-
*
|
|
1675
|
-
* `
|
|
1676
|
-
*
|
|
1677
|
-
*
|
|
1678
|
-
* children. `elapsed` over-counts when children ran in parallel.
|
|
1835
|
+
* Resolves with `{ code, state }` on a successful callback. Rejects with:
|
|
1836
|
+
* - The OAuth-spec `error` field (`access_denied`, `server_error`, ...)
|
|
1837
|
+
* when the authorization server redirects with `?error=...`.
|
|
1838
|
+
* - `'OAuth callback aborted'` when the external `AbortSignal` fires.
|
|
1839
|
+
* - `'OAuth callback server closed'` when `close()` is called before any
|
|
1840
|
+
* callback arrives.
|
|
1679
1841
|
*
|
|
1680
|
-
*
|
|
1842
|
+
* Single-shot — only the first matching request resolves the promise.
|
|
1681
1843
|
*/
|
|
1682
|
-
|
|
1844
|
+
promise: Promise<OAuthCallbackResult>;
|
|
1845
|
+
/**
|
|
1846
|
+
* Idempotent shutdown. Safe to call from a `finally` block whether the
|
|
1847
|
+
* flow succeeded, failed, or was aborted. Resolves once the server stops
|
|
1848
|
+
* accepting connections.
|
|
1849
|
+
*/
|
|
1850
|
+
close: () => Promise<void>;
|
|
1683
1851
|
}
|
|
1684
|
-
interface
|
|
1685
|
-
/**
|
|
1686
|
-
|
|
1852
|
+
interface OAuthCallbackOptions {
|
|
1853
|
+
/** Cancels the flow — rejects `promise` and closes the server. */
|
|
1854
|
+
signal?: AbortSignal;
|
|
1687
1855
|
/**
|
|
1688
|
-
*
|
|
1689
|
-
*
|
|
1690
|
-
*
|
|
1691
|
-
* against runaway loops.
|
|
1856
|
+
* Path component the authorization server should redirect to. Defaults
|
|
1857
|
+
* to `/callback`. Useful when matching a pre-registered URI that uses a
|
|
1858
|
+
* different path.
|
|
1692
1859
|
*/
|
|
1693
|
-
|
|
1694
|
-
/** Child model override. */
|
|
1695
|
-
model?: string;
|
|
1696
|
-
/** Child system prompt override. Per-spawn `input.system` takes precedence. */
|
|
1697
|
-
system?: string;
|
|
1698
|
-
/** Child thinking level. */
|
|
1699
|
-
thinking?: 'off' | 'minimal' | 'low' | 'medium' | 'high';
|
|
1700
|
-
/** Preset override for children. Shallow-merged over the parent's preset (parent fields still win for anything left unset). */
|
|
1701
|
-
preset?: Preset;
|
|
1860
|
+
path?: string;
|
|
1702
1861
|
/**
|
|
1703
|
-
*
|
|
1704
|
-
*
|
|
1705
|
-
*
|
|
1862
|
+
* Override the loopback host. Defaults to `127.0.0.1`. Don't bind to
|
|
1863
|
+
* `0.0.0.0` here — the OAuth code is a one-time secret and the server
|
|
1864
|
+
* would otherwise accept it from any host on the LAN.
|
|
1706
1865
|
*/
|
|
1707
|
-
|
|
1866
|
+
host?: string;
|
|
1708
1867
|
/**
|
|
1709
|
-
*
|
|
1710
|
-
*
|
|
1711
|
-
*
|
|
1712
|
-
* reconstructible. Default: `false` (child is in-memory only).
|
|
1713
|
-
*
|
|
1714
|
-
* **Read-state isolation.** Sharing the session also shares the
|
|
1715
|
-
* `read_file` / `requireReadBeforeEdit` tracking map (it's keyed
|
|
1716
|
-
* by `Session`). With `persist: false` the child gets no session,
|
|
1717
|
-
* so reads inside the subagent populate nothing the parent can see —
|
|
1718
|
-
* a follow-up `edit` / `multi_edit` in the parent will trip the
|
|
1719
|
-
* gate with `"has not been read"` even though the model just
|
|
1720
|
-
* read the file in the child. Use {@link shareReadState} when
|
|
1721
|
-
* you want the parent's gate to honor the child's reads WITHOUT
|
|
1722
|
-
* also persisting child turns to the parent's session.
|
|
1868
|
+
* Override the port. Defaults to `0` (OS-assigned). Pin to a fixed port
|
|
1869
|
+
* only when the authorization server requires a pre-registered redirect
|
|
1870
|
+
* URI; the random-port path is preferred so concurrent flows don't clash.
|
|
1723
1871
|
*/
|
|
1724
|
-
|
|
1872
|
+
port?: number;
|
|
1873
|
+
}
|
|
1874
|
+
/**
|
|
1875
|
+
* Start a one-shot OAuth callback server. The returned handle's `redirectUri`
|
|
1876
|
+
* should be passed to the authorization server as the `redirect_uri` query
|
|
1877
|
+
* parameter; `promise` resolves once the user finishes the browser flow.
|
|
1878
|
+
*
|
|
1879
|
+
* Always `await handle.close()` in a `finally` block — even on success, the
|
|
1880
|
+
* server stays open until told to shut down (so it can serve the
|
|
1881
|
+
* "you can close this tab" page).
|
|
1882
|
+
*/
|
|
1883
|
+
declare function startOAuthCallback(opts?: OAuthCallbackOptions): Promise<OAuthCallbackHandle>;
|
|
1884
|
+
//#endregion
|
|
1885
|
+
//#region src/metrics.d.ts
|
|
1886
|
+
type MetricAttributes = Record<string, string | number | boolean | undefined>;
|
|
1887
|
+
interface Counter {
|
|
1888
|
+
add: (value: number, attributes?: MetricAttributes) => void;
|
|
1889
|
+
}
|
|
1890
|
+
interface Histogram {
|
|
1891
|
+
record: (value: number, attributes?: MetricAttributes) => void;
|
|
1892
|
+
}
|
|
1893
|
+
interface UpDownCounter {
|
|
1894
|
+
add: (value: number, attributes?: MetricAttributes) => void;
|
|
1895
|
+
}
|
|
1896
|
+
interface InstrumentOptions {
|
|
1897
|
+
description?: string;
|
|
1898
|
+
unit?: string;
|
|
1899
|
+
}
|
|
1900
|
+
/**
|
|
1901
|
+
* Minimal Meter interface — structurally identical to OTel's `Meter`.
|
|
1902
|
+
* Hosts passing `metrics.getMeter(name)` (from `@opentelemetry/api`)
|
|
1903
|
+
* satisfy this without adaptation.
|
|
1904
|
+
*/
|
|
1905
|
+
interface Meter {
|
|
1906
|
+
createCounter: (name: string, options?: InstrumentOptions) => Counter;
|
|
1907
|
+
createHistogram: (name: string, options?: InstrumentOptions) => Histogram;
|
|
1908
|
+
createUpDownCounter: (name: string, options?: InstrumentOptions) => UpDownCounter;
|
|
1909
|
+
}
|
|
1910
|
+
interface MetricsHooksOptions {
|
|
1911
|
+
meter: Meter;
|
|
1725
1912
|
/**
|
|
1726
|
-
*
|
|
1727
|
-
*
|
|
1728
|
-
*
|
|
1729
|
-
*
|
|
1730
|
-
* session's turn history. Default: `false`.
|
|
1731
|
-
*
|
|
1732
|
-
* Has no effect when the parent has no read-state to share (no
|
|
1733
|
-
* session and no explicit `readState` on the parent agent's
|
|
1734
|
-
* options). Implementation: passes the parent's resolved
|
|
1735
|
-
* `ReadStateMap` to the child via `AgentOptions.readState`, which
|
|
1736
|
-
* tools resolve via `ctx.readState ?? getReadState(ctx.session)`.
|
|
1913
|
+
* Optional prefix prepended to every instrument name. Default: no prefix
|
|
1914
|
+
* (instrument names follow OTel Gen AI semantic conventions verbatim,
|
|
1915
|
+
* which is the most-portable shape). Set to e.g. `'zidane.'` to
|
|
1916
|
+
* namespace inside a shared meter registry.
|
|
1737
1917
|
*/
|
|
1738
|
-
|
|
1918
|
+
namespace?: string;
|
|
1739
1919
|
/**
|
|
1740
|
-
*
|
|
1741
|
-
*
|
|
1742
|
-
*
|
|
1920
|
+
* Optional baseline attributes applied to every measurement. Typical
|
|
1921
|
+
* use: `{ service: 'tui', env: 'prod' }`. Per-event attributes win on
|
|
1922
|
+
* key collision.
|
|
1743
1923
|
*/
|
|
1744
|
-
|
|
1745
|
-
/** Called when a child agent starts. */
|
|
1746
|
-
onSpawn?: (child: ChildAgent) => void;
|
|
1747
|
-
/** Called when a child agent completes (success, abort, timeout, or error). */
|
|
1748
|
-
onComplete?: (child: ChildAgent, stats: AgentStats, status: NonNullable<ChildRunStats['status']>) => void;
|
|
1924
|
+
baseAttributes?: MetricAttributes;
|
|
1749
1925
|
/**
|
|
1750
|
-
*
|
|
1751
|
-
*
|
|
1752
|
-
*
|
|
1753
|
-
* 'Verification' | 'general-purpose'`, and without a registry the
|
|
1754
|
-
* field is silently dropped, so hosts wanting type-specialized
|
|
1755
|
-
* subagents have to invent their own dispatch layer.
|
|
1756
|
-
*
|
|
1757
|
-
* Each entry overlays the base spawn config for that particular
|
|
1758
|
-
* dispatch. Per-call `input.system` still wins over `subagents[type].system`
|
|
1759
|
-
* so the model can always specialize further.
|
|
1760
|
-
*
|
|
1761
|
-
* When the registry is non-empty:
|
|
1762
|
-
* - `subagent_type` appears in the spawn input schema as a `string`
|
|
1763
|
-
* enum of the registered keys (plus the always-available
|
|
1764
|
-
* `'general-purpose'` fallback).
|
|
1765
|
-
* - Models that pass an unregistered type are routed to
|
|
1766
|
-
* `'general-purpose'` (no error — degrade gracefully so trained
|
|
1767
|
-
* models keep working even on hosts that haven't wired every
|
|
1768
|
-
* type Claude Code uses).
|
|
1769
|
-
*
|
|
1770
|
-
* When the registry is empty / unset, the field is omitted entirely
|
|
1771
|
-
* (preserves the historical schema for hosts that never use this).
|
|
1772
|
-
*
|
|
1773
|
-
* Default: `undefined` (no subagent types; `subagent_type` schema
|
|
1774
|
-
* field hidden).
|
|
1926
|
+
* Error sink for meter failures. The helper still swallows the throw
|
|
1927
|
+
* so a broken backend can't crash a run; this callback surfaces the
|
|
1928
|
+
* failure for ops dashboards.
|
|
1775
1929
|
*/
|
|
1776
|
-
|
|
1930
|
+
onError?: (kind: string, err: unknown) => void;
|
|
1931
|
+
}
|
|
1932
|
+
interface MetricsHookSet {
|
|
1933
|
+
install: (hooks: Hookable<AgentHooks>) => () => void;
|
|
1934
|
+
}
|
|
1935
|
+
/**
|
|
1936
|
+
* Build a set of metrics hook handlers that can be installed on an agent.
|
|
1937
|
+
*
|
|
1938
|
+
* @example OpenTelemetry
|
|
1939
|
+
* ```ts
|
|
1940
|
+
* import { metrics } from '@opentelemetry/api'
|
|
1941
|
+
* const meter = metrics.getMeter('zidane')
|
|
1942
|
+
* const m = createMetricsHooks({ meter, baseAttributes: { service: 'tui' } })
|
|
1943
|
+
* const uninstall = m.install(agent.hooks)
|
|
1944
|
+
* try { await agent.run({ prompt }) }
|
|
1945
|
+
* finally { uninstall() }
|
|
1946
|
+
* ```
|
|
1947
|
+
*/
|
|
1948
|
+
declare function createMetricsHooks(options: MetricsHooksOptions): MetricsHookSet;
|
|
1949
|
+
//#endregion
|
|
1950
|
+
//#region src/stats.d.ts
|
|
1951
|
+
/**
|
|
1952
|
+
* Per-model usage rollup produced by {@link statsByModel}.
|
|
1953
|
+
*
|
|
1954
|
+
* `turns` counts the number of `TurnUsage` entries attributed to the model
|
|
1955
|
+
* across the whole tree (parent loop + every recursively-spawned child).
|
|
1956
|
+
* Cache and cost numbers are summed from the same set of turns.
|
|
1957
|
+
*/
|
|
1958
|
+
interface ModelUsage {
|
|
1959
|
+
input: number;
|
|
1960
|
+
output: number;
|
|
1961
|
+
cost: number;
|
|
1962
|
+
cacheRead: number;
|
|
1963
|
+
cacheCreation: number;
|
|
1964
|
+
turns: number;
|
|
1777
1965
|
}
|
|
1778
1966
|
/**
|
|
1779
|
-
*
|
|
1780
|
-
*
|
|
1781
|
-
*
|
|
1782
|
-
*
|
|
1967
|
+
* Depth-first walk over the stats tree, returning every `TurnUsage` entry
|
|
1968
|
+
* — parent loop first, then each child subtree in completion order.
|
|
1969
|
+
*
|
|
1970
|
+
* Closes the cache-token aggregation gap: `TurnUsage.cacheRead` /
|
|
1971
|
+
* `cacheCreation` live only on per-turn entries, and the top-level
|
|
1972
|
+
* `AgentStats` deliberately doesn't carry cumulative forms (one source of
|
|
1973
|
+
* truth, no risk of drift). Anything that needs a tree-wide sum walks
|
|
1974
|
+
* through this.
|
|
1975
|
+
*/
|
|
1976
|
+
declare function flattenTurns(stats: AgentStats): TurnUsage[];
|
|
1977
|
+
/**
|
|
1978
|
+
* Group cumulative usage by `TurnUsage.modelId`. Each entry sums the input,
|
|
1979
|
+
* output, cache, cost, and turn-count across every turn the tree attributed
|
|
1980
|
+
* to that model — naturally handling cross-model runs (vision-fallback,
|
|
1981
|
+
* model-shifted subagents, mixed-provider workflows).
|
|
1982
|
+
*
|
|
1983
|
+
* Turns missing `modelId` (mock providers, providers that don't echo a model
|
|
1984
|
+
* id) are bucketed under the literal string `'(unknown)'`.
|
|
1985
|
+
*/
|
|
1986
|
+
declare function statsByModel(stats: AgentStats): Map<string, ModelUsage>;
|
|
1987
|
+
//#endregion
|
|
1988
|
+
//#region src/system-prompt.d.ts
|
|
1989
|
+
/**
|
|
1990
|
+
* System-prompt boundary marker — splits a system prompt into a stable static
|
|
1991
|
+
* prefix (cached) and a per-turn dynamic suffix (NOT cached).
|
|
1992
|
+
*
|
|
1993
|
+
* Why this exists: providers attach `cache_control` markers on the last block
|
|
1994
|
+
* of the system prompt, so the cached prefix covers the entire system text.
|
|
1995
|
+
* Any byte change anywhere — including a per-turn `<env>` rewrite — busts the
|
|
1996
|
+
* cache for the doctrine that sits below. A literal marker in the system
|
|
1997
|
+
* string lets providers split it into:
|
|
1998
|
+
*
|
|
1999
|
+
* ┌──────────────┐ cache_control: ephemeral
|
|
2000
|
+
* │ STATIC half │ — doctrine, skills catalog, tool catalog,
|
|
2001
|
+
* │ │ user instructions
|
|
2002
|
+
* ├──────────────┤ ← SYSTEM_PROMPT_BOUNDARY
|
|
2003
|
+
* │ DYNAMIC half │ — env, cwd, mtimes, anything per-turn
|
|
2004
|
+
* └──────────────┘ (no cache_control)
|
|
2005
|
+
*
|
|
2006
|
+
* The static prefix rides the prompt cache across turns/sessions; the dynamic
|
|
2007
|
+
* suffix re-bills per turn. Net effect: a cwd change between turns no longer
|
|
2008
|
+
* invalidates 4 KB of doctrine.
|
|
2009
|
+
*
|
|
2010
|
+
* Wire contract:
|
|
2011
|
+
*
|
|
2012
|
+
* - `splitSystemPrompt(s)` is pure; missing marker ⇒ entire string is static
|
|
2013
|
+
* (current behavior — no caller is forced to opt in).
|
|
2014
|
+
* - `renderSystemForWire(s)` strips the marker so it never reaches the model;
|
|
2015
|
+
* used by every provider before the bytes hit the wire, including the
|
|
2016
|
+
* cache-disabled path on providers that DO support `cache_control`.
|
|
2017
|
+
* - The marker uses underscores rather than XML/punctuation so it's
|
|
2018
|
+
* unambiguous when scanning prompts manually and unlikely to collide with
|
|
2019
|
+
* model-written content.
|
|
2020
|
+
* - Providers handle the split internally (Anthropic emits a 2-block array;
|
|
2021
|
+
* OpenAI-compat splits the leading `system` message into multi-part text).
|
|
2022
|
+
* Callers always pass a single `string` — no API break.
|
|
2023
|
+
*/
|
|
2024
|
+
/**
|
|
2025
|
+
* Literal marker inserted in a system prompt to separate cacheable doctrine
|
|
2026
|
+
* from per-turn dynamic content. Providers split on this token.
|
|
2027
|
+
*
|
|
2028
|
+
* Underscored on both sides for visual distinctiveness — a stray instance in
|
|
2029
|
+
* model-written prose is implausible. Don't change the value without shipping
|
|
2030
|
+
* a migration; existing sessions carry the old marker in their cached
|
|
2031
|
+
* prompts.
|
|
1783
2032
|
*/
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
/**
|
|
1792
|
-
* Restrict the child agent's tool registry to this list of canonical
|
|
1793
|
-
* tool names. Operates as a filter over the parent's tools (the
|
|
1794
|
-
* parent's selection is the upper bound — a subagent can never gain
|
|
1795
|
-
* tools the parent doesn't have). When unset, the child inherits the
|
|
1796
|
-
* parent's full tool list.
|
|
1797
|
-
*
|
|
1798
|
-
* Tool names are canonical (registry-key) not wire/alias names — the
|
|
1799
|
-
* filter runs before aliases are applied. Names that don't match a
|
|
1800
|
-
* parent tool are silently dropped (matches the lenient behaviour of
|
|
1801
|
-
* `enabledTools` on MCP configs).
|
|
1802
|
-
*/
|
|
1803
|
-
tools?: readonly string[];
|
|
1804
|
-
/**
|
|
1805
|
-
* Mark this subagent as read-only — equivalent to listing only
|
|
1806
|
-
* obviously-non-mutating tools (`read_file`, `grep`, `glob`,
|
|
1807
|
-
* `list_files`) in {@link SubagentDef.tools}. Convenience for the
|
|
1808
|
-
* common "Plan" / "Explore" subagent shape Claude Code ships.
|
|
1809
|
-
*
|
|
1810
|
-
* When both `readonly: true` and `tools` are set, `tools` wins
|
|
1811
|
-
* (explicit beats implicit).
|
|
1812
|
-
*/
|
|
1813
|
-
readonly?: boolean;
|
|
1814
|
-
/**
|
|
1815
|
-
* Short description rendered into the spawn tool's schema (the
|
|
1816
|
-
* `subagent_type` field's description) so the model can pick a type
|
|
1817
|
-
* that matches the task without round-tripping through docs.
|
|
1818
|
-
*/
|
|
1819
|
-
description?: string;
|
|
2033
|
+
declare const SYSTEM_PROMPT_BOUNDARY = "__ZIDANE_SYSTEM_PROMPT_BOUNDARY__";
|
|
2034
|
+
/** Result of {@link splitSystemPrompt} — both halves stripped of the marker. */
|
|
2035
|
+
interface SystemPromptParts {
|
|
2036
|
+
/** Bytes BEFORE the marker (or the entire string when no marker present). Cacheable. */
|
|
2037
|
+
static: string;
|
|
2038
|
+
/** Bytes AFTER the marker. Empty when no marker present. NOT cached. */
|
|
2039
|
+
dynamic: string;
|
|
1820
2040
|
}
|
|
1821
2041
|
/**
|
|
1822
|
-
*
|
|
1823
|
-
*
|
|
1824
|
-
*
|
|
1825
|
-
*
|
|
1826
|
-
*
|
|
2042
|
+
* Split a system prompt around the first {@link SYSTEM_PROMPT_BOUNDARY}.
|
|
2043
|
+
*
|
|
2044
|
+
* Splits on the FIRST occurrence — subsequent markers are folded into the
|
|
2045
|
+
* dynamic half. This way callers can append additional `<env>` style blocks
|
|
2046
|
+
* with extra markers without each one creating a new cache layer (Anthropic
|
|
2047
|
+
* caps breakpoints; we use the budget elsewhere). The marker itself is
|
|
2048
|
+
* stripped from both sides — providers attach `cache_control` directly to
|
|
2049
|
+
* the static half's text content.
|
|
2050
|
+
*
|
|
2051
|
+
* A single blank line (`\n\n`) immediately adjacent to the marker on each
|
|
2052
|
+
* side is trimmed — callers conventionally write
|
|
2053
|
+
* `<doctrine>\n\n<MARKER>\n\n<env>` and expect the rendered wire bytes to
|
|
2054
|
+
* read as one logical paragraph. Blank lines beyond that immediate pair
|
|
2055
|
+
* (e.g. `\n\n\n<env>`) are preserved verbatim so callers composing their
|
|
2056
|
+
* own spacing don't lose intentional gaps.
|
|
2057
|
+
*
|
|
2058
|
+
* Pure / no I/O / no allocation when the marker is absent (returns the input
|
|
2059
|
+
* verbatim on the static side and the empty string on the dynamic side).
|
|
1827
2060
|
*/
|
|
1828
|
-
|
|
2061
|
+
declare function splitSystemPrompt(system: string): SystemPromptParts;
|
|
1829
2062
|
/**
|
|
1830
|
-
*
|
|
2063
|
+
* Compose a system prompt from a static prefix and an optional dynamic
|
|
2064
|
+
* suffix. Inserts {@link SYSTEM_PROMPT_BOUNDARY} between them only when the
|
|
2065
|
+
* dynamic side is non-empty — single-block prompts stay marker-free, so
|
|
2066
|
+
* callers that never opt in pay zero overhead and providers fall back to the
|
|
2067
|
+
* existing whole-string caching path.
|
|
1831
2068
|
*
|
|
1832
|
-
*
|
|
1833
|
-
*
|
|
1834
|
-
*
|
|
1835
|
-
* agent (or use the stateless default `spawn`) to keep them isolated.
|
|
2069
|
+
* Spacing is `\n\n` on both sides of the marker so doctrine fragments,
|
|
2070
|
+
* which conventionally separate sections with a blank line, read cleanly
|
|
2071
|
+
* around the boundary.
|
|
1836
2072
|
*/
|
|
1837
|
-
declare function
|
|
1838
|
-
//#endregion
|
|
1839
|
-
//#region src/tools/tool-search.d.ts
|
|
1840
|
-
interface LazyToolEntry {
|
|
1841
|
-
/**
|
|
1842
|
-
* Wire name (after `toolAliases` rewrite). What the model sees in the
|
|
1843
|
-
* catalog, what `tool_search` matches against, and what the provider's
|
|
1844
|
-
* tool list will carry once the entry is unlocked.
|
|
1845
|
-
*/
|
|
1846
|
-
name: string;
|
|
1847
|
-
/**
|
|
1848
|
-
* Canonical (registry-key) name used for unlock-set membership and for the
|
|
1849
|
-
* loop's `ctx.tools[name]` dispatch lookup. Equal to `name` when no alias
|
|
1850
|
-
* is configured for this tool.
|
|
1851
|
-
*/
|
|
1852
|
-
canonicalName: string;
|
|
1853
|
-
description: string;
|
|
1854
|
-
inputSchema: Record<string, unknown>;
|
|
1855
|
-
/** Source MCP server, when applicable. Used for `server`-bulk unlock. */
|
|
1856
|
-
server?: string;
|
|
1857
|
-
}
|
|
1858
|
-
interface ToolSearchToolOptions {
|
|
1859
|
-
/**
|
|
1860
|
-
* Snapshot of every lazy tool the model can discover. Built once per run by
|
|
1861
|
-
* the agent — the tool closes over this array and never mutates it.
|
|
1862
|
-
*/
|
|
1863
|
-
catalog: readonly LazyToolEntry[];
|
|
1864
|
-
/**
|
|
1865
|
-
* Mutable per-run set of unlocked **canonical** tool names. The tool adds
|
|
1866
|
-
* matches in place; the loop reads the set when rebuilding the wire-level
|
|
1867
|
-
* tool list. Keyed by canonical (not wire) so dispatch lookups stay
|
|
1868
|
-
* alias-stable.
|
|
1869
|
-
*
|
|
1870
|
-
* Prefer `addUnlock` for cache-stable wire-tool ordering: writes through a
|
|
1871
|
-
* Set lose unlock order, so the wire-level rebuild that filters by `unlocked`
|
|
1872
|
-
* has to fall back to registry iteration order — which moves entries every
|
|
1873
|
-
* time a lazy tool earlier in the registry is unlocked, breaking provider
|
|
1874
|
-
* prompt-cache breakpoints. The agent passes both when it owns the unlock
|
|
1875
|
-
* tracker, with `addUnlock` mirroring writes into an ordered log.
|
|
1876
|
-
*/
|
|
1877
|
-
unlocked: Set<string>;
|
|
1878
|
-
/**
|
|
1879
|
-
* Optional callback fired for every canonical name the tool unlocks. When
|
|
1880
|
-
* set, the agent uses this to maintain an append-only `dynamicUnlockOrder`
|
|
1881
|
-
* so the wire-level tool list emits new unlocks at the tail and keeps the
|
|
1882
|
-
* provider prefix cache warm. Idempotent on repeat unlocks of the same
|
|
1883
|
-
* name — callers may dedupe internally.
|
|
1884
|
-
*
|
|
1885
|
-
* Invoked **in addition to** the `unlocked.add` (which still happens for
|
|
1886
|
-
* back-compat with callers that only watch the Set).
|
|
1887
|
-
*/
|
|
1888
|
-
addUnlock?: (canonical: string) => void;
|
|
1889
|
-
/** Default cap on returned matches when the model omits `limit`. */
|
|
1890
|
-
defaultLimit?: number;
|
|
1891
|
-
}
|
|
2073
|
+
declare function joinSystemPrompt(staticPart: string, dynamicPart: string): string;
|
|
1892
2074
|
/**
|
|
1893
|
-
*
|
|
1894
|
-
*
|
|
1895
|
-
*
|
|
2075
|
+
* Append `extra` to the STATIC half of a system prompt, preserving any
|
|
2076
|
+
* existing dynamic suffix.
|
|
2077
|
+
*
|
|
2078
|
+
* Used by the agent to fold in run-stable content (skills catalog, lazy tool
|
|
2079
|
+
* catalog) without bumping it into the dynamic half — both catalogs are
|
|
2080
|
+
* built once per run and remain byte-stable for the duration, so they
|
|
2081
|
+
* belong in the cached prefix.
|
|
2082
|
+
*
|
|
2083
|
+
* Returns a new string; the input is not mutated. When `extra` is empty,
|
|
2084
|
+
* returns the input verbatim.
|
|
1896
2085
|
*/
|
|
1897
|
-
declare function
|
|
1898
|
-
//#endregion
|
|
1899
|
-
//#region src/tools/validation.d.ts
|
|
2086
|
+
declare function appendStaticSection(system: string, extra: string): string;
|
|
1900
2087
|
/**
|
|
1901
|
-
*
|
|
2088
|
+
* Append `extra` to the DYNAMIC half of a system prompt. Inserts the boundary
|
|
2089
|
+
* marker if the input didn't already carry one.
|
|
1902
2090
|
*
|
|
1903
|
-
*
|
|
1904
|
-
*
|
|
1905
|
-
*
|
|
1906
|
-
*
|
|
1907
|
-
*
|
|
1908
|
-
* coerce when the conversion is unambiguous, fail only when the value
|
|
1909
|
-
* cannot be reasonably normalized to any of the declared types.
|
|
2091
|
+
* Used by hosts (typically the TUI) to inject per-turn state — current cwd,
|
|
2092
|
+
* IDE selection, project root — without forcing every caller to know the
|
|
2093
|
+
* marker format. The host's `system:transform` hook rewrites the dynamic
|
|
2094
|
+
* half each turn; the static doctrine above stays byte-stable and rides the
|
|
2095
|
+
* cache.
|
|
1910
2096
|
*
|
|
1911
|
-
*
|
|
1912
|
-
*
|
|
1913
|
-
* deep (their declared `properties` get the same coercion + enum checks the
|
|
1914
|
-
* top level does). Items that can't be coerced are dropped rather than
|
|
1915
|
-
* rejecting the whole call — the model rarely benefits from an
|
|
1916
|
-
* all-or-nothing failure on a 20-item list because one entry was malformed.
|
|
1917
|
-
* Dropped items are reported back via `droppedItems` so the tool's `execute`
|
|
1918
|
-
* can surface a hint to the model if it wants to.
|
|
2097
|
+
* Returns a new string; the input is not mutated. When `extra` is empty,
|
|
2098
|
+
* returns the input verbatim.
|
|
1919
2099
|
*/
|
|
1920
|
-
|
|
1921
|
-
valid: boolean;
|
|
1922
|
-
/** Human-readable reason. Present on failure only. */
|
|
1923
|
-
error?: string;
|
|
1924
|
-
/**
|
|
1925
|
-
* Possibly-coerced input. Present iff `valid: true`. Tools should call
|
|
1926
|
-
* `execute(coercedInput, ctx)` so auto-healed values reach the tool body.
|
|
1927
|
-
* When no coercion was applied, this is reference-equal to the input.
|
|
1928
|
-
*/
|
|
1929
|
-
coercedInput?: Record<string, unknown>;
|
|
1930
|
-
/**
|
|
1931
|
-
* Names of fields whose values were coerced. Empty when nothing changed.
|
|
1932
|
-
* Useful for telemetry (`validation:reject` on failure already carries the
|
|
1933
|
-
* reason; this is the success-path equivalent).
|
|
1934
|
-
*/
|
|
1935
|
-
coercions?: readonly string[];
|
|
1936
|
-
/**
|
|
1937
|
-
* Indexes of array items dropped during recursive validation, keyed by
|
|
1938
|
-
* the property name. Empty / absent when nothing was dropped. Tools that
|
|
1939
|
-
* care about the discrepancy (e.g. `todowrite` wanting to surface
|
|
1940
|
-
* "ignored 2 malformed items") can inspect this.
|
|
1941
|
-
*/
|
|
1942
|
-
droppedItems?: Readonly<Record<string, readonly number[]>>;
|
|
1943
|
-
}
|
|
1944
|
-
declare function validateToolArgs(input: Record<string, unknown>, schema: Record<string, unknown>): ValidationResult;
|
|
1945
|
-
//#endregion
|
|
1946
|
-
//#region src/tools/write-file.d.ts
|
|
2100
|
+
declare function appendDynamicSection(system: string, extra: string): string;
|
|
1947
2101
|
/**
|
|
1948
|
-
*
|
|
2102
|
+
* Replace the entire dynamic half of a system prompt with `next`. Used by
|
|
2103
|
+
* the TUI's `<env>` rewriter where the entire dynamic section is regenerated
|
|
2104
|
+
* each turn rather than appended to.
|
|
1949
2105
|
*
|
|
1950
|
-
*
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
*
|
|
2106
|
+
* When `next` is empty, drops the dynamic half (and the marker) entirely.
|
|
2107
|
+
*/
|
|
2108
|
+
declare function replaceDynamicSection(system: string, next: string): string;
|
|
2109
|
+
/**
|
|
2110
|
+
* Strip the boundary marker so it never reaches the wire — collapses
|
|
2111
|
+
* `<static>${BOUNDARY}<dynamic>` into `<static>\n\n<dynamic>` for providers
|
|
2112
|
+
* that can't honor `cache_control` (vanilla OpenAI Chat Completions, Codex,
|
|
2113
|
+
* Cerebras, ...) or for the cache-disabled path on any provider.
|
|
1955
2114
|
*
|
|
1956
|
-
*
|
|
1957
|
-
*
|
|
1958
|
-
*
|
|
1959
|
-
*
|
|
1960
|
-
*
|
|
2115
|
+
* Cache-aware providers re-derive the split from the original (un-rendered)
|
|
2116
|
+
* system string via `splitSystemPrompt` — `renderSystemForWire` is the
|
|
2117
|
+
* marker-free counterpart used to build the actual wire bytes.
|
|
2118
|
+
*
|
|
2119
|
+
* No-op when the input has no marker. Pure / no I/O.
|
|
1961
2120
|
*/
|
|
1962
|
-
declare
|
|
2121
|
+
declare function renderSystemForWire(system: string): string;
|
|
2122
|
+
/** True when `system` contains the boundary marker. */
|
|
2123
|
+
declare function hasSystemPromptBoundary(system: string): boolean;
|
|
1963
2124
|
//#endregion
|
|
1964
2125
|
//#region src/tracing.d.ts
|
|
1965
2126
|
/** Minimal span shape — any tracer that provides these methods is compatible. */
|
|
@@ -2281,5 +2442,5 @@ declare function definePreset(config: Preset): Preset;
|
|
|
2281
2442
|
*/
|
|
2282
2443
|
declare function composePresets(...presets: Preset[]): Preset;
|
|
2283
2444
|
//#endregion
|
|
2284
|
-
export {
|
|
2285
|
-
//# sourceMappingURL=index-
|
|
2445
|
+
export { cleanupPersistedSession as $, CacheDimensionSnapshot as $n, InteractionToolOptions as $t, MetricAttributes as A, BASE_INSTRUCTIONS as An, validateToolArgs as At, LoginMcpServerResult as B, buildUpToCompactPrompt as Bn, SkillsUseToolOptions as Bt, ModelUsage as C, selectFilesFromSession as Cn, HeadlessUsage as Ct, Histogram as D, compactConversation as Dn, transcriptToOpenAIMessages as Dt, Counter as E, CompactResult as En, runHeadless as Et, OAuthCallbackHandle as F, TRAILER as Fn, SpawnToolOptions as Ft, McpOAuthProviderOptions as G, anchorPreviewFor as Gn, createSkillsReadTool as Gt, McpCredentialEntry as H, CompactScope as Hn, SkillsRunScriptToolOptions as Ht, OAuthCallbackOptions as I, buildCompactPrompt as In, SpawnToolState as It, PERSISTED_STUB_PREFIX as J, summaryToTurn as Jn, createShellTool as Jt, createMemoryMcpCredentialStore as K, sliceForCompaction as Kn, shellKill as Kt, OAuthCallbackResult as L, buildFromCompactPrompt as Ln, SubagentDef as Lt, MetricsHooksOptions as M, CompactPromptBuilder as Mn, ToolSearchToolOptions as Mt, UpDownCounter as N, CompactPromptOptions as Nn, createToolSearchTool as Nt, InstrumentOptions as O, CompactInvalidInputError as On, writeFile as Ot, createMetricsHooks as P, NO_TOOLS_PREAMBLE as Pn, ChildAgent as Pt, buildPersistedStub as Q, CacheDimensionName as Qn, listFiles as Qt, startOAuthCallback as R, buildFullCompactPrompt as Rn, SubagentRegistry as Rt, splitSystemPrompt as S, selectFilesFromReadState as Sn, HeadlessStatus as St, statsByModel as T, CompactOptions as Tn, headlessEventToJsonl as Tt, McpCredentialStore as U, CompactionSlice as Un, createSkillsRunScriptTool as Ut, loginMcpServer as V, ANCHOR_PREVIEW_MAX_CHARS as Vn, createSkillsUseTool as Vt, McpOAuthProvider as W, SummaryToTurnInput as Wn, SkillsReadToolOptions as Wt, PersistInput as X, CacheBreakLoggerOptions as Xn, readFile as Xt, PERSISTENCE_PREVIEW_BYTES as Y, truncateHeadForPtlRetry as Yn, shell as Yt, PersistOutcome as Z, CacheDimensionDiff as Zn, multiEdit as Zt, appendStaticSection as _, utf8ByteLength as _n, jsonSink as _t, basicTools as a, RunSummaryBlock as an, TOOL_USE_CANCELLED_MESSAGE as at, renderSystemForWire as b, RecentFile as bn, HeadlessOptions as bt, Span as c, RunSummaryCollector as cn, LogLevel as ct, TracingHookSet as d, RunSummaryRepeatGuard as dn, Logger as dt, createInteractionTool as en, diffCacheDimensions as er, maybePersistToolResult as et, TracingHooksOptions as f, RunSummaryTokens as fn, LoggingHookSet as ft, appendDynamicSection as g, estimateTokens as gn, createLoggingHooks as gt, SystemPromptParts as h, BYTES_PER_TOKEN as hn, createLogger as ht, _default as i, RunSummary as in, SHELL_CASCADE_CANCEL_MESSAGE as it, MetricsHookSet as j, CompactDirection as jn, LazyToolEntry as jt, Meter as k, CompactPromptTooLongError as kn, ValidationResult as kt, StartSpan as l, RunSummaryCollectorOptions as ln, LogRecord as lt, SYSTEM_PROMPT_BOUNDARY as m, createRunSummaryCollector as mn, consoleSink as mt, composePresets as n, glob as nn, installCacheBreakLogger as nr, resolveTasksDir as nt, zodToJsonSchema as o, RunSummaryBudget as on, TOOL_USE_SKIPPED_MESSAGE as ot, createTracingHooks as p, RunSummaryValidation as pn, LoggingHooksOptions as pt, hasAuthorizationHeader as q, stripImagesFromTurns as qn, CreateShellToolOptions as qt, definePreset as r, edit as rn, snapshotCacheDimensions as rr, INTERRUPT_MESSAGE_FOR_TOOL_USE as rt, GEN_AI_ATTRIBUTES as s, RunSummaryByModel as sn, ConsoleSinkOptions as st, Preset as t, grep as tn, fnv1a32 as tr, resolvePersistDir as tt, TracingConventions as u, RunSummaryError as un, LogSink as ut, hasSystemPromptBoundary as v, PostCompactAttachments as vn, HeadlessErrorInfo as vt, flattenTurns as w, selectRecentFiles as wn, OpenAIChatMessage as wt, replaceDynamicSection as x, buildPostCompactAttachments as xn, HeadlessResult as xt, joinSystemPrompt as y, PostCompactRestoreOptions as yn, HeadlessEvent as yt, LoginMcpServerOptions as z, buildTailCompactPrompt as zn, createSpawnTool as zt };
|
|
2446
|
+
//# sourceMappingURL=index-B2cMuK6S.d.ts.map
|