@demicodes/agent 0.22.1 → 0.23.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/index.d.mts CHANGED
@@ -244,6 +244,78 @@ declare class AgentSession<State> {
244
244
  declare function applyTranscriptPatches(blocks: Block[], patches: TranscriptPatch[]): Block[];
245
245
  declare function cloneBlocks(blocks: Block[]): Block[];
246
246
  //#endregion
247
+ //#region src/tools.d.ts
248
+ interface StandardAgentToolOptions<State = unknown> {
249
+ environment: BashEnvironment | ((ctx: AgentToolInvokeContext<State>, handle: {
250
+ shellId?: string;
251
+ commandId?: string;
252
+ }) => BashEnvironment | Promise<BashEnvironment>);
253
+ scheduleYield(ctx: AgentToolInvokeContext<State>, durationMs: number): AgentToolInvokeResult;
254
+ /**
255
+ * Tool-result preview budget in tokens for a given model context window.
256
+ * Defaults to {@link shellPreviewBudgetTokens}.
257
+ */
258
+ previewBudgetTokens?: ShellPreviewBudget;
259
+ }
260
+ type ShellPreviewBudget = (contextWindow: number) => number;
261
+ declare function createStandardAgentTools<State = unknown>(options: StandardAgentToolOptions<State>): AgentTool<State>[];
262
+ interface ShellToolResultOptions {
263
+ includePreview?: boolean;
264
+ previewBudgetTokens?: number;
265
+ exposeCommandHandle?: boolean;
266
+ /** Model receiving this result; gates binary-stream media attachment. */
267
+ model?: Model;
268
+ /** Per-modality byte caps on attached media; unset modalities keep the defaults. */
269
+ maxMediaBytes?: Partial<Record<ModelMediaKind, number>>;
270
+ }
271
+ /**
272
+ * How many bytes of each modality a tool may hand to the model.
273
+ *
274
+ * One number cannot serve both, because bytes buy wildly different amounts of
275
+ * context per modality — measured against a frontier model, a KiB of video
276
+ * costs ~2 tokens where a KiB of image costs ~50. A cap generous enough to show
277
+ * a five-minute clip would let a single still eat a six-figure token budget.
278
+ *
279
+ * image (4 MiB): well past any sane still — a 4000x3000 PNG lands under it — so
280
+ * crossing this line is a mistake, not a use case.
281
+ * video (16 MiB): roughly ten minutes at a viewing-grade encoding, and
282
+ * deliberately under the ~20 MB inline-payload ceiling the major APIs enforce.
283
+ * A larger cap buys no reach, only a rejection further downstream where the
284
+ * reason is harder to read.
285
+ *
286
+ * Bytes are a proxy, not a budget: for video they track cost reasonably at a
287
+ * fixed encoding, but an image's real driver is its pixel dimensions.
288
+ */
289
+ declare const DEFAULT_MAX_MEDIA_BYTES: Record<ModelMediaKind, number>;
290
+ declare function shellPreviewBudgetTokens(contextWindow: number): number;
291
+ declare function toShellToolResult(result: ShellCommandStatus, options?: ShellToolResultOptions): AgentToolInvokeResult;
292
+ /** Character budget for a shell view's render window (tail-biased). */
293
+ declare const SHELL_VIEW_MAX_CHARS = 32768;
294
+ /**
295
+ * Bounded UI view of a shell command stored on the tool_call block. Full
296
+ * output lives in the command artifact directory (real files on the host
297
+ * filesystem, see `artifactDir`), keyed by
298
+ * `commandId`; the view carries only the tail render window and never embeds
299
+ * raw or base64 bytes.
300
+ */
301
+ interface ShellToolView {
302
+ kind: 'shell';
303
+ status: 'running' | 'exited' | 'aborted';
304
+ shellId: string;
305
+ commandId: string;
306
+ exitCode?: number;
307
+ runningMs: number;
308
+ idleMs: number;
309
+ /** Tail of the merged output, capped at SHELL_VIEW_MAX_CHARS. */
310
+ chunks: ShellOutputChunk[];
311
+ /** True when chunks were capped; the artifact has the full output. */
312
+ viewTruncated: boolean;
313
+ audit?: BashAuditEvent[];
314
+ commandMeta?: CommandMetadataRecord[];
315
+ }
316
+ declare function finishShellToolResult<State>(environment: BashEnvironment, result: ShellCommandStatus, ctx: AgentToolInvokeContext<State>, previewBudget?: ShellPreviewBudget): Promise<AgentToolInvokeResult>;
317
+ declare function shellCommandHandleRequired(result: ShellCommandStatus, budgetTokens: number): boolean;
318
+ //#endregion
247
319
  //#region src/server.d.ts
248
320
  /** Session tuning forwarded to every AgentSession this server creates. */
249
321
  interface AgentServerSessionOptions {
@@ -288,6 +360,14 @@ interface AgentServerOptions {
288
360
  */
289
361
  maxLiveSubagents?: number;
290
362
  };
363
+ tools?: {
364
+ /**
365
+ * Shell tool-result preview budget in tokens as a function of the current
366
+ * model's context window, applied to every session in the tree. Defaults
367
+ * to the built-in 10k / 100k split at an 800k context window.
368
+ */
369
+ shellPreviewBudgetTokens?: ShellPreviewBudget;
370
+ };
291
371
  /**
292
372
  * Optional host-side shell prep (env, PATH, etc.). Implementation-agnostic —
293
373
  * command bridge wiring lives in `@demicodes/host-local`, not here.
@@ -333,6 +413,7 @@ declare class AgentServer {
333
413
  private readonly prepareShell;
334
414
  private readonly notifyParentOnIdle;
335
415
  private readonly maxLiveSubagents;
416
+ private readonly shellPreviewBudgetTokens;
336
417
  private readonly bindings;
337
418
  private readonly sessionOwnership;
338
419
  constructor(options: AgentServerOptions);
@@ -450,6 +531,8 @@ interface ChildSupervisorOptions<State> {
450
531
  directory: AgentDirectory<State>;
451
532
  /** Live-children ceiling for this supervisor (from `AgentServerOptions.subagents.maxLiveSubagents`). */
452
533
  maxLiveSubagents: number;
534
+ /** Shell preview budget for every child (from `AgentServerOptions.tools.shellPreviewBudgetTokens`); null uses the built-in split. */
535
+ shellPreviewBudgetTokens: ShellPreviewBudget | null;
453
536
  /** When false, this supervisor's owner may not spawn: its `demi agent` tree carries communication and reads only. */
454
537
  canSpawn: boolean;
455
538
  /** Invoked whenever the live-children set changes; wired to the owning job's settle loop. */
@@ -616,70 +699,4 @@ declare function injectSubagentCommand(commands: Command[], agentNode: Command):
616
699
  */
617
700
  declare function createReadonlyHost(host: Host): Host;
618
701
  //#endregion
619
- //#region src/tools.d.ts
620
- interface StandardAgentToolOptions<State = unknown> {
621
- environment: BashEnvironment | ((ctx: AgentToolInvokeContext<State>, handle: {
622
- shellId?: string;
623
- commandId?: string;
624
- }) => BashEnvironment | Promise<BashEnvironment>);
625
- scheduleYield(ctx: AgentToolInvokeContext<State>, durationMs: number): AgentToolInvokeResult;
626
- }
627
- declare function createStandardAgentTools<State = unknown>(options: StandardAgentToolOptions<State>): AgentTool<State>[];
628
- interface ShellToolResultOptions {
629
- includePreview?: boolean;
630
- previewBudgetTokens?: number;
631
- exposeCommandHandle?: boolean;
632
- /** Model receiving this result; gates binary-stream media attachment. */
633
- model?: Model;
634
- /** Per-modality byte caps on attached media; unset modalities keep the defaults. */
635
- maxMediaBytes?: Partial<Record<ModelMediaKind, number>>;
636
- }
637
- /**
638
- * How many bytes of each modality a tool may hand to the model.
639
- *
640
- * One number cannot serve both, because bytes buy wildly different amounts of
641
- * context per modality — measured against a frontier model, a KiB of video
642
- * costs ~2 tokens where a KiB of image costs ~50. A cap generous enough to show
643
- * a five-minute clip would let a single still eat a six-figure token budget.
644
- *
645
- * image (4 MiB): well past any sane still — a 4000x3000 PNG lands under it — so
646
- * crossing this line is a mistake, not a use case.
647
- * video (16 MiB): roughly ten minutes at a viewing-grade encoding, and
648
- * deliberately under the ~20 MB inline-payload ceiling the major APIs enforce.
649
- * A larger cap buys no reach, only a rejection further downstream where the
650
- * reason is harder to read.
651
- *
652
- * Bytes are a proxy, not a budget: for video they track cost reasonably at a
653
- * fixed encoding, but an image's real driver is its pixel dimensions.
654
- */
655
- declare const DEFAULT_MAX_MEDIA_BYTES: Record<ModelMediaKind, number>;
656
- declare function shellPreviewBudgetTokens(contextWindow: number): number;
657
- declare function toShellToolResult(result: ShellCommandStatus, options?: ShellToolResultOptions): AgentToolInvokeResult;
658
- /** Character budget for a shell view's render window (tail-biased). */
659
- declare const SHELL_VIEW_MAX_CHARS = 32768;
660
- /**
661
- * Bounded UI view of a shell command stored on the tool_call block. Full
662
- * output lives in the command artifact directory (real files on the host
663
- * filesystem, see `artifactDir`), keyed by
664
- * `commandId`; the view carries only the tail render window and never embeds
665
- * raw or base64 bytes.
666
- */
667
- interface ShellToolView {
668
- kind: 'shell';
669
- status: 'running' | 'exited' | 'aborted';
670
- shellId: string;
671
- commandId: string;
672
- exitCode?: number;
673
- runningMs: number;
674
- idleMs: number;
675
- /** Tail of the merged output, capped at SHELL_VIEW_MAX_CHARS. */
676
- chunks: ShellOutputChunk[];
677
- /** True when chunks were capped; the artifact has the full output. */
678
- viewTruncated: boolean;
679
- audit?: BashAuditEvent[];
680
- commandMeta?: CommandMetadataRecord[];
681
- }
682
- declare function finishShellToolResult<State>(environment: BashEnvironment, result: ShellCommandStatus, ctx: AgentToolInvokeContext<State>): Promise<AgentToolInvokeResult>;
683
- declare function shellCommandHandleRequired(result: ShellCommandStatus, budgetTokens: number): boolean;
684
- //#endregion
685
- export { AbortResult, AbortTarget, ActiveTurnPhase, AgentActionOptions, AgentClient, AgentClientListener, AgentClientTransport, AgentDirectory, 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, AgentTreeNode, 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 };
702
+ export { AbortResult, AbortTarget, ActiveTurnPhase, AgentActionOptions, AgentClient, AgentClientListener, AgentClientTransport, AgentDirectory, 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, AgentTreeNode, 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, ShellPreviewBudget, 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
@@ -2248,8 +2248,8 @@ var InProcessEndpoint = class {
2248
2248
  const MAX_CONSECUTIVE_IDENTICAL_EXEC = 6;
2249
2249
  const REPEAT_WINDOW_MS = 6e4;
2250
2250
  const MAX_DELAY_MS = 6e5;
2251
- const SMALL_CONTEXT_PREVIEW_TOKENS = 1e3;
2252
- const LARGE_CONTEXT_PREVIEW_TOKENS = 1e4;
2251
+ const SMALL_CONTEXT_PREVIEW_TOKENS = 1e4;
2252
+ const LARGE_CONTEXT_PREVIEW_TOKENS = 1e5;
2253
2253
  const LARGE_CONTEXT_THRESHOLD_TOKENS = 8e5;
2254
2254
  const APPROX_CHARS_PER_TOKEN = 4;
2255
2255
  const TOOL_DESCRIPTION_FIELD = "Concise title for the concrete user-visible state or result to make visible or confirm. Do not describe waiting, pausing, tool mechanics, generic actions, object labels, steps, tool names, ids, internals, or reasons.";
@@ -2288,7 +2288,7 @@ function createStandardAgentTools(options) {
2288
2288
  signal: ctx.signal
2289
2289
  });
2290
2290
  ctx.emitProgress(result);
2291
- return finishShellToolResult(environment, result, ctx);
2291
+ return finishShellToolResult(environment, result, ctx, options.previewBudgetTokens);
2292
2292
  }
2293
2293
  },
2294
2294
  {
@@ -2311,7 +2311,7 @@ function createStandardAgentTools(options) {
2311
2311
  const environment = await resolveEnvironment(options.environment, ctx, { commandId: parsed.commandId });
2312
2312
  const result = await environment.status(parsed);
2313
2313
  ctx.emitProgress(result);
2314
- return finishShellToolResult(environment, result, ctx);
2314
+ return finishShellToolResult(environment, result, ctx, options.previewBudgetTokens);
2315
2315
  }
2316
2316
  },
2317
2317
  {
@@ -2338,7 +2338,7 @@ function createStandardAgentTools(options) {
2338
2338
  signal: ctx.signal
2339
2339
  });
2340
2340
  ctx.emitProgress(result);
2341
- return finishShellToolResult(environment, result, ctx);
2341
+ return finishShellToolResult(environment, result, ctx, options.previewBudgetTokens);
2342
2342
  }
2343
2343
  },
2344
2344
  {
@@ -2362,7 +2362,7 @@ function createStandardAgentTools(options) {
2362
2362
  const result = await environment.abort(parsed);
2363
2363
  ctx.emitProgress(result);
2364
2364
  return {
2365
- ...await finishShellToolResult(environment, result, ctx),
2365
+ ...await finishShellToolResult(environment, result, ctx, options.previewBudgetTokens),
2366
2366
  isError: false
2367
2367
  };
2368
2368
  }
@@ -2636,8 +2636,8 @@ function boundedPreview(text, budgetTokens) {
2636
2636
  truncated: true
2637
2637
  };
2638
2638
  }
2639
- async function finishShellToolResult(environment, result, ctx) {
2640
- const previewBudgetTokens = shellPreviewBudgetTokens(ctx.model.model.contextWindow);
2639
+ async function finishShellToolResult(environment, result, ctx, previewBudget = shellPreviewBudgetTokens) {
2640
+ const previewBudgetTokens = previewBudget(ctx.model.model.contextWindow);
2641
2641
  const exposeCommandHandle = shellCommandHandleRequired(result, previewBudgetTokens);
2642
2642
  const toolResult = toShellToolResult(result, {
2643
2643
  includePreview: true,
@@ -3279,7 +3279,8 @@ var ChildSupervisor = class ChildSupervisor {
3279
3279
  },
3280
3280
  tools: () => createStandardAgentTools({
3281
3281
  environment: (ctx) => this.childEnvironment(job, ctx),
3282
- scheduleYield: (ctx, durationMs) => job.session.scheduleYieldWakeup(durationMs, ctx.metadata)
3282
+ scheduleYield: (ctx, durationMs) => job.session.scheduleYieldWakeup(durationMs, ctx.metadata),
3283
+ ...this.options.shellPreviewBudgetTokens === null ? {} : { previewBudgetTokens: this.options.shellPreviewBudgetTokens }
3283
3284
  })
3284
3285
  }
3285
3286
  };
@@ -3920,6 +3921,7 @@ var AgentServer = class {
3920
3921
  prepareShell;
3921
3922
  notifyParentOnIdle;
3922
3923
  maxLiveSubagents;
3924
+ shellPreviewBudgetTokens;
3923
3925
  bindings = /* @__PURE__ */ new Set();
3924
3926
  sessionOwnership = new SessionOwnershipRegistry();
3925
3927
  constructor(options) {
@@ -3930,6 +3932,7 @@ var AgentServer = class {
3930
3932
  this.prepareShell = options.prepareShell ?? null;
3931
3933
  this.notifyParentOnIdle = options.subagents?.notifyParentOnIdle ?? true;
3932
3934
  this.maxLiveSubagents = options.subagents?.maxLiveSubagents ?? 8;
3935
+ this.shellPreviewBudgetTokens = options.tools?.shellPreviewBudgetTokens ?? null;
3933
3936
  }
3934
3937
  client() {
3935
3938
  const transports = createInProcessTransportPair();
@@ -3946,6 +3949,7 @@ var AgentServer = class {
3946
3949
  prepareShell: this.prepareShell,
3947
3950
  notifyParentOnIdle: this.notifyParentOnIdle,
3948
3951
  maxLiveSubagents: this.maxLiveSubagents,
3952
+ shellPreviewBudgetTokens: this.shellPreviewBudgetTokens,
3949
3953
  sessions: this.sessionOwnership
3950
3954
  });
3951
3955
  this.bindings.add(binding);
@@ -3997,6 +4001,7 @@ var AgentTransportBindingImpl = class {
3997
4001
  prepareShell;
3998
4002
  notifyParentOnIdle;
3999
4003
  maxLiveSubagents;
4004
+ shellPreviewBudgetTokens;
4000
4005
  sessions;
4001
4006
  session = null;
4002
4007
  currentAgent = null;
@@ -4020,6 +4025,7 @@ var AgentTransportBindingImpl = class {
4020
4025
  this.prepareShell = options.prepareShell;
4021
4026
  this.notifyParentOnIdle = options.notifyParentOnIdle;
4022
4027
  this.maxLiveSubagents = options.maxLiveSubagents;
4028
+ this.shellPreviewBudgetTokens = options.shellPreviewBudgetTokens;
4023
4029
  this.sessions = options.sessions;
4024
4030
  this.unsubscribeTransport = this.transport.onFrame((frame) => {
4025
4031
  this.handleFrame(frame);
@@ -4245,6 +4251,7 @@ var AgentTransportBindingImpl = class {
4245
4251
  storePrefix: `agent-sessions/${agentSessionId}`,
4246
4252
  directory,
4247
4253
  maxLiveSubagents: this.maxLiveSubagents,
4254
+ shellPreviewBudgetTokens: this.shellPreviewBudgetTokens,
4248
4255
  canSpawn: true,
4249
4256
  onJobsChanged: null,
4250
4257
  emit: (subagentFrame) => this.send(subagentFrame)
@@ -4259,7 +4266,8 @@ var AgentTransportBindingImpl = class {
4259
4266
  scheduleYield: (ctx, durationMs) => {
4260
4267
  if (!sessionRef) throw new Error("AgentServer: session is not ready for yield scheduling");
4261
4268
  return sessionRef.scheduleYieldWakeup(durationMs, ctx.metadata);
4262
- }
4269
+ },
4270
+ ...this.shellPreviewBudgetTokens === null ? {} : { previewBudgetTokens: this.shellPreviewBudgetTokens }
4263
4271
  });
4264
4272
  const commandsPrompt = commandRegistry.renderHelp();
4265
4273
  const runtime = {
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.22.1",
4
+ "version": "0.23.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.22.1",
23
- "@demicodes/provider": "^0.22.1",
24
- "@demicodes/shell": "^0.22.1",
25
- "@demicodes/utils": "^0.22.1",
22
+ "@demicodes/core": "^0.23.0",
23
+ "@demicodes/provider": "^0.23.0",
24
+ "@demicodes/shell": "^0.23.0",
25
+ "@demicodes/utils": "^0.23.0",
26
26
  "zod": "^4.0.0"
27
27
  },
28
28
  "license": "Apache-2.0",