Merge branch 'codex/goal-commands' into codex/ralph-tool

# Conflicts:
#	examples/acp-agent/tests/snapshots/advanced-toolchain/system-prompt.expected.md
#	examples/acp-agent/tests/snapshots/advanced-toolchain/tool-schemas.expected.json
#	examples/acp-agent/tests/snapshots/both-mode-turn/system-prompt.expected.md
#	examples/acp-agent/tests/snapshots/both-mode-turn/tool-schemas.expected.json
#	examples/acp-agent/tests/snapshots/code-mode-turn/system-prompt.expected.md
#	examples/acp-agent/tests/snapshots/model-switching/tool-schemas.expected.json
#	examples/acp-agent/tests/snapshots/permission-switching/tool-schemas.expected.json
#	examples/acp-agent/tests/snapshots/skill-load/tool-schemas.expected.json
#	examples/acp-agent/tests/snapshots/text-turn/tool-schemas.expected.json
#	examples/acp-agent/tests/snapshots/workspace-edit/system-prompt.expected.md
#	examples/acp-agent/tests/snapshots/workspace-edit/tool-schemas.expected.json
#	scripts/gen-tool-catalog.ts
This commit is contained in:
Tianyi Cui
2026-07-20 21:05:05 +08:00
466 changed files with 13130 additions and 8908 deletions

View File

@@ -263,12 +263,12 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
jsDoc: '/**\n * List direct children of a directory in stable name order. Returns resolved\n * child targets plus cheap metadata only; never reads file contents.\n * @param target - the resolved directory target.\n * @param signal - aborts the listing.\n * @returns one entry per direct child, in stable name order.\n */',
},
{
signature: 'abstract writeText(target: FsTarget, content: string, expected?: FsWriteIntent, signal?: AbortSignal): Promise<FsWriteOutcome>',
jsDoc: '/**\n * Atomically create or replace UTF-8 text. `expected` guards intent and\n * staleness; omission allows unconditional overwrite.\n * @param target - the resolved target to write.\n * @param content - the full new file content.\n * @param expected - the write intent guarding the write; omit for unconditional.\n * @param signal - aborts before the atomic rename takes effect.\n * @returns the outcome, including the version the write produced.\n */',
signature: 'abstract writeText( target: FsTarget, content: string, expected?: FsWriteIntent, signal?: AbortSignal, sandboxMode?: SandboxMode, ): Promise<FsWriteOutcome>',
jsDoc: '/**\n * Atomically create or replace UTF-8 text. `expected` guards intent and\n * staleness; omission allows unconditional overwrite.\n * @param target - the resolved target to write.\n * @param content - the full new file content.\n * @param expected - the write intent guarding the write; omit for unconditional.\n * @param signal - aborts before the atomic rename takes effect.\n * @param sandboxMode - the per-call sandbox mode this write runs under; a\n * sandboxing backend fences the write by it, the bare backend ignores it.\n * Omit to leave the backend its own default.\n * @returns the outcome, including the version the write produced.\n */',
},
{
signature: 'abstract editText(target: FsTarget, edit: FsEditRequest, expected?: { version: FsVersion }, signal?: AbortSignal): Promise<FsEditOutcome>',
jsDoc: '/**\n * Atomically edit literal text. When supplied, the version guard is checked\n * before matching so stale content reports `FS_STALE_VERSION`; omission edits\n * the current content without a freshness precondition.\n * @param target - the resolved target to edit.\n * @param edit - the literal search/replace request.\n * @param expected - the version guard; omit for an unconditional edit.\n * @param signal - aborts before the atomic rename takes effect.\n * @returns the outcome, including the version the edit produced.\n */',
signature: 'abstract editText( target: FsTarget, edit: FsEditRequest, expected?: { version: FsVersion }, signal?: AbortSignal, sandboxMode?: SandboxMode, ): Promise<FsEditOutcome>',
jsDoc: '/**\n * Atomically edit literal text. When supplied, the version guard is checked\n * before matching so stale content reports `FS_STALE_VERSION`; omission edits\n * the current content without a freshness precondition.\n * @param target - the resolved target to edit.\n * @param edit - the literal search/replace request.\n * @param expected - the version guard; omit for an unconditional edit.\n * @param signal - aborts before the atomic rename takes effect.\n * @param sandboxMode - the per-call sandbox mode this edit runs under; a\n * sandboxing backend fences the edit by it, the bare backend ignores it.\n * Omit to leave the backend its own default.\n * @returns the outcome, including the version the edit produced.\n */',
},
],
},
@@ -368,6 +368,11 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
},
],
},
{
key: 'sandboxPolicy',
summary: 'The sandbox-policy service (`ctx.sandboxPolicy`).',
methods: [],
},
{
key: 'sessionPersistence',
summary: 'Durable append-only session storage.',
@@ -426,7 +431,7 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
methods: [
{
signature: 'create(id?: SessionId, options?: CreateSessionOptions): Session',
jsDoc: '/**\n * Create a session owned by the calling fiber: disposing that fiber stops\n * event notification and removes the session from the store. `options.seed`\n * populates the session with a copy of those events (replay/fork);\n * `options.meta` attaches creation metadata (validated absolute `cwd`,\n * `parentSession` lineage) as the immutable {@link SessionHeader} (the store\n * fills `version`/`id`/`createdAt`).\n *\n * For an agent whose session must be torn down IN ORDER with its loop (so the\n * loop\'s final flush is captured before the store attachment ends), do NOT use this\n * — fold the session lifecycle into the agent\'s own effect via\n * {@link prepare} + {@link enter} + {@link announce} (see\n * `dsh-agent-loop`\'s creation transaction).\n *\n * @param id - the session id; omitted, the store mints `session-<n>`.\n * @param options - seed events and/or creation metadata for the header.\n * @returns the live session, already entered and announced.\n * @throws if a session with `id` already exists, metadata is not a plain\n * lossless-JSON record with valid scalar fields, or `meta.cwd` is a\n * non-absolute path (storage backends key directories off it).\n */',
jsDoc: '/**\n * Create a session owned by the calling fiber: disposing that fiber stops\n * event notification and removes the session from the store. `options.seed`\n * populates the session with a copy of those events (replay/fork);\n * `options.meta` attaches creation metadata (validated absolute `cwd`, seed\n * and parent lineage, and delegation depth) as the immutable\n * {@link SessionHeader} (the store fills `version`/`id`/`createdAt`).\n *\n * For an agent whose session must be torn down IN ORDER with its loop (so the\n * loop\'s final flush is captured before the store attachment ends), do NOT use this\n * — fold the session lifecycle into the agent\'s own effect via\n * {@link prepare} + {@link enter} + {@link announce} (see\n * `dsh-agent-loop`\'s creation transaction).\n *\n * @param id - the session id; omitted, the store mints `session-<n>`.\n * @param options - seed events and/or creation metadata for the header.\n * @returns the live session, already entered and announced.\n * @throws if a session with `id` already exists, metadata is not a plain\n * lossless-JSON record with valid scalar fields, or `meta.cwd` is a\n * non-absolute path (storage backends key directories off it).\n */',
},
{
signature: 'prepare(id?: SessionId, options?: CreateSessionOptions): Session',
@@ -586,6 +591,24 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
},
],
},
{
key: 'toolResultPrune',
summary: 'Deterministic head/middle/tail pruning for current tool-result surface nodes.',
methods: [
{
signature: 'measureContent(blocks: readonly ContentBlock[]): number',
jsDoc: '/**\n * Measure text content in Unicode code points; non-text blocks cost zero.\n * @param blocks - tool-result content to measure.\n * @returns total Unicode code points across text blocks.\n */',
},
{
signature: 'pruneContent(blocks: readonly ContentBlock[]): ContentBlock[] | null',
jsDoc: '/**\n * Replace an over-budget text middle while retaining rich-block order.\n * Text slicing is by Unicode code point, not UTF-16 code unit, so a retained\n * boundary cannot split a surrogate pair. Grapheme clusters may still split.\n * @param blocks - original tool-result content.\n * @returns pruned content, or `null` when the text is within budget.\n */',
},
{
signature: 'pruneSession(session: Session): PruneResult',
jsDoc: '/**\n * Prune every over-budget tool result from one stable current-surface snapshot.\n * Each replacement preserves the complete event data except for `content`,\n * and points at the shadowed node for durable provenance and replay.\n * @param session - session whose current surface is rewritten.\n * @returns landed replacements and aggregate Unicode-code-point savings.\n * @throws when the session rejects a replacement; replacements committed\n * earlier in the pass remain durable.\n */',
},
],
},
{
key: 'tools',
summary: 'Tool registry and execution pipeline.',
@@ -723,8 +746,8 @@ export const EVENT_API: readonly EventApiEntry[] = [
name: 'agent/prompt-submit',
mode: 'waterfall',
signature: '\'agent/prompt-submit\'(this: Scoped<Agent>, agent: Agent, content: ContentBlock[], source: MessageSource, next: () => Promise<PromptDecision>): Promise<PromptDecision>',
jsDoc: '/**\n * Allow, rewrite, or block one drained prompt before it becomes a user\n * message. Call `next()` for the unchanged default.\n * @param agent - the agent draining its inbox.\n * @param content - the drained message\'s blocks, as queued.\n * @param source - the message\'s resolved source.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode waterfall\n */',
summary: 'Allow, rewrite, or block one drained prompt before it becomes a user message.',
jsDoc: '/**\n * Allow, rewrite, or block one claimed prompt before it becomes a user\n * message. Call `next()` for the unchanged default.\n * @param agent - the agent whose turn claimed the message.\n * @param content - the claimed message\'s blocks, as queued.\n * @param source - the message\'s resolved source.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode waterfall\n */',
summary: 'Allow, rewrite, or block one claimed prompt before it becomes a user message.',
},
{
name: 'agent/queued',
@@ -1173,13 +1196,9 @@ export const TYPE_API: readonly TypeApiEntry[] = [
name: 'ContentBlockType',
declaration: 'export type ContentBlockType = keyof ContentBlockMap;',
},
{
name: 'ContextEnvelope',
declaration: 'export type ContextEnvelope = \'context\' | \'raw\';',
},
{
name: 'CreateAgentOptions',
declaration: 'export interface CreateAgentOptions {\n readonly sessionId: SessionId;\n readonly meta?: {\n readonly cwd?: string;\n readonly parentSession?: SessionId;\n readonly seedLength?: number;\n };\n readonly seed?: readonly SessionEvent[];\n readonly agentOptions?: AgentOptions;\n readonly signal?: AbortSignal;\n readonly setup?: (agentCtx: Context) => Promise<void> | void;\n}',
declaration: 'export interface CreateAgentOptions {\n readonly sessionId: SessionId;\n readonly meta?: {\n readonly cwd?: string;\n readonly parentSession?: SessionId;\n readonly seedLength?: number;\n readonly delegationDepth?: number;\n };\n readonly seed?: readonly SessionEvent[];\n readonly agentOptions?: AgentOptions;\n readonly signal?: AbortSignal;\n readonly setup?: (agentCtx: Context) => Promise<void> | void;\n}',
},
{
name: 'CreateGoalRequest',
@@ -1187,7 +1206,7 @@ export const TYPE_API: readonly TypeApiEntry[] = [
},
{
name: 'CreateSessionOptions',
declaration: 'export interface CreateSessionOptions {\n readonly seed?: readonly SessionEvent[];\n readonly meta?: {\n readonly cwd?: string;\n readonly parentSession?: SessionId;\n readonly createdAt?: number;\n readonly seedLength?: number;\n };\n}',
declaration: 'export interface CreateSessionOptions {\n readonly seed?: readonly SessionEvent[];\n readonly meta?: {\n readonly cwd?: string;\n readonly parentSession?: SessionId;\n readonly createdAt?: number;\n readonly seedLength?: number;\n readonly delegationDepth?: number;\n };\n}',
},
{
name: 'DiffCallView',
@@ -1311,11 +1330,11 @@ export const TYPE_API: readonly TypeApiEntry[] = [
},
{
name: 'HookContext',
declaration: 'export interface HookContext {\n content: ContentBlock[];\n source: MessageSource;\n envelope?: ContextEnvelope;\n meta?: JsonValue;\n}',
declaration: 'export interface HookContext {\n content: ContentBlock[];\n source: MessageSource;\n meta?: JsonValue;\n}',
},
{
name: 'InjectOptions',
declaration: 'export interface InjectOptions extends SendOptions {\n envelope?: ContextEnvelope;\n meta?: JsonValue;\n}',
declaration: 'export interface InjectOptions extends SendOptions {\n meta?: JsonValue;\n}',
},
{
name: 'JsonValue',
@@ -1361,6 +1380,14 @@ export const TYPE_API: readonly TypeApiEntry[] = [
name: 'PromptSection',
declaration: 'export interface PromptSection {\n readonly name: string;\n readonly order: number;\n readonly text: string | ((context: AssembleContext) => string);\n}',
},
{
name: 'PrunedEntry',
declaration: 'export interface PrunedEntry {\n readonly originalSeq: number;\n readonly replacementSeq: number;\n readonly callId: CallId;\n readonly charsBefore: number;\n readonly charsAfter: number;\n}',
},
{
name: 'PruneResult',
declaration: 'export interface PruneResult {\n readonly pruned: readonly PrunedEntry[];\n readonly charsRemoved: number;\n}',
},
{
name: 'ReasoningBlock',
declaration: 'export interface ReasoningBlock {\n type: \'reasoning\';\n text: string;\n}',
@@ -1399,7 +1426,7 @@ export const TYPE_API: readonly TypeApiEntry[] = [
},
{
name: 'SessionEventMap',
declaration: 'export interface SessionEventMap {\n \'turn/start\': {\n turn: number;\n trigger: TurnTrigger;\n };\n \'turn/end\': {\n turn: number;\n reason: TurnEndReason;\n };\n \'step/start\': {\n turn: number;\n step: number;\n };\n \'step/end\': {\n turn: number;\n step: number;\n };\n \'user/message\': {\n content: ContentBlock[];\n source: MessageSource;\n };\n \'prompt/blocked\': {\n content: ContentBlock[];\n source: MessageSource;\n reason: string;\n };\n \'context/message\': {\n content: ContentBlock[];\n source: MessageSource;\n envelope?: ContextEnvelope;\n meta?: JsonValue;\n };\n \'assistant/chunk\': {\n turn: number;\n step: number;\n chunk: StreamChunk;\n };\n \'assistant/message\': {\n turn: number;\n step: number;\n content: ContentBlock[];\n provenance: AssistantProvenance;\n usage?: TokenUsage;\n };\n \'tool/call\': {\n turn: number;\n step: number;\n callId: CallId;\n name: string;\n arguments: string;\n };\n \'tool/result\': {\n turn: number;\n step: number;\n callId: CallId;\n content: ContentBlock[];\n isError: boolean;\n error?: {\n name: string;\n code: string;\n };\n meta?: unknown;\n };\n \'steering/message\': {\n turn: number;\n content: ContentBlock[];\n source: MessageSource; /* …truncated — full shape in source */',
declaration: 'export interface SessionEventMap {\n \'turn/start\': {\n turn: number;\n trigger: TurnTrigger;\n };\n \'turn/end\': {\n turn: number;\n reason: TurnEndReason;\n };\n \'step/start\': {\n turn: number;\n step: number;\n };\n \'step/end\': {\n turn: number;\n step: number;\n };\n \'user/message\': {\n content: ContentBlock[];\n source: MessageSource;\n };\n \'prompt/blocked\': {\n content: ContentBlock[];\n source: MessageSource;\n reason: string;\n };\n \'context/message\': {\n content: ContentBlock[];\n source: MessageSource;\n meta?: JsonValue;\n };\n \'assistant/chunk\': {\n turn: number;\n step: number;\n chunk: StreamChunk;\n };\n \'assistant/message\': {\n turn: number;\n step: number;\n content: ContentBlock[];\n provenance: AssistantProvenance;\n usage?: TokenUsage;\n };\n \'tool/call\': {\n turn: number;\n step: number;\n callId: CallId;\n name: string;\n arguments: string;\n };\n \'tool/result\': {\n turn: number;\n step: number;\n callId: CallId;\n content: ContentBlock[];\n isError: boolean;\n error?: {\n name: string;\n code: string;\n };\n meta?: unknown;\n };\n \'steering/message\': {\n turn: number;\n content: ContentBlock[];\n source: MessageSource;\n };\n \'todo/write\': {\n /* …truncated — full shape in source */',
},
{
name: 'SessionEventReadRequest',
@@ -1435,7 +1462,7 @@ export const TYPE_API: readonly TypeApiEntry[] = [
},
{
name: 'SessionHeader',
declaration: 'export interface SessionHeader {\n readonly version: number;\n readonly id: SessionId;\n readonly createdAt: number;\n readonly cwd?: string;\n readonly parentSession?: SessionId;\n readonly seedLength?: number;\n}',
declaration: 'export interface SessionHeader {\n readonly version: number;\n readonly id: SessionId;\n readonly createdAt: number;\n readonly cwd?: string;\n readonly parentSession?: SessionId;\n readonly seedLength?: number;\n readonly delegationDepth?: number;\n}',
},
{
name: 'SessionId',