@demicodes/agent 0.3.4 → 0.4.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 CHANGED
@@ -8,6 +8,8 @@ that the REPL and web UI both consume.
8
8
  - `AgentServer` — owns sessions; `server.client()` returns an in-process client.
9
9
  - `AgentClient` — `open` / `send` / `steer` / `abort` / `close` / `subscribe`.
10
10
  - Transports: in-process, stdio (`@demicodes/agent/stdio`), or WebSocket.
11
+ - Actions accept caller-defined `metadata` that is available to harness and
12
+ tool contexts without becoming transcript or provider content.
11
13
 
12
14
  ```ts
13
15
  import { AgentServer } from '@demicodes/agent'
@@ -1,4 +1,4 @@
1
- import { d as TranscriptPatch, l as ServerFrame, n as AgentServerTransport, o as ClientFrame, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandStatusLike } from "./transport-0l1a6QD9.mjs";
2
- import { a as AgentClientListener, i as AgentClient, n as createWebSocketClientTransport, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-C0R8AiHD.mjs";
1
+ import { d as TranscriptPatch, l as ServerFrame, n as AgentServerTransport, o as ClientFrame, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandStatusLike, y as AgentMetadata } from "./transport-qMjHM60a.mjs";
2
+ import { a as AgentClient, i as AgentActionOptions, n as createWebSocketClientTransport, o as AgentClientListener, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-Bf-hWn0D.mjs";
3
3
  import { ProviderSelection } from "@demicodes/provider";
4
- export { AgentClient, type AgentClientListener, type AgentClientTransport, type AgentServerTransport, type AgentTransport, type ClientFrame, type ClientSessionEvent, type JsonWebSocket, type ProviderSelection, type ServerFrame, type ShellCommandStatusLike, type TranscriptPatch, createWebSocketClientTransport, createWebSocketServerTransport };
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 };
@@ -1,2 +1,2 @@
1
- import { n as createWebSocketServerTransport, r as AgentClient, t as createWebSocketClientTransport } from "./websocket-transport-CcSuuo4T.mjs";
1
+ import { n as createWebSocketServerTransport, r as AgentClient, t as createWebSocketClientTransport } from "./websocket-transport-DajIApki.mjs";
2
2
  export { AgentClient, createWebSocketClientTransport, createWebSocketServerTransport };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as AgentToolInvokeResult, B as TurnRetryPolicy, C as AgentSessionParams, D as AgentTool, E as AgentSystemPromptContext, F as DrainedTranscriptPatches, H as resolveRetryPolicy, I as TranscriptLog, L as TranscriptOptions, M as SessionEvent, N as SessionEventListener, O as AgentToolContext, P as CompactionWindow, R as estimateTranscriptBlockTokens, S as AgentSessionOptions, T as AgentSessionStore, U as retryDelayMs, V as isRetryableCode, _ as AgentHarnessRuntime, a as createInProcessTransportPair, b as AgentReferenceResolveContext, c as ConversationSummary, d as TranscriptPatch, f as AbortResult, g as AgentHarnessContext, h as AgentHarness, i as InProcessTransportPair, j as ExternalMutationReservation, k as AgentToolInvokeContext, l as ServerFrame, m as AgentDisposeContext, n as AgentServerTransport, o as ClientFrame, p as AbortTarget, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandStatusLike, v as AgentLifecycleEvent, w as AgentSessionRestoreParams, x as AgentSessionCheckpoint, y as AgentPromptContext, z as DEFAULT_TURN_RETRY_POLICY } from "./transport-0l1a6QD9.mjs";
2
- import { a as AgentClientListener, i as AgentClient, n as createWebSocketClientTransport, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-C0R8AiHD.mjs";
1
+ import { A as AgentToolInvokeContext, B as DEFAULT_TURN_RETRY_POLICY, C as AgentSessionOptions, D as AgentSystemPromptContext, E as AgentSessionStore, F as CompactionWindow, H as isRetryableCode, I as DrainedTranscriptPatches, L as TranscriptLog, M as ExternalMutationReservation, N as SessionEvent, O as AgentTool, P as SessionEventListener, R as TranscriptOptions, S as AgentSessionCheckpoint, T as AgentSessionRestoreParams, U as resolveRetryPolicy, V as TurnRetryPolicy, W as retryDelayMs, _ as AgentHarnessRuntime, a as createInProcessTransportPair, b as AgentPromptContext, c as ConversationSummary, d as TranscriptPatch, f as AbortResult, g as AgentHarnessContext, h as AgentHarness, i as InProcessTransportPair, j as AgentToolInvokeResult, k as AgentToolContext, l as ServerFrame, m as AgentDisposeContext, n as AgentServerTransport, o as ClientFrame, p as AbortTarget, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandStatusLike, v as AgentLifecycleEvent, w as AgentSessionParams, x as AgentReferenceResolveContext, y as AgentMetadata, z as estimateTranscriptBlockTokens } from "./transport-qMjHM60a.mjs";
2
+ import { a as AgentClient, i as AgentActionOptions, n as createWebSocketClientTransport, o as AgentClientListener, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-Bf-hWn0D.mjs";
3
3
  import { BashAuditEvent, BashEnvironment, BashEnvironmentOptions, CommandMetadataRecord, Host, ShellCommandStatus, ShellOutputChunk } from "@demicodes/shell";
4
4
  import { AgentProvider, Provider } from "@demicodes/provider";
5
5
  import { Block, Model, ModelSelection, QueuedMessage, SessionPhase, UserContentBlock } from "@demicodes/core";
@@ -29,6 +29,7 @@ declare class AgentSession<State> {
29
29
  private activeTurnId;
30
30
  private activeTurnPhase;
31
31
  private activeProviderRun;
32
+ private activeMetadata;
32
33
  private readonly steerQueue;
33
34
  private readonly yields;
34
35
  private readonly compaction;
@@ -49,10 +50,17 @@ declare class AgentSession<State> {
49
50
  constructor(params: AgentSessionParams<State>, options?: AgentSessionOptions<State>);
50
51
  send(content: UserContentBlock[], options?: {
51
52
  id?: string;
53
+ metadata?: AgentMetadata;
54
+ }): Promise<void>;
55
+ retry(options?: {
56
+ metadata?: AgentMetadata;
57
+ }): Promise<void>;
58
+ resume(options?: {
59
+ metadata?: AgentMetadata;
60
+ }): Promise<void>;
61
+ compact(options?: {
62
+ metadata?: AgentMetadata;
52
63
  }): Promise<void>;
53
- retry(): Promise<void>;
54
- resume(): Promise<void>;
55
- compact(): Promise<void>;
56
64
  steer(content: UserContentBlock[], options?: {
57
65
  id?: string;
58
66
  }): Promise<void>;
@@ -71,7 +79,7 @@ declare class AgentSession<State> {
71
79
  */
72
80
  updateModel(provider: AgentProvider | null, model: ModelSelection): void;
73
81
  abort(): Promise<AbortResult>;
74
- scheduleYieldWakeup(durationMs: number): AgentToolInvokeResult;
82
+ scheduleYieldWakeup(durationMs: number, metadata?: AgentMetadata | null): AgentToolInvokeResult;
75
83
  waitUntilDone(): Promise<void>;
76
84
  /**
77
85
  * Tears the session down: aborts any in-flight turn and releases provider-held resources
@@ -279,4 +287,4 @@ interface ShellToolView {
279
287
  declare function finishShellToolResult<State>(environment: BashEnvironment, result: ShellCommandStatus, ctx: AgentToolInvokeContext<State>): Promise<AgentToolInvokeResult>;
280
288
  declare function shellCommandHandleRequired(result: ShellCommandStatus, budgetTokens: number): boolean;
281
289
  //#endregion
282
- export { AbortResult, AbortTarget, ActiveTurnPhase, AgentClient, AgentClientListener, AgentClientTransport, AgentDisposeContext, AgentHarness, AgentHarnessContext, AgentHarnessRuntime, AgentLifecycleEvent, AgentPromptContext, AgentReferenceResolveContext, AgentServer, AgentServerOptions, AgentServerSessionOptions, AgentServerTransport, AgentSession, AgentSessionCheckpoint, AgentSessionOptions, AgentSessionParams, AgentSessionRestoreParams, AgentSessionStore, AgentSystemPromptContext, AgentTool, AgentToolContext, AgentToolInvokeContext, AgentToolInvokeResult, AgentTransport, AgentTransportBinding, ClientFrame, ClientSessionEvent, CompactionWindow, ConversationSummary, DEFAULT_TURN_RETRY_POLICY, DrainedTranscriptPatches, ExternalMutationReservation, InProcessTransportPair, JsonWebSocket, PrepareSessionShell, PrepareSessionShellContext, RunCommandLineCommandNotRegisteredError, RunCommandLineOptions, RunCommandLineResult, RunCommandLineSessionNotFoundError, RunCommandLineTimeoutError, SHELL_VIEW_MAX_CHARS, ServerFrame, SessionEvent, SessionEventListener, ShellCommandStatusLike, ShellToolResultOptions, ShellToolView, StandardAgentToolOptions, TranscriptLog, TranscriptOptions, TranscriptPatch, TurnRetryPolicy, applyTranscriptPatches, cloneBlocks, createInProcessTransportPair, createStandardAgentTools, createWebSocketClientTransport, createWebSocketServerTransport, estimateTranscriptBlockTokens, finishShellToolResult, isRetryableCode, resolveRetryPolicy, retryDelayMs, shellCommandHandleRequired, shellPreviewBudgetTokens, toShellToolResult };
290
+ export { AbortResult, AbortTarget, ActiveTurnPhase, AgentActionOptions, AgentClient, AgentClientListener, AgentClientTransport, AgentDisposeContext, AgentHarness, AgentHarnessContext, AgentHarnessRuntime, AgentLifecycleEvent, AgentMetadata, AgentPromptContext, AgentReferenceResolveContext, AgentServer, AgentServerOptions, AgentServerSessionOptions, AgentServerTransport, AgentSession, AgentSessionCheckpoint, AgentSessionOptions, AgentSessionParams, AgentSessionRestoreParams, AgentSessionStore, AgentSystemPromptContext, AgentTool, AgentToolContext, AgentToolInvokeContext, AgentToolInvokeResult, AgentTransport, AgentTransportBinding, ClientFrame, ClientSessionEvent, CompactionWindow, ConversationSummary, DEFAULT_TURN_RETRY_POLICY, DrainedTranscriptPatches, ExternalMutationReservation, InProcessTransportPair, JsonWebSocket, PrepareSessionShell, PrepareSessionShellContext, RunCommandLineCommandNotRegisteredError, RunCommandLineOptions, RunCommandLineResult, RunCommandLineSessionNotFoundError, RunCommandLineTimeoutError, SHELL_VIEW_MAX_CHARS, ServerFrame, SessionEvent, SessionEventListener, ShellCommandStatusLike, ShellToolResultOptions, ShellToolView, StandardAgentToolOptions, TranscriptLog, TranscriptOptions, TranscriptPatch, TurnRetryPolicy, applyTranscriptPatches, cloneBlocks, createInProcessTransportPair, createStandardAgentTools, createWebSocketClientTransport, createWebSocketServerTransport, estimateTranscriptBlockTokens, finishShellToolResult, 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, r as AgentClient, t as createWebSocketClientTransport } from "./websocket-transport-CcSuuo4T.mjs";
1
+ import { a as cloneBlocks, i as applyTranscriptPatches, n as createWebSocketServerTransport, r as AgentClient, t as createWebSocketClientTransport } from "./websocket-transport-DajIApki.mjs";
2
2
  import { AbortError, abortable, asError, asRecord, asString, bytesToBase64, createId, delay, isAbortError, isRecord, noop, parseJsonOrString, safeJsonStringify, throwIfAborted, truncate } from "@demicodes/utils";
3
3
  import { BashEnvironment, CommandRegistry, MAX_TIMEOUT_MS, heredocDelimiter, shellQuote } from "@demicodes/shell";
4
4
  import { providerRuntime } from "@demicodes/provider";
@@ -621,14 +621,15 @@ var YieldScheduler = class {
621
621
  return this.pending.length > 0;
622
622
  }
623
623
  /** Registers a new (unarmed) wakeup and returns its id. */
624
- schedule(durationMs) {
624
+ schedule(durationMs, metadata) {
625
625
  const id = this.idFactory();
626
626
  this.pending.push({
627
627
  id,
628
628
  durationMs,
629
629
  timer: null,
630
630
  dueAt: null,
631
- armed: false
631
+ armed: false,
632
+ metadata
632
633
  });
633
634
  return id;
634
635
  }
@@ -639,7 +640,7 @@ var YieldScheduler = class {
639
640
  if (wakeup.armed) continue;
640
641
  wakeup.armed = true;
641
642
  wakeup.dueAt = now + wakeup.durationMs;
642
- wakeup.timer = setTimeout(() => this.onFire(wakeup.id), wakeup.durationMs);
643
+ wakeup.timer = setTimeout(() => this.onFire(wakeup.id, wakeup.metadata), wakeup.durationMs);
643
644
  }
644
645
  }
645
646
  /** Removes the wakeup with `wakeupId` (clearing its timer); returns whether it existed. */
@@ -1041,7 +1042,8 @@ var ProviderTurnLoop = class {
1041
1042
  transcript: this.host.transcript,
1042
1043
  toolCallId: toolCall.toolUseId,
1043
1044
  toolName: toolCall.toolName,
1044
- result
1045
+ result,
1046
+ metadata: this.host.metadata
1045
1047
  });
1046
1048
  await this.host.commitTranscript();
1047
1049
  if (!options.deferSteerMaterialization) await this.host.materializeSteersArrivedSince(steerContinuationBeforeTool);
@@ -1064,6 +1066,7 @@ var ProviderTurnLoop = class {
1064
1066
  model: this.host.model,
1065
1067
  toolCallId,
1066
1068
  signal,
1069
+ metadata: this.host.metadata,
1067
1070
  emitProgress: (progress) => {
1068
1071
  this.host.emit({
1069
1072
  type: "tool_progress",
@@ -1097,7 +1100,8 @@ var ProviderTurnLoop = class {
1097
1100
  return this.host.runtime.tools({
1098
1101
  agentSessionId: this.host.agentSessionId,
1099
1102
  state: this.host.agentState,
1100
- cwd: this.host.cwd
1103
+ cwd: this.host.cwd,
1104
+ metadata: this.host.metadata
1101
1105
  });
1102
1106
  }
1103
1107
  buildInferenceRequest() {
@@ -1163,6 +1167,7 @@ var AgentSession = class AgentSession {
1163
1167
  activeTurnId = null;
1164
1168
  activeTurnPhase = null;
1165
1169
  activeProviderRun = null;
1170
+ activeMetadata = null;
1166
1171
  steerQueue = new PendingSteerQueue();
1167
1172
  yields;
1168
1173
  compaction;
@@ -1182,7 +1187,7 @@ var AgentSession = class AgentSession {
1182
1187
  static fromCheckpoint(params, options = {}) {
1183
1188
  if (params.checkpoint.harnessName !== params.runtime.harnessName) throw new Error(`AgentSession: checkpoint harness "${params.checkpoint.harnessName}" does not match "${params.runtime.harnessName}"`);
1184
1189
  const checkpoint = params.checkpoint;
1185
- return new AgentSession({
1190
+ const session = new AgentSession({
1186
1191
  provider: params.provider,
1187
1192
  model: checkpoint.model,
1188
1193
  cwd: checkpoint.cwd,
@@ -1190,6 +1195,11 @@ var AgentSession = class AgentSession {
1190
1195
  transcript: checkpoint.transcript,
1191
1196
  state: checkpoint.state
1192
1197
  }, options);
1198
+ for (const toolCall of session.transcriptLog.pendingToolCalls()) session.transcriptLog.completeToolCall(toolCall.toolUseId, [{
1199
+ type: "text",
1200
+ text: `Tool call interrupted: ${toolCall.toolName} (the process died before a result was recorded)`
1201
+ }], true);
1202
+ return session;
1193
1203
  }
1194
1204
  constructor(params, options = {}) {
1195
1205
  this.provider = params.provider;
@@ -1199,8 +1209,8 @@ var AgentSession = class AgentSession {
1199
1209
  this.agentState = params.state === void 0 ? params.runtime.initialState() : params.state;
1200
1210
  this.agentSessionId = options.agentSessionId ?? createId();
1201
1211
  this.idFactory = options.idFactory ?? createId;
1202
- this.yields = new YieldScheduler(this.idFactory, (wakeupId) => {
1203
- this.deliverYieldWakeup(wakeupId);
1212
+ this.yields = new YieldScheduler(this.idFactory, (wakeupId, metadata) => {
1213
+ this.deliverYieldWakeup(wakeupId, metadata);
1204
1214
  });
1205
1215
  this.store = options.store;
1206
1216
  this.persistIntervalMs = options.persistIntervalMs ?? DEFAULT_PERSIST_INTERVAL_MS;
@@ -1278,6 +1288,9 @@ var AgentSession = class AgentSession {
1278
1288
  get retryPolicy() {
1279
1289
  return self.retryPolicy;
1280
1290
  },
1291
+ get metadata() {
1292
+ return self.activeMetadata;
1293
+ },
1281
1294
  currentSignal: () => self.currentSignal(),
1282
1295
  currentTurnId: () => self.currentTurnId(),
1283
1296
  nextRequestId: () => self.idFactory(),
@@ -1306,27 +1319,31 @@ var AgentSession = class AgentSession {
1306
1319
  type: "send",
1307
1320
  id,
1308
1321
  content,
1322
+ metadata: cloneMetadata(options.metadata),
1309
1323
  resolve: noop,
1310
1324
  reject: noop
1311
1325
  });
1312
1326
  }
1313
- retry() {
1327
+ retry(options = {}) {
1314
1328
  return this.enqueue({
1315
1329
  type: "retry",
1330
+ metadata: cloneMetadata(options.metadata),
1316
1331
  resolve: noop,
1317
1332
  reject: noop
1318
1333
  });
1319
1334
  }
1320
- resume() {
1335
+ resume(options = {}) {
1321
1336
  return this.enqueue({
1322
1337
  type: "resume",
1338
+ metadata: cloneMetadata(options.metadata),
1323
1339
  resolve: noop,
1324
1340
  reject: noop
1325
1341
  });
1326
1342
  }
1327
- compact() {
1343
+ compact(options = {}) {
1328
1344
  return this.enqueue({
1329
1345
  type: "compact",
1346
+ metadata: cloneMetadata(options.metadata),
1330
1347
  resolve: noop,
1331
1348
  reject: noop
1332
1349
  });
@@ -1429,8 +1446,8 @@ var AgentSession = class AgentSession {
1429
1446
  canAbortAgain: false
1430
1447
  };
1431
1448
  }
1432
- scheduleYieldWakeup(durationMs) {
1433
- const wakeupId = this.yields.schedule(durationMs);
1449
+ scheduleYieldWakeup(durationMs, metadata = this.activeMetadata) {
1450
+ const wakeupId = this.yields.schedule(durationMs, metadata);
1434
1451
  return {
1435
1452
  output: [{
1436
1453
  type: "text",
@@ -1589,13 +1606,13 @@ var AgentSession = class AgentSession {
1589
1606
  action.resolve();
1590
1607
  }
1591
1608
  }
1592
- async deliverYieldWakeup(wakeupId) {
1609
+ async deliverYieldWakeup(wakeupId, metadata) {
1593
1610
  if (!this.yields.take(wakeupId)) return;
1594
1611
  const content = [{
1595
1612
  type: "text",
1596
1613
  text: "Scheduled yield wakeup fired. Continue the previous work and inspect any running command with shell_status when needed."
1597
1614
  }];
1598
- if (this.canAcceptInternalSteer()) try {
1615
+ if (metadata === this.activeMetadata && this.canAcceptInternalSteer()) try {
1599
1616
  await this.steerInternal(content, wakeupId, true);
1600
1617
  return;
1601
1618
  } catch (error) {
@@ -1604,7 +1621,7 @@ var AgentSession = class AgentSession {
1604
1621
  error: asError(error)
1605
1622
  });
1606
1623
  }
1607
- this.enqueueHiddenSend(content);
1624
+ this.enqueueHiddenSend(content, metadata);
1608
1625
  }
1609
1626
  canAcceptInternalSteer() {
1610
1627
  try {
@@ -1636,11 +1653,12 @@ var AgentSession = class AgentSession {
1636
1653
  hidden
1637
1654
  });
1638
1655
  }
1639
- enqueueHiddenSend(content) {
1656
+ enqueueHiddenSend(content, metadata) {
1640
1657
  this.enqueue({
1641
1658
  type: "send",
1642
1659
  id: this.idFactory(),
1643
1660
  content,
1661
+ metadata,
1644
1662
  hidden: true,
1645
1663
  resolve: noop,
1646
1664
  reject: noop
@@ -1688,6 +1706,7 @@ var AgentSession = class AgentSession {
1688
1706
  if (action.type === "send") this.removeQueuedMessage(action.id);
1689
1707
  this.currentAbortController = new AbortController();
1690
1708
  this.activeTurnId = action.type === "send" ? action.id : this.idFactory();
1709
+ this.activeMetadata = action.metadata;
1691
1710
  this.abortRecorded = false;
1692
1711
  try {
1693
1712
  await this.executeAction(action);
@@ -1729,6 +1748,7 @@ var AgentSession = class AgentSession {
1729
1748
  this.discardPendingSteersForCurrentTurn();
1730
1749
  this.activeTurnPhase = "finalizing";
1731
1750
  this.activeProviderRun = null;
1751
+ this.activeMetadata = null;
1732
1752
  this.currentAbortController = null;
1733
1753
  this.activeTurnId = null;
1734
1754
  this.activeTurnPhase = null;
@@ -1803,7 +1823,8 @@ var AgentSession = class AgentSession {
1803
1823
  agentSessionId: this.agentSessionId,
1804
1824
  state: this.agentState,
1805
1825
  transcript: this.transcriptLog,
1806
- content
1826
+ content,
1827
+ metadata: this.activeMetadata
1807
1828
  });
1808
1829
  const resolvedContent = await this.resolveReferences(content);
1809
1830
  await this.applyPendingModelSwitch();
@@ -1822,7 +1843,8 @@ var AgentSession = class AgentSession {
1822
1843
  agentSessionId: this.agentSessionId,
1823
1844
  cwd: this.cwd,
1824
1845
  transcript: this.transcriptLog,
1825
- signal
1846
+ signal,
1847
+ metadata: this.activeMetadata
1826
1848
  }, content)), signal);
1827
1849
  }
1828
1850
  async executeRetry() {
@@ -1834,7 +1856,8 @@ var AgentSession = class AgentSession {
1834
1856
  agentSessionId: this.agentSessionId,
1835
1857
  state: this.agentState,
1836
1858
  transcript: this.transcriptLog,
1837
- reason: "retry"
1859
+ reason: "retry",
1860
+ metadata: this.activeMetadata
1838
1861
  });
1839
1862
  await this.commitTranscript();
1840
1863
  await this.applyPendingModelSwitch();
@@ -1870,7 +1893,8 @@ var AgentSession = class AgentSession {
1870
1893
  agentSessionId: this.agentSessionId,
1871
1894
  state: this.agentState,
1872
1895
  cwd: this.cwd,
1873
- transcript: this.transcriptLog
1896
+ transcript: this.transcriptLog,
1897
+ metadata: this.activeMetadata
1874
1898
  };
1875
1899
  }
1876
1900
  currentSignal() {
@@ -2017,6 +2041,9 @@ var AgentSession = class AgentSession {
2017
2041
  function textContentSummary(content) {
2018
2042
  return truncate(content.map((block) => block.type === "text" ? block.text : `[${block.type}]`).join("\n").trim(), 120, "...");
2019
2043
  }
2044
+ function cloneMetadata(metadata) {
2045
+ return metadata === void 0 ? null : structuredClone(metadata);
2046
+ }
2020
2047
  async function readProviderIterator(iterator, signal) {
2021
2048
  try {
2022
2049
  return await abortable(iterator.next(), signal);
@@ -2616,7 +2643,10 @@ var AgentTransportBindingImpl = class {
2616
2643
  case "send": {
2617
2644
  const session = this.sessionFor("send");
2618
2645
  if (!session) return;
2619
- this.observeSessionAction(session.send(frame.content, { id: frame.messageId }));
2646
+ this.observeSessionAction(session.send(frame.content, {
2647
+ id: frame.messageId,
2648
+ metadata: frame.metadata
2649
+ }));
2620
2650
  return;
2621
2651
  }
2622
2652
  case "dequeue_message": {
@@ -2709,19 +2739,19 @@ var AgentTransportBindingImpl = class {
2709
2739
  case "retry": {
2710
2740
  const session = this.sessionFor("retry");
2711
2741
  if (!session || this.rejectIfBusy(session, "retry")) return;
2712
- this.observeSessionAction(session.retry());
2742
+ this.observeSessionAction(session.retry({ metadata: frame.metadata }));
2713
2743
  return;
2714
2744
  }
2715
2745
  case "resume": {
2716
2746
  const session = this.sessionFor("resume");
2717
2747
  if (!session || this.rejectIfBusy(session, "resume")) return;
2718
- this.observeSessionAction(session.resume());
2748
+ this.observeSessionAction(session.resume({ metadata: frame.metadata }));
2719
2749
  return;
2720
2750
  }
2721
2751
  case "compact": {
2722
2752
  const session = this.sessionFor("compact");
2723
2753
  if (!session || this.rejectIfBusy(session, "compact")) return;
2724
- this.observeSessionAction(session.compact());
2754
+ this.observeSessionAction(session.compact({ metadata: frame.metadata }));
2725
2755
  return;
2726
2756
  }
2727
2757
  case "abort": {
@@ -2800,9 +2830,9 @@ var AgentTransportBindingImpl = class {
2800
2830
  let sessionRef = null;
2801
2831
  const tools = createStandardAgentTools({
2802
2832
  environment,
2803
- scheduleYield: (_ctx, durationMs) => {
2833
+ scheduleYield: (ctx, durationMs) => {
2804
2834
  if (!sessionRef) throw new Error("AgentServer: session is not ready for yield scheduling");
2805
- return sessionRef.scheduleYieldWakeup(durationMs);
2835
+ return sessionRef.scheduleYieldWakeup(durationMs, ctx.metadata);
2806
2836
  }
2807
2837
  });
2808
2838
  const commandsPrompt = commandRegistry.renderHelp();
@@ -1,4 +1,4 @@
1
- import { n as AgentServerTransport, t as AgentClientTransport } from "./transport-0l1a6QD9.mjs";
1
+ import { n as AgentServerTransport, t as AgentClientTransport } from "./transport-qMjHM60a.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,3 +1,4 @@
1
+ import { PortableJsonValue } from "@demicodes/utils";
1
2
  import { BashAuditEvent, Command, Host, ShellCommandStatus } from "@demicodes/shell";
2
3
  import { AgentProvider, InferenceItem, ProviderEvent, ProviderSelection, ToolDefinition } from "@demicodes/provider";
3
4
  import { Block, ModelSelection, QueuedMessage, SessionPhase, ToolResultContentBlock, Transcript, UserContentBlock } from "@demicodes/core";
@@ -127,11 +128,14 @@ declare class TranscriptLog implements Transcript {
127
128
  declare function estimateTranscriptBlockTokens(block: Block): number;
128
129
  //#endregion
129
130
  //#region src/types.d.ts
131
+ /** Caller-defined data carried with one agent action. Demi transports it without interpreting it. */
132
+ type AgentMetadata = Readonly<Record<string, PortableJsonValue>>;
130
133
  interface AgentPromptContext<State> {
131
134
  agentSessionId: string;
132
135
  state: State;
133
136
  cwd: string;
134
137
  transcript: TranscriptLog;
138
+ metadata: AgentMetadata | null;
135
139
  }
136
140
  interface AgentSystemPromptContext<State> extends AgentPromptContext<State> {
137
141
  /**
@@ -146,6 +150,7 @@ interface AgentToolContext<State> {
146
150
  agentSessionId: string;
147
151
  state: State;
148
152
  cwd: string;
153
+ metadata: AgentMetadata | null;
149
154
  }
150
155
  interface AgentDisposeContext<State> {
151
156
  agentSessionId: string;
@@ -159,6 +164,7 @@ interface AgentReferenceResolveContext<State> {
159
164
  cwd: string;
160
165
  transcript: TranscriptLog;
161
166
  signal: AbortSignal;
167
+ metadata: AgentMetadata | null;
162
168
  }
163
169
  interface AgentHarnessContext<State> {
164
170
  state: State;
@@ -182,6 +188,7 @@ interface AgentToolInvokeContext<State> {
182
188
  model: ModelSelection;
183
189
  toolCallId: string;
184
190
  signal: AbortSignal;
191
+ metadata: AgentMetadata | null;
185
192
  emitProgress(progress: unknown): void;
186
193
  }
187
194
  interface AgentToolInvokeResult {
@@ -206,6 +213,7 @@ type AgentLifecycleEvent<State> = {
206
213
  state: State;
207
214
  transcript: TranscriptLog;
208
215
  content: UserContentBlock[];
216
+ metadata: AgentMetadata | null;
209
217
  } | {
210
218
  type: 'after_tool_call';
211
219
  agentSessionId: string;
@@ -214,12 +222,14 @@ type AgentLifecycleEvent<State> = {
214
222
  toolCallId: string;
215
223
  toolName: string;
216
224
  result: AgentToolInvokeResult;
225
+ metadata: AgentMetadata | null;
217
226
  } | {
218
227
  type: 'after_transcript_rewrite';
219
228
  agentSessionId: string;
220
229
  state: State;
221
230
  transcript: TranscriptLog;
222
231
  reason: 'retry';
232
+ metadata: AgentMetadata | null;
223
233
  };
224
234
  interface AgentHarnessRuntime<State> {
225
235
  harnessName: string;
@@ -322,6 +332,7 @@ type ClientFrame = {
322
332
  type: 'send';
323
333
  messageId: string;
324
334
  content: UserContentBlock[];
335
+ metadata?: AgentMetadata;
325
336
  } | {
326
337
  type: 'dequeue_message';
327
338
  messageId: string;
@@ -348,10 +359,13 @@ type ClientFrame = {
348
359
  type: 'abort';
349
360
  } | {
350
361
  type: 'retry';
362
+ metadata?: AgentMetadata;
351
363
  } | {
352
364
  type: 'resume';
365
+ metadata?: AgentMetadata;
353
366
  } | {
354
367
  type: 'compact';
368
+ metadata?: AgentMetadata;
355
369
  } | {
356
370
  type: 'shell_write';
357
371
  commandId: string;
@@ -528,4 +542,4 @@ interface InProcessTransportPair {
528
542
  }
529
543
  declare function createInProcessTransportPair(): InProcessTransportPair;
530
544
  //#endregion
531
- export { AgentToolInvokeResult as A, TurnRetryPolicy as B, AgentSessionParams as C, AgentTool as D, AgentSystemPromptContext as E, DrainedTranscriptPatches as F, resolveRetryPolicy as H, TranscriptLog as I, TranscriptOptions as L, SessionEvent as M, SessionEventListener as N, AgentToolContext as O, CompactionWindow as P, estimateTranscriptBlockTokens as R, AgentSessionOptions as S, AgentSessionStore as T, retryDelayMs as U, isRetryableCode as V, AgentHarnessRuntime as _, createInProcessTransportPair as a, AgentReferenceResolveContext as b, ConversationSummary as c, TranscriptPatch as d, AbortResult as f, AgentHarnessContext as g, AgentHarness as h, InProcessTransportPair as i, ExternalMutationReservation as j, AgentToolInvokeContext as k, ServerFrame as l, AgentDisposeContext as m, AgentServerTransport as n, ClientFrame as o, AbortTarget as p, AgentTransport as r, ClientSessionEvent as s, AgentClientTransport as t, ShellCommandStatusLike as u, AgentLifecycleEvent as v, AgentSessionRestoreParams as w, AgentSessionCheckpoint as x, AgentPromptContext as y, DEFAULT_TURN_RETRY_POLICY as z };
545
+ export { AgentToolInvokeContext as A, DEFAULT_TURN_RETRY_POLICY as B, AgentSessionOptions as C, AgentSystemPromptContext as D, AgentSessionStore as E, CompactionWindow as F, isRetryableCode as H, DrainedTranscriptPatches as I, TranscriptLog as L, ExternalMutationReservation as M, SessionEvent as N, AgentTool as O, SessionEventListener as P, TranscriptOptions as R, AgentSessionCheckpoint as S, AgentSessionRestoreParams as T, resolveRetryPolicy as U, TurnRetryPolicy as V, retryDelayMs as W, AgentHarnessRuntime as _, createInProcessTransportPair as a, AgentPromptContext as b, ConversationSummary as c, TranscriptPatch as d, AbortResult as f, AgentHarnessContext as g, AgentHarness as h, InProcessTransportPair as i, AgentToolInvokeResult as j, AgentToolContext as k, ServerFrame as l, AgentDisposeContext as m, AgentServerTransport as n, ClientFrame as o, AbortTarget as p, AgentTransport as r, ClientSessionEvent as s, AgentClientTransport as t, ShellCommandStatusLike as u, AgentLifecycleEvent as v, AgentSessionParams as w, AgentReferenceResolveContext as x, AgentMetadata as y, estimateTranscriptBlockTokens as z };
@@ -1,8 +1,11 @@
1
- import { c as ConversationSummary, f as AbortResult, n as AgentServerTransport, s as ClientSessionEvent, t as AgentClientTransport } from "./transport-0l1a6QD9.mjs";
1
+ import { c as ConversationSummary, f as AbortResult, n as AgentServerTransport, s as ClientSessionEvent, t as AgentClientTransport, y as AgentMetadata } from "./transport-qMjHM60a.mjs";
2
2
  import { ProviderSelection } from "@demicodes/provider";
3
3
  import { Block, UserContentBlock } from "@demicodes/core";
4
4
  //#region src/client.d.ts
5
5
  type AgentClientListener = (event: ClientSessionEvent) => void;
6
+ interface AgentActionOptions {
7
+ metadata?: AgentMetadata;
8
+ }
6
9
  declare class AgentClient {
7
10
  private readonly transport;
8
11
  private readonly listeners;
@@ -19,8 +22,8 @@ declare class AgentClient {
19
22
  constructor(transport: AgentClientTransport);
20
23
  open(provider: ProviderSelection, cwd: string, sessionId: string): Promise<void>;
21
24
  listConversations(cwd: string): Promise<ConversationSummary[]>;
22
- sendMessage(content: UserContentBlock[]): Promise<void>;
23
- send(content: UserContentBlock[]): Promise<void>;
25
+ sendMessage(content: UserContentBlock[], options?: AgentActionOptions): Promise<void>;
26
+ send(content: UserContentBlock[], options?: AgentActionOptions): Promise<void>;
24
27
  dequeueMessage(messageId: string): void;
25
28
  sendQueuedMessage(messageId: string): void;
26
29
  steerQueuedMessage(messageId: string, options?: {
@@ -36,9 +39,9 @@ declare class AgentClient {
36
39
  * turn (the server applies it at a turn boundary), so this is fire-and-forget.
37
40
  */
38
41
  setProvider(provider: ProviderSelection): void;
39
- retry(): Promise<void>;
40
- resume(): Promise<void>;
41
- compact(): Promise<void>;
42
+ retry(options?: AgentActionOptions): Promise<void>;
43
+ resume(options?: AgentActionOptions): Promise<void>;
44
+ compact(options?: AgentActionOptions): Promise<void>;
42
45
  abort(): Promise<AbortResult>;
43
46
  shellWrite(commandId: string, stdin: string): Promise<void>;
44
47
  close(): Promise<void>;
@@ -84,4 +87,4 @@ interface JsonWebSocket {
84
87
  declare function createWebSocketClientTransport(socket: JsonWebSocket): AgentClientTransport;
85
88
  declare function createWebSocketServerTransport(socket: JsonWebSocket): AgentServerTransport;
86
89
  //#endregion
87
- export { AgentClientListener as a, AgentClient as i, createWebSocketClientTransport as n, createWebSocketServerTransport as r, JsonWebSocket as t };
90
+ export { AgentClient as a, AgentActionOptions as i, createWebSocketClientTransport as n, AgentClientListener as o, createWebSocketServerTransport as r, JsonWebSocket as t };
@@ -73,18 +73,19 @@ var AgentClient = class {
73
73
  });
74
74
  });
75
75
  }
76
- sendMessage(content) {
76
+ sendMessage(content, options = {}) {
77
77
  const messageId = globalThis.crypto.randomUUID();
78
78
  const wait = this.waitForAction("send", messageId);
79
79
  this.sendFrame({
80
80
  type: "send",
81
81
  messageId,
82
- content
82
+ content,
83
+ metadata: options.metadata
83
84
  });
84
85
  return wait;
85
86
  }
86
- send(content) {
87
- return this.sendMessage(content);
87
+ send(content, options = {}) {
88
+ return this.sendMessage(content, options);
88
89
  }
89
90
  dequeueMessage(messageId) {
90
91
  this.sendFrame({
@@ -147,19 +148,28 @@ var AgentClient = class {
147
148
  provider
148
149
  });
149
150
  }
150
- retry() {
151
+ retry(options = {}) {
151
152
  const wait = this.waitForAction("retry");
152
- this.sendFrame({ type: "retry" });
153
+ this.sendFrame({
154
+ type: "retry",
155
+ metadata: options.metadata
156
+ });
153
157
  return wait;
154
158
  }
155
- resume() {
159
+ resume(options = {}) {
156
160
  const wait = this.waitForAction("resume");
157
- this.sendFrame({ type: "resume" });
161
+ this.sendFrame({
162
+ type: "resume",
163
+ metadata: options.metadata
164
+ });
158
165
  return wait;
159
166
  }
160
- compact() {
167
+ compact(options = {}) {
161
168
  const wait = this.waitForAction("compact");
162
- this.sendFrame({ type: "compact" });
169
+ this.sendFrame({
170
+ type: "compact",
171
+ metadata: options.metadata
172
+ });
163
173
  return wait;
164
174
  }
165
175
  abort() {
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.3.4",
4
+ "version": "0.4.0",
5
5
  "private": false,
6
6
  "type": "module",
7
7
  "exports": {
@@ -20,9 +20,9 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@demicodes/core": "^0.3.2",
23
- "@demicodes/provider": "^0.4.2",
24
- "@demicodes/shell": "^0.3.2",
25
- "@demicodes/utils": "^0.3.2"
23
+ "@demicodes/provider": "^0.4.3",
24
+ "@demicodes/shell": "^0.3.3",
25
+ "@demicodes/utils": "^0.4.0"
26
26
  },
27
27
  "license": "Apache-2.0",
28
28
  "main": "./dist/index.mjs",