@theokit/sdk 2.25.0 → 2.27.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/dist/a2a/index.cjs +208 -4
  3. package/dist/a2a/index.cjs.map +1 -1
  4. package/dist/a2a/index.js +208 -4
  5. package/dist/a2a/index.js.map +1 -1
  6. package/dist/{cron-B44D-678.d.ts → cron-BR1NCSk1.d.cts} +11 -1
  7. package/dist/{cron-qI-dbG7c.d.cts → cron-DgEQCJ2i.d.ts} +11 -1
  8. package/dist/cron.cjs +187 -4
  9. package/dist/cron.cjs.map +1 -1
  10. package/dist/cron.d.cts +2 -2
  11. package/dist/cron.d.ts +2 -2
  12. package/dist/cron.js +187 -4
  13. package/dist/cron.js.map +1 -1
  14. package/dist/{errors-DRS-kqOK.d.ts → errors-CbY3pxY7.d.ts} +1 -1
  15. package/dist/{errors-DIKBXffg.d.cts → errors-DLMNb4Ka.d.cts} +1 -1
  16. package/dist/errors.d.cts +2 -2
  17. package/dist/eval.cjs +187 -4
  18. package/dist/eval.cjs.map +1 -1
  19. package/dist/eval.js +187 -4
  20. package/dist/eval.js.map +1 -1
  21. package/dist/index.cjs +483 -51
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +69 -7
  24. package/dist/index.d.ts +69 -7
  25. package/dist/index.js +481 -52
  26. package/dist/index.js.map +1 -1
  27. package/dist/internal/runtime/processors/run-processors.d.ts +10 -0
  28. package/dist/internal/runtime/processors/tripwire-run.d.ts +16 -0
  29. package/dist/internal/runtime/processors/wrap-output-run.d.ts +18 -0
  30. package/dist/internal/workflow/ctx.d.ts +6 -1
  31. package/dist/internal/workflow/event-stream.d.ts +13 -0
  32. package/dist/internal/workflow/executor-helpers.d.ts +30 -0
  33. package/dist/{run-Cr0C6cOM.d.cts → run-CdWiihyU.d.cts} +109 -2
  34. package/dist/{run-Cr0C6cOM.d.ts → run-CdWiihyU.d.ts} +109 -2
  35. package/dist/types/agent.d.ts +10 -0
  36. package/dist/types/index.d.ts +1 -0
  37. package/dist/types/processors.d.ts +84 -0
  38. package/dist/types/run-events.d.ts +11 -1
  39. package/dist/types/run.d.ts +12 -0
  40. package/dist/types/workflow.d.ts +134 -1
  41. package/dist/workflow.cjs +289 -45
  42. package/dist/workflow.cjs.map +1 -1
  43. package/dist/workflow.d.cts +42 -2
  44. package/dist/workflow.d.ts +42 -2
  45. package/dist/workflow.js +288 -46
  46. package/dist/workflow.js.map +1 -1
  47. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4333,7 +4333,7 @@ var init_batch = __esm({
4333
4333
  });
4334
4334
 
4335
4335
  // src/types/workflow.ts
4336
- var WorkflowDuplicateStepIdError, WorkflowAlreadyRunningError, WorkflowSnapshotNotFoundError, WorkflowMaxIterationsExceededError, WorkflowNotSerializableError, WorkflowResumeStepNotFoundError, WorkflowParallelError, WorkflowCompensateNotImplementedError;
4336
+ var WorkflowDuplicateStepIdError, WorkflowInputError, WorkflowOutputError, WorkflowStateError, WorkflowAlreadyRunningError, WorkflowSnapshotNotFoundError, WorkflowMaxIterationsExceededError, WorkflowNotSerializableError, WorkflowResumeStepNotFoundError, WorkflowParallelError, WorkflowCompensateNotImplementedError;
4337
4337
  var init_workflow = __esm({
4338
4338
  "src/types/workflow.ts"() {
4339
4339
  WorkflowDuplicateStepIdError = class extends Error {
@@ -4344,6 +4344,36 @@ var init_workflow = __esm({
4344
4344
  stepId;
4345
4345
  name = "WorkflowDuplicateStepIdError";
4346
4346
  };
4347
+ WorkflowInputError = class extends Error {
4348
+ constructor(workflowName, detail) {
4349
+ super(`Workflow "${workflowName}" input failed schema validation: ${detail}`);
4350
+ this.workflowName = workflowName;
4351
+ this.detail = detail;
4352
+ }
4353
+ workflowName;
4354
+ detail;
4355
+ name = "WorkflowInputError";
4356
+ };
4357
+ WorkflowOutputError = class extends Error {
4358
+ constructor(workflowName, detail) {
4359
+ super(`Workflow "${workflowName}" output failed schema validation: ${detail}`);
4360
+ this.workflowName = workflowName;
4361
+ this.detail = detail;
4362
+ }
4363
+ workflowName;
4364
+ detail;
4365
+ name = "WorkflowOutputError";
4366
+ };
4367
+ WorkflowStateError = class extends Error {
4368
+ constructor(workflowName, detail) {
4369
+ super(`Workflow "${workflowName}" state failed schema validation: ${detail}`);
4370
+ this.workflowName = workflowName;
4371
+ this.detail = detail;
4372
+ }
4373
+ workflowName;
4374
+ detail;
4375
+ name = "WorkflowStateError";
4376
+ };
4347
4377
  WorkflowAlreadyRunningError = class extends Error {
4348
4378
  constructor(workflowName, runId) {
4349
4379
  super(`Workflow "${workflowName}" run "${runId}" already in-flight.`);
@@ -4536,7 +4566,7 @@ var init_snapshot_store = __esm({
4536
4566
  });
4537
4567
 
4538
4568
  // src/internal/workflow/ctx.ts
4539
- function makeStepContext(runId, signal) {
4569
+ function makeStepContext(runId, signal, state4) {
4540
4570
  return {
4541
4571
  runId,
4542
4572
  signal,
@@ -4547,7 +4577,13 @@ function makeStepContext(runId, signal) {
4547
4577
  },
4548
4578
  suspend: async (payload) => {
4549
4579
  throw new WorkflowSuspendedSentinel(payload);
4550
- }
4580
+ },
4581
+ // SE29 — read reflects the current shared state; write goes through the
4582
+ // controller (which validates against `stateSchema`).
4583
+ get state() {
4584
+ return state4.getState();
4585
+ },
4586
+ setState: (next) => state4.setState(next)
4551
4587
  };
4552
4588
  }
4553
4589
  function emit(level, runId, msg, attrs) {
@@ -4600,6 +4636,57 @@ var init_error_shape = __esm({
4600
4636
  }
4601
4637
  });
4602
4638
 
4639
+ // src/internal/workflow/executor-helpers.ts
4640
+ function assembleRun(params) {
4641
+ return {
4642
+ id: params.runId,
4643
+ name: params.name,
4644
+ status: params.status,
4645
+ startedAt: params.startedAt,
4646
+ endedAt: Date.now(),
4647
+ stepResults: params.stepResults,
4648
+ ...params.output !== void 0 ? { output: params.output } : {},
4649
+ ...params.error !== void 0 ? { error: params.error } : {}
4650
+ };
4651
+ }
4652
+ function abortRun(name, runId, startedAt, stepResults, signal) {
4653
+ return assembleRun({
4654
+ runId,
4655
+ name,
4656
+ status: "cancelled",
4657
+ stepResults,
4658
+ startedAt,
4659
+ error: { name: "AbortError", message: String(signal.reason ?? "Aborted") }
4660
+ });
4661
+ }
4662
+ function validateWorkflowSchema(schema, value) {
4663
+ if (schema === void 0) return void 0;
4664
+ let parsed;
4665
+ try {
4666
+ parsed = schema.safeParse(value);
4667
+ } catch {
4668
+ return "schema uses async refinements, which whole-workflow validation does not support (use a synchronous Zod schema)";
4669
+ }
4670
+ if (parsed.success) return void 0;
4671
+ return parsed.error.issues.map((issue) => `${issue.path.join(".") || "(root)"}: ${issue.message}`).join("; ");
4672
+ }
4673
+ function makeStateController(options, initial) {
4674
+ let current = initial;
4675
+ return {
4676
+ getState: () => current,
4677
+ setState: (next) => {
4678
+ const issues = validateWorkflowSchema(options.stateSchema, next);
4679
+ if (issues !== void 0) throw new WorkflowStateError(options.name, issues);
4680
+ current = next;
4681
+ }
4682
+ };
4683
+ }
4684
+ var init_executor_helpers = __esm({
4685
+ "src/internal/workflow/executor-helpers.ts"() {
4686
+ init_workflow();
4687
+ }
4688
+ });
4689
+
4603
4690
  // src/internal/workflow/run-id.ts
4604
4691
  function mintRunId() {
4605
4692
  return `wfr-${globalThis.crypto.randomUUID().replace(/-/g, "").slice(0, 8)}`;
@@ -5266,6 +5353,8 @@ async function handleSuspend(err, ctx) {
5266
5353
  suspendedPayload: err.payload,
5267
5354
  stepResults: ctx.stepResults,
5268
5355
  accumulatedInput: ctx.acc,
5356
+ state: ctx.stepCtx.state,
5357
+ // SE29 — capture the shared state at suspend
5269
5358
  options: ctx.options
5270
5359
  });
5271
5360
  } catch (snapErr) {
@@ -5317,7 +5406,7 @@ async function runOneStep(args) {
5317
5406
  result = await dispatchStep(args.step, args.acc, args.ctx, args.options, args.stepResults);
5318
5407
  } catch (err) {
5319
5408
  if (err instanceof WorkflowSuspendedSentinel) {
5320
- const outcome = await handleSuspend(err, { ...args, stepSpan });
5409
+ const outcome = await handleSuspend(err, { ...args, stepSpan, stepCtx: args.ctx });
5321
5410
  return { kind: "terminal", run: outcome.run };
5322
5411
  }
5323
5412
  result = {
@@ -5334,22 +5423,42 @@ async function runOneStep(args) {
5334
5423
  stepSpan.end();
5335
5424
  return { kind: "ok", result };
5336
5425
  }
5337
- function abortRun(name, runId, startedAt, stepResults, signal) {
5338
- return assembleRun({
5339
- runId,
5340
- name,
5341
- status: "cancelled",
5342
- stepResults,
5343
- startedAt,
5344
- error: { name: "AbortError", message: String(signal.reason ?? "Aborted") }
5345
- });
5426
+ function handleStepOutcome(outcome, step, loop, onStepEvent) {
5427
+ if (outcome.kind === "terminal") {
5428
+ if (outcome.run.status === "suspended") {
5429
+ onStepEvent?.({ type: "workflow_suspended", stepId: step.id });
5430
+ }
5431
+ return { terminal: outcome.run };
5432
+ }
5433
+ loop.stepResults.push(outcome.result);
5434
+ if (outcome.result.status === "failed") {
5435
+ onStepEvent?.({
5436
+ type: "step_failed",
5437
+ stepId: step.id,
5438
+ error: outcome.result.error ?? { name: "WorkflowStepError", message: "step failed" }
5439
+ });
5440
+ return {
5441
+ terminal: assembleRun({
5442
+ runId: loop.runId,
5443
+ name: loop.name,
5444
+ status: "failed",
5445
+ stepResults: loop.stepResults,
5446
+ startedAt: loop.startedAt,
5447
+ error: outcome.result.error
5448
+ })
5449
+ };
5450
+ }
5451
+ onStepEvent?.({ type: "step_completed", stepId: step.id, output: outcome.result.output });
5452
+ return { acc: outcome.result.output };
5346
5453
  }
5347
5454
  async function runStepsLoop(params) {
5348
- const { options, steps, ctx, runId, startedAt, signal } = params;
5455
+ const { options, steps, ctx, runId, startedAt, signal, onStepEvent } = params;
5349
5456
  const stepResults = [...params.initialStepResults ?? []];
5457
+ const loop = { stepResults, runId, name: options.name, startedAt };
5350
5458
  let acc = params.input;
5351
5459
  for (const step of steps) {
5352
5460
  if (signal.aborted) return abortRun(options.name, runId, startedAt, stepResults, signal);
5461
+ onStepEvent?.({ type: "step_started", stepId: step.id });
5353
5462
  const outcome = await runOneStep({
5354
5463
  step,
5355
5464
  acc,
@@ -5360,20 +5469,22 @@ async function runStepsLoop(params) {
5360
5469
  name: options.name,
5361
5470
  startedAt
5362
5471
  });
5363
- if (outcome.kind === "terminal") return outcome.run;
5364
- stepResults.push(outcome.result);
5365
- if (outcome.result.status === "failed") {
5366
- return assembleRun({
5367
- runId,
5368
- name: options.name,
5369
- status: "failed",
5370
- stepResults,
5371
- startedAt,
5372
- error: outcome.result.error
5373
- });
5374
- }
5375
- acc = outcome.result.output;
5472
+ const handled = handleStepOutcome(outcome, step, loop, onStepEvent);
5473
+ if ("terminal" in handled) return handled.terminal;
5474
+ acc = handled.acc;
5475
+ }
5476
+ const outputIssues = validateWorkflowSchema(options.outputSchema, acc);
5477
+ if (outputIssues !== void 0) {
5478
+ return assembleRun({
5479
+ runId,
5480
+ name: options.name,
5481
+ status: "failed",
5482
+ stepResults,
5483
+ startedAt,
5484
+ error: errToShape(new WorkflowOutputError(options.name, outputIssues))
5485
+ });
5376
5486
  }
5487
+ onStepEvent?.({ type: "workflow_completed" });
5377
5488
  return assembleRun({
5378
5489
  runId,
5379
5490
  name: options.name,
@@ -5396,8 +5507,33 @@ async function executeWorkflow(options, steps, input, runOpts) {
5396
5507
  runSpan.end();
5397
5508
  return abortRun(options.name, runId, startedAt, [], signal);
5398
5509
  }
5399
- const ctx = makeStepContext(runId, signal);
5510
+ const internal = runOpts;
5511
+ const seededState = internal?.restoredState !== void 0 ? internal.restoredState : options.initialState;
5512
+ const stateController = makeStateController(options, seededState);
5513
+ const ctx = makeStepContext(runId, signal, stateController);
5400
5514
  try {
5515
+ const inputIssues = validateWorkflowSchema(options.inputSchema, input);
5516
+ if (inputIssues !== void 0) {
5517
+ return assembleRun({
5518
+ runId,
5519
+ name: options.name,
5520
+ status: "failed",
5521
+ stepResults: [],
5522
+ startedAt,
5523
+ error: errToShape(new WorkflowInputError(options.name, inputIssues))
5524
+ });
5525
+ }
5526
+ const stateIssues = seededState !== void 0 ? validateWorkflowSchema(options.stateSchema, seededState) : void 0;
5527
+ if (stateIssues !== void 0) {
5528
+ return assembleRun({
5529
+ runId,
5530
+ name: options.name,
5531
+ status: "failed",
5532
+ stepResults: [],
5533
+ startedAt,
5534
+ error: errToShape(new WorkflowStateError(options.name, stateIssues))
5535
+ });
5536
+ }
5401
5537
  return await runStepsLoop({
5402
5538
  options,
5403
5539
  steps,
@@ -5406,7 +5542,8 @@ async function executeWorkflow(options, steps, input, runOpts) {
5406
5542
  runId,
5407
5543
  startedAt,
5408
5544
  signal,
5409
- ...runOpts?.initialStepResults !== void 0 ? { initialStepResults: runOpts.initialStepResults } : {}
5545
+ ...internal?.initialStepResults !== void 0 ? { initialStepResults: internal.initialStepResults } : {},
5546
+ ...internal?.onStepEvent !== void 0 ? { onStepEvent: internal.onStepEvent } : {}
5410
5547
  });
5411
5548
  } finally {
5412
5549
  runSpan.end();
@@ -5437,28 +5574,17 @@ async function dispatchStep(step, input, ctx, options, prevStepResults) {
5437
5574
  }
5438
5575
  }
5439
5576
  }
5440
- function assembleRun(params) {
5441
- const endedAt = Date.now();
5442
- return {
5443
- id: params.runId,
5444
- name: params.name,
5445
- status: params.status,
5446
- startedAt: params.startedAt,
5447
- endedAt,
5448
- stepResults: params.stepResults,
5449
- ...params.output !== void 0 ? { output: params.output } : {},
5450
- ...params.error !== void 0 ? { error: params.error } : {}
5451
- };
5452
- }
5453
5577
  async function saveSnapshot(p) {
5454
5578
  const snapshot = {
5455
- _schemaVersion: 1,
5579
+ _schemaVersion: 2,
5580
+ // SE29 — carries `state`
5456
5581
  runId: p.runId,
5457
5582
  workflowName: p.workflowName,
5458
5583
  currentStepId: p.currentStepId,
5459
5584
  suspendedPayload: p.suspendedPayload,
5460
5585
  stepResults: p.stepResults,
5461
5586
  accumulatedInput: p.accumulatedInput,
5587
+ ...p.state !== void 0 ? { state: p.state } : {},
5462
5588
  suspendedAt: Date.now()
5463
5589
  };
5464
5590
  const store = getSnapshotStoreFor(p.options);
@@ -5491,7 +5617,10 @@ async function resumeWorkflow(opts) {
5491
5617
  signal: opts.signal,
5492
5618
  runId: opts.runId,
5493
5619
  // M3 #62 — restore prior step outputs so the resumed run is not lossy (internal seam).
5494
- initialStepResults: snapshot.stepResults
5620
+ initialStepResults: snapshot.stepResults,
5621
+ // SE29 — restore shared state (v2 snapshot). A v1 snapshot has no `state` →
5622
+ // executeWorkflow falls back to `options.initialState`.
5623
+ ...snapshot.state !== void 0 ? { restoredState: snapshot.state } : {}
5495
5624
  });
5496
5625
  }
5497
5626
  var init_executor = __esm({
@@ -5499,6 +5628,7 @@ var init_executor = __esm({
5499
5628
  init_workflow();
5500
5629
  init_ctx();
5501
5630
  init_error_shape();
5631
+ init_executor_helpers();
5502
5632
  init_run_id();
5503
5633
  init_single_flight();
5504
5634
  init_snapshot_store();
@@ -7734,8 +7864,18 @@ function validateCloudToolParity(options) {
7734
7864
  if (options.cloud === void 0) return;
7735
7865
  rejectFunctionSystemPrompt(options);
7736
7866
  rejectFunctionSkills(options);
7867
+ rejectProcessors(options);
7737
7868
  rejectStdioMcpLocalPaths(options);
7738
7869
  }
7870
+ function rejectProcessors(options) {
7871
+ const hasProcessors = (options.inputProcessors?.length ?? 0) > 0 || (options.outputProcessors?.length ?? 0) > 0;
7872
+ if (hasProcessors) {
7873
+ throw new ConfigurationError(
7874
+ "Cloud agents can't run guardrail processors \u2014 a Processor carries function handlers that don't survive serialization to PaaS. Run processors on a local agent, or move the guardrail into a server-side gateway in front of TheoCloud.",
7875
+ { code: "cloud_incompatible_function_resolver" }
7876
+ );
7877
+ }
7878
+ }
7739
7879
  function rejectFunctionSystemPrompt(options) {
7740
7880
  if (typeof options.systemPrompt === "function") {
7741
7881
  throw new ConfigurationError(
@@ -17674,6 +17814,145 @@ function ponyfillAny(signals) {
17674
17814
  return ctrl.signal;
17675
17815
  }
17676
17816
 
17817
+ // src/internal/runtime/processors/run-processors.ts
17818
+ var ProcessorAbort = class {
17819
+ constructor(processorId, reason) {
17820
+ this.processorId = processorId;
17821
+ this.reason = reason;
17822
+ }
17823
+ processorId;
17824
+ reason;
17825
+ };
17826
+ function fireViolation(processor, violation) {
17827
+ try {
17828
+ processor.onViolation?.(violation);
17829
+ } catch {
17830
+ }
17831
+ }
17832
+ function controlsFor(processor) {
17833
+ return {
17834
+ abort(reason) {
17835
+ throw new ProcessorAbort(processor.id, reason);
17836
+ },
17837
+ warn(message, detail) {
17838
+ fireViolation(processor, {
17839
+ processorId: processor.id,
17840
+ message,
17841
+ ...detail !== void 0 ? { detail } : {}
17842
+ });
17843
+ }
17844
+ };
17845
+ }
17846
+ function selectHandler(processor, phase) {
17847
+ if (phase === "input") {
17848
+ return processor.processInput ? { kind: "input", fn: processor.processInput } : void 0;
17849
+ }
17850
+ return processor.processOutput ? { kind: "output", fn: processor.processOutput } : void 0;
17851
+ }
17852
+ function invokeHandler(handler, value, agentId, controls) {
17853
+ return handler.kind === "input" ? handler.fn({ message: value, agentId, ...controls }) : handler.fn({ text: value, agentId, ...controls });
17854
+ }
17855
+ async function runOneProcessor(processor, value, agentId, phase) {
17856
+ const handler = selectHandler(processor, phase);
17857
+ if (handler === void 0) return { value };
17858
+ try {
17859
+ const out = await invokeHandler(handler, value, agentId, controlsFor(processor));
17860
+ return { value: typeof out === "string" ? out : value };
17861
+ } catch (err) {
17862
+ if (!(err instanceof ProcessorAbort)) throw err;
17863
+ fireViolation(processor, { processorId: err.processorId, message: err.reason });
17864
+ return { tripwire: { reason: err.reason, processorId: err.processorId } };
17865
+ }
17866
+ }
17867
+ async function runPipeline(processors, initial, agentId, phase) {
17868
+ let value = initial;
17869
+ for (const processor of processors) {
17870
+ const step = await runOneProcessor(processor, value, agentId, phase);
17871
+ if ("tripwire" in step) return { kind: "tripwire", tripwire: step.tripwire };
17872
+ value = step.value;
17873
+ }
17874
+ return { kind: "ok", value };
17875
+ }
17876
+ function runInputProcessors(processors, message, agentId) {
17877
+ return runPipeline(processors, message, agentId, "input");
17878
+ }
17879
+ function runOutputProcessors(processors, text, agentId) {
17880
+ return runPipeline(processors, text, agentId, "output");
17881
+ }
17882
+
17883
+ // src/internal/runtime/processors/tripwire-run.ts
17884
+ var SUPPORTED = /* @__PURE__ */ new Set([
17885
+ "stream",
17886
+ "wait",
17887
+ "cancel",
17888
+ "conversation"
17889
+ ]);
17890
+ function emptyStream() {
17891
+ return {
17892
+ next: () => Promise.resolve({ done: true, value: void 0 }),
17893
+ return: () => Promise.resolve({ done: true, value: void 0 }),
17894
+ throw: (err) => Promise.reject(err),
17895
+ [Symbol.asyncIterator]() {
17896
+ return this;
17897
+ }
17898
+ };
17899
+ }
17900
+ function createTripwireRun(args) {
17901
+ const id = globalThis.crypto.randomUUID();
17902
+ const result = {
17903
+ id,
17904
+ status: "cancelled",
17905
+ tripwire: args.tripwire,
17906
+ ...args.model !== void 0 ? { model: args.model } : {}
17907
+ };
17908
+ const run = {
17909
+ id,
17910
+ agentId: args.agentId,
17911
+ status: "cancelled",
17912
+ ...args.model !== void 0 ? { model: args.model } : {},
17913
+ stream: () => emptyStream(),
17914
+ wait: () => Promise.resolve(result),
17915
+ cancel: () => Promise.resolve(),
17916
+ conversation: () => Promise.resolve([]),
17917
+ supports: (op) => SUPPORTED.has(op),
17918
+ unsupportedReason: (op) => SUPPORTED.has(op) ? void 0 : `operation "${op}" is not available on a tripwire run`,
17919
+ onDidChangeStatus: () => () => {
17920
+ }
17921
+ // already terminal — status never changes
17922
+ };
17923
+ registerRun(run);
17924
+ return run;
17925
+ }
17926
+
17927
+ // src/internal/runtime/processors/wrap-output-run.ts
17928
+ function wrapRunWithOutputProcessors(args) {
17929
+ if (args.processors.length === 0) return args.run;
17930
+ const compute = async () => {
17931
+ const result = await args.run.wait();
17932
+ if (result.status !== "finished" || result.result === void 0) return result;
17933
+ const res = await runOutputProcessors(args.processors, result.result, args.agentId);
17934
+ if (res.kind === "ok") return { ...result, result: res.value };
17935
+ emitRunEvent(args.onRunEvent, {
17936
+ type: "tripwire",
17937
+ reason: res.tripwire.reason,
17938
+ processorId: res.tripwire.processorId
17939
+ });
17940
+ const { result: _suppressed, ...metadata } = result;
17941
+ return { ...metadata, status: "cancelled", tripwire: res.tripwire };
17942
+ };
17943
+ let processed;
17944
+ const wrappedWait = () => {
17945
+ processed ??= compute();
17946
+ return processed;
17947
+ };
17948
+ return new Proxy(args.run, {
17949
+ get(target, prop, receiver) {
17950
+ if (prop === "wait") return wrappedWait;
17951
+ return Reflect.get(target, prop, receiver);
17952
+ }
17953
+ });
17954
+ }
17955
+
17677
17956
  // src/internal/runtime/local-agent/local-agent-memory-hooks.ts
17678
17957
  var DEFAULT_MAX_RECALL_BYTES = 16e3;
17679
17958
  async function applyPreUserSendHook(args) {
@@ -17721,11 +18000,38 @@ function wrapRunWithPostReplyHook(args) {
17721
18000
  }
17722
18001
 
17723
18002
  // src/internal/runtime/local-agent/local-agent-send.ts
18003
+ async function applyInputProcessors(inputs, message, rawUserText, options, sendModel) {
18004
+ const processors = inputs.options.inputProcessors;
18005
+ if (processors === void 0 || processors.length === 0) {
18006
+ return { userText: rawUserText, effectiveMessage: message };
18007
+ }
18008
+ const res = await runInputProcessors(processors, rawUserText, inputs.agentId);
18009
+ if (res.kind === "tripwire") {
18010
+ emitRunEvent(options.onRunEvent, {
18011
+ type: "tripwire",
18012
+ reason: res.tripwire.reason,
18013
+ processorId: res.tripwire.processorId
18014
+ });
18015
+ return {
18016
+ tripwireRun: createTripwireRun({
18017
+ agentId: inputs.agentId,
18018
+ tripwire: res.tripwire,
18019
+ model: sendModel
18020
+ })
18021
+ };
18022
+ }
18023
+ const effectiveMessage = typeof message === "string" ? res.value : { ...message, text: res.value };
18024
+ return { userText: res.value, effectiveMessage };
18025
+ }
17724
18026
  async function executeSendLocked(inputs, message, options) {
17725
18027
  if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
17726
18028
  await consumePending(inputs.agentId, inputs.invalidationPending, inputs.clearInvalidation, inputs.reload);
17727
- inputs.applyModelOverride(normalizeModel(options.model));
17728
- const userText = typeof message === "string" ? message : message.text;
18029
+ const sendModel = normalizeModel(options.model);
18030
+ inputs.applyModelOverride(sendModel);
18031
+ const rawUserText = typeof message === "string" ? message : message.text;
18032
+ const gated = await applyInputProcessors(inputs, message, rawUserText, options, sendModel);
18033
+ if ("tripwireRun" in gated) return gated.tripwireRun;
18034
+ const { userText, effectiveMessage } = gated;
17729
18035
  if (inputs.options.onBeforeSend !== void 0) {
17730
18036
  await inputs.options.onBeforeSend({
17731
18037
  conversationId: inputs.agentId,
@@ -17737,7 +18043,7 @@ async function executeSendLocked(inputs, message, options) {
17737
18043
  pluginManager: inputs.pluginManagerCode,
17738
18044
  agentId: inputs.agentId,
17739
18045
  options: inputs.options,
17740
- original: message,
18046
+ original: effectiveMessage,
17741
18047
  userText,
17742
18048
  sendOptions: options
17743
18049
  });
@@ -17775,11 +18081,18 @@ async function executeSendLocked(inputs, message, options) {
17775
18081
  memoryTools,
17776
18082
  effectiveMemoryProvider
17777
18083
  );
18084
+ const outputProcessors = inputs.options.outputProcessors;
18085
+ const processedRun = outputProcessors !== void 0 && outputProcessors.length > 0 ? wrapRunWithOutputProcessors({
18086
+ run,
18087
+ processors: outputProcessors,
18088
+ agentId: inputs.agentId,
18089
+ onRunEvent: options.onRunEvent
18090
+ }) : run;
17778
18091
  return wrapRunWithPostReplyHook({
17779
18092
  pluginManager: inputs.pluginManagerCode,
17780
18093
  agentId: inputs.agentId,
17781
18094
  options: inputs.options,
17782
- run,
18095
+ run: processedRun,
17783
18096
  userText
17784
18097
  });
17785
18098
  }
@@ -19138,6 +19451,48 @@ var Budget = class {
19138
19451
  }
19139
19452
  };
19140
19453
 
19454
+ // src/built-in-processors.ts
19455
+ var CHARS_PER_TOKEN = 4;
19456
+ function estimateTokens(text) {
19457
+ return Math.ceil(text.length / CHARS_PER_TOKEN);
19458
+ }
19459
+ var CONTROL_CHARS = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g;
19460
+ function createUnicodeNormalizer(opts = {}) {
19461
+ const stripControlChars = opts.stripControlChars ?? false;
19462
+ const collapseWhitespace = opts.collapseWhitespace ?? false;
19463
+ return {
19464
+ id: "unicode-normalizer",
19465
+ processInput(ctx) {
19466
+ let s = ctx.message.normalize("NFC");
19467
+ if (stripControlChars) s = s.replace(CONTROL_CHARS, "");
19468
+ if (collapseWhitespace) {
19469
+ s = s.replace(/[^\S\n]+/g, " ").replace(/ *\n */g, "\n").replace(/\n{3,}/g, "\n\n").trim();
19470
+ }
19471
+ return s;
19472
+ }
19473
+ };
19474
+ }
19475
+ function createTokenLimiter(opts) {
19476
+ if (!Number.isInteger(opts.limit) || opts.limit <= 0) {
19477
+ throw new Error("createTokenLimiter: `limit` must be a positive integer.");
19478
+ }
19479
+ const limit = opts.limit;
19480
+ const strategy = opts.strategy ?? "truncate";
19481
+ const cap2 = (text, controls) => {
19482
+ const estimated = estimateTokens(text);
19483
+ if (estimated <= limit) return text;
19484
+ if (strategy === "block") {
19485
+ controls.abort(`exceeds token limit ${limit} (~${estimated} estimated)`);
19486
+ }
19487
+ return [...text].slice(0, limit * CHARS_PER_TOKEN).join("");
19488
+ };
19489
+ return {
19490
+ id: "token-limiter",
19491
+ processInput: (ctx) => cap2(ctx.message, ctx),
19492
+ processOutput: (ctx) => cap2(ctx.text, ctx)
19493
+ };
19494
+ }
19495
+
19141
19496
  // src/create-skill.ts
19142
19497
  function createSkill(spec) {
19143
19498
  if (!spec.name) throw new Error("createSkill: `name` is required.");
@@ -19819,7 +20174,7 @@ function createCounterBudgetTracker(options = {}) {
19819
20174
  }
19820
20175
 
19821
20176
  // src/internal/runtime/context/replay-history.ts
19822
- var CHARS_PER_TOKEN = 4;
20177
+ var CHARS_PER_TOKEN2 = 4;
19823
20178
  var DEFAULT_RESERVE_TOKENS = 8e3;
19824
20179
  function finiteOr(value, fallback) {
19825
20180
  return Number.isFinite(value) ? value : fallback;
@@ -19827,7 +20182,7 @@ function finiteOr(value, fallback) {
19827
20182
  function charBudget(options) {
19828
20183
  const window = finiteOr(options.contextWindowTokens, 0);
19829
20184
  const reserve = finiteOr(options.reserveTokens ?? DEFAULT_RESERVE_TOKENS, DEFAULT_RESERVE_TOKENS);
19830
- return Math.max(0, window - reserve) * CHARS_PER_TOKEN;
20185
+ return Math.max(0, window - reserve) * CHARS_PER_TOKEN2;
19831
20186
  }
19832
20187
  function assistantText2(event) {
19833
20188
  return event.message.content.filter((block) => block.type === "text").map((block) => block.text).join("");
@@ -20803,6 +21158,45 @@ var PersistenceSchema = z.object({
20803
21158
 
20804
21159
  // src/workflow.ts
20805
21160
  init_path_guard();
21161
+
21162
+ // src/internal/workflow/event-stream.ts
21163
+ function createEventStream() {
21164
+ const buffer = [];
21165
+ const waiters = [];
21166
+ let ended = false;
21167
+ const stream = {
21168
+ push(event) {
21169
+ if (ended) return;
21170
+ const waiter = waiters.shift();
21171
+ if (waiter !== void 0) waiter({ value: event, done: false });
21172
+ else buffer.push(event);
21173
+ },
21174
+ end() {
21175
+ if (ended) return;
21176
+ ended = true;
21177
+ for (const waiter of waiters.splice(0)) waiter({ value: void 0, done: true });
21178
+ },
21179
+ next() {
21180
+ const buffered = buffer.shift();
21181
+ if (buffered !== void 0) return Promise.resolve({ value: buffered, done: false });
21182
+ if (ended) return Promise.resolve({ value: void 0, done: true });
21183
+ return new Promise((resolve3) => waiters.push(resolve3));
21184
+ },
21185
+ // `for await` calls return() on break/throw — close early so events stop
21186
+ // buffering in memory for a consumer that stopped iterating.
21187
+ return() {
21188
+ stream.end();
21189
+ buffer.length = 0;
21190
+ return Promise.resolve({ value: void 0, done: true });
21191
+ },
21192
+ [Symbol.asyncIterator]() {
21193
+ return stream;
21194
+ }
21195
+ };
21196
+ return stream;
21197
+ }
21198
+
21199
+ // src/workflow.ts
20806
21200
  init_workflow();
20807
21201
  var RetryPolicySchema = z.object({
20808
21202
  // EC-3 absorbed: maxAttempts MUST be a finite int in [1, 20].
@@ -20814,7 +21208,12 @@ var RetryPolicySchema = z.object({
20814
21208
  });
20815
21209
  var WorkflowOptionsSchema = z.object({
20816
21210
  name: z.string().min(1).max(128),
20817
- persistence: PersistenceSchema
21211
+ persistence: PersistenceSchema,
21212
+ // SE27 — declared so a future `new WorkflowBuilder(parsed)` refactor cannot
21213
+ // silently drop them (create() passes the ORIGINAL options today, but the
21214
+ // schema is also the documentation of the shape).
21215
+ inputSchema: z.custom().optional(),
21216
+ outputSchema: z.custom().optional()
20818
21217
  });
20819
21218
  var WorkflowBuilder = class {
20820
21219
  /** @internal */
@@ -20991,6 +21390,36 @@ var Workflow = class {
20991
21390
  }
20992
21391
  return result;
20993
21392
  }
21393
+ /**
21394
+ * SE28 — run the workflow and STREAM step-level events as they happen. Returns
21395
+ * an async iterator of {@link WorkflowEvent}s (`step_started` / `step_completed`
21396
+ * / `step_failed` / `workflow_suspended` / `workflow_completed`, top-level
21397
+ * steps) plus a `result` promise resolving to the same terminal
21398
+ * {@link WorkflowRun} `run()` returns. Iterate for progress; await `result` for
21399
+ * the outcome. The stream ends when the run terminates.
21400
+ *
21401
+ * `result` is the AUTHORITATIVE terminal status. Not every terminal state has a
21402
+ * closing event: a step failure emits `step_failed`, but an `outputSchema`
21403
+ * rejection (SE27) or an abort ends the stream WITHOUT `workflow_completed` —
21404
+ * always `await result` to read the final `status`. Consuming order is free:
21405
+ * awaiting `result` without draining, or draining without awaiting `result`,
21406
+ * both work (breaking out of `for await` stops the buffering early).
21407
+ */
21408
+ stream(input, opts) {
21409
+ const queue = createEventStream();
21410
+ const result = (async () => {
21411
+ const { executeWorkflow: executeWorkflow2 } = await Promise.resolve().then(() => (init_executor(), executor_exports));
21412
+ try {
21413
+ return await executeWorkflow2(this._options, this._steps, input, {
21414
+ ...opts,
21415
+ onStepEvent: (event) => queue.push(event)
21416
+ });
21417
+ } finally {
21418
+ queue.end();
21419
+ }
21420
+ })();
21421
+ return Object.assign(queue, { result });
21422
+ }
20994
21423
  /**
20995
21424
  * Resume a suspended workflow from its snapshot. Throws
20996
21425
  * `WorkflowSnapshotNotFoundError` if `runId` is unknown.
@@ -21513,6 +21942,6 @@ function safeStringify2(v) {
21513
21942
  }
21514
21943
  }
21515
21944
 
21516
- export { Agent, AgentBuilder, AgentDisposedError, AgentRunError, AuthenticationError, Budget, BudgetExceededError, ConfigurationError, Cron, EventBus, FileSystemConversationStorage, GenerateObjectError, InMemoryConversationStorage, IntegrationNotConnectedError, InvalidTaskIdError, JobQueue, Memory, MemoryAdapterError, NetworkError, PermissionEngine, RateLimitError, Security, StreamObjectError, Task, TaskNotFoundError, Theokit, TheokitAgentError, ToolError, UnknownAgentError, UnsupportedBudgetOperationError, UnsupportedRunOperationError, UnsupportedTaskOperationError, UsageAccumulator, applyMode, buildReplayHistory, chargeAndCheckThresholds, computeCost, createAgentFactory, createCounterBudgetTracker, createNoopMemoryProvider, createPermissionPlugin, createSessionManager, createSkill, createSquad, definePlugin, defineProvider, defineSkillReadTool, defineTool, emitRunEvent, extractRawId, getPricingEntry, inferApiMode, isTransientError, migrateSqliteToLance2 as migrateSqliteToLance, mkMemoryId, normalizeSchema, normalizeUsage, preflightCheck, scopedConversationId, sessionScopePrefix, toShareGptTrajectory, withCwdMutex };
21945
+ export { Agent, AgentBuilder, AgentDisposedError, AgentRunError, AuthenticationError, Budget, BudgetExceededError, ConfigurationError, Cron, EventBus, FileSystemConversationStorage, GenerateObjectError, InMemoryConversationStorage, IntegrationNotConnectedError, InvalidTaskIdError, JobQueue, Memory, MemoryAdapterError, NetworkError, PermissionEngine, RateLimitError, Security, StreamObjectError, Task, TaskNotFoundError, Theokit, TheokitAgentError, ToolError, UnknownAgentError, UnsupportedBudgetOperationError, UnsupportedRunOperationError, UnsupportedTaskOperationError, UsageAccumulator, applyMode, buildReplayHistory, chargeAndCheckThresholds, computeCost, createAgentFactory, createCounterBudgetTracker, createNoopMemoryProvider, createPermissionPlugin, createSessionManager, createSkill, createSquad, createTokenLimiter, createUnicodeNormalizer, definePlugin, defineProvider, defineSkillReadTool, defineTool, emitRunEvent, estimateTokens, extractRawId, getPricingEntry, inferApiMode, isTransientError, migrateSqliteToLance2 as migrateSqliteToLance, mkMemoryId, normalizeSchema, normalizeUsage, preflightCheck, scopedConversationId, sessionScopePrefix, toShareGptTrajectory, withCwdMutex };
21517
21946
  //# sourceMappingURL=index.js.map
21518
21947
  //# sourceMappingURL=index.js.map