@demicodes/agent 0.19.2 → 0.20.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/dist/client-entry.d.mts +2 -2
- package/dist/client-entry.mjs +1 -1
- package/dist/index.d.mts +22 -4
- package/dist/index.mjs +176 -38
- package/dist/stdio-transport.d.mts +1 -1
- package/dist/{transport-CHrPzcrU.d.mts → transport-_eV2zg9M.d.mts} +2 -0
- package/dist/{websocket-transport-NZ5Btmb4.d.mts → websocket-transport-BC7OstFf.d.mts} +7 -1
- package/dist/{websocket-transport-CIOotpd-.mjs → websocket-transport-BsKvbXIp.mjs} +8 -0
- package/package.json +5 -5
package/dist/client-entry.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { f as TranscriptPatch, l as ServerFrame, n as AgentServerTransport, o as ClientFrame, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandStatusLike, x as AgentMetadata } from "./transport-
|
|
2
|
-
import { a as AgentClient, i as AgentActionOptions, n as createWebSocketClientTransport, o as AgentClientListener, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-
|
|
1
|
+
import { f as TranscriptPatch, l as ServerFrame, n as AgentServerTransport, o as ClientFrame, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandStatusLike, x as AgentMetadata } from "./transport-_eV2zg9M.mjs";
|
|
2
|
+
import { a as AgentClient, i as AgentActionOptions, n as createWebSocketClientTransport, o as AgentClientListener, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-BC7OstFf.mjs";
|
|
3
3
|
import { ProviderSelection } from "@demicodes/provider";
|
|
4
4
|
export { type AgentActionOptions, AgentClient, type AgentClientListener, type AgentClientTransport, type AgentMetadata, type AgentServerTransport, type AgentTransport, type ClientFrame, type ClientSessionEvent, type JsonWebSocket, type ProviderSelection, type ServerFrame, type ShellCommandStatusLike, type TranscriptPatch, createWebSocketClientTransport, createWebSocketServerTransport };
|
package/dist/client-entry.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as createWebSocketServerTransport, r as AgentClient, t as createWebSocketClientTransport } from "./websocket-transport-
|
|
1
|
+
import { n as createWebSocketServerTransport, r as AgentClient, t as createWebSocketClientTransport } from "./websocket-transport-BsKvbXIp.mjs";
|
|
2
2
|
export { AgentClient, createWebSocketClientTransport, createWebSocketServerTransport };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AgentSystemPromptContext, B as CompactionWindow, C as AgentReferenceResolveContext, D as AgentSessionParams, E as AgentSessionOptions, F as ExternalMutationReservation, G as DEFAULT_TURN_RETRY_POLICY, H as TranscriptLog, I as ModelSwitchApply, J as resolveRetryPolicy, K as TurnRetryPolicy, L as SessionEvent, M as AgentToolContext, N as AgentToolInvokeContext, O as AgentSessionRestoreParams, P as AgentToolInvokeResult, R as SessionEventListener, S as AgentPromptContext, T as AgentSessionCloneParams, U as TranscriptOptions, V as DrainedTranscriptPatches, W as estimateTranscriptBlockTokens, Y as retryDelayMs, _ as AgentHarnessContext, a as createInProcessTransportPair, b as AgentLifecycleEvent, c as ConversationSummary, d as SubagentJob, f as TranscriptPatch, g as AgentHarness, h as AgentDisposeContext, i as InProcessTransportPair, j as AgentTool, k as AgentSessionStore, l as ServerFrame, m as AbortTarget, n as AgentServerTransport, o as ClientFrame, p as AbortResult, q as isRetryableCode, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandStatusLike, v as AgentHarnessRuntime, w as AgentSessionCheckpoint, x as AgentMetadata, y as AgentHostContext, z as SubagentProfile } from "./transport-
|
|
2
|
-
import { a as AgentClient, i as AgentActionOptions, n as createWebSocketClientTransport, o as AgentClientListener, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-
|
|
1
|
+
import { A as AgentSystemPromptContext, B as CompactionWindow, C as AgentReferenceResolveContext, D as AgentSessionParams, E as AgentSessionOptions, F as ExternalMutationReservation, G as DEFAULT_TURN_RETRY_POLICY, H as TranscriptLog, I as ModelSwitchApply, J as resolveRetryPolicy, K as TurnRetryPolicy, L as SessionEvent, M as AgentToolContext, N as AgentToolInvokeContext, O as AgentSessionRestoreParams, P as AgentToolInvokeResult, R as SessionEventListener, S as AgentPromptContext, T as AgentSessionCloneParams, U as TranscriptOptions, V as DrainedTranscriptPatches, W as estimateTranscriptBlockTokens, Y as retryDelayMs, _ as AgentHarnessContext, a as createInProcessTransportPair, b as AgentLifecycleEvent, c as ConversationSummary, d as SubagentJob, f as TranscriptPatch, g as AgentHarness, h as AgentDisposeContext, i as InProcessTransportPair, j as AgentTool, k as AgentSessionStore, l as ServerFrame, m as AbortTarget, n as AgentServerTransport, o as ClientFrame, p as AbortResult, q as isRetryableCode, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandStatusLike, v as AgentHarnessRuntime, w as AgentSessionCheckpoint, x as AgentMetadata, y as AgentHostContext, z as SubagentProfile } from "./transport-_eV2zg9M.mjs";
|
|
2
|
+
import { a as AgentClient, i as AgentActionOptions, n as createWebSocketClientTransport, o as AgentClientListener, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-BC7OstFf.mjs";
|
|
3
3
|
import { BashAuditEvent, BashEnvironment, BashEnvironmentOptions, Command, CommandMetadataRecord, Host, HostStore, ShellCommandStatus, ShellOutputChunk } from "@demicodes/shell";
|
|
4
4
|
import { AgentProvider, Provider } from "@demicodes/provider";
|
|
5
5
|
import { Block, Model, ModelMediaKind, ModelSelection, ProviderErrorDiagnostics, QueuedMessage, SessionPhase, UserContentBlock } from "@demicodes/core";
|
|
@@ -339,6 +339,7 @@ declare class AgentServer {
|
|
|
339
339
|
//#endregion
|
|
340
340
|
//#region src/subagent.d.ts
|
|
341
341
|
declare const MAX_LIVE_SUBAGENTS = 8;
|
|
342
|
+
declare const MAX_ARCHIVED_SUBAGENTS = 16;
|
|
342
343
|
declare const SUBAGENT_RESULT_MAX_BYTES: number;
|
|
343
344
|
type SubagentExecution = 'idle' | 'provider_streaming' | 'tool_executing' | 'compacting' | 'finalizing' | 'pending_yield';
|
|
344
345
|
interface ChildSupervisorOptions<State> {
|
|
@@ -364,7 +365,8 @@ interface ChildSupervisorOptions<State> {
|
|
|
364
365
|
* on the parent connection. Children persist exactly like the parent: each
|
|
365
366
|
* live child keeps a checkpoint and job record under the parent's session
|
|
366
367
|
* directory, and reopening the parent restores and resumes them (`restore`).
|
|
367
|
-
* A closed child
|
|
368
|
+
* A closed child moves to the archive: its transcript checkpoint stays on
|
|
369
|
+
* store and `demi agent resume` revives it with a new user message.
|
|
368
370
|
*/
|
|
369
371
|
declare class ChildSupervisor<State = unknown> {
|
|
370
372
|
private readonly options;
|
|
@@ -399,7 +401,21 @@ declare class ChildSupervisor<State = unknown> {
|
|
|
399
401
|
*/
|
|
400
402
|
restore(): Promise<void>;
|
|
401
403
|
private restoreJob;
|
|
404
|
+
/** Shared by restore and resume: rebuild a persisted child's job and session from its checkpoint. */
|
|
405
|
+
private reassembleJob;
|
|
406
|
+
/**
|
|
407
|
+
* Revives an archived child: its job record turns live again (this round's
|
|
408
|
+
* metadata, a fresh spawnedAt), the session rebuilds from the preserved
|
|
409
|
+
* checkpoint, and the message opens its next turn on top of the old
|
|
410
|
+
* transcript.
|
|
411
|
+
*/
|
|
412
|
+
private resumeArchived;
|
|
413
|
+
/** Every archived (finished, revivable) child of this parent, newest first. */
|
|
414
|
+
private listArchivedJobs;
|
|
415
|
+
private pruneArchive;
|
|
402
416
|
abortSubtree(id: string): Promise<void>;
|
|
417
|
+
/** Aborts every live child; the archive is untouched. */
|
|
418
|
+
abortAll(): Promise<void>;
|
|
403
419
|
private spawn;
|
|
404
420
|
/** Everything spawn and restore share: the command tree, the harness runtime, and the job record (session attached separately). */
|
|
405
421
|
private assembleJob;
|
|
@@ -407,6 +423,8 @@ declare class ChildSupervisor<State = unknown> {
|
|
|
407
423
|
private childStoreKey;
|
|
408
424
|
private childSessionStore;
|
|
409
425
|
private deletePersistedJob;
|
|
426
|
+
/** Shared spawn/resume foreground behaviour: announce the id, wire abort and stdin steers, wait for close, report the outcome. */
|
|
427
|
+
private attendChild;
|
|
410
428
|
/** Delivers one steer to a child: mid-turn as a steer, idle as a new user turn. */
|
|
411
429
|
private steerChild;
|
|
412
430
|
private pumpStdinSteers;
|
|
@@ -516,4 +534,4 @@ interface ShellToolView {
|
|
|
516
534
|
declare function finishShellToolResult<State>(environment: BashEnvironment, result: ShellCommandStatus, ctx: AgentToolInvokeContext<State>): Promise<AgentToolInvokeResult>;
|
|
517
535
|
declare function shellCommandHandleRequired(result: ShellCommandStatus, budgetTokens: number): boolean;
|
|
518
536
|
//#endregion
|
|
519
|
-
export { AbortResult, AbortTarget, ActiveTurnPhase, AgentActionOptions, AgentClient, AgentClientListener, AgentClientTransport, AgentDisposeContext, AgentHarness, AgentHarnessContext, AgentHarnessRuntime, AgentHostContext, AgentLifecycleEvent, AgentMetadata, AgentPromptContext, AgentReferenceResolveContext, AgentServer, AgentServerOptions, AgentServerSessionOptions, AgentServerTransport, AgentSession, AgentSessionCheckpoint, AgentSessionCloneParams, AgentSessionOptions, AgentSessionParams, AgentSessionRestoreParams, AgentSessionStore, AgentSystemPromptContext, AgentTool, AgentToolContext, AgentToolInvokeContext, AgentToolInvokeResult, AgentTransport, AgentTransportBinding, ChildSupervisor, ChildSupervisorOptions, ClientFrame, ClientSessionEvent, CompactionWindow, ConversationSummary, DEFAULT_MAX_MEDIA_BYTES, DEFAULT_TURN_RETRY_POLICY, DrainedTranscriptPatches, ExternalMutationReservation, InProcessTransportPair, JsonWebSocket, MAX_LIVE_SUBAGENTS, ModelSwitchApply, PrepareShell, PrepareShellContext, ProviderStreamError, ResumePoint, RunCommandLineCommandNotRegisteredError, RunCommandLineOptions, RunCommandLineResult, RunCommandLineShellNotFoundError, RunCommandLineTimeoutError, SHELL_VIEW_MAX_CHARS, SUBAGENT_RESULT_MAX_BYTES, ServerFrame, SessionEvent, SessionEventListener, ShellCommandStatusLike, ShellToolResultOptions, ShellToolView, StandardAgentToolOptions, SubagentExecution, SubagentJob, SubagentProfile, TranscriptLog, TranscriptOptions, TranscriptPatch, TurnRetryPolicy, applyTranscriptPatches, cloneBlocks, createInProcessTransportPair, createReadonlyHost, createStandardAgentTools, createWebSocketClientTransport, createWebSocketServerTransport, estimateTranscriptBlockTokens, findResumePoint, finishShellToolResult, injectSubagentCommand, isContextLengthExceeded, isRetryableCode, resolveRetryPolicy, retryDelayMs, shellCommandHandleRequired, shellPreviewBudgetTokens, toShellToolResult };
|
|
537
|
+
export { AbortResult, AbortTarget, ActiveTurnPhase, AgentActionOptions, AgentClient, AgentClientListener, AgentClientTransport, AgentDisposeContext, AgentHarness, AgentHarnessContext, AgentHarnessRuntime, AgentHostContext, AgentLifecycleEvent, AgentMetadata, AgentPromptContext, AgentReferenceResolveContext, AgentServer, AgentServerOptions, AgentServerSessionOptions, AgentServerTransport, AgentSession, AgentSessionCheckpoint, AgentSessionCloneParams, AgentSessionOptions, AgentSessionParams, AgentSessionRestoreParams, AgentSessionStore, AgentSystemPromptContext, AgentTool, AgentToolContext, AgentToolInvokeContext, AgentToolInvokeResult, AgentTransport, AgentTransportBinding, ChildSupervisor, ChildSupervisorOptions, ClientFrame, ClientSessionEvent, CompactionWindow, ConversationSummary, DEFAULT_MAX_MEDIA_BYTES, DEFAULT_TURN_RETRY_POLICY, DrainedTranscriptPatches, ExternalMutationReservation, InProcessTransportPair, JsonWebSocket, MAX_ARCHIVED_SUBAGENTS, MAX_LIVE_SUBAGENTS, ModelSwitchApply, PrepareShell, PrepareShellContext, ProviderStreamError, ResumePoint, RunCommandLineCommandNotRegisteredError, RunCommandLineOptions, RunCommandLineResult, RunCommandLineShellNotFoundError, RunCommandLineTimeoutError, SHELL_VIEW_MAX_CHARS, SUBAGENT_RESULT_MAX_BYTES, ServerFrame, SessionEvent, SessionEventListener, ShellCommandStatusLike, ShellToolResultOptions, ShellToolView, StandardAgentToolOptions, SubagentExecution, SubagentJob, SubagentProfile, TranscriptLog, TranscriptOptions, TranscriptPatch, TurnRetryPolicy, applyTranscriptPatches, cloneBlocks, createInProcessTransportPair, createReadonlyHost, createStandardAgentTools, createWebSocketClientTransport, createWebSocketServerTransport, estimateTranscriptBlockTokens, findResumePoint, finishShellToolResult, injectSubagentCommand, isContextLengthExceeded, isRetryableCode, resolveRetryPolicy, retryDelayMs, shellCommandHandleRequired, shellPreviewBudgetTokens, toShellToolResult };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as cloneBlocks, i as applyTranscriptPatches, n as createWebSocketServerTransport, o as ProviderStreamError, r as AgentClient, s as isContextLengthExceeded, t as createWebSocketClientTransport } from "./websocket-transport-
|
|
1
|
+
import { a as cloneBlocks, i as applyTranscriptPatches, n as createWebSocketServerTransport, o as ProviderStreamError, r as AgentClient, s as isContextLengthExceeded, t as createWebSocketClientTransport } from "./websocket-transport-BsKvbXIp.mjs";
|
|
2
2
|
import { AbortError, abortable, asError, asRecord, asString, bytesToBase64, createId, decodeUtf8, delay, errorMessage, isAbortError, isRecord, noop, parseJsonOrString, safeJsonStringify, sliceHead, sliceTail, throwIfAborted, toWellFormedText, truncate, utf8Slice } from "@demicodes/utils";
|
|
3
3
|
import { BashEnvironment, CommandRegistry, MAX_TIMEOUT_MS, heredocDelimiter, shellQuote } from "@demicodes/shell";
|
|
4
4
|
import { providerRuntime } from "@demicodes/provider";
|
|
@@ -2653,6 +2653,7 @@ function shellCommandHandleRequired(result, budgetTokens) {
|
|
|
2653
2653
|
//#endregion
|
|
2654
2654
|
//#region src/subagent.ts
|
|
2655
2655
|
const MAX_LIVE_SUBAGENTS = 8;
|
|
2656
|
+
const MAX_ARCHIVED_SUBAGENTS = 16;
|
|
2656
2657
|
const SUBAGENT_RESULT_MAX_BYTES = 32768;
|
|
2657
2658
|
const SHOW_RECENT_TOOLS = 8;
|
|
2658
2659
|
const SPAWN_PROMPT_DESCRIPTION = "The child's first user message and only task brief. The child starts with an empty transcript and cannot see this conversation: do not refer to prior turns, and do not paste this conversation or the product user's message unchanged. Include the goal for this child, applicable decisions and constraints, whether to edit or only report, how to verify, and every concrete identifier it needs (paths, ids, error text, commands already tried and their key results). State the exact shape of the last assistant text it should return.";
|
|
@@ -2663,7 +2664,8 @@ const SPAWN_PROMPT_DESCRIPTION = "The child's first user message and only task b
|
|
|
2663
2664
|
* on the parent connection. Children persist exactly like the parent: each
|
|
2664
2665
|
* live child keeps a checkpoint and job record under the parent's session
|
|
2665
2666
|
* directory, and reopening the parent restores and resumes them (`restore`).
|
|
2666
|
-
* A closed child
|
|
2667
|
+
* A closed child moves to the archive: its transcript checkpoint stays on
|
|
2668
|
+
* store and `demi agent resume` revives it with a new user message.
|
|
2667
2669
|
*/
|
|
2668
2670
|
var ChildSupervisor = class {
|
|
2669
2671
|
options;
|
|
@@ -2712,30 +2714,12 @@ var ChildSupervisor = class {
|
|
|
2712
2714
|
await io.stderr(`demi agent: ${errorMessage(error)}\n`);
|
|
2713
2715
|
return { exitCode: 1 };
|
|
2714
2716
|
}
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
this.pumpStdinSteers(job.id, stdinStream);
|
|
2722
|
-
const close = await job.closed;
|
|
2723
|
-
signal.removeEventListener("abort", onAbort);
|
|
2724
|
-
if (close.phase === "completed") {
|
|
2725
|
-
const text = close.result ?? "";
|
|
2726
|
-
if (parsed.json) await io.stdout(`${JSON.stringify({
|
|
2727
|
-
subagentId: job.id,
|
|
2728
|
-
text
|
|
2729
|
-
})}\n`);
|
|
2730
|
-
else if (text.length > 0) await io.stdout(text.endsWith("\n") ? text : `${text}\n`);
|
|
2731
|
-
return { exitCode: 0 };
|
|
2732
|
-
}
|
|
2733
|
-
if (close.phase === "aborted") {
|
|
2734
|
-
await io.stderr(`demi agent: subagent ${job.id} aborted\n`);
|
|
2735
|
-
return { exitCode: 130 };
|
|
2736
|
-
}
|
|
2737
|
-
await io.stderr(`demi agent: subagent ${job.id} failed: ${close.failure ?? "unknown error"}\n`);
|
|
2738
|
-
return { exitCode: 1 };
|
|
2717
|
+
return this.attendChild(job, {
|
|
2718
|
+
io,
|
|
2719
|
+
isJson: parsed.json === true,
|
|
2720
|
+
signal,
|
|
2721
|
+
stdinStream
|
|
2722
|
+
});
|
|
2739
2723
|
},
|
|
2740
2724
|
subcommands: [
|
|
2741
2725
|
{
|
|
@@ -2794,21 +2778,73 @@ var ChildSupervisor = class {
|
|
|
2794
2778
|
return { exitCode: 0 };
|
|
2795
2779
|
}
|
|
2796
2780
|
},
|
|
2781
|
+
{
|
|
2782
|
+
name: "resume",
|
|
2783
|
+
summary: "Revive an archived (finished) child with a new user message on top of its preserved transcript. Behaves like the spawn command afterwards: stays running until the child ends again, stdout is its new last assistant text, shell_write steers, shell_abort aborts. Archived ids are in `demi agent list`.",
|
|
2784
|
+
input: {
|
|
2785
|
+
id: z.string().describe("subagentId of an archived child"),
|
|
2786
|
+
message: z.string().optional().describe("The reviving user message; positional, or stdin/heredoc when omitted.")
|
|
2787
|
+
},
|
|
2788
|
+
positionals: ["id", "message"],
|
|
2789
|
+
stdinField: "message",
|
|
2790
|
+
output: { json: z.object({
|
|
2791
|
+
subagentId: z.string(),
|
|
2792
|
+
text: z.string()
|
|
2793
|
+
}) },
|
|
2794
|
+
run: async ({ parsed, io, signal, stdinStream }) => {
|
|
2795
|
+
const id = String(parsed.values.id);
|
|
2796
|
+
const message = String(parsed.values.message ?? "").trim();
|
|
2797
|
+
if (!message) {
|
|
2798
|
+
await io.stderr("demi agent resume: message must not be empty\n");
|
|
2799
|
+
return { exitCode: 1 };
|
|
2800
|
+
}
|
|
2801
|
+
let job;
|
|
2802
|
+
try {
|
|
2803
|
+
job = await this.resumeArchived(id, message);
|
|
2804
|
+
} catch (error) {
|
|
2805
|
+
await io.stderr(`demi agent resume: ${errorMessage(error)}\n`);
|
|
2806
|
+
return { exitCode: 1 };
|
|
2807
|
+
}
|
|
2808
|
+
return this.attendChild(job, {
|
|
2809
|
+
io,
|
|
2810
|
+
isJson: parsed.json === true,
|
|
2811
|
+
signal,
|
|
2812
|
+
stdinStream
|
|
2813
|
+
});
|
|
2814
|
+
}
|
|
2815
|
+
},
|
|
2797
2816
|
{
|
|
2798
2817
|
name: "list",
|
|
2799
|
-
summary: "Snapshot roster of this session's running children (finished
|
|
2800
|
-
output: { json: z.object({
|
|
2818
|
+
summary: "Snapshot roster of this session's running children, then its archived (finished, revivable via resume) children. One line per child with ages relative to now. A read, not a wait — not for polling loops.",
|
|
2819
|
+
output: { json: z.object({
|
|
2820
|
+
agents: z.array(z.unknown()),
|
|
2821
|
+
archived: z.array(z.unknown())
|
|
2822
|
+
}) },
|
|
2801
2823
|
run: async ({ parsed, io }) => {
|
|
2802
2824
|
const jobs = [...this.jobs.values()];
|
|
2825
|
+
const archived = await this.listArchivedJobs();
|
|
2803
2826
|
if (parsed.json) {
|
|
2804
|
-
await io.stdout(`${JSON.stringify({
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2827
|
+
await io.stdout(`${JSON.stringify({
|
|
2828
|
+
agents: jobs.map((job) => this.snapshot(job, false)),
|
|
2829
|
+
archived: archived.map(({ id, meta }) => ({
|
|
2830
|
+
subagentId: id,
|
|
2831
|
+
description: meta.description,
|
|
2832
|
+
profile: meta.profileName,
|
|
2833
|
+
phase: meta.closedPhase,
|
|
2834
|
+
closedAgoMs: meta.closedAt === void 0 ? null : Date.now() - meta.closedAt
|
|
2835
|
+
}))
|
|
2836
|
+
})}\n`);
|
|
2809
2837
|
return { exitCode: 0 };
|
|
2810
2838
|
}
|
|
2839
|
+
if (jobs.length === 0) await io.stdout("no running subagents\n");
|
|
2811
2840
|
for (const job of jobs) await io.stdout(`${this.renderListLine(job)}\n`);
|
|
2841
|
+
if (archived.length > 0) {
|
|
2842
|
+
await io.stdout("archived (revivable with `demi agent resume <id>`):\n");
|
|
2843
|
+
for (const { id, meta } of archived) {
|
|
2844
|
+
const closedAgo = meta.closedAt === void 0 ? "" : ` closed ${formatDuration(Date.now() - meta.closedAt)} ago`;
|
|
2845
|
+
await io.stdout(` ${id} ${meta.closedPhase}${closedAgo} ${meta.description ? `"${meta.description}"` : "(no description)"}\n`);
|
|
2846
|
+
}
|
|
2847
|
+
}
|
|
2812
2848
|
return { exitCode: 0 };
|
|
2813
2849
|
}
|
|
2814
2850
|
},
|
|
@@ -2901,11 +2937,18 @@ var ChildSupervisor = class {
|
|
|
2901
2937
|
}
|
|
2902
2938
|
}
|
|
2903
2939
|
async restoreJob(id) {
|
|
2904
|
-
|
|
2905
|
-
if (!parent) return;
|
|
2940
|
+
if (!this.parentSession) return;
|
|
2906
2941
|
const meta = await this.options.store.readJson(this.childStoreKey(id, "job.json"));
|
|
2942
|
+
if (meta?.closedPhase) return;
|
|
2907
2943
|
const checkpoint = await this.childSessionStore(id).loadCheckpoint();
|
|
2908
2944
|
if (!meta || !checkpoint) throw new Error("incomplete persisted subagent");
|
|
2945
|
+
const job = this.reassembleJob(id, meta, checkpoint);
|
|
2946
|
+
this.watchTurn(job, job.session.resume(meta.metadata ? { metadata: meta.metadata } : {}));
|
|
2947
|
+
}
|
|
2948
|
+
/** Shared by restore and resume: rebuild a persisted child's job and session from its checkpoint. */
|
|
2949
|
+
reassembleJob(id, meta, checkpoint) {
|
|
2950
|
+
const parent = this.parentSession;
|
|
2951
|
+
if (!parent) throw new Error("subagent supervisor has no parent session");
|
|
2909
2952
|
const profile = this.resolveProfile(meta.profileName ?? void 0);
|
|
2910
2953
|
const { job, runtime } = this.assembleJob({
|
|
2911
2954
|
id,
|
|
@@ -2925,13 +2968,69 @@ var ChildSupervisor = class {
|
|
|
2925
2968
|
...this.options.sessionOptions
|
|
2926
2969
|
});
|
|
2927
2970
|
this.attachSession(job, session);
|
|
2928
|
-
|
|
2971
|
+
return job;
|
|
2972
|
+
}
|
|
2973
|
+
/**
|
|
2974
|
+
* Revives an archived child: its job record turns live again (this round's
|
|
2975
|
+
* metadata, a fresh spawnedAt), the session rebuilds from the preserved
|
|
2976
|
+
* checkpoint, and the message opens its next turn on top of the old
|
|
2977
|
+
* transcript.
|
|
2978
|
+
*/
|
|
2979
|
+
async resumeArchived(id, message) {
|
|
2980
|
+
const parent = this.parentSession;
|
|
2981
|
+
if (!parent) throw new Error("subagent supervisor has no parent session");
|
|
2982
|
+
if (this.isDisposed) throw new Error("parent session is closing");
|
|
2983
|
+
if (this.jobs.has(id)) throw new Error(`subagent "${id}" is still running; steer it instead`);
|
|
2984
|
+
if (this.jobs.size >= 8) throw new Error(`at most 8 running subagents per session; abort one or wait for a result`);
|
|
2985
|
+
const meta = await this.options.store.readJson(this.childStoreKey(id, "job.json"));
|
|
2986
|
+
if (!meta?.closedPhase) throw new Error(`no archived subagent "${id}" (see \`demi agent list\`)`);
|
|
2987
|
+
const checkpoint = await this.childSessionStore(id).loadCheckpoint();
|
|
2988
|
+
if (!checkpoint) throw new Error(`archived subagent "${id}" has no checkpoint left`);
|
|
2989
|
+
const liveMeta = {
|
|
2990
|
+
description: meta.description,
|
|
2991
|
+
profileName: meta.profileName,
|
|
2992
|
+
metadata: parent.actionMetadata(),
|
|
2993
|
+
spawnedAt: Date.now()
|
|
2994
|
+
};
|
|
2995
|
+
await this.options.store.writeJson(this.childStoreKey(id, "job.json"), liveMeta);
|
|
2996
|
+
const job = this.reassembleJob(id, liveMeta, checkpoint);
|
|
2997
|
+
this.watchTurn(job, job.session.send([{
|
|
2998
|
+
type: "text",
|
|
2999
|
+
text: message
|
|
3000
|
+
}], liveMeta.metadata ? { metadata: liveMeta.metadata } : {}));
|
|
3001
|
+
return job;
|
|
3002
|
+
}
|
|
3003
|
+
/** Every archived (finished, revivable) child of this parent, newest first. */
|
|
3004
|
+
async listArchivedJobs() {
|
|
3005
|
+
const parent = this.parentSession;
|
|
3006
|
+
if (!parent) return [];
|
|
3007
|
+
const prefix = `agent-sessions/${parent.id()}/subagents/`;
|
|
3008
|
+
const keys = await this.options.store.list(prefix).catch(() => []);
|
|
3009
|
+
const ids = [...new Set(keys.map((key) => key.slice(prefix.length).split("/")[0] ?? "").filter(Boolean))];
|
|
3010
|
+
const archived = [];
|
|
3011
|
+
for (const id of ids) {
|
|
3012
|
+
if (this.jobs.has(id)) continue;
|
|
3013
|
+
const meta = await this.options.store.readJson(this.childStoreKey(id, "job.json"));
|
|
3014
|
+
if (meta?.closedPhase) archived.push({
|
|
3015
|
+
id,
|
|
3016
|
+
meta
|
|
3017
|
+
});
|
|
3018
|
+
}
|
|
3019
|
+
return archived.sort((a, b) => (b.meta.closedAt ?? 0) - (a.meta.closedAt ?? 0));
|
|
3020
|
+
}
|
|
3021
|
+
async pruneArchive() {
|
|
3022
|
+
const archived = await this.listArchivedJobs();
|
|
3023
|
+
for (const stale of archived.slice(16)) await this.deletePersistedJob(stale.id);
|
|
2929
3024
|
}
|
|
2930
3025
|
async abortSubtree(id) {
|
|
2931
3026
|
const job = this.jobs.get(id);
|
|
2932
3027
|
if (!job) return;
|
|
2933
3028
|
await this.closeJob(job, "aborted");
|
|
2934
3029
|
}
|
|
3030
|
+
/** Aborts every live child; the archive is untouched. */
|
|
3031
|
+
async abortAll() {
|
|
3032
|
+
for (const id of [...this.jobs.keys()]) await this.abortSubtree(id);
|
|
3033
|
+
}
|
|
2935
3034
|
async spawn(input) {
|
|
2936
3035
|
const parent = this.parentSession;
|
|
2937
3036
|
if (!parent) throw new Error("subagent supervisor has no parent session");
|
|
@@ -3068,6 +3167,34 @@ var ChildSupervisor = class {
|
|
|
3068
3167
|
await this.options.store.delete(this.childStoreKey(id, "checkpoint.json")).catch(noop);
|
|
3069
3168
|
await this.options.store.delete(this.childStoreKey(id, "job.json")).catch(noop);
|
|
3070
3169
|
}
|
|
3170
|
+
/** Shared spawn/resume foreground behaviour: announce the id, wire abort and stdin steers, wait for close, report the outcome. */
|
|
3171
|
+
async attendChild(job, ctx) {
|
|
3172
|
+
const { io, isJson, signal, stdinStream } = ctx;
|
|
3173
|
+
await io.stderr(`subagentId: ${job.id}\n`);
|
|
3174
|
+
const onAbort = () => {
|
|
3175
|
+
this.abortSubtree(job.id).catch(noop);
|
|
3176
|
+
};
|
|
3177
|
+
if (signal.aborted) onAbort();
|
|
3178
|
+
else signal.addEventListener("abort", onAbort, { once: true });
|
|
3179
|
+
this.pumpStdinSteers(job.id, stdinStream);
|
|
3180
|
+
const close = await job.closed;
|
|
3181
|
+
signal.removeEventListener("abort", onAbort);
|
|
3182
|
+
if (close.phase === "completed") {
|
|
3183
|
+
const text = close.result ?? "";
|
|
3184
|
+
if (isJson) await io.stdout(`${JSON.stringify({
|
|
3185
|
+
subagentId: job.id,
|
|
3186
|
+
text
|
|
3187
|
+
})}\n`);
|
|
3188
|
+
else if (text.length > 0) await io.stdout(text.endsWith("\n") ? text : `${text}\n`);
|
|
3189
|
+
return { exitCode: 0 };
|
|
3190
|
+
}
|
|
3191
|
+
if (close.phase === "aborted") {
|
|
3192
|
+
await io.stderr(`demi agent: subagent ${job.id} aborted\n`);
|
|
3193
|
+
return { exitCode: 130 };
|
|
3194
|
+
}
|
|
3195
|
+
await io.stderr(`demi agent: subagent ${job.id} failed: ${close.failure ?? "unknown error"}\n`);
|
|
3196
|
+
return { exitCode: 1 };
|
|
3197
|
+
}
|
|
3071
3198
|
/** Delivers one steer to a child: mid-turn as a steer, idle as a new user turn. */
|
|
3072
3199
|
async steerChild(job, message) {
|
|
3073
3200
|
const content = [{
|
|
@@ -3134,7 +3261,15 @@ var ChildSupervisor = class {
|
|
|
3134
3261
|
const result = phase === "completed" ? boundedResultText(lastAssistantText(job.session.transcript().blocks)) : void 0;
|
|
3135
3262
|
await job.session.dispose().catch(noop);
|
|
3136
3263
|
await this.disposeJobShells(job);
|
|
3137
|
-
await this.
|
|
3264
|
+
await this.options.store.writeJson(this.childStoreKey(job.id, "job.json"), {
|
|
3265
|
+
description: job.description,
|
|
3266
|
+
profileName: job.profileName,
|
|
3267
|
+
metadata: job.metadata,
|
|
3268
|
+
spawnedAt: job.spawnedAt,
|
|
3269
|
+
closedPhase: phase,
|
|
3270
|
+
closedAt: Date.now()
|
|
3271
|
+
}).catch(noop);
|
|
3272
|
+
await this.pruneArchive().catch(noop);
|
|
3138
3273
|
const close = {
|
|
3139
3274
|
phase,
|
|
3140
3275
|
...result !== void 0 ? { result } : {},
|
|
@@ -3811,6 +3946,9 @@ var AgentTransportBindingImpl = class {
|
|
|
3811
3946
|
});
|
|
3812
3947
|
return;
|
|
3813
3948
|
}
|
|
3949
|
+
case "abort_subagents":
|
|
3950
|
+
await this.supervisor?.abortAll();
|
|
3951
|
+
return;
|
|
3814
3952
|
case "shell_write":
|
|
3815
3953
|
await this.handleShellWrite(frame);
|
|
3816
3954
|
return;
|
|
@@ -4360,4 +4498,4 @@ function createProviderMap(providers) {
|
|
|
4360
4498
|
return map;
|
|
4361
4499
|
}
|
|
4362
4500
|
//#endregion
|
|
4363
|
-
export { AgentClient, AgentServer, AgentSession, ChildSupervisor, DEFAULT_MAX_MEDIA_BYTES, DEFAULT_TURN_RETRY_POLICY, MAX_LIVE_SUBAGENTS, ProviderStreamError, RunCommandLineCommandNotRegisteredError, RunCommandLineShellNotFoundError, RunCommandLineTimeoutError, SHELL_VIEW_MAX_CHARS, SUBAGENT_RESULT_MAX_BYTES, TranscriptLog, applyTranscriptPatches, cloneBlocks, createInProcessTransportPair, createReadonlyHost, createStandardAgentTools, createWebSocketClientTransport, createWebSocketServerTransport, estimateTranscriptBlockTokens, findResumePoint, finishShellToolResult, injectSubagentCommand, isContextLengthExceeded, isRetryableCode, resolveRetryPolicy, retryDelayMs, shellCommandHandleRequired, shellPreviewBudgetTokens, toShellToolResult };
|
|
4501
|
+
export { AgentClient, AgentServer, AgentSession, ChildSupervisor, DEFAULT_MAX_MEDIA_BYTES, DEFAULT_TURN_RETRY_POLICY, MAX_ARCHIVED_SUBAGENTS, MAX_LIVE_SUBAGENTS, ProviderStreamError, RunCommandLineCommandNotRegisteredError, RunCommandLineShellNotFoundError, RunCommandLineTimeoutError, SHELL_VIEW_MAX_CHARS, SUBAGENT_RESULT_MAX_BYTES, TranscriptLog, applyTranscriptPatches, cloneBlocks, createInProcessTransportPair, createReadonlyHost, createStandardAgentTools, createWebSocketClientTransport, createWebSocketServerTransport, estimateTranscriptBlockTokens, findResumePoint, finishShellToolResult, injectSubagentCommand, isContextLengthExceeded, isRetryableCode, resolveRetryPolicy, retryDelayMs, shellCommandHandleRequired, shellPreviewBudgetTokens, toShellToolResult };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as AgentServerTransport, t as AgentClientTransport } from "./transport-
|
|
1
|
+
import { n as AgentServerTransport, t as AgentClientTransport } from "./transport-_eV2zg9M.mjs";
|
|
2
2
|
import { Readable, Writable } from "node:stream";
|
|
3
3
|
//#region src/stdio-transport.d.ts
|
|
4
4
|
declare function createStdioClientTransport(readable: Readable, writable: Writable): AgentClientTransport;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as ModelSwitchApply, c as ConversationSummary, n as AgentServerTransport, p as AbortResult, s as ClientSessionEvent, t as AgentClientTransport, x as AgentMetadata } from "./transport-
|
|
1
|
+
import { I as ModelSwitchApply, c as ConversationSummary, n as AgentServerTransport, p as AbortResult, s as ClientSessionEvent, t as AgentClientTransport, x as AgentMetadata } from "./transport-_eV2zg9M.mjs";
|
|
2
2
|
import { ProviderSelection } from "@demicodes/provider";
|
|
3
3
|
import { Block, UserContentBlock } from "@demicodes/core";
|
|
4
4
|
//#region src/client.d.ts
|
|
@@ -59,6 +59,12 @@ declare class AgentClient {
|
|
|
59
59
|
resume(options?: AgentActionOptions): Promise<void>;
|
|
60
60
|
compact(options?: AgentActionOptions): Promise<void>;
|
|
61
61
|
abort(): Promise<AbortResult>;
|
|
62
|
+
/**
|
|
63
|
+
* Aborts every live child agent of this session (the archive is untouched).
|
|
64
|
+
* Fire-and-forget: each child settles through its own `subagent closed`
|
|
65
|
+
* frame with phase 'aborted'.
|
|
66
|
+
*/
|
|
67
|
+
abortSubagents(): void;
|
|
62
68
|
shellWrite(commandId: string, stdin: string, options?: AgentActionOptions): Promise<void>;
|
|
63
69
|
close(): Promise<void>;
|
|
64
70
|
subscribe(listener: AgentClientListener): () => void;
|
|
@@ -209,6 +209,14 @@ var AgentClient = class {
|
|
|
209
209
|
this.sendFrame({ type: "abort" });
|
|
210
210
|
return wait;
|
|
211
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Aborts every live child agent of this session (the archive is untouched).
|
|
214
|
+
* Fire-and-forget: each child settles through its own `subagent closed`
|
|
215
|
+
* frame with phase 'aborted'.
|
|
216
|
+
*/
|
|
217
|
+
abortSubagents() {
|
|
218
|
+
this.sendFrame({ type: "abort_subagents" });
|
|
219
|
+
}
|
|
212
220
|
shellWrite(commandId, stdin, options = {}) {
|
|
213
221
|
const wait = this.waitForShellWrite(commandId);
|
|
214
222
|
this.sendFrame({
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@demicodes/agent",
|
|
3
3
|
"description": "Session runtime and transport-neutral client and server protocol for Demi.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.20.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@demicodes/core": "^0.
|
|
23
|
-
"@demicodes/provider": "^0.
|
|
24
|
-
"@demicodes/shell": "^0.
|
|
25
|
-
"@demicodes/utils": "^0.
|
|
22
|
+
"@demicodes/core": "^0.20.0",
|
|
23
|
+
"@demicodes/provider": "^0.20.0",
|
|
24
|
+
"@demicodes/shell": "^0.20.0",
|
|
25
|
+
"@demicodes/utils": "^0.20.0",
|
|
26
26
|
"zod": "^4.0.0"
|
|
27
27
|
},
|
|
28
28
|
"license": "Apache-2.0",
|