@demicodes/agent 0.22.1 → 0.24.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. */
@@ -589,6 +672,11 @@ declare class ChildSupervisor<State = unknown> {
589
672
  private notifyIdleParent;
590
673
  private childEnvironment;
591
674
  private createChildEnvironment;
675
+ /**
676
+ * No name means the unnamed inherit profile: the parent harness, model, Host
677
+ * and commands, always available and never configurable. A name must match a
678
+ * declared profile; "default" is not a name.
679
+ */
592
680
  private resolveProfile;
593
681
  private configuredProfileNames;
594
682
  private subagentPreamble;
@@ -616,70 +704,4 @@ declare function injectSubagentCommand(commands: Command[], agentNode: Command):
616
704
  */
617
705
  declare function createReadonlyHost(host: Host): Host;
618
706
  //#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 };
707
+ 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,
@@ -2751,6 +2751,13 @@ var AgentDirectory = class {
2751
2751
  return [await build(this.rootId(), null, null, null, this.root.supervisor)];
2752
2752
  }
2753
2753
  };
2754
+ /** The reserved word a harness may not use as a profile name: it is not a profile, it is the absence of one. */
2755
+ const INHERIT_PROFILE_NAME = "default";
2756
+ const INHERIT_PROFILE_LABEL = "(inherit)";
2757
+ const INHERIT_PROFILE = {
2758
+ name: INHERIT_PROFILE_LABEL,
2759
+ description: "Inherits the parent harness, model, Host, and commands."
2760
+ };
2754
2761
  /**
2755
2762
  * Per-session subagent supervisor. Every session — root or subagent — owns one
2756
2763
  * and carries the identical `demi agent` command tree, so spawn nests to any
@@ -2767,6 +2774,7 @@ var ChildSupervisor = class ChildSupervisor {
2767
2774
  parentSession = null;
2768
2775
  isDisposed = false;
2769
2776
  constructor(options) {
2777
+ if (options.profiles?.some((profile) => profile.name === INHERIT_PROFILE_NAME)) throw new Error(`subagent profile name "${INHERIT_PROFILE_NAME}" is reserved: omitting --profile already inherits the parent`);
2770
2778
  this.options = options;
2771
2779
  }
2772
2780
  attachParent(session) {
@@ -2798,7 +2806,7 @@ var ChildSupervisor = class ChildSupervisor {
2798
2806
  failureOutput: "non-zero exit with the abort or failure reason on stderr",
2799
2807
  input: {
2800
2808
  prompt: z.string().optional().describe(SPAWN_PROMPT_DESCRIPTION),
2801
- profile: z.string().optional().describe(`Named subagent profile configured at harness assembly. Available: ${profileNames.join(", ")}.`),
2809
+ profile: z.string().optional().describe(`Named subagent profile configured at harness assembly; omit to inherit the parent's model, prompt, Host and commands. Available: ${profileNames.length > 0 ? profileNames.join(", ") : "none"}.`),
2802
2810
  description: z.string().optional().describe("Short UI title distinguishing concurrent children."),
2803
2811
  "no-subagents": z.boolean().optional().describe("Forbid this child from spawning subagents of its own; it can still send, steer, list, and show.")
2804
2812
  },
@@ -3123,6 +3131,7 @@ var ChildSupervisor = class ChildSupervisor {
3123
3131
  if (!meta?.closedPhase) throw new Error(`no archived subagent "${id}" (see \`demi agent list\`)`);
3124
3132
  const checkpoint = await this.childSessionStore(id).loadCheckpoint();
3125
3133
  if (!checkpoint) throw new Error(`archived subagent "${id}" has no checkpoint left`);
3134
+ this.resolveProfile(meta.profileName ?? void 0);
3126
3135
  const liveMeta = {
3127
3136
  description: meta.description,
3128
3137
  profileName: meta.profileName,
@@ -3174,7 +3183,7 @@ var ChildSupervisor = class ChildSupervisor {
3174
3183
  const profile = this.resolveProfile(input.profileName);
3175
3184
  const id = createId();
3176
3185
  const metadata = parent.actionMetadata();
3177
- const profileName = input.profileName ?? (this.options.profiles ? profile.name : null);
3186
+ const profileName = input.profileName ?? null;
3178
3187
  const spawnedAt = Date.now();
3179
3188
  const canSpawnSubagents = !input.isSpawnForbidden && profile.canSpawnSubagents !== false;
3180
3189
  const { job, runtime } = this.assembleJob({
@@ -3279,7 +3288,8 @@ var ChildSupervisor = class ChildSupervisor {
3279
3288
  },
3280
3289
  tools: () => createStandardAgentTools({
3281
3290
  environment: (ctx) => this.childEnvironment(job, ctx),
3282
- scheduleYield: (ctx, durationMs) => job.session.scheduleYieldWakeup(durationMs, ctx.metadata)
3291
+ scheduleYield: (ctx, durationMs) => job.session.scheduleYieldWakeup(durationMs, ctx.metadata),
3292
+ ...this.options.shellPreviewBudgetTokens === null ? {} : { previewBudgetTokens: this.options.shellPreviewBudgetTokens }
3283
3293
  })
3284
3294
  }
3285
3295
  };
@@ -3586,25 +3596,20 @@ var ChildSupervisor = class ChildSupervisor {
3586
3596
  commands: job.commandRegistry
3587
3597
  });
3588
3598
  }
3599
+ /**
3600
+ * No name means the unnamed inherit profile: the parent harness, model, Host
3601
+ * and commands, always available and never configurable. A name must match a
3602
+ * declared profile; "default" is not a name.
3603
+ */
3589
3604
  resolveProfile(name) {
3590
- const profiles = this.options.profiles;
3591
- const implicitDefault = {
3592
- name: "default",
3593
- description: "Inherits the parent harness, model, Host, and commands."
3594
- };
3595
- if (!profiles || profiles.length === 0) {
3596
- if (name !== void 0 && name !== "default") throw new Error(`unknown profile "${name}" (available: default)`);
3597
- return implicitDefault;
3598
- }
3599
- const target = name ?? "default";
3600
- const profile = profiles.find((candidate) => candidate.name === target);
3605
+ if (name === void 0) return INHERIT_PROFILE;
3606
+ const profile = this.options.profiles?.find((candidate) => candidate.name === name);
3601
3607
  if (profile) return profile;
3602
- if (name === void 0) return implicitDefault;
3603
- throw new Error(`unknown profile "${name}" (available: ${this.configuredProfileNames().join(", ")})`);
3608
+ const names = this.configuredProfileNames();
3609
+ throw new Error(`unknown profile "${name}" (available: ${names.length > 0 ? names.join(", ") : "none; omit --profile to inherit the parent"})`);
3604
3610
  }
3605
3611
  configuredProfileNames() {
3606
- const names = (this.options.profiles ?? []).map((profile) => profile.name);
3607
- return names.includes("default") ? names : ["default", ...names];
3612
+ return (this.options.profiles ?? []).map((profile) => profile.name);
3608
3613
  }
3609
3614
  subagentPreamble(childId) {
3610
3615
  return [
@@ -3710,7 +3715,7 @@ var ChildSupervisor = class ChildSupervisor {
3710
3715
  job.phase,
3711
3716
  `up ${formatDuration(now - job.spawnedAt)}`,
3712
3717
  `last-event ${formatDuration(now - job.lastEventAt)} ago`,
3713
- `profile=${job.profileName ?? "default"}`,
3718
+ `profile=${job.profileName ?? INHERIT_PROFILE_LABEL}`,
3714
3719
  job.description ? `"${job.description}"` : "(no description)",
3715
3720
  `execution=${execution}`,
3716
3721
  `activity=${this.activityOf(job, execution)}`
@@ -3723,7 +3728,7 @@ var ChildSupervisor = class ChildSupervisor {
3723
3728
  `id: ${job.id}`,
3724
3729
  `parent: ${this.ownerId()}`,
3725
3730
  `description: ${job.description || "(none)"}`,
3726
- `profile: ${job.profileName ?? "default"}`,
3731
+ `profile: ${job.profileName ?? INHERIT_PROFILE_LABEL}`,
3727
3732
  `phase: ${job.phase}`,
3728
3733
  `elapsed: ${formatDuration(now - job.spawnedAt)}`,
3729
3734
  `execution: ${execution} (for ${formatDuration(this.executionForMs(job, execution, now))})`,
@@ -3920,6 +3925,7 @@ var AgentServer = class {
3920
3925
  prepareShell;
3921
3926
  notifyParentOnIdle;
3922
3927
  maxLiveSubagents;
3928
+ shellPreviewBudgetTokens;
3923
3929
  bindings = /* @__PURE__ */ new Set();
3924
3930
  sessionOwnership = new SessionOwnershipRegistry();
3925
3931
  constructor(options) {
@@ -3930,6 +3936,7 @@ var AgentServer = class {
3930
3936
  this.prepareShell = options.prepareShell ?? null;
3931
3937
  this.notifyParentOnIdle = options.subagents?.notifyParentOnIdle ?? true;
3932
3938
  this.maxLiveSubagents = options.subagents?.maxLiveSubagents ?? 8;
3939
+ this.shellPreviewBudgetTokens = options.tools?.shellPreviewBudgetTokens ?? null;
3933
3940
  }
3934
3941
  client() {
3935
3942
  const transports = createInProcessTransportPair();
@@ -3946,6 +3953,7 @@ var AgentServer = class {
3946
3953
  prepareShell: this.prepareShell,
3947
3954
  notifyParentOnIdle: this.notifyParentOnIdle,
3948
3955
  maxLiveSubagents: this.maxLiveSubagents,
3956
+ shellPreviewBudgetTokens: this.shellPreviewBudgetTokens,
3949
3957
  sessions: this.sessionOwnership
3950
3958
  });
3951
3959
  this.bindings.add(binding);
@@ -3997,6 +4005,7 @@ var AgentTransportBindingImpl = class {
3997
4005
  prepareShell;
3998
4006
  notifyParentOnIdle;
3999
4007
  maxLiveSubagents;
4008
+ shellPreviewBudgetTokens;
4000
4009
  sessions;
4001
4010
  session = null;
4002
4011
  currentAgent = null;
@@ -4020,6 +4029,7 @@ var AgentTransportBindingImpl = class {
4020
4029
  this.prepareShell = options.prepareShell;
4021
4030
  this.notifyParentOnIdle = options.notifyParentOnIdle;
4022
4031
  this.maxLiveSubagents = options.maxLiveSubagents;
4032
+ this.shellPreviewBudgetTokens = options.shellPreviewBudgetTokens;
4023
4033
  this.sessions = options.sessions;
4024
4034
  this.unsubscribeTransport = this.transport.onFrame((frame) => {
4025
4035
  this.handleFrame(frame);
@@ -4245,6 +4255,7 @@ var AgentTransportBindingImpl = class {
4245
4255
  storePrefix: `agent-sessions/${agentSessionId}`,
4246
4256
  directory,
4247
4257
  maxLiveSubagents: this.maxLiveSubagents,
4258
+ shellPreviewBudgetTokens: this.shellPreviewBudgetTokens,
4248
4259
  canSpawn: true,
4249
4260
  onJobsChanged: null,
4250
4261
  emit: (subagentFrame) => this.send(subagentFrame)
@@ -4259,7 +4270,8 @@ var AgentTransportBindingImpl = class {
4259
4270
  scheduleYield: (ctx, durationMs) => {
4260
4271
  if (!sessionRef) throw new Error("AgentServer: session is not ready for yield scheduling");
4261
4272
  return sessionRef.scheduleYieldWakeup(durationMs, ctx.metadata);
4262
- }
4273
+ },
4274
+ ...this.shellPreviewBudgetTokens === null ? {} : { previewBudgetTokens: this.shellPreviewBudgetTokens }
4263
4275
  });
4264
4276
  const commandsPrompt = commandRegistry.renderHelp();
4265
4277
  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.24.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.24.0",
23
+ "@demicodes/provider": "^0.24.0",
24
+ "@demicodes/shell": "^0.24.0",
25
+ "@demicodes/utils": "^0.24.0",
26
26
  "zod": "^4.0.0"
27
27
  },
28
28
  "license": "Apache-2.0",