@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/a2a/index.js CHANGED
@@ -2310,6 +2310,11 @@ function makeNotifier() {
2310
2310
  });
2311
2311
  return { promise, resolve: resolve3 };
2312
2312
  }
2313
+ function applyScriptMetrics(base, script) {
2314
+ if (script.usage !== void 0) base.usage = script.usage;
2315
+ if (script.cost !== void 0) base.cost = script.cost;
2316
+ if (script.stoppedAtIterationLimit === true) base.stoppedAtIterationLimit = true;
2317
+ }
2313
2318
  var FixtureRunBase;
2314
2319
  var init_fixture_run_base = __esm({
2315
2320
  "src/internal/runtime/fixtures/fixture-run-base.ts"() {
@@ -2416,8 +2421,7 @@ var init_fixture_run_base = __esm({
2416
2421
  if (status === "error" && this.script.errorDetail !== void 0) {
2417
2422
  base.error = this.script.errorDetail;
2418
2423
  }
2419
- if (this.script.usage !== void 0) base.usage = this.script.usage;
2420
- if (this.script.cost !== void 0) base.cost = this.script.cost;
2424
+ applyScriptMetrics(base, this.script);
2421
2425
  return this.extendRunResult(applyExtraRunFields(base, this.script));
2422
2426
  }
2423
2427
  /** Subclasses override to attach runtime-specific fields (e.g. cloud git info). */
@@ -2996,6 +3000,18 @@ var init_cloud_agent = __esm({
2996
3000
  "fork"
2997
3001
  );
2998
3002
  }
3003
+ /**
3004
+ * The continuation driver re-sends against a stateful local session; the
3005
+ * cloud runtime manages its own continuation policy server-side (M1 Phase 3).
3006
+ *
3007
+ * @public
3008
+ */
3009
+ runToCompletion() {
3010
+ throw new UnsupportedRunOperationError(
3011
+ "Agent.runToCompletion() is not supported on cloud agents. Cloud runtime manages continuation server-side. Use a local agent.",
3012
+ "runToCompletion"
3013
+ );
3014
+ }
2999
3015
  /**
3000
3016
  * Personality presets require consistent server-side enforcement that
3001
3017
  * the cloud runtime (pre-release) does not yet provide. Reject explicitly
@@ -8005,6 +8021,7 @@ async function runAgentLoop(inputs) {
8005
8021
  const ctx = await initLoopContext(inputs);
8006
8022
  ctxRef = ctx;
8007
8023
  const budget = inputs.budget ?? new IterationBudget({ maxIterations: inputs.maxIterations ?? 8 });
8024
+ let lastTurnDecision;
8008
8025
  while (budget.shouldContinue()) {
8009
8026
  if (inputs.budgetTracker !== void 0) {
8010
8027
  const decision2 = evaluateBudgetGate(inputs.budgetTracker);
@@ -8013,18 +8030,26 @@ async function runAgentLoop(inputs) {
8013
8030
  if (decision2.detail !== void 0) {
8014
8031
  ctx.error = { message: decision2.detail, code: decision2.reason ?? "budget" };
8015
8032
  }
8033
+ if (decision2.reason === "iteration_limit") {
8034
+ ctx.stoppedAtIterationLimit = true;
8035
+ }
8016
8036
  break;
8017
8037
  }
8018
8038
  }
8019
8039
  const usingGrace = budget.remaining <= 0 && !budget.graceCallUsed;
8020
8040
  if (usingGrace) budget.useGraceCall();
8021
8041
  const decision = await runIteration(inputs, ctx);
8042
+ lastTurnDecision = decision;
8022
8043
  if (decision === "done") break;
8023
8044
  if (decision === "error") {
8024
8045
  ctx.finalStatus = "error";
8025
8046
  break;
8026
8047
  }
8027
8048
  budget.consume();
8049
+ inputs.budgetTracker?.nextIteration?.();
8050
+ }
8051
+ if (lastTurnDecision === "continue" && budget.shouldContinue() === false) {
8052
+ ctx.stoppedAtIterationLimit = true;
8028
8053
  }
8029
8054
  if (budget.shouldContinue() === false && ctx.finalStatus === "finished" && ctx.finalText === "") {
8030
8055
  ctx.finalStatus = "error";
@@ -8055,7 +8080,8 @@ async function runAgentLoop(inputs) {
8055
8080
  conversation: ctx.conversation,
8056
8081
  ...usage !== void 0 ? { usage } : {},
8057
8082
  ...cost !== void 0 ? { cost } : {},
8058
- ...ctx.error !== void 0 ? { error: ctx.error } : {}
8083
+ ...ctx.error !== void 0 ? { error: ctx.error } : {},
8084
+ ...ctx.stoppedAtIterationLimit === true ? { stoppedAtIterationLimit: true } : {}
8059
8085
  };
8060
8086
  } finally {
8061
8087
  if (ctxRef !== void 0 && ctxRef.memoryProviderHandle !== void 0 && inputs.memoryProvider !== void 0) {
@@ -11004,6 +11030,13 @@ function resolveRunProvider(options) {
11004
11030
  return { primary, effectiveModelId };
11005
11031
  }
11006
11032
  function buildLoopInputs(options, runId, userText) {
11033
+ const maxIterations = options.sendOptions.maxIterations;
11034
+ if (maxIterations !== void 0 && (!Number.isInteger(maxIterations) || maxIterations < 1)) {
11035
+ throw new ConfigurationError(
11036
+ `SendOptions.maxIterations must be a positive integer, got ${maxIterations}`,
11037
+ { code: "invalid_max_iterations" }
11038
+ );
11039
+ }
11007
11040
  const { primary, effectiveModelId } = resolveRunProvider(options);
11008
11041
  const fallback = options.agentOptions.providers?.fallback;
11009
11042
  const apiKeys = options.agentOptions.providers?.apiKeys;
@@ -11042,6 +11075,9 @@ function buildLoopInputs(options, runId, userText) {
11042
11075
  // D318 — forward SendOptions.signal to the agent loop so streamLlmTurn
11043
11076
  // can attach it to the LLM `fetch({ signal })` call.
11044
11077
  ...options.sendOptions.signal !== void 0 ? { signal: options.sendOptions.signal } : {},
11078
+ // M1-2: per-send iteration ceiling (validated above). The loop reads
11079
+ // inputs.maxIterations (default 8 when unset).
11080
+ ...maxIterations !== void 0 ? { maxIterations } : {},
11045
11081
  // D315-D317 — tool lifecycle hooks (cost tracking + audit + retry/alert)
11046
11082
  ...options.agentOptions.onToolStart !== void 0 ? { onToolStart: options.agentOptions.onToolStart } : {},
11047
11083
  ...options.agentOptions.onToolEnd !== void 0 ? { onToolEnd: options.agentOptions.onToolEnd } : {},
@@ -11101,6 +11137,7 @@ function buildMcpMap(options) {
11101
11137
  var pluginProvidersAnnounced, RealLocalRun;
11102
11138
  var init_real_local_run = __esm({
11103
11139
  "src/internal/runtime/local-agent/real-local-run.ts"() {
11140
+ init_errors();
11104
11141
  init_loop();
11105
11142
  init_fallback_client();
11106
11143
  init_model_identifier();
@@ -11188,6 +11225,7 @@ var init_real_local_run = __esm({
11188
11225
  if (output.result.length > 0) this.script.result = output.result;
11189
11226
  if (output.usage !== void 0) this.script.usage = output.usage;
11190
11227
  if (output.cost !== void 0) this.script.cost = output.cost;
11228
+ if (output.stoppedAtIterationLimit === true) this.script.stoppedAtIterationLimit = true;
11191
11229
  if (output.error !== void 0 && this.script.errorDetail === void 0) {
11192
11230
  this.script.errorDetail = {
11193
11231
  message: output.error.message,
@@ -14161,6 +14199,71 @@ var init_agent_factory_registry = __esm({
14161
14199
  }
14162
14200
  });
14163
14201
 
14202
+ // src/internal/runtime/lifecycle/run-to-completion.ts
14203
+ var run_to_completion_exports = {};
14204
+ __export(run_to_completion_exports, {
14205
+ classifyRound: () => classifyRound,
14206
+ runToCompletionImpl: () => runToCompletionImpl
14207
+ });
14208
+ function isEmptyRound(result) {
14209
+ return (result.result ?? "").trim() === "";
14210
+ }
14211
+ function classifyRound(result, round, maxRounds, emptyStreak) {
14212
+ if (result.stoppedAtIterationLimit !== true) return "done";
14213
+ if (isEmptyRound(result) && emptyStreak >= 1) return "no_progress";
14214
+ if (round >= maxRounds) return "step_limit";
14215
+ return "continue";
14216
+ }
14217
+ function addUsage(acc, u) {
14218
+ if (u === void 0) return acc;
14219
+ const inputTokens = (acc?.inputTokens ?? 0) + u.inputTokens;
14220
+ const outputTokens = (acc?.outputTokens ?? 0) + u.outputTokens;
14221
+ const sumOpt = (a, b) => a === void 0 && b === void 0 ? void 0 : (a ?? 0) + (b ?? 0);
14222
+ return {
14223
+ inputTokens,
14224
+ outputTokens,
14225
+ totalTokens: inputTokens + outputTokens,
14226
+ cacheReadTokens: sumOpt(acc?.cacheReadTokens, u.cacheReadTokens),
14227
+ cacheWriteTokens: sumOpt(acc?.cacheWriteTokens, u.cacheWriteTokens),
14228
+ reasoningTokens: sumOpt(acc?.reasoningTokens, u.reasoningTokens)
14229
+ };
14230
+ }
14231
+ function buildResult(terminal, rounds, lastResult, usage) {
14232
+ return { terminal, rounds, lastResult, ...usage !== void 0 ? { usage } : {} };
14233
+ }
14234
+ async function stepRound(agent, prompt, sendOptions, round, maxRounds, state2) {
14235
+ const run = await agent.send(prompt, sendOptions);
14236
+ const result = await run.wait();
14237
+ const usage = addUsage(state2.usage, result.usage);
14238
+ const decision = classifyRound(result, round, maxRounds, state2.emptyStreak);
14239
+ if (decision !== "continue") return { terminal: buildResult(decision, round, result, usage) };
14240
+ const emptyStreak = isEmptyRound(result) ? state2.emptyStreak + 1 : 0;
14241
+ return { next: { usage, emptyStreak }, lastResult: result };
14242
+ }
14243
+ async function runToCompletionImpl(agent, message, options) {
14244
+ const maxRounds = options?.maxRounds ?? DEFAULT_MAX_ROUNDS;
14245
+ const continuationPrompt = options?.continuationPrompt ?? DEFAULT_CONTINUATION_PROMPT;
14246
+ const { onTruncated, signal, sendOptions } = options ?? {};
14247
+ let state2 = { usage: void 0, emptyStreak: 0 };
14248
+ for (let round = 0; ; round += 1) {
14249
+ const prompt = round === 0 ? message : continuationPrompt;
14250
+ const outcome = await stepRound(agent, prompt, sendOptions, round, maxRounds, state2);
14251
+ if ("terminal" in outcome) return outcome.terminal;
14252
+ state2 = outcome.next;
14253
+ await onTruncated?.({ round });
14254
+ if (signal?.aborted === true) {
14255
+ return buildResult("step_limit", round, outcome.lastResult, state2.usage);
14256
+ }
14257
+ }
14258
+ }
14259
+ var DEFAULT_MAX_ROUNDS, DEFAULT_CONTINUATION_PROMPT;
14260
+ var init_run_to_completion = __esm({
14261
+ "src/internal/runtime/lifecycle/run-to-completion.ts"() {
14262
+ DEFAULT_MAX_ROUNDS = 5;
14263
+ DEFAULT_CONTINUATION_PROMPT = "Continue from where you left off and finish the task. If it is already complete, give the final answer.";
14264
+ }
14265
+ });
14266
+
14164
14267
  // src/internal/runtime/lifecycle/fork-agent.ts
14165
14268
  var fork_agent_exports = {};
14166
14269
  __export(fork_agent_exports, {
@@ -14241,6 +14344,13 @@ function localAgentRunUntil(agent, goal, options) {
14241
14344
  }
14242
14345
  return wrap();
14243
14346
  }
14347
+ function localAgentRunToCompletion(agent, message, options) {
14348
+ async function run() {
14349
+ const { runToCompletionImpl: runToCompletionImpl2 } = await Promise.resolve().then(() => (init_run_to_completion(), run_to_completion_exports));
14350
+ return runToCompletionImpl2({ send: (m, o) => agent.send(m, o) }, message, options);
14351
+ }
14352
+ return run();
14353
+ }
14244
14354
  async function localAgentFork(parent, options) {
14245
14355
  const { forkAgentImpl: forkAgentImpl2 } = await Promise.resolve().then(() => (init_fork_agent(), fork_agent_exports));
14246
14356
  const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
@@ -15375,6 +15485,10 @@ var init_local_agent = __esm({
15375
15485
  fork(options) {
15376
15486
  return localAgentFork({ agentId: this.agentId, options: this.options, personalitySlugSnapshot: this.personalityStore.active(this.agentId) }, options);
15377
15487
  }
15488
+ // biome-ignore format: G8 budget — see runUntil comment above.
15489
+ runToCompletion(message, options) {
15490
+ return localAgentRunToCompletion(this, message, options);
15491
+ }
15378
15492
  };
15379
15493
  }
15380
15494
  });