@agentproto/runtime 4.0.0 → 4.1.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 +1 -0
- package/dist/app-ui-build.d.ts +96 -0
- package/dist/app-ui-build.mjs +250 -0
- package/dist/app-ui-build.mjs.map +1 -0
- package/dist/app-ui-placeholder.d.ts +73 -0
- package/dist/app-ui-placeholder.mjs +89 -0
- package/dist/app-ui-placeholder.mjs.map +1 -0
- package/dist/config-schema.mjs +93 -83
- package/dist/config-schema.mjs.map +1 -1
- package/dist/config.d.ts +12 -0
- package/dist/config.mjs +93 -83
- package/dist/config.mjs.map +1 -1
- package/dist/index.d.ts +867 -37
- package/dist/index.mjs +2885 -646
- package/dist/index.mjs.map +1 -1
- package/dist/resume-strategies.mjs +7 -0
- package/dist/resume-strategies.mjs.map +1 -1
- package/dist/session-presence.mjs +93 -83
- package/dist/session-presence.mjs.map +1 -1
- package/docs/TRANSMITTER.md +356 -0
- package/docs/mcp-tools/agent_start.md +476 -0
- package/docs/mcp-tools/app_run.md +47 -0
- package/package.json +26 -15
package/dist/config.d.ts
CHANGED
|
@@ -70,6 +70,18 @@ interface DaemonConfig {
|
|
|
70
70
|
* `agentproto config set daemon.resumeSessionsOnBoot true`. Surfaced in
|
|
71
71
|
* `daemon_health` / `GET /health`. */
|
|
72
72
|
resumeSessionsOnBoot?: boolean;
|
|
73
|
+
/** Opt-in continue-on-boot (continue-interrupted). When true, right after
|
|
74
|
+
* the eager resume pass, the boot sends a "the daemon restarted mid-turn,
|
|
75
|
+
* check the state on disk and continue" prompt to every session the LAST
|
|
76
|
+
* restart interrupted mid-turn (`interrupted: true`) that is resumable,
|
|
77
|
+
* under the resume cap, idle, and whose resume didn't fail. Never loops: at
|
|
78
|
+
* most one auto-continue per restart and `MAX_AUTO_CONTINUE_ATTEMPTS` in a
|
|
79
|
+
* row without a successful turn-end. Default false — the interrupted prompt
|
|
80
|
+
* itself is never auto-retried, and a continue prompt is still a prompt
|
|
81
|
+
* (tokens, side effects), so it's opt-in. The manual
|
|
82
|
+
* `session_continue_interrupted` verb works regardless. Set via
|
|
83
|
+
* `agentproto config set daemon.continueInterruptedOnBoot true`. */
|
|
84
|
+
continueInterruptedOnBoot?: boolean;
|
|
73
85
|
/** Idle agent-session reaper (PR-6). When set to a positive number of
|
|
74
86
|
* milliseconds, the daemon periodically retires agent-cli sessions that have
|
|
75
87
|
* been idle (not busy, not awaiting input, `status:"running"`) longer than
|
package/dist/config.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createHash } from 'crypto';
|
|
2
2
|
import { join, resolve, dirname } from 'path';
|
|
3
|
+
import '@agentproto/model-catalog/llm';
|
|
3
4
|
import { createReadStream, promises } from 'fs';
|
|
4
5
|
import { homedir } from 'os';
|
|
5
6
|
import { createInterface } from 'readline';
|
|
6
7
|
import 'fs/promises';
|
|
7
8
|
import * as providers_store_star from '@agentproto/providers-store';
|
|
8
|
-
import '@agentproto/model-catalog/llm';
|
|
9
9
|
import '@agentproto/model-catalog/route-identity';
|
|
10
10
|
import '@agentproto/provider-presets';
|
|
11
11
|
import '@agentproto/secrets/provision/recipe';
|
|
@@ -179,6 +179,10 @@ var init_tool_call_record = __esm({
|
|
|
179
179
|
"src/tool-call-record.ts"() {
|
|
180
180
|
}
|
|
181
181
|
});
|
|
182
|
+
var init_usage = __esm({
|
|
183
|
+
"src/usage.ts"() {
|
|
184
|
+
}
|
|
185
|
+
});
|
|
182
186
|
function defaultTranscriptBaseDir() {
|
|
183
187
|
return join(homedir(), ".agentproto", "sessions");
|
|
184
188
|
}
|
|
@@ -192,6 +196,7 @@ var init_transcript_writer = __esm({
|
|
|
192
196
|
"src/transcript-writer.ts"() {
|
|
193
197
|
init_tool_call_record();
|
|
194
198
|
init_pr_provenance();
|
|
199
|
+
init_usage();
|
|
195
200
|
}
|
|
196
201
|
});
|
|
197
202
|
|
|
@@ -588,11 +593,11 @@ async function discoverHermesSessions(cwd, since, expectedId) {
|
|
|
588
593
|
}
|
|
589
594
|
}
|
|
590
595
|
async function defaultHermesRunner(adapterSessionId) {
|
|
591
|
-
const { spawn:
|
|
596
|
+
const { spawn: spawn5 } = await import('child_process');
|
|
592
597
|
return new Promise((resolve16, reject) => {
|
|
593
598
|
const chunks = [];
|
|
594
599
|
const errChunks = [];
|
|
595
|
-
const proc =
|
|
600
|
+
const proc = spawn5(
|
|
596
601
|
"hermes",
|
|
597
602
|
["sessions", "export", "--session-id", adapterSessionId, "-"],
|
|
598
603
|
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
@@ -2199,7 +2204,7 @@ var init_sandbox_spec_schema = __esm({
|
|
|
2199
2204
|
}).strict();
|
|
2200
2205
|
}
|
|
2201
2206
|
});
|
|
2202
|
-
var commandSandboxSchema, attachFieldSchema, contextContinuityInputSchema;
|
|
2207
|
+
var commandSandboxSchema, attachFieldSchema, contentBlockSchema, promptInputSchema, contextContinuityInputSchema;
|
|
2203
2208
|
var init_spawn_field_schemas = __esm({
|
|
2204
2209
|
"src/spawn-field-schemas.ts"() {
|
|
2205
2210
|
commandSandboxSchema = z.enum(["off", "workspace", "strict"]);
|
|
@@ -2207,6 +2212,12 @@ var init_spawn_field_schemas = __esm({
|
|
|
2207
2212
|
z.boolean(),
|
|
2208
2213
|
z.object({ parent: z.string().min(1).optional() })
|
|
2209
2214
|
]);
|
|
2215
|
+
contentBlockSchema = z.record(z.string(), z.unknown());
|
|
2216
|
+
promptInputSchema = z.union([
|
|
2217
|
+
z.string().min(1),
|
|
2218
|
+
contentBlockSchema,
|
|
2219
|
+
z.array(contentBlockSchema).min(1)
|
|
2220
|
+
]);
|
|
2210
2221
|
contextContinuityInputSchema = z.object({
|
|
2211
2222
|
mode: z.enum(["manual", "ask", "auto"]).optional(),
|
|
2212
2223
|
warnAtPct: z.number().int().min(0).max(100).optional(),
|
|
@@ -2227,7 +2238,7 @@ var init_spawn_field_schemas = __esm({
|
|
|
2227
2238
|
});
|
|
2228
2239
|
}
|
|
2229
2240
|
});
|
|
2230
|
-
var mcpBool, mcpPositiveNumber, agentStartInputShape, agentStartInputSchema;
|
|
2241
|
+
var mcpBool, mcpPositiveNumber, help, agentStartInputShape, agentStartInputSchema;
|
|
2231
2242
|
var init_agent_start_schema = __esm({
|
|
2232
2243
|
"src/agent-start-schema.ts"() {
|
|
2233
2244
|
init_json_tolerant();
|
|
@@ -2241,78 +2252,73 @@ var init_agent_start_schema = __esm({
|
|
|
2241
2252
|
(v) => typeof v === "string" && v.trim() !== "" ? Number(v) : v,
|
|
2242
2253
|
z.number().positive()
|
|
2243
2254
|
);
|
|
2255
|
+
help = (field) => `Details: tool_help {name:"agent_start", topic:"${field}"}`;
|
|
2244
2256
|
agentStartInputShape = {
|
|
2245
2257
|
adapter: z.string().min(1).optional().describe(
|
|
2246
|
-
|
|
2247
|
-
),
|
|
2248
|
-
harness: z.string().min(1).optional().describe(
|
|
2249
|
-
"Canonical harness slug \u2014 alias for `adapter`. Accepts the same values; use whichever field your caller produces."
|
|
2258
|
+
`Adapter slug (e.g. 'claude-code', 'hermes', 'aider'). Omit only when \`presetId\` supplies one. ${help("adapter")}`
|
|
2250
2259
|
),
|
|
2260
|
+
harness: z.string().min(1).optional().describe(`Alias for \`adapter\` \u2014 same values, whichever your caller produces.`),
|
|
2251
2261
|
presetId: z.string().min(1).optional().describe(
|
|
2252
|
-
"Saved
|
|
2262
|
+
"Saved spawn preset id from `agentproto preset list`. Explicit fields on this call override its values."
|
|
2253
2263
|
),
|
|
2254
2264
|
workspaceSlug: z.string().optional().describe(
|
|
2255
|
-
"Workspace slug from `agentproto workspace list
|
|
2265
|
+
"Workspace slug from `agentproto workspace list`, resolved to a path. Omit to use `cwd` or the active workspace."
|
|
2256
2266
|
),
|
|
2257
|
-
cwd: z.string().optional().describe(
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
prompt: z.string().optional().describe(
|
|
2261
|
-
"Optional initial prompt. The session is spawned and the prompt dispatched in one shot \u2014 equivalent to `start` then `prompt` back-to-back. Skip to spawn idle."
|
|
2262
|
-
),
|
|
2263
|
-
label: z.string().optional().describe(
|
|
2264
|
-
"Free-text label that surfaces in `agent_sessions_list` and the UI \u2014 useful for tagging sessions with a conversation id or operator name."
|
|
2267
|
+
cwd: z.string().optional().describe("Absolute path to spawn the agent in. Wins over `workspaceSlug` when both are set."),
|
|
2268
|
+
prompt: promptInputSchema.optional().describe(
|
|
2269
|
+
'Optional initial prompt \u2014 spawns and dispatches it in one call (spawn + `agent_prompt` combined). Omit to spawn idle. A plain string is composed with the role/AGENTS.md disposition preamble as usual; a content block or block array (e.g. a pasted image, `{type:"image", data, mimeType}`) SKIPS that composition and is sent to the adapter verbatim \u2014 the adapter negotiates its own multimodal support. ' + help("prompt")
|
|
2265
2270
|
),
|
|
2271
|
+
label: z.string().optional().describe("Free-text label shown in `agent_sessions_list` and the UI."),
|
|
2266
2272
|
mode: z.string().optional().describe(
|
|
2267
|
-
|
|
2273
|
+
`Manifest-declared mode id (AIP-45 \`modes\`), applied before the child starts (e.g. claude-code's 'plan'/'accept-edits'/'bypass-permissions'). Adapters with no declared \`modes\` REJECT any value here. ${help("mode")}`
|
|
2268
2274
|
),
|
|
2269
2275
|
origin: z.string().min(1).optional().describe(
|
|
2270
|
-
"Source label for this spawn
|
|
2276
|
+
"Source label for this spawn (codex, cowork, vscode, cron, \u2026) \u2014 descriptor-only, groups the session under a source node in the tree."
|
|
2271
2277
|
),
|
|
2272
2278
|
parentSessionId: z.string().min(1).optional().describe(
|
|
2273
|
-
|
|
2279
|
+
`Parent-lineage hint: nests this spawn under that session in the tree instead of a depth-0 root. Ignored through the scoped orchestrator gateway (its own token wins). ${help("parentSessionId")}`
|
|
2274
2280
|
),
|
|
2275
2281
|
attach: jsonTolerant(attachFieldSchema).optional().describe(
|
|
2276
|
-
|
|
2282
|
+
`Parent-attach override, mirrors \`worktree\`. Default attaches under the calling session; \`false\` = independent root; \`true\` forces attach; \`{ parent: "<id>" }\` pins an explicit parent. ${help("attach")}`
|
|
2277
2283
|
),
|
|
2278
2284
|
boardId: z.string().min(1).optional().describe(
|
|
2279
|
-
|
|
2285
|
+
`Task-board pin for the child (\`meta.boardId\`), resolved before parent-lineage. An explicit board on a task verb still wins. ${help("boardId")}`
|
|
2280
2286
|
),
|
|
2281
2287
|
idempotencyKey: z.string().min(1).optional().describe(
|
|
2282
|
-
|
|
2288
|
+
`Caller-declared dedup token: a retried call with the SAME key for the same \`adapter\`+\`cwd\` within ~10min of a successful spawn returns that SAME session (\`deduped: true\`) instead of forking a new one. Always wins over the implicit key \`dedupe\` derives. ${help("idempotencyKey")}`
|
|
2283
2289
|
),
|
|
2284
2290
|
dedupe: mcpBool.optional().describe(
|
|
2285
|
-
|
|
2291
|
+
`Override the implicit dedup-by-\`label\` default (on when no \`idempotencyKey\` is given): \`false\` opts this spawn out, \`true\` forces it even under an "on-request" daemon policy. ${help("dedupe")}`
|
|
2286
2292
|
),
|
|
2287
2293
|
permissionHold: mcpBool.optional().describe(
|
|
2288
|
-
"
|
|
2294
|
+
"Hold every ACP permission request in the cross-session inbox (`permissions_list`/`permissions_respond`) instead of auto-answering. ACP adapters only; default false."
|
|
2289
2295
|
),
|
|
2290
2296
|
notifyParentOnCrash: mcpBool.optional().describe(
|
|
2291
|
-
|
|
2297
|
+
`Notify this session's parent directly (in-band) if it later crashes. Independent of the global \`notifyUrl\` webhook, which fires either way. ${help("notifyParentOnCrash")}`
|
|
2292
2298
|
),
|
|
2293
2299
|
allowSharedCwd: mcpBool.optional().describe(
|
|
2294
|
-
"Acknowledge
|
|
2300
|
+
"Acknowledge running a nested spawn in the parent's dirty working tree, silencing the shared-dirty-cwd warning. Only relevant with no `worktree`/`sandbox`; default false = warn."
|
|
2295
2301
|
),
|
|
2296
2302
|
keepAlive: mcpBool.optional().describe(
|
|
2297
|
-
"Exempt this session from the idle-reaper
|
|
2303
|
+
"Exempt this session from the idle-reaper \u2014 never auto-retired for sitting idle. Default false. Toggle later with `session_set_keepalive`."
|
|
2298
2304
|
),
|
|
2299
2305
|
options: jsonTolerant(
|
|
2300
2306
|
z.record(z.string(), z.union([z.boolean(), z.number(), z.string()]))
|
|
2301
2307
|
).optional().describe(
|
|
2302
|
-
"Manifest-declared option id \u2192 value map (AIP-45 `options`),
|
|
2308
|
+
"Manifest-declared option id \u2192 value map (AIP-45 `options`), validated against each option's declared type/enum/min/max. Unknown ids reject."
|
|
2303
2309
|
),
|
|
2304
2310
|
skills: jsonTolerant(z.array(z.string())).optional().describe(
|
|
2305
|
-
|
|
2311
|
+
`Normalized skill ids for this session (e.g. ['agentproto']). REPLACES (not unions) config defaults when set. Adapters with no \`skills\` option (e.g. claude-code) ignore it. ${help("skills")}`
|
|
2306
2312
|
),
|
|
2307
2313
|
model: z.string().optional().describe(
|
|
2308
|
-
"Model identifier to pass to the adapter
|
|
2314
|
+
"Model identifier to pass to the adapter. For claude-code, applied via session/set_config_option \u2014 NOT a CLI flag."
|
|
2309
2315
|
),
|
|
2310
2316
|
effort: z.string().optional().describe(
|
|
2311
|
-
"Reasoning effort
|
|
2317
|
+
"Reasoning effort label ('low'/'medium'/'high'/'xhigh'/'max'/'ultracode'). Calibrated PER MODEL \u2014 the same label means different compute budgets across models. Omit to keep the model's own default."
|
|
2312
2318
|
),
|
|
2313
2319
|
route: jsonTolerant(
|
|
2314
2320
|
z.object({ gateway: z.string().min(1), baseUrl: z.string().url().optional() })
|
|
2315
|
-
).optional().describe("Billing route/gateway.
|
|
2321
|
+
).optional().describe("Billing route/gateway. Independent of `model` and `access`."),
|
|
2316
2322
|
access: jsonTolerant(z.object({ profileRef: z.string().min(1).optional() })).optional().describe("Named auth profile to bill at initial spawn; resolved from the local keychain."),
|
|
2317
2323
|
posture: z.string().optional().describe("Canonical agent posture (plan, bypass, accept-edits, read-only) or native harness mode."),
|
|
2318
2324
|
contextProfile: z.string().optional().describe("Context intake profile (for example full or lean)."),
|
|
@@ -2324,7 +2330,7 @@ var init_agent_start_schema = __esm({
|
|
|
2324
2330
|
apiKey: z.string().optional()
|
|
2325
2331
|
})
|
|
2326
2332
|
).optional().describe(
|
|
2327
|
-
|
|
2333
|
+
`Explicit billing-auth mode + credential for adapters that declare it (today: claude-code) \u2014 'subscription' (default) bills the Max/Pro plan, 'api-key' bills API credits. FAILS FAST with no fallback if the resolved mode has no credential configured anywhere. ${help("auth")}`
|
|
2328
2334
|
),
|
|
2329
2335
|
mcpServers: jsonTolerant(
|
|
2330
2336
|
z.array(
|
|
@@ -2332,42 +2338,34 @@ var init_agent_start_schema = __esm({
|
|
|
2332
2338
|
name: z.string(),
|
|
2333
2339
|
transport: z.enum(["stdio", "http", "sse"]),
|
|
2334
2340
|
ref: z.string().optional(),
|
|
2335
|
-
headers: z.record(z.string(), z.string()).optional().describe(
|
|
2336
|
-
"Static HTTP headers sent with every request to an `http` or `sse` MCP server (e.g. a fixed auth token). Ignored for `stdio` transports."
|
|
2337
|
-
),
|
|
2341
|
+
headers: z.record(z.string(), z.string()).optional().describe("Static HTTP headers for `http`/`sse` transports. Ignored for `stdio`."),
|
|
2338
2342
|
credentialRef: z.string().optional().describe(
|
|
2339
|
-
"Brokered credential
|
|
2343
|
+
"Brokered credential resolved into `headers` at spawn time (wins on collision with `headers`); the secret never lives in env/config."
|
|
2340
2344
|
),
|
|
2341
|
-
args: z.array(z.string()).optional().describe("`stdio` only: argv passed to the `ref` command.
|
|
2342
|
-
env: z.record(z.string(), z.string()).optional().describe("`stdio` only: extra environment for the launched server.
|
|
2345
|
+
args: z.array(z.string()).optional().describe("`stdio` only: argv passed to the `ref` command."),
|
|
2346
|
+
env: z.record(z.string(), z.string()).optional().describe("`stdio` only: extra environment for the launched server.")
|
|
2343
2347
|
})
|
|
2344
2348
|
)
|
|
2345
2349
|
).optional().describe(
|
|
2346
|
-
"MCP servers to mount into the spawned agent's session at spawn time.
|
|
2350
|
+
"MCP servers to mount into the spawned agent's session at spawn time. Adapters that don't model MCP mounting ignore it."
|
|
2347
2351
|
),
|
|
2348
2352
|
orchestrator: jsonTolerant(
|
|
2349
2353
|
z.union([
|
|
2350
2354
|
z.boolean(),
|
|
2351
2355
|
z.object({
|
|
2352
|
-
tools: z.array(z.string()).optional().describe(
|
|
2353
|
-
|
|
2354
|
-
),
|
|
2355
|
-
maxDepth: z.number().int().min(1).max(8).optional().describe(
|
|
2356
|
-
"Max recursion depth reachable through this child (default 3, hard ceiling 8). A spawn that would exceed it is rejected. For a recursive spawn it can only LOWER the inherited cap, never raise it."
|
|
2357
|
-
),
|
|
2358
|
-
maxChildren: z.number().int().min(1).optional().describe(
|
|
2359
|
-
"Max concurrently-alive sub-agents this child may spawn (default 8). For a recursive spawn it can only lower the inherited quota."
|
|
2360
|
-
)
|
|
2356
|
+
tools: z.array(z.string()).optional().describe("Explicit allowlist \u2286 the default subset \u2014 a child can never widen its own scope."),
|
|
2357
|
+
maxDepth: z.number().int().min(1).max(8).optional().describe("Max recursion depth reachable through this child (default 3, ceiling 8, lower-only on recursion)."),
|
|
2358
|
+
maxChildren: z.number().int().min(1).optional().describe("Max concurrently-alive sub-agents this child may spawn (default 8, lower-only on recursion).")
|
|
2361
2359
|
})
|
|
2362
2360
|
])
|
|
2363
2361
|
).optional().describe(
|
|
2364
|
-
|
|
2362
|
+
`Make this child a SCOPED orchestrator \u2014 auto-mounts the daemon's own spawn/supervise tools, scoped to its own sub-agents. \`true\` = default subset; \`{ tools }\` narrows it. Shell/fs/remote tools are NEVER exposed. ${help("orchestrator")}`
|
|
2365
2363
|
),
|
|
2366
2364
|
notifyUrl: z.string().url().optional().describe(
|
|
2367
2365
|
"Optional per-session webhook URL. POSTed (fire-and-forget) on this session's turn-end / awaiting-input / exited events, in addition to any global notify URL."
|
|
2368
2366
|
),
|
|
2369
2367
|
wait: mcpBool.optional().describe(
|
|
2370
|
-
|
|
2368
|
+
`Block until the spawned session's first turn completes (~40-90s+) and include its output. Default false = return immediately. Batched \`wait:true\` calls do NOT run in parallel \u2014 see \`tool_help {name:"agent_start", topic:"wait"}\` for the fan-out pattern.`
|
|
2371
2369
|
),
|
|
2372
2370
|
maxCostUsd: mcpPositiveNumber.optional().describe(
|
|
2373
2371
|
"Hard ceiling on cumulative session cost (USD). The session is stopped at a turn-end once exceeded."
|
|
@@ -2379,45 +2377,39 @@ var init_agent_start_schema = __esm({
|
|
|
2379
2377
|
scope: z.enum(["session", "profile"]).describe("Spend surface: this session, or every session on its auth profile.")
|
|
2380
2378
|
})
|
|
2381
2379
|
).optional().describe(
|
|
2382
|
-
"Windowed cost-budget cap (DISTINCT from `maxCostUsd`)
|
|
2380
|
+
"Windowed cost-budget cap (DISTINCT from `maxCostUsd`) \u2014 trips `policy:failed` on overage, never kills the session."
|
|
2383
2381
|
),
|
|
2384
2382
|
restartPolicy: jsonTolerant(
|
|
2385
2383
|
z.object({
|
|
2386
|
-
on: z.array(z.enum(["crashed", "error"])).min(1).describe(
|
|
2387
|
-
|
|
2388
|
-
),
|
|
2389
|
-
maxRetries: z.number().int().positive().describe(
|
|
2390
|
-
"Rolling-window crash-loop cap: give up (leave the session dead, no further auto-restart) once this many restarts have fired within `windowMs`."
|
|
2391
|
-
),
|
|
2384
|
+
on: z.array(z.enum(["crashed", "error"])).min(1).describe("Which automatic death reasons trigger a restart. Never a clean exit, kill, idle-reap, or cost-budget kill."),
|
|
2385
|
+
maxRetries: z.number().int().positive().describe("Rolling-window crash-loop cap: give up after this many restarts within `windowMs`."),
|
|
2392
2386
|
windowMs: z.number().int().positive().describe("Rolling window (ms) `maxRetries` counts restarts over."),
|
|
2393
2387
|
baseDelayMs: z.number().int().positive().describe("First restart's backoff delay (ms), before `factor` compounds it."),
|
|
2394
2388
|
factor: z.number().positive().describe("Exponential backoff multiplier applied per consecutive restart."),
|
|
2395
2389
|
maxDelayMs: z.number().int().positive().describe("Backoff ceiling (ms) \u2014 the computed delay never grows past this."),
|
|
2396
|
-
resume: z.boolean().optional().describe(
|
|
2397
|
-
"Reserved for a future explicit resume-vs-fresh-spawn toggle; this PR always revives in place (same session id, same conversation)."
|
|
2398
|
-
)
|
|
2390
|
+
resume: z.boolean().optional().describe("Reserved for a future resume-vs-fresh-spawn toggle; this always revives in place today.")
|
|
2399
2391
|
})
|
|
2400
2392
|
).optional().describe(
|
|
2401
|
-
|
|
2393
|
+
`Opt-in auto-restart policy: an unexpected death (\`crashed\`/\`error\`, per \`on\`) is revived IN PLACE after exponential backoff, up to a rolling-window crash-loop cap. Omit for today's stay-dead behaviour. ${help("restartPolicy")}`
|
|
2402
2394
|
),
|
|
2403
2395
|
contextContinuity: jsonTolerant(contextContinuityInputSchema).optional().describe(
|
|
2404
2396
|
"Context-continuity policy for this session \u2014 controls warning, opportunistic compaction, fresh-continuation, and hard-stop thresholds. Resolved from global \u2192 per-adapter \u2192 explicit override."
|
|
2405
2397
|
),
|
|
2406
2398
|
role: z.string().optional().describe(
|
|
2407
|
-
|
|
2399
|
+
`Spawn-time delegation gate. 'executor' = leaf, cannot delegate (\`agent_start\`/\`agent_prompt\` stripped). 'supervisor' = may delegate (default). Custom role packs resolve the same way. Omit to derive from spawn depth. ${help("role")}`
|
|
2408
2400
|
),
|
|
2409
2401
|
promptAppend: z.string().optional().describe(
|
|
2410
|
-
"One-off runtime text layered
|
|
2402
|
+
"One-off runtime text layered onto the resolved role's disposition and prepended to `prompt` \u2014 specializes it, cannot reopen a denied tool gate."
|
|
2411
2403
|
),
|
|
2412
2404
|
deferredTools: z.boolean().optional().describe(
|
|
2413
|
-
|
|
2405
|
+
`Override lazy MCP tool loading for this spawn: \`true\` hides most tools from \`tools/list\` (still callable via \`tool_search\`), \`false\` keeps the full eager surface. Omit to use the role/daemon default. ${help("deferredTools")}`
|
|
2414
2406
|
),
|
|
2415
2407
|
browser: z.preprocess(
|
|
2416
2408
|
// `true` is sugar for the only mode; stringified booleans tolerated.
|
|
2417
2409
|
(v) => v === true || v === "true" ? "headless" : v === "false" ? false : v,
|
|
2418
2410
|
z.union([z.literal("headless"), z.literal(false)])
|
|
2419
2411
|
).optional().describe(
|
|
2420
|
-
|
|
2412
|
+
`\`"headless"\` gives the spawned agent its own isolated headless Chrome as a per-session \`browser\` MCP server, torn down with the session. \`false\` = none (default). Not supported with \`sandbox\`. ${help("browser")}`
|
|
2421
2413
|
),
|
|
2422
2414
|
trace: z.boolean().optional().describe(
|
|
2423
2415
|
"Emit Langfuse observability traces for this session (prompt/completion + tool spans + tokens/cost). Off by default; requires langfuse eval-reporter creds configured."
|
|
@@ -2426,22 +2418,22 @@ var init_agent_start_schema = __esm({
|
|
|
2426
2418
|
z.union([
|
|
2427
2419
|
z.string().min(1).describe("Sandbox provider slug from `list_sandbox_providers` (e.g. 'local', 'e2b')."),
|
|
2428
2420
|
sandboxSpecWithReuseSchema.describe(
|
|
2429
|
-
"Inline AIP-36 SandboxDefinition \u2014 boots this exact spec instead of a catalog slug. Set `reuse`
|
|
2421
|
+
"Inline AIP-36 SandboxDefinition \u2014 boots this exact spec instead of a catalog slug. Set `reuse` to reconnect to an existing sandbox instead of booting fresh."
|
|
2430
2422
|
)
|
|
2431
2423
|
])
|
|
2432
2424
|
).optional().describe(
|
|
2433
|
-
|
|
2425
|
+
`Run this session inside a sandbox instead of on the host (provider slug or inline AIP-36 spec) \u2014 the daemon boots the box, spawns \`adapter\` on its own agentproto daemon, and proxies the conversation back here. DISTINCT from \`commandSandbox\` (whole separate machine vs. confining this host's own process). Omit to run locally. ${help("sandbox")}`
|
|
2434
2426
|
),
|
|
2435
2427
|
appServe: jsonTolerant(
|
|
2436
2428
|
z.object({
|
|
2437
2429
|
dir: z.string().min(1).describe("Absolute path to the app's directory INSIDE the sandbox box (e.g. '/home/user/apps/<slug>')."),
|
|
2438
|
-
port: z.number().int().min(1).max(65535).optional().describe("Port the UI binds inside the box (default 3210).
|
|
2430
|
+
port: z.number().int().min(1).max(65535).optional().describe("Port the UI binds inside the box (default 3210). Exposed by the sandbox provider as a public URL.")
|
|
2439
2431
|
}).strict()
|
|
2440
2432
|
).optional().describe(
|
|
2441
|
-
|
|
2433
|
+
`Serve an agentproto app's UI from INSIDE the sandbox box and return its public URL. Requires \`sandbox\` (rejected otherwise). ${help("appServe")}`
|
|
2442
2434
|
),
|
|
2443
2435
|
commandSandbox: commandSandboxSchema.optional().describe(
|
|
2444
|
-
|
|
2436
|
+
`OS-level confinement (macOS Seatbelt / Linux bubblewrap) of the adapter's OWN process on THIS host \u2014 NOT \`sandbox\` above, which boots a separate machine. \`"off"\` (default) = unconfined; \`"workspace"\` = deny reads/writes outside cwd; \`"strict"\` = + deny network. Fails the spawn if the OS backend isn't installed. ${help("commandSandbox")}`
|
|
2445
2437
|
),
|
|
2446
2438
|
worktree: jsonTolerant(
|
|
2447
2439
|
z.union([
|
|
@@ -2450,17 +2442,15 @@ var init_agent_start_schema = __esm({
|
|
|
2450
2442
|
slug: z.string().regex(
|
|
2451
2443
|
/^[a-z0-9][a-z0-9-]*$/,
|
|
2452
2444
|
"slug must be lowercase kebab-case (letters, digits, hyphens)"
|
|
2453
|
-
).optional().describe(
|
|
2454
|
-
"Pin the worktree's slug (names its branch `wt/<slug>` and its directory). Omit to auto-mint a collision-free one from the label."
|
|
2455
|
-
),
|
|
2445
|
+
).optional().describe("Pin the worktree's slug (branch `wt/<slug>`). Omit to auto-mint one from the label."),
|
|
2456
2446
|
base: z.string().min(1).optional().describe("Git ref the worktree branch is cut from. Default 'origin/main'."),
|
|
2457
2447
|
async: z.boolean().optional().describe(
|
|
2458
|
-
|
|
2448
|
+
`Return a registered session immediately (status "starting") instead of blocking on provisioning; incompatible with \`wait\`. Defaults true whenever a worktree is provisioned. ${help("worktree")}`
|
|
2459
2449
|
)
|
|
2460
2450
|
}).strict()
|
|
2461
2451
|
])
|
|
2462
2452
|
).optional().describe(
|
|
2463
|
-
|
|
2453
|
+
`Isolate this session in its OWN git worktree instead of \`cwd\`. \`true\` provisions one on a fresh \`wt/<slug>\` branch; \`{ slug, base, async }\` pins details. ROOT spawns only (rejected on a nested spawn \u2014 use \`sandbox\` there); ignored when \`cwd\` isn't a git repo. NOT auto-removed on session close \u2014 tear down with \`agentproto worktree rm\`. ${help("worktree")}`
|
|
2464
2454
|
)
|
|
2465
2455
|
};
|
|
2466
2456
|
agentStartInputSchema = z.object(agentStartInputShape);
|
|
@@ -2504,8 +2494,20 @@ var init_catalog_provider_models = __esm({
|
|
|
2504
2494
|
"src/catalog-provider-models.ts"() {
|
|
2505
2495
|
}
|
|
2506
2496
|
});
|
|
2497
|
+
var init_app_ui_build = __esm({
|
|
2498
|
+
"src/app-ui-build.ts"() {
|
|
2499
|
+
}
|
|
2500
|
+
});
|
|
2501
|
+
|
|
2502
|
+
// src/app-ui-placeholder.ts
|
|
2503
|
+
var init_app_ui_placeholder = __esm({
|
|
2504
|
+
"src/app-ui-placeholder.ts"() {
|
|
2505
|
+
}
|
|
2506
|
+
});
|
|
2507
2507
|
var init_app_ui_apps = __esm({
|
|
2508
2508
|
"src/app-ui-apps.ts"() {
|
|
2509
|
+
init_app_ui_build();
|
|
2510
|
+
init_app_ui_placeholder();
|
|
2509
2511
|
}
|
|
2510
2512
|
});
|
|
2511
2513
|
var MESSAGE_KINDS, MESSAGE_URGENCIES;
|
|
@@ -2527,6 +2529,7 @@ var init_agent_tools = __esm({
|
|
|
2527
2529
|
"src/agent-tools.ts"() {
|
|
2528
2530
|
init_transcript_export();
|
|
2529
2531
|
init_agent_start_schema();
|
|
2532
|
+
init_spawn_field_schemas();
|
|
2530
2533
|
init_session_spawn();
|
|
2531
2534
|
init_canonical_posture();
|
|
2532
2535
|
init_user_presets();
|
|
@@ -2597,10 +2600,6 @@ var init_terminal_transcript_writer = __esm({
|
|
|
2597
2600
|
init_transcript_writer();
|
|
2598
2601
|
}
|
|
2599
2602
|
});
|
|
2600
|
-
var init_usage = __esm({
|
|
2601
|
-
"src/usage.ts"() {
|
|
2602
|
-
}
|
|
2603
|
-
});
|
|
2604
2603
|
var init_context_window = __esm({
|
|
2605
2604
|
"src/context-window.ts"() {
|
|
2606
2605
|
}
|
|
@@ -2765,6 +2764,7 @@ var init_config_schema = __esm({
|
|
|
2765
2764
|
label: z.string().optional(),
|
|
2766
2765
|
authToken: z.string().optional(),
|
|
2767
2766
|
resumeSessionsOnBoot: z.boolean().optional(),
|
|
2767
|
+
continueInterruptedOnBoot: z.boolean().optional(),
|
|
2768
2768
|
idleReapAfterMs: z.number().optional(),
|
|
2769
2769
|
crashDetectIntervalMs: z.number().optional(),
|
|
2770
2770
|
restartSweepIntervalMs: z.number().optional(),
|
|
@@ -2939,6 +2939,16 @@ var init_config_schema = __esm({
|
|
|
2939
2939
|
help: "Eagerly re-spawn eligible agent-cli sessions that died from a daemon restart.",
|
|
2940
2940
|
default: false
|
|
2941
2941
|
},
|
|
2942
|
+
{
|
|
2943
|
+
path: "daemon.continueInterruptedOnBoot",
|
|
2944
|
+
schema: bool,
|
|
2945
|
+
apply: "restart",
|
|
2946
|
+
writable: true,
|
|
2947
|
+
section: "daemon",
|
|
2948
|
+
label: "Continue interrupted sessions on boot",
|
|
2949
|
+
help: 'After the eager resume pass, send a one-shot "continue" prompt to sessions the last restart cut off mid-turn.',
|
|
2950
|
+
default: false
|
|
2951
|
+
},
|
|
2942
2952
|
{
|
|
2943
2953
|
path: "daemon.idleReapAfterMs",
|
|
2944
2954
|
schema: num,
|