Merge remote-tracking branch 'origin/master' into xtr/react-loop-simplification

# Conflicts:
#	.agents/notes/implemented/architecture/2026-07-12-agent-scope-runtime-design.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-31-goal-owned-durable-events.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-19-model-facing-goal-tools.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-22-docked-web-goal-bar.i18n.yaml
#	docs/architecture.i18n.yaml
#	docs/architecture.md
#	docs/architecture.zh.md
#	docs/config-catalog.md
#	docs/cordis-catalog/events.md
#	docs/cordis-catalog/services.md
#	docs/core-data-structures/core.i18n.yaml
#	docs/core-data-structures/core.md
#	docs/core-data-structures/core.zh.md
#	docs/event-producer-consumer.md
#	docs/module-graph.md
#	docs/persistence-catalog.md
#	examples/acp-agent/tests/snapshots/advanced-toolchain/session.1.jsonl
#	examples/acp-agent/tests/snapshots/advanced-toolchain/session.2.jsonl
#	examples/acp-agent/tests/snapshots/code-mode-workspace-context/session.jsonl
#	examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/session.jsonl
#	examples/acp-agent/tests/snapshots/skill-load/session.jsonl
#	examples/acp-agent/tests/snapshots/subagent-depth-two-rejection/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-depth-two-rejection/session.2.jsonl
#	examples/acp-agent/tests/snapshots/subagent-fork/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-mixed/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-mixed/session.2.jsonl
#	examples/acp-agent/tests/snapshots/subagent-multi/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-multi/session.2.jsonl
#	examples/acp-agent/tests/snapshots/subagent-spawn/session.1.jsonl
#	examples/acp-agent/tests/snapshots/workflow-run/session.1.jsonl
#	examples/acp-agent/tests/snapshots/workspace-context/session.jsonl
#	examples/headless-agent/tests/snapshots/advanced-toolchain/session.1.jsonl
#	examples/headless-agent/tests/snapshots/advanced-toolchain/session.2.jsonl
#	examples/headless-agent/tests/snapshots/advanced-toolchain/session.jsonl
#	examples/headless-agent/tests/snapshots/pty-tools/session.jsonl
#	examples/headless-agent/tests/subagent-inheritance-snapshots/parent-override/child.expected.jsonl
#	examples/jsonrpc-agent/tests/snapshots/subagent-spawn/notifications.expected.jsonl
#	examples/jsonrpc-agent/tests/snapshots/subagent-spawn/session.1.jsonl
#	packages/acp/acp/README.i18n.yaml
#	packages/acp/acp/src/index.ts
#	packages/client/connection/src/client/index.ts
#	packages/client/runtime/README.i18n.yaml
#	packages/client/runtime/README.md
#	packages/client/runtime/README.zh.md
#	packages/client/runtime/src/client/sessions/conversation.ts
#	packages/client/runtime/src/client/sessions/session.ts
#	packages/client/runtime/tests/queue-store.spec.ts
#	packages/client/ui-conversation/src/client/input/contract.ts
#	packages/client/ui-goal/README.i18n.yaml
#	packages/compact/compact-basic/src/index.ts
#	packages/context/time-context/tests/time-context.spec.ts
#	packages/context/tmux-context/tests/tmux-context.spec.ts
#	packages/context/workspace-context/tests/workspace-context.spec.ts
#	packages/cordis/tool-cordis/src/api-catalog.ts
#	packages/core/agent-loop/README.i18n.yaml
#	packages/core/agent-loop/README.md
#	packages/core/agent-loop/README.zh.md
#	packages/core/agent-loop/src/agent.ts
#	packages/core/agent-loop/tests/agent.spec.ts
#	packages/core/agent-loop/tests/loop.spec.ts
#	packages/core/agent/README.i18n.yaml
#	packages/core/agent/README.md
#	packages/core/agent/README.zh.md
#	packages/core/agent/src/types.ts
#	packages/core/session/README.i18n.yaml
#	packages/core/session/README.md
#	packages/core/session/README.zh.md
#	packages/goal/command-goal/tests/command-goal.spec.ts
#	packages/goal/goal/tests/goal.spec.ts
#	packages/goal/tool-goal/README.i18n.yaml
#	packages/goal/tool-goal/README.md
#	packages/goal/tool-goal/README.zh.md
#	packages/host/apiproxy/README.i18n.yaml
#	packages/host/apiproxy/README.md
#	packages/host/apiproxy/README.zh.md
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/host/apiproxy/src/api/events.schema.ts
#	packages/host/apiproxy/src/api/events.ts
#	packages/host/apiproxy/src/api/rpc.ts
#	packages/host/apiproxy/tests/api-proxy-commands.spec.ts
#	packages/host/apiproxy/tests/api-proxy-projections.spec.ts
#	packages/host/apiproxy/tests/rpc-schemas.spec.ts
#	packages/pty/pty-local/tests/index.spec.ts
#	packages/pty/pty-local/tests/local.spec.ts
#	packages/pty/tool-pty/tests/loader-composition.spec.ts
#	packages/pty/tool-pty/tests/tools.spec.ts
#	packages/session-persistence/session-checkpoint-policy/src/index.ts
#	packages/session-persistence/session-persistence/tests/coordinator-contract.ts
#	packages/skill/tool-skill/tests/tool-skill.spec.ts
#	packages/subagent/subagent-inprocess/README.i18n.yaml
#	packages/subagent/subagent-inprocess/README.md
#	packages/subagent/subagent-inprocess/README.zh.md
#	packages/subagent/subagent-inprocess/src/index.ts
#	packages/subagent/subagent-inprocess/tests/subagent-inprocess.spec.ts
#	packages/support/acp-snapshot/src/harness.ts
#	packages/ui/tui/tests/tui.spec.ts
This commit is contained in:
_Kerman
2026-08-03 10:56:09 +08:00
605 changed files with 25740 additions and 2265 deletions

View File

@@ -1,8 +1,8 @@
/**
* commands domain contract: the web catalog/dispatch face of the host command
* registry (`ctx.commands`). Both methods address one session's agent via
* `sessionId` — every served session has an Agent (Session+Agent are born
* together), so there is no agent-less surface on this wire.
* registry (`ctx.commands`). Both methods address an ordinary session's Agent
* via `sessionId`, resuming it when cold. Session-backed subagents reject with
* `agent-busy` and retain their dedicated continuation owner.
*/
import type { CommandId } from '@deepseek-ai/dsh-commands/brand'
@@ -27,7 +27,8 @@ export interface CommandDescriptor {
export interface CommandsApi {
/**
* Lists the addressed agent's effective command catalog (name-sorted,
* globals plus its scoped shadows).
* globals plus its scoped shadows). Session-backed subagents reject with
* `agent-busy`.
*/
list(request: RpcRequest<{ sessionId: SessionId }>): Promise<RpcResponse<{ commands: readonly CommandDescriptor[] }>>
@@ -42,6 +43,7 @@ export interface CommandsApi {
* pairing id, letting the issuing client correlate this acknowledgment
* with that flow node. The signal rides beside the request, never on the
* wire: the fetch carrier's request signal cancels the running handler.
* Session-backed subagents reject with `agent-busy` before dispatch.
*/
execute(request: RpcRequest<{ sessionId: SessionId; line: string }>, signal: AbortSignal):
Promise<RpcResponse<{ matched: boolean; commandId?: CommandId }>>

View File

@@ -22,7 +22,11 @@ export interface GoalRef {
readonly revision: number
}
/** Goal-domain unary methods (every mutation resolves the session's agent and applies one CAS-guarded verb). */
/**
* Goal-domain unary methods. Every mutation resolves an ordinary session's
* Agent and applies one CAS-guarded verb; session-backed subagents reject with
* `agent-busy`.
*/
export interface GoalsApi {
/** Create and arm a goal. */
create(request: RpcRequest<{ sessionId: SessionId; objective: string; maxGoalRounds?: number }>):

View File

@@ -9,6 +9,7 @@ import type { HostApi } from './host.ts'
import type { WorkspaceApi } from './workspace.ts'
import type { CommandsApi } from './commands.ts'
import type { SkillsApi } from './skills.ts'
import type { SubagentsApi } from './subagents.ts'
import type { EventsApi } from './events.ts'
import type { GoalsApi } from './goals.ts'
import type { SettingsApi } from './settings.ts'
@@ -19,6 +20,7 @@ import type { ClientResponse, RpcReceipt } from './rpc.ts'
/** Root interface of the unified API surface. New client-request domain = one new file pair + one field here + one map row. */
export interface ApiProxy {
sessions: SessionsApi
subagents: SubagentsApi
host: HostApi
workspace: WorkspaceApi
commands: CommandsApi
@@ -39,6 +41,9 @@ export type {
SessionsApi, SessionSummary,
} from './sessions.ts'
export type { DirectoryEntry, DirectoryListing, HostApi } from './host.ts'
export type {
SubagentAddress, SubagentCatalog, SubagentListEntry, SubagentPromptReceipt, SubagentsApi,
} from './subagents.ts'
export type { WorkspaceApi, WorkspaceId, WorkspaceView } from './workspace.ts'
export type { CommandsApi, CommandDescriptor } from './commands.ts'
export type { SkillsApi, SkillEntry } from './skills.ts'

View File

@@ -13,6 +13,7 @@ import type { GoalsApi } from './goals.ts'
import type { SettingsApi } from './settings.ts'
import type { CredentialsApi } from './credentials.ts'
import type { LlmApi } from './llm.ts'
import type { SubagentsApi } from './subagents.ts'
import type { RpcResponse } from './rpc.ts'
/**
@@ -32,6 +33,9 @@ export interface RpcMethodMap {
'session.prompt': SessionsApi['prompt']
'session.updateQueue': SessionsApi['updateQueue']
'session.cancel': SessionsApi['cancel']
'subagent.list': SubagentsApi['list']
'subagent.history': SubagentsApi['history']
'subagent.prompt': SubagentsApi['prompt']
'host.describe': HostApi['describe']
'host.pickDirectory': HostApi['pickDirectory']
'host.listDirectory': HostApi['listDirectory']

View File

@@ -48,6 +48,7 @@ export const rpcErrorSchema: z.ZodType<RpcError> = z.discriminatedUnion('code',
z.object({ code: z.literal('directory-picker-unavailable'), message: z.string(), details: z.object({ capability: z.string() }) }),
z.object({ code: z.literal('agent-busy'), message: z.string(), details: z.object({ reason: z.string() }) }),
z.object({ code: z.literal('queue-item-not-found'), message: z.string(), details: z.object({ itemId: z.string() }) }),
z.object({ code: z.literal('steer-unavailable'), message: z.string(), details: z.object({ itemId: z.string() }) }),
z.object({ code: z.literal('command-error'), message: z.string(), details: z.object({}) }),
z.object({ code: z.literal('unknown-command'), message: z.string(), details: z.object({}) }),
z.object({ code: z.literal('settings-rejected'), message: z.string(), details: z.object({ ns: z.string() }) }),
@@ -56,6 +57,16 @@ export const rpcErrorSchema: z.ZodType<RpcError> = z.discriminatedUnion('code',
z.object({ code: z.literal('credential-rejected'), message: z.string(), details: z.object({ ref: z.string() }) }),
z.object({ code: z.literal('title-invalid'), message: z.string(), details: z.object({ sessionId: z.string() }) }),
z.object({ code: z.literal('fork-unavailable'), message: z.string(), details: z.object({ sessionId: z.string() }) }),
z.object({ code: z.literal('subagent-parent-unavailable'), message: z.string(), details: z.object({ parentSessionId: z.string() }) }),
z.object({ code: z.literal('subagent-not-found'), message: z.string(), details: z.object({ parentSessionId: z.string(), childSessionId: z.string() }) }),
z.object({ code: z.literal('subagent-catalog-diagnostic'), message: z.string(), details: z.object({
parentSessionId: z.string(),
childSessionId: z.string(),
reason: z.union([z.literal('corrupt'), z.literal('unsupported'), z.literal('unavailable')]),
}) }),
z.object({ code: z.literal('subagent-not-resumable'), message: z.string(), details: z.object({ childSessionId: z.string() }) }),
z.object({ code: z.literal('subagent-unauthorized'), message: z.string(), details: z.object({ childSessionId: z.string() }) }),
z.object({ code: z.literal('subagent-delivery-unavailable'), message: z.string(), details: z.object({ childSessionId: z.string() }) }),
z.object({ code: z.literal('internal'), message: z.string(), details: z.object({}) }),
]) as unknown as z.ZodType<RpcError>

View File

@@ -53,6 +53,7 @@ export const sessionSummarySchema = z.object({
running: z.boolean(),
blank: z.boolean(),
parentSessionId: sessionIdSchema.optional(),
origin: z.literal('subagent').optional(),
cwd: z.string().optional(),
projections: z.lazy(() => sessionProjectionsBlockSchema).optional(),
}) as unknown as z.ZodType<Wire<SessionSummary>>
@@ -194,10 +195,10 @@ export const toolEventViewSchema = z.discriminatedUnion('for', [
]) as unknown as z.ZodType<ToolEventView>
/** One session.history item: the session event plus its optional host-computed tool view. */
export const historyEntrySchema = z.object({
export const historyEntrySchema: z.ZodType<Wire<HistoryEntry>> = z.object({
event: sessionEventSchema,
view: toolEventViewSchema.optional(),
}) satisfies z.ZodType<Wire<HistoryEntry>>
}) as unknown as z.ZodType<Wire<HistoryEntry>>
/**
* Projection baseline passthrough: `values` stays a wide record — each value
@@ -211,11 +212,11 @@ export const sessionProjectionsBlockSchema = z.object({
}) as unknown as z.ZodType<SessionProjectionsBlock>
/** session.history response value (projections rides the tail page only). */
export const sessionHistoryValueSchema = z.object({
export const sessionHistoryValueSchema: z.ZodType<Wire<ResponseValue<'session.history'>>> = z.object({
events: z.array(historyEntrySchema),
hasMore: z.boolean(),
projections: sessionProjectionsBlockSchema.optional(),
}) satisfies z.ZodType<Wire<ResponseValue<'session.history'>>>
})
/** session.models request payload. */
export const sessionModelsRequestSchema = z.object({
@@ -268,6 +269,7 @@ export const sessionUpdateQueueRequestSchema = z.object({
action: z.discriminatedUnion('kind', [
z.object({ kind: z.literal('edit'), content: z.array(contentBlockSchema) }),
z.object({ kind: z.literal('remove') }),
z.object({ kind: z.literal('steer') }),
]),
}) as unknown as z.ZodType<RequestPayload<'session.updateQueue'>>

View File

@@ -129,6 +129,7 @@ export interface SessionModels {
export type QueueAction =
| { kind: 'edit'; content: ContentBlock[] }
| { kind: 'remove' }
| { kind: 'steer' }
/** Session list entry (v1 builds no index: list does readdir+stat). */
export interface SessionSummary {
@@ -153,6 +154,8 @@ export interface SessionSummary {
blank: boolean
/** fork/spawn lineage (session.header.parentSession passthrough); absent for root sessions. */
parentSessionId?: SessionId
/** Coarse durable origin used by navigation surfaces; never proves resumability. */
origin?: 'subagent'
/** Session working directory (header.cwd passthrough); absent when unrecorded. */
cwd?: string
/**
@@ -217,17 +220,22 @@ export interface SessionsApi {
* the client needs a fresh baseline already pulls the tail page, and
* loadOlder (the only beforeSeq path) is the only path that never needs one.
* A deployment without the registry serves histories without the block.
* Reading history uses an attached Session or persistence inspection and
* never resumes or publishes an Agent.
*/
history(request: RpcRequest<{ sessionId: SessionId; beforeSeq?: number; maxMessages?: number }>):
Promise<RpcResponse<{ events: HistoryEntry[]; hasMore: boolean; projections?: SessionProjectionsBlock }>>
/** Reads a fresh advisory model directory for this session. Provider lookups run independently. */
/**
* Reads a fresh advisory model directory for an ordinary session. Provider
* lookups run independently; subagents reject with `agent-busy`.
*/
models(request: RpcRequest<{ sessionId: SessionId }>): Promise<RpcResponse<SessionModels>>
/**
* Selects the complete target for this session. Exact model metadata
* validates an optional reasoning effort, while catalog membership remains
* advisory.
* advisory. Session-backed subagents reject with `agent-busy`.
*/
selectModel(request: RpcRequest<{
sessionId: SessionId
@@ -243,6 +251,7 @@ export interface SessionsApi {
* normalized accepted title and the title event's seq return so the caller
* can settle its projection cell without waiting for the push frame. A
* title that normalizes to empty fails with `title-invalid`.
* Session-backed subagents reject with `agent-busy`.
*/
rename(request: RpcRequest<{ sessionId: SessionId; title: string }>):
Promise<RpcResponse<{ title: string; seq: number }>>
@@ -263,23 +272,31 @@ export interface SessionsApi {
* falls back to the source's last completed turn. An in-log anchor whose
* turn is still open fails with `fork-unavailable` instead of clipping to
* an earlier turn. The child inherits the source cwd, latest logged model
* target, workspace attachment, and `parentSessionId` lineage; the seed
* prefix carries the source title.
* target and `parentSessionId` lineage; the seed prefix carries the source
* title. Reading the source uses attached state or persistence inspection
* without acquiring an Agent. Workspace attachment follows the source
* directly, or the nearest workspace-owning ancestor when the source is a
* subagent.
*/
fork(request: RpcRequest<{ sessionId: SessionId; atSeq?: number }>):
Promise<RpcResponse<{ sessionId: SessionId }>>
/** Sends a message. content is core's ContentBlock[] verbatim; mode maps 1:1 — queue→send, steer→steer. */
/** Sends a message to an ordinary session Agent. Session-backed subagents reject with `agent-busy` and use `subagent.prompt`. */
prompt(request: RpcRequest<{ sessionId: SessionId; mode: 'queue' | 'steer'; content: ContentBlock[] }>):
Promise<RpcResponse<{ accepted: true; command?: { kind: 'success'; text?: string } }>>
/**
* Edits or removes one pending queued occurrence.
* Edits, removes, or strictly steers one pending queued occurrence on an ordinary session.
* Session-backed subagents reject with `agent-busy`.
*/
updateQueue(request: RpcRequest<{ sessionId: SessionId; itemId: MessageId; action: QueueAction }>):
Promise<RpcResponse<{ accepted: true }>>
/** Stops the active turn, preserving pending inbox work that resumes in FIFO order after cancellation settles. */
/**
* Stops an ordinary session's active turn, preserving pending inbox work
* that resumes in FIFO order after cancellation settles. Session-backed
* subagents reject with `agent-busy`.
*/
cancel(request: RpcRequest<{ sessionId: SessionId }>): Promise<RpcResponse<{ accepted: true }>>
}

View File

@@ -0,0 +1,77 @@
/** Zod schemas for the browser-safe subagent domain. */
import { z } from 'zod'
import type { MessageId } from '@deepseek-ai/dsh-llm/brand'
import type { RequestPayload, ResponseValue } from './rpc-map.ts'
import type { Wire } from './rpc.schema.ts'
import {
contentBlockSchema, historyEntrySchema, sessionIdSchema, sessionProjectionsBlockSchema,
} from './sessions.schema.ts'
import type { SubagentListEntry } from './subagents.ts'
/** Healthy and diagnostic durable catalog rows. */
export const subagentListEntrySchema = z.union([
z.object({
kind: z.literal('child'),
id: sessionIdSchema,
mode: z.literal('one-shot'),
activity: z.union([z.literal('running'), z.literal('inactive')]),
hasChildren: z.boolean(),
label: z.string().optional(),
}),
z.object({
kind: z.literal('child'),
id: sessionIdSchema,
mode: z.literal('continuable'),
activity: z.union([z.literal('running'), z.literal('inactive')]),
hasChildren: z.boolean(),
label: z.string(),
}),
z.object({
kind: z.literal('diagnostic'),
id: sessionIdSchema,
reason: z.union([z.literal('corrupt'), z.literal('unsupported'), z.literal('unavailable')]),
}),
]) satisfies z.ZodType<Wire<SubagentListEntry>>
/** subagent.list request payload. */
export const subagentListRequestSchema = z.object({
parentSessionId: sessionIdSchema,
}) satisfies z.ZodType<Wire<RequestPayload<'subagent.list'>>>
/** subagent.list response value. */
export const subagentListValueSchema = z.object({
entries: z.array(subagentListEntrySchema),
parentAvailable: z.boolean(),
}) satisfies z.ZodType<Wire<ResponseValue<'subagent.list'>>>
/** subagent.history request payload. */
export const subagentHistoryRequestSchema = z.object({
parentSessionId: sessionIdSchema,
childSessionId: sessionIdSchema,
mode: z.union([z.literal('one-shot'), z.literal('continuable')]),
beforeSeq: z.number().int().nonnegative().optional(),
maxMessages: z.number().int().positive().optional(),
}) satisfies z.ZodType<Wire<RequestPayload<'subagent.history'>>>
/** subagent.history response value. */
export const subagentHistoryValueSchema = z.object({
events: z.array(historyEntrySchema),
hasMore: z.boolean(),
projections: sessionProjectionsBlockSchema.optional(),
}) as unknown as z.ZodType<Wire<ResponseValue<'subagent.history'>>>
/** subagent.prompt request payload. */
export const subagentPromptRequestSchema = z.object({
parentSessionId: sessionIdSchema,
childSessionId: sessionIdSchema,
mode: z.literal('continuable'),
content: z.array(contentBlockSchema),
}) as unknown as z.ZodType<RequestPayload<'subagent.prompt'>>
const messageIdSchema = z.string() as unknown as z.ZodType<MessageId>
/** subagent.prompt response value. */
export const subagentPromptValueSchema = z.object({
messageId: messageIdSchema,
}) satisfies z.ZodType<Wire<ResponseValue<'subagent.prompt'>>>

View File

@@ -0,0 +1,96 @@
/**
* Browser-safe subagent domain contract. Persisted transcript reads never
* activate an Agent, while continuable prompts route through the exact live
* direct parent into the child's Agent inbox.
*/
import type { MessageId } from '@deepseek-ai/dsh-llm/brand'
import type { ContentBlock } from '@deepseek-ai/dsh-llm/types'
import type { SessionId } from '@deepseek-ai/dsh-session/types'
import type { RpcRequest, RpcResponse } from './rpc.ts'
import type { HistoryEntry, SessionProjectionsBlock } from './sessions.ts'
/** Complete durable direct-child catalog row. */
export type SubagentListEntry =
| {
kind: 'child'
id: SessionId
/** Whether the child Agent driver is running at the Host sampling boundary. */
activity: 'running' | 'inactive'
/** Whether a direct descendant has durable `origin: 'subagent'`. */
hasChildren: boolean
} & (
| {
mode: 'one-shot'
label?: string
}
| {
mode: 'continuable'
label: string
}
)
| {
kind: 'diagnostic'
id: SessionId
reason: 'corrupt' | 'unsupported' | 'unavailable'
}
/** Inbox identity returned once the continuation accepts one human message. */
export interface SubagentPromptReceipt {
messageId: MessageId
}
/** Durable parent/child address that selects subagent transport in the client. */
export type SubagentAddress =
& {
parentSessionId: SessionId
childSessionId: SessionId
}
& (
| { mode: 'one-shot' }
| { mode: 'continuable' }
)
/** Complete direct-child catalog plus the delivery-time parent availability hint. */
export interface SubagentCatalog {
entries: SubagentListEntry[]
parentAvailable: boolean
}
/** Subagent-domain unary methods. */
export interface SubagentsApi {
/**
* Lists direct session-backed children without loading either side. Parent
* availability is a hint; continuable prompt performs the authoritative
* check.
*/
list(
request: RpcRequest<{ parentSessionId: SessionId }>,
signal?: AbortSignal,
): Promise<RpcResponse<SubagentCatalog>>
/**
* Reads one healthy catalog child's persisted raw log with ordinary
* message-aligned pagination and render intents, without Agent activation.
*/
history(
request: RpcRequest<SubagentAddress & { beforeSeq?: number; maxMessages?: number }>,
signal?: AbortSignal,
): Promise<RpcResponse<{
events: HistoryEntry[]
hasMore: boolean
projections?: SessionProjectionsBlock
}>>
/**
* Delivers human content to a continuable child through the exact live
* parent's continuation owner. Success identifies the message accepted by
* the child's FIFO inbox; later execution is independent of this request.
*/
prompt(
request: RpcRequest<
Extract<SubagentAddress, { mode: 'continuable' }> & { content: ContentBlock[] }
>,
signal: AbortSignal,
): Promise<RpcResponse<SubagentPromptReceipt>>
}