@theokit/sdk 2.1.0 → 2.3.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/cron.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import './run-DrwUpFxZ.cjs';
2
- export { I as Cron } from './cron-CSTqNZp9.cjs';
1
+ import './run-BPRYG1Id.cjs';
2
+ export { I as Cron } from './cron-B_H8rn-j.cjs';
package/dist/cron.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import './run-DrwUpFxZ.js';
2
- export { I as Cron } from './cron-Da6vF_2y.js';
1
+ import './run-BPRYG1Id.js';
2
+ export { I as Cron } from './cron-DX6HbHxd.js';
package/dist/cron.js CHANGED
@@ -1437,6 +1437,71 @@ var init_agent_factory_registry = __esm({
1437
1437
  }
1438
1438
  });
1439
1439
 
1440
+ // src/internal/runtime/lifecycle/run-to-completion.ts
1441
+ var run_to_completion_exports = {};
1442
+ __export(run_to_completion_exports, {
1443
+ classifyRound: () => classifyRound,
1444
+ runToCompletionImpl: () => runToCompletionImpl
1445
+ });
1446
+ function isEmptyRound(result) {
1447
+ return (result.result ?? "").trim() === "";
1448
+ }
1449
+ function classifyRound(result, round, maxRounds, emptyStreak) {
1450
+ if (result.stoppedAtIterationLimit !== true) return "done";
1451
+ if (isEmptyRound(result) && emptyStreak >= 1) return "no_progress";
1452
+ if (round >= maxRounds) return "step_limit";
1453
+ return "continue";
1454
+ }
1455
+ function addUsage(acc, u) {
1456
+ if (u === void 0) return acc;
1457
+ const inputTokens = (acc?.inputTokens ?? 0) + u.inputTokens;
1458
+ const outputTokens = (acc?.outputTokens ?? 0) + u.outputTokens;
1459
+ const sumOpt = (a, b) => a === void 0 && b === void 0 ? void 0 : (a ?? 0) + (b ?? 0);
1460
+ return {
1461
+ inputTokens,
1462
+ outputTokens,
1463
+ totalTokens: inputTokens + outputTokens,
1464
+ cacheReadTokens: sumOpt(acc?.cacheReadTokens, u.cacheReadTokens),
1465
+ cacheWriteTokens: sumOpt(acc?.cacheWriteTokens, u.cacheWriteTokens),
1466
+ reasoningTokens: sumOpt(acc?.reasoningTokens, u.reasoningTokens)
1467
+ };
1468
+ }
1469
+ function buildResult(terminal, rounds, lastResult, usage) {
1470
+ return { terminal, rounds, lastResult, ...usage !== void 0 ? { usage } : {} };
1471
+ }
1472
+ async function stepRound(agent, prompt, sendOptions, round, maxRounds, state3) {
1473
+ const run = await agent.send(prompt, sendOptions);
1474
+ const result = await run.wait();
1475
+ const usage = addUsage(state3.usage, result.usage);
1476
+ const decision = classifyRound(result, round, maxRounds, state3.emptyStreak);
1477
+ if (decision !== "continue") return { terminal: buildResult(decision, round, result, usage) };
1478
+ const emptyStreak = isEmptyRound(result) ? state3.emptyStreak + 1 : 0;
1479
+ return { next: { usage, emptyStreak }, lastResult: result };
1480
+ }
1481
+ async function runToCompletionImpl(agent, message, options) {
1482
+ const maxRounds = options?.maxRounds ?? DEFAULT_MAX_ROUNDS;
1483
+ const continuationPrompt = options?.continuationPrompt ?? DEFAULT_CONTINUATION_PROMPT;
1484
+ const { onTruncated, signal, sendOptions } = options ?? {};
1485
+ let state3 = { usage: void 0, emptyStreak: 0 };
1486
+ for (let round = 0; ; round += 1) {
1487
+ const prompt = round === 0 ? message : continuationPrompt;
1488
+ const outcome = await stepRound(agent, prompt, sendOptions, round, maxRounds, state3);
1489
+ if ("terminal" in outcome) return outcome.terminal;
1490
+ state3 = outcome.next;
1491
+ await onTruncated?.({ round });
1492
+ if (signal?.aborted === true) {
1493
+ return buildResult("step_limit", round, outcome.lastResult, state3.usage);
1494
+ }
1495
+ }
1496
+ }
1497
+ var DEFAULT_MAX_ROUNDS, DEFAULT_CONTINUATION_PROMPT;
1498
+ var init_run_to_completion = __esm({
1499
+ "src/internal/runtime/lifecycle/run-to-completion.ts"() {
1500
+ DEFAULT_MAX_ROUNDS = 5;
1501
+ DEFAULT_CONTINUATION_PROMPT = "Continue from where you left off and finish the task. If it is already complete, give the final answer.";
1502
+ }
1503
+ });
1504
+
1440
1505
  // src/internal/runtime/lifecycle/fork-agent.ts
1441
1506
  var fork_agent_exports = {};
1442
1507
  __export(fork_agent_exports, {
@@ -4317,8 +4382,7 @@ var FixtureRunBase = class {
4317
4382
  if (status === "error" && this.script.errorDetail !== void 0) {
4318
4383
  base.error = this.script.errorDetail;
4319
4384
  }
4320
- if (this.script.usage !== void 0) base.usage = this.script.usage;
4321
- if (this.script.cost !== void 0) base.cost = this.script.cost;
4385
+ applyScriptMetrics(base, this.script);
4322
4386
  return this.extendRunResult(applyExtraRunFields(base, this.script));
4323
4387
  }
4324
4388
  /** Subclasses override to attach runtime-specific fields (e.g. cloud git info). */
@@ -4352,6 +4416,11 @@ function makeNotifier() {
4352
4416
  });
4353
4417
  return { promise, resolve: resolve3 };
4354
4418
  }
4419
+ function applyScriptMetrics(base, script) {
4420
+ if (script.usage !== void 0) base.usage = script.usage;
4421
+ if (script.cost !== void 0) base.cost = script.cost;
4422
+ if (script.stoppedAtIterationLimit === true) base.stoppedAtIterationLimit = true;
4423
+ }
4355
4424
 
4356
4425
  // src/internal/runtime/cloud/cloud-run.ts
4357
4426
  function createCloudRun(options) {
@@ -4860,6 +4929,18 @@ var CloudAgent = class {
4860
4929
  "fork"
4861
4930
  );
4862
4931
  }
4932
+ /**
4933
+ * The continuation driver re-sends against a stateful local session; the
4934
+ * cloud runtime manages its own continuation policy server-side (M1 Phase 3).
4935
+ *
4936
+ * @public
4937
+ */
4938
+ runToCompletion() {
4939
+ throw new UnsupportedRunOperationError(
4940
+ "Agent.runToCompletion() is not supported on cloud agents. Cloud runtime manages continuation server-side. Use a local agent.",
4941
+ "runToCompletion"
4942
+ );
4943
+ }
4863
4944
  /**
4864
4945
  * Personality presets require consistent server-side enforcement that
4865
4946
  * the cloud runtime (pre-release) does not yet provide. Reject explicitly
@@ -7984,6 +8065,9 @@ var LocalRun = class extends FixtureRunBase {
7984
8065
  }
7985
8066
  };
7986
8067
 
8068
+ // src/internal/runtime/local-agent/real-local-run.ts
8069
+ init_errors();
8070
+
7987
8071
  // src/internal/runtime/budget/budget.ts
7988
8072
  var IterationBudget = class {
7989
8073
  #remaining;
@@ -9208,6 +9292,7 @@ async function runAgentLoop(inputs) {
9208
9292
  const ctx = await initLoopContext(inputs);
9209
9293
  ctxRef = ctx;
9210
9294
  const budget = inputs.budget ?? new IterationBudget({ maxIterations: inputs.maxIterations ?? 8 });
9295
+ let lastTurnDecision;
9211
9296
  while (budget.shouldContinue()) {
9212
9297
  if (inputs.budgetTracker !== void 0) {
9213
9298
  const decision2 = evaluateBudgetGate(inputs.budgetTracker);
@@ -9216,18 +9301,26 @@ async function runAgentLoop(inputs) {
9216
9301
  if (decision2.detail !== void 0) {
9217
9302
  ctx.error = { message: decision2.detail, code: decision2.reason ?? "budget" };
9218
9303
  }
9304
+ if (decision2.reason === "iteration_limit") {
9305
+ ctx.stoppedAtIterationLimit = true;
9306
+ }
9219
9307
  break;
9220
9308
  }
9221
9309
  }
9222
9310
  const usingGrace = budget.remaining <= 0 && !budget.graceCallUsed;
9223
9311
  if (usingGrace) budget.useGraceCall();
9224
9312
  const decision = await runIteration(inputs, ctx);
9313
+ lastTurnDecision = decision;
9225
9314
  if (decision === "done") break;
9226
9315
  if (decision === "error") {
9227
9316
  ctx.finalStatus = "error";
9228
9317
  break;
9229
9318
  }
9230
9319
  budget.consume();
9320
+ inputs.budgetTracker?.nextIteration?.();
9321
+ }
9322
+ if (lastTurnDecision === "continue" && budget.shouldContinue() === false) {
9323
+ ctx.stoppedAtIterationLimit = true;
9231
9324
  }
9232
9325
  if (budget.shouldContinue() === false && ctx.finalStatus === "finished" && ctx.finalText === "") {
9233
9326
  ctx.finalStatus = "error";
@@ -9258,7 +9351,8 @@ async function runAgentLoop(inputs) {
9258
9351
  conversation: ctx.conversation,
9259
9352
  ...usage !== void 0 ? { usage } : {},
9260
9353
  ...cost !== void 0 ? { cost } : {},
9261
- ...ctx.error !== void 0 ? { error: ctx.error } : {}
9354
+ ...ctx.error !== void 0 ? { error: ctx.error } : {},
9355
+ ...ctx.stoppedAtIterationLimit === true ? { stoppedAtIterationLimit: true } : {}
9262
9356
  };
9263
9357
  } finally {
9264
9358
  if (ctxRef !== void 0 && ctxRef.memoryProviderHandle !== void 0 && inputs.memoryProvider !== void 0) {
@@ -11677,6 +11771,13 @@ function resolveRunProvider(options) {
11677
11771
  return { primary, effectiveModelId };
11678
11772
  }
11679
11773
  function buildLoopInputs(options, runId, userText) {
11774
+ const maxIterations = options.sendOptions.maxIterations;
11775
+ if (maxIterations !== void 0 && (!Number.isInteger(maxIterations) || maxIterations < 1)) {
11776
+ throw new ConfigurationError(
11777
+ `SendOptions.maxIterations must be a positive integer, got ${maxIterations}`,
11778
+ { code: "invalid_max_iterations" }
11779
+ );
11780
+ }
11680
11781
  const { primary, effectiveModelId } = resolveRunProvider(options);
11681
11782
  const fallback = options.agentOptions.providers?.fallback;
11682
11783
  const apiKeys = options.agentOptions.providers?.apiKeys;
@@ -11715,6 +11816,9 @@ function buildLoopInputs(options, runId, userText) {
11715
11816
  // D318 — forward SendOptions.signal to the agent loop so streamLlmTurn
11716
11817
  // can attach it to the LLM `fetch({ signal })` call.
11717
11818
  ...options.sendOptions.signal !== void 0 ? { signal: options.sendOptions.signal } : {},
11819
+ // M1-2: per-send iteration ceiling (validated above). The loop reads
11820
+ // inputs.maxIterations (default 8 when unset).
11821
+ ...maxIterations !== void 0 ? { maxIterations } : {},
11718
11822
  // D315-D317 — tool lifecycle hooks (cost tracking + audit + retry/alert)
11719
11823
  ...options.agentOptions.onToolStart !== void 0 ? { onToolStart: options.agentOptions.onToolStart } : {},
11720
11824
  ...options.agentOptions.onToolEnd !== void 0 ? { onToolEnd: options.agentOptions.onToolEnd } : {},
@@ -11846,6 +11950,7 @@ var RealLocalRun = class extends FixtureRunBase {
11846
11950
  if (output.result.length > 0) this.script.result = output.result;
11847
11951
  if (output.usage !== void 0) this.script.usage = output.usage;
11848
11952
  if (output.cost !== void 0) this.script.cost = output.cost;
11953
+ if (output.stoppedAtIterationLimit === true) this.script.stoppedAtIterationLimit = true;
11849
11954
  if (output.error !== void 0 && this.script.errorDetail === void 0) {
11850
11955
  this.script.errorDetail = {
11851
11956
  message: output.error.message,
@@ -14316,6 +14421,13 @@ function localAgentRunUntil(agent, goal, options) {
14316
14421
  }
14317
14422
  return wrap();
14318
14423
  }
14424
+ function localAgentRunToCompletion(agent, message, options) {
14425
+ async function run() {
14426
+ const { runToCompletionImpl: runToCompletionImpl2 } = await Promise.resolve().then(() => (init_run_to_completion(), run_to_completion_exports));
14427
+ return runToCompletionImpl2({ send: (m, o) => agent.send(m, o) }, message, options);
14428
+ }
14429
+ return run();
14430
+ }
14319
14431
  async function localAgentFork(parent, options) {
14320
14432
  const { forkAgentImpl: forkAgentImpl2 } = await Promise.resolve().then(() => (init_fork_agent(), fork_agent_exports));
14321
14433
  const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
@@ -14856,6 +14968,10 @@ var LocalAgent = class {
14856
14968
  fork(options) {
14857
14969
  return localAgentFork({ agentId: this.agentId, options: this.options, personalitySlugSnapshot: this.personalityStore.active(this.agentId) }, options);
14858
14970
  }
14971
+ // biome-ignore format: G8 budget — see runUntil comment above.
14972
+ runToCompletion(message, options) {
14973
+ return localAgentRunToCompletion(this, message, options);
14974
+ }
14859
14975
  };
14860
14976
  function resolveCwd(cwd) {
14861
14977
  return (Array.isArray(cwd) ? cwd[0] : cwd) ?? process.cwd();