@theokit/agents 0.29.0 → 0.30.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.
@@ -9,9 +9,11 @@ import {
9
9
  TOOL_METHODS,
10
10
  Trace,
11
11
  getAgentConfig,
12
+ getCheckpointConfig,
12
13
  getCompactionConfig,
13
14
  getContextWindowConfig,
14
15
  getGatewayConfig,
16
+ getHumanInTheLoopConfig,
15
17
  getMcpConfig,
16
18
  getMemoryConfig,
17
19
  getMeta,
@@ -19,7 +21,7 @@ import {
19
21
  getProjectContextConfig,
20
22
  getSkillsConfig,
21
23
  getSubAgents
22
- } from "./chunk-GVPUUKKE.js";
24
+ } from "./chunk-FI6ZG2YP.js";
23
25
  import {
24
26
  __name
25
27
  } from "./chunk-7QVYU63E.js";
@@ -117,7 +119,8 @@ var AgentWarningCode = {
117
119
  FILTER_METADATA_ONLY: "THEO_AGENT_FILTER_METADATA_ONLY",
118
120
  BUDGET_TOP_LEVEL_METADATA_ONLY: "THEO_AGENT_BUDGET_TOP_LEVEL_METADATA_ONLY",
119
121
  CONTEXT_STRATEGY_METADATA_ONLY: "THEO_AGENT_CONTEXT_STRATEGY_METADATA_ONLY",
120
- PROJECT_CONTEXT_KNOB_METADATA_ONLY: "THEO_AGENT_PROJECT_CONTEXT_KNOB_METADATA_ONLY"
122
+ PROJECT_CONTEXT_KNOB_METADATA_ONLY: "THEO_AGENT_PROJECT_CONTEXT_KNOB_METADATA_ONLY",
123
+ CHECKPOINT_STORAGE_METADATA_ONLY: "THEO_AGENT_CHECKPOINT_STORAGE_METADATA_ONLY"
121
124
  };
122
125
  var reflectorInstance = new Reflector();
123
126
  function walkToolbox(ToolboxClass) {
@@ -145,7 +148,8 @@ function walkToolbox(ToolboxClass) {
145
148
  capabilities: void 0,
146
149
  budget: void 0,
147
150
  trace: traceVal ?? false,
148
- audit: auditVal ?? false
151
+ audit: auditVal ?? false,
152
+ hitl: getHumanInTheLoopConfig(ToolboxClass, propertyKey)
149
153
  };
150
154
  });
151
155
  return {
@@ -171,6 +175,12 @@ function warnUnmappedDecoratorKnobs(agentName, contextWindow, projectContext) {
171
175
  }
172
176
  }
173
177
  __name(warnUnmappedDecoratorKnobs, "warnUnmappedDecoratorKnobs");
178
+ function warnNonDurableCheckpoint(agentName, checkpoint) {
179
+ if (checkpoint && checkpoint.storage !== "filesystem") {
180
+ console.warn(`[${AgentWarningCode.CHECKPOINT_STORAGE_METADATA_ONLY}] Agent ${agentName}: @Checkpoint({ storage: '${checkpoint.storage ?? "memory"}' }) does NOT resume across requests \u2014 only 'filesystem' selects the SDK's durable conversation store. Use @Checkpoint({ storage: 'filesystem' }) for cross-request resume.`);
181
+ }
182
+ }
183
+ __name(warnNonDurableCheckpoint, "warnNonDurableCheckpoint");
174
184
  var agentWalkCache = /* @__PURE__ */ new WeakMap();
175
185
  function walkAgentMetadata(AgentClass, toolboxClasses = []) {
176
186
  if (toolboxClasses.length === 0) {
@@ -208,6 +218,8 @@ function walkAgentMetadata(AgentClass, toolboxClasses = []) {
208
218
  const projectContext = getProjectContextConfig(AgentClass);
209
219
  warnUnmappedDecoratorKnobs(AgentClass.name, contextWindow, projectContext);
210
220
  const compaction = getCompactionConfig(AgentClass);
221
+ const checkpoint = getCheckpointConfig(AgentClass);
222
+ warnNonDurableCheckpoint(AgentClass.name, checkpoint);
211
223
  const result = {
212
224
  agentConfig,
213
225
  mainLoop,
@@ -223,7 +235,8 @@ function walkAgentMetadata(AgentClass, toolboxClasses = []) {
223
235
  contextWindow,
224
236
  projectContext,
225
237
  mcpServers,
226
- compaction
238
+ compaction,
239
+ checkpoint
227
240
  };
228
241
  if (toolboxClasses.length === 0) {
229
242
  agentWalkCache.set(AgentClass, result);
@@ -258,6 +271,22 @@ function compileSkills(options) {
258
271
  __name(compileSkills, "compileSkills");
259
272
 
260
273
  // src/bridge/agent-compiler.ts
274
+ function toolRuntimeName(namespace, toolName) {
275
+ return namespace ? `${namespace}.${toolName}` : toolName;
276
+ }
277
+ __name(toolRuntimeName, "toolRuntimeName");
278
+ function compileHitlGates(toolboxes) {
279
+ const gates = /* @__PURE__ */ new Map();
280
+ for (const tb of toolboxes) {
281
+ for (const tool of tb.tools) {
282
+ if (tool.hitl) {
283
+ gates.set(toolRuntimeName(tb.namespace, tool.config.name), tool.hitl);
284
+ }
285
+ }
286
+ }
287
+ return gates;
288
+ }
289
+ __name(compileHitlGates, "compileHitlGates");
261
290
  function compileTools(toolboxes, toolboxInstances) {
262
291
  const tools = [];
263
292
  for (const tb of toolboxes) {
@@ -270,7 +299,7 @@ function compileTools(toolboxes, toolboxInstances) {
270
299
  if (typeof handler !== "function") {
271
300
  throw new Error(`[@theokit/agents] Toolbox ${tb.class.name}: '${String(tool.propertyKey)}' is not a function.`);
272
301
  }
273
- const name = tb.namespace ? `${tb.namespace}.${tool.config.name}` : tool.config.name;
302
+ const name = toolRuntimeName(tb.namespace, tool.config.name);
274
303
  tools.push({
275
304
  name,
276
305
  description: tool.config.description,
@@ -298,6 +327,7 @@ __name(compileSubAgents, "compileSubAgents");
298
327
  function compileAgent(walkResult, toolboxInstances = /* @__PURE__ */ new Map()) {
299
328
  const tools = compileTools(walkResult.toolboxes, toolboxInstances);
300
329
  const agents = compileSubAgents(walkResult.subAgentClasses);
330
+ const hitl = compileHitlGates(walkResult.toolboxes);
301
331
  return {
302
332
  model: walkResult.agentConfig.model,
303
333
  reasoningEffort: walkResult.agentConfig.reasoningEffort,
@@ -314,7 +344,9 @@ function compileAgent(walkResult, toolboxInstances = /* @__PURE__ */ new Map())
314
344
  mcpServers: walkResult.mcpServers,
315
345
  maxIterations: walkResult.mainLoop.maxIterations ?? walkResult.agentConfig.maxIterations,
316
346
  timeoutMs: walkResult.mainLoop.timeoutMs ?? walkResult.agentConfig.timeoutMs,
317
- stream: walkResult.agentConfig.stream ?? true
347
+ stream: walkResult.agentConfig.stream ?? true,
348
+ hitl: hitl.size > 0 ? hitl : void 0,
349
+ checkpoint: walkResult.checkpoint
318
350
  };
319
351
  }
320
352
  __name(compileAgent, "compileAgent");
@@ -940,6 +972,25 @@ function buildExtraCreateOptions(overrides, compiled) {
940
972
  return extra;
941
973
  }
942
974
  __name(buildExtraCreateOptions, "buildExtraCreateOptions");
975
+ async function loadSdkRuntime() {
976
+ try {
977
+ const sdk = await import("@theokit/sdk");
978
+ const InMemory = sdk.InMemoryConversationStorage;
979
+ return {
980
+ Agent: sdk.Agent,
981
+ defineTool: sdk.defineTool,
982
+ InMemoryConversationStorage: InMemory,
983
+ FileSystemConversationStorage: "FileSystemConversationStorage" in sdk ? sdk.FileSystemConversationStorage : InMemory
984
+ };
985
+ } catch {
986
+ return null;
987
+ }
988
+ }
989
+ __name(loadSdkRuntime, "loadSdkRuntime");
990
+ function newConversationStorage(compiled, InMemory, FileSystem) {
991
+ return compiled.checkpoint?.storage === "filesystem" ? new FileSystem() : new InMemory();
992
+ }
993
+ __name(newConversationStorage, "newConversationStorage");
943
994
  function createAsyncQueue() {
944
995
  const items = [];
945
996
  let wake = null;
@@ -1090,15 +1141,8 @@ function createSdkAgentStream(compiled, compiledTools, apiKey, overrides = {}) {
1090
1141
  async *[Symbol.asyncIterator]() {
1091
1142
  const runId = `run-${Date.now()}`;
1092
1143
  const t0 = Date.now();
1093
- let Agent;
1094
- let defineTool;
1095
- let InMemoryConversationStorage;
1096
- try {
1097
- const sdk = await import("@theokit/sdk");
1098
- Agent = sdk.Agent;
1099
- defineTool = sdk.defineTool;
1100
- InMemoryConversationStorage = sdk.InMemoryConversationStorage;
1101
- } catch {
1144
+ const rt = await loadSdkRuntime();
1145
+ if (!rt) {
1102
1146
  yield {
1103
1147
  type: "error",
1104
1148
  code: "SDK_NOT_INSTALLED",
@@ -1107,6 +1151,7 @@ function createSdkAgentStream(compiled, compiledTools, apiKey, overrides = {}) {
1107
1151
  };
1108
1152
  return;
1109
1153
  }
1154
+ const { Agent, defineTool, InMemoryConversationStorage, FileSystemConversationStorage } = rt;
1110
1155
  const sdkTools = buildSdkTools(compiledTools, defineTool, overrides.sdkTools);
1111
1156
  let agent;
1112
1157
  try {
@@ -1116,7 +1161,7 @@ function createSdkAgentStream(compiled, compiledTools, apiKey, overrides = {}) {
1116
1161
  cwd: overrides.cwd
1117
1162
  };
1118
1163
  const extra = buildExtraCreateOptions(overrides, compiled);
1119
- storage ??= new InMemoryConversationStorage();
1164
+ storage ??= newConversationStorage(compiled, InMemoryConversationStorage, FileSystemConversationStorage);
1120
1165
  if (applied.length > 0) {
1121
1166
  console.debug("[THEO_AGENT_M8_RUNTIME_APPLIED]", {
1122
1167
  skills: applied.includes("skills"),
@@ -1220,6 +1265,36 @@ function* emitToolResult(event, seen) {
1220
1265
  }
1221
1266
  }
1222
1267
  __name(emitToolResult, "emitToolResult");
1268
+ function* emitApprovalRequest(event, seen) {
1269
+ if (!seen.has(event.callId)) {
1270
+ seen.add(event.callId);
1271
+ yield {
1272
+ type: "tool-input-available",
1273
+ toolCallId: event.callId,
1274
+ toolName: event.toolName,
1275
+ input: event.input ?? {},
1276
+ dynamic: true
1277
+ };
1278
+ }
1279
+ yield {
1280
+ type: "tool-approval-request",
1281
+ approvalId: event.callId,
1282
+ toolCallId: event.callId
1283
+ };
1284
+ }
1285
+ __name(emitApprovalRequest, "emitApprovalRequest");
1286
+ function* emitCheckpointSaved(event) {
1287
+ yield {
1288
+ type: "data-checkpoint",
1289
+ data: {
1290
+ checkpointId: event.checkpointId,
1291
+ resumeToken: event.resumeToken,
1292
+ step: event.step
1293
+ },
1294
+ transient: true
1295
+ };
1296
+ }
1297
+ __name(emitCheckpointSaved, "emitCheckpointSaved");
1223
1298
  async function* translateToUIMessageStream(events, opts) {
1224
1299
  yield {
1225
1300
  type: "start"
@@ -1265,9 +1340,15 @@ async function* translateToUIMessageStream(events, opts) {
1265
1340
  } else if (event.type === "tool_call") {
1266
1341
  yield* closeOpenBlock(state, opts.textId);
1267
1342
  yield* emitToolCall(event, seenToolCallIds);
1343
+ } else if (event.type === "approval_required") {
1344
+ yield* closeOpenBlock(state, opts.textId);
1345
+ yield* emitApprovalRequest(event, seenToolCallIds);
1268
1346
  } else if (event.type === "tool_result") {
1269
1347
  yield* closeOpenBlock(state, opts.textId);
1270
1348
  yield* emitToolResult(event, seenToolCallIds);
1349
+ } else if (event.type === "checkpoint_saved") {
1350
+ yield* closeOpenBlock(state, opts.textId);
1351
+ yield* emitCheckpointSaved(event);
1271
1352
  } else if (event.type === "error") {
1272
1353
  yield {
1273
1354
  type: "error",
@@ -1316,6 +1397,35 @@ function compileAgentDefinition(def) {
1316
1397
  }
1317
1398
  __name(compileAgentDefinition, "compileAgentDefinition");
1318
1399
 
1400
+ // src/bridge/hitl-plugin.ts
1401
+ function createHitlPlugin(wiring) {
1402
+ return {
1403
+ name: "theokit-hitl",
1404
+ register(ctx) {
1405
+ ctx.on("pre_tool_call", async (c) => {
1406
+ const opts = wiring.gated.get(c.name);
1407
+ if (!opts) return void 0;
1408
+ const approvalId = crypto.randomUUID();
1409
+ wiring.emit({
1410
+ type: "approval_required",
1411
+ callId: approvalId,
1412
+ toolName: c.name,
1413
+ question: opts.question,
1414
+ input: c.args,
1415
+ callbackUrl: `approve/${approvalId}`,
1416
+ timeoutMs: opts.timeout ?? 3e5
1417
+ });
1418
+ const approved = await wiring.awaitApproval(approvalId, opts);
1419
+ return approved ? void 0 : {
1420
+ block: true,
1421
+ message: `Tool '${c.name}' denied by human approver`
1422
+ };
1423
+ });
1424
+ }
1425
+ };
1426
+ }
1427
+ __name(createHitlPlugin, "createHitlPlugin");
1428
+
1319
1429
  // src/bridge/agent-endpoint.ts
1320
1430
  var AgentDefinitionError = class extends Error {
1321
1431
  static {
@@ -1339,7 +1449,12 @@ function compileAgentModule(mod, source = "agent module") {
1339
1449
  return compileAgentDefinition(def);
1340
1450
  }
1341
1451
  if (typeof def === "function" && getAgentConfig(def) !== void 0) {
1342
- return compileAgent(walkAgentMetadata(def));
1452
+ const walk = walkAgentMetadata(def, getMixins(def));
1453
+ const instances = /* @__PURE__ */ new Map();
1454
+ for (const tb of walk.toolboxes) {
1455
+ instances.set(tb.class, new tb.class());
1456
+ }
1457
+ return compileAgent(walk, instances);
1343
1458
  }
1344
1459
  throw new AgentDefinitionError(source);
1345
1460
  }
@@ -1348,10 +1463,106 @@ async function* asAgentStream(events) {
1348
1463
  for await (const e of events) yield e;
1349
1464
  }
1350
1465
  __name(asAgentStream, "asAgentStream");
1466
+ var EventQueue = class EventQueue2 {
1467
+ static {
1468
+ __name(this, "EventQueue");
1469
+ }
1470
+ #items = [];
1471
+ #resolvers = [];
1472
+ #closed = false;
1473
+ push(item) {
1474
+ if (this.#closed) return;
1475
+ const r = this.#resolvers.shift();
1476
+ if (r) r({
1477
+ value: item,
1478
+ done: false
1479
+ });
1480
+ else this.#items.push(item);
1481
+ }
1482
+ close() {
1483
+ this.#closed = true;
1484
+ for (const r of this.#resolvers.splice(0)) r({
1485
+ value: void 0,
1486
+ done: true
1487
+ });
1488
+ }
1489
+ async *drain() {
1490
+ for (; ; ) {
1491
+ if (this.#items.length > 0) {
1492
+ yield this.#items.shift();
1493
+ continue;
1494
+ }
1495
+ if (this.#closed) return;
1496
+ const next = await new Promise((resolve) => this.#resolvers.push(resolve));
1497
+ if (next.done) return;
1498
+ yield next.value;
1499
+ }
1500
+ }
1501
+ };
1502
+ async function* appendCheckpointSaved(source, sessionId) {
1503
+ let emitted = false;
1504
+ const checkpoint = /* @__PURE__ */ __name(() => ({
1505
+ type: "checkpoint_saved",
1506
+ checkpointId: crypto.randomUUID(),
1507
+ step: 0,
1508
+ resumeToken: sessionId
1509
+ }), "checkpoint");
1510
+ for await (const ev of source) {
1511
+ if (ev.type === "done" && !emitted) {
1512
+ emitted = true;
1513
+ yield checkpoint();
1514
+ }
1515
+ yield ev;
1516
+ }
1517
+ if (!emitted) yield checkpoint();
1518
+ }
1519
+ __name(appendCheckpointSaved, "appendCheckpointSaved");
1351
1520
  function streamAgentUIMessages(compiled, apiKey, input) {
1352
- const events = createSdkAgentStream(compiled, compiled.tools, apiKey)(input.message, input.sessionId);
1353
- return translateToUIMessageStream(asAgentStream(events), {
1354
- textId: crypto.randomUUID()
1521
+ const textId = crypto.randomUUID();
1522
+ const overrides = {};
1523
+ if (input.conversationStorage) overrides.conversationStorage = input.conversationStorage;
1524
+ let source;
1525
+ if (!input.hitl || input.hitl.gated.size === 0) {
1526
+ const events2 = createSdkAgentStream(compiled, compiled.tools, apiKey, overrides)(input.message, input.sessionId);
1527
+ source = asAgentStream(events2);
1528
+ } else {
1529
+ const queue = new EventQueue();
1530
+ input.signal?.addEventListener("abort", () => queue.close(), {
1531
+ once: true
1532
+ });
1533
+ const plugin = createHitlPlugin({
1534
+ gated: input.hitl.gated,
1535
+ emit: /* @__PURE__ */ __name((e) => queue.push(e), "emit"),
1536
+ awaitApproval: input.hitl.awaitApproval
1537
+ });
1538
+ const sdkStream = createSdkAgentStream(compiled, compiled.tools, apiKey, {
1539
+ ...overrides,
1540
+ // The HITL plugin is a structural @theokit/sdk Plugin (createHitlPlugin returns the
1541
+ // { name, register } shape); the RuntimeOverrides.plugins union is widened at the SDK edge.
1542
+ plugins: [
1543
+ plugin
1544
+ ]
1545
+ })(input.message, input.sessionId);
1546
+ void (async () => {
1547
+ try {
1548
+ for await (const e of sdkStream) queue.push(e);
1549
+ } catch (err) {
1550
+ queue.push({
1551
+ type: "error",
1552
+ code: "SDK_STREAM_ERROR",
1553
+ message: err instanceof Error ? err.message : String(err),
1554
+ retryable: false
1555
+ });
1556
+ } finally {
1557
+ queue.close();
1558
+ }
1559
+ })();
1560
+ source = queue.drain();
1561
+ }
1562
+ const durableCheckpoint = compiled.checkpoint?.storage === "filesystem";
1563
+ const events = durableCheckpoint ? appendCheckpointSaved(source, input.sessionId) : source;
1564
+ return translateToUIMessageStream(events, {
1565
+ textId
1355
1566
  });
1356
1567
  }
1357
1568
  __name(streamAgentUIMessages, "streamAgentUIMessages");
@@ -2101,4 +2312,4 @@ export {
2101
2312
  generateAgentManifest,
2102
2313
  agentsPlugin
2103
2314
  };
2104
- //# sourceMappingURL=chunk-4AN6LDJS.js.map
2315
+ //# sourceMappingURL=chunk-AUOCWGPS.js.map