@theokit/sdk 2.2.0 → 2.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.
Files changed (85) hide show
  1. package/CHANGELOG.md +122 -0
  2. package/dist/a2a/index.cjs +191 -48
  3. package/dist/a2a/index.cjs.map +1 -1
  4. package/dist/a2a/index.js +192 -49
  5. package/dist/a2a/index.js.map +1 -1
  6. package/dist/compaction.cjs +78 -0
  7. package/dist/compaction.cjs.map +1 -0
  8. package/dist/compaction.d.cts +76 -0
  9. package/dist/compaction.d.ts +76 -0
  10. package/dist/compaction.js +70 -0
  11. package/dist/compaction.js.map +1 -0
  12. package/dist/{cron-JSPSFczQ.d.cts → cron-B656C3iq.d.cts} +28 -2
  13. package/dist/{cron-Aksw2Hy4.d.ts → cron-CM2M9mhB.d.ts} +28 -2
  14. package/dist/cron.cjs +192 -57
  15. package/dist/cron.cjs.map +1 -1
  16. package/dist/cron.d.cts +2 -2
  17. package/dist/cron.d.ts +2 -2
  18. package/dist/cron.js +192 -57
  19. package/dist/cron.js.map +1 -1
  20. package/dist/{errors-Bcw_Pakm.d.ts → errors-DG_7CAUg.d.ts} +1 -1
  21. package/dist/{errors-Vhg6ZV4o.d.cts → errors-QDYUPABr.d.cts} +1 -1
  22. package/dist/errors.d.cts +2 -2
  23. package/dist/eval.cjs +192 -57
  24. package/dist/eval.cjs.map +1 -1
  25. package/dist/eval.js +192 -57
  26. package/dist/eval.js.map +1 -1
  27. package/dist/index.cjs +275 -68
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +50 -7
  30. package/dist/index.d.ts +50 -7
  31. package/dist/index.js +275 -69
  32. package/dist/index.js.map +1 -1
  33. package/dist/internal/agent-loop/loop.d.ts +5 -0
  34. package/dist/internal/llm/model-capabilities.d.ts +40 -0
  35. package/dist/internal/llm/model-identifier.d.ts +9 -1
  36. package/dist/internal/llm/model-option.d.ts +38 -0
  37. package/dist/internal/runtime/compression/compression-attempt.d.ts +24 -0
  38. package/dist/internal/runtime/compression/compression-config.d.ts +33 -0
  39. package/dist/internal/runtime/compression/compression-decision.d.ts +10 -0
  40. package/dist/internal/runtime/compression/compression-helpers.d.ts +18 -0
  41. package/dist/internal/runtime/compression/compression-model-registry.d.ts +41 -0
  42. package/dist/internal/runtime/compression/compression-summarizer.d.ts +29 -0
  43. package/dist/internal/runtime/context/project-instructions.d.ts +66 -0
  44. package/dist/internal/runtime/context/replay-history.d.ts +43 -0
  45. package/dist/internal/runtime/hooks/hooks-frontmatter.d.ts +1 -1
  46. package/dist/internal/runtime/lifecycle/run-to-completion.d.ts +22 -0
  47. package/dist/internal/runtime/skills/discover-skills.d.ts +68 -0
  48. package/dist/internal/runtime/skills/skills-block.d.ts +18 -0
  49. package/dist/internal/runtime/skills/subagent-tool-scope.d.ts +25 -0
  50. package/dist/messages.cjs +24 -0
  51. package/dist/messages.cjs.map +1 -0
  52. package/dist/messages.d.cts +33 -0
  53. package/dist/messages.d.ts +33 -0
  54. package/dist/messages.js +20 -0
  55. package/dist/messages.js.map +1 -0
  56. package/dist/models.cjs +233 -0
  57. package/dist/models.cjs.map +1 -0
  58. package/dist/models.d.cts +16 -0
  59. package/dist/models.d.ts +16 -0
  60. package/dist/models.js +228 -0
  61. package/dist/models.js.map +1 -0
  62. package/dist/project.cjs +149 -0
  63. package/dist/project.cjs.map +1 -0
  64. package/dist/project.d.cts +14 -0
  65. package/dist/project.d.ts +14 -0
  66. package/dist/project.js +146 -0
  67. package/dist/project.js.map +1 -0
  68. package/dist/{run-ekGKZlmg.d.cts → run-BPRYG1Id.d.cts} +55 -2
  69. package/dist/{run-ekGKZlmg.d.ts → run-BPRYG1Id.d.ts} +55 -2
  70. package/dist/skills.cjs +282 -0
  71. package/dist/skills.cjs.map +1 -0
  72. package/dist/skills.d.cts +19 -0
  73. package/dist/skills.d.ts +19 -0
  74. package/dist/skills.js +279 -0
  75. package/dist/skills.js.map +1 -0
  76. package/dist/subagents.cjs +24 -0
  77. package/dist/subagents.cjs.map +1 -0
  78. package/dist/subagents.d.cts +14 -0
  79. package/dist/subagents.d.ts +14 -0
  80. package/dist/subagents.js +21 -0
  81. package/dist/subagents.js.map +1 -0
  82. package/dist/types/agent.d.ts +22 -0
  83. package/dist/types/conversation-storage.d.ts +5 -1
  84. package/dist/types/run.d.ts +54 -1
  85. package/package.json +62 -2
package/dist/index.cjs CHANGED
@@ -2799,6 +2799,71 @@ var init_agent_factory_registry = __esm({
2799
2799
  }
2800
2800
  });
2801
2801
 
2802
+ // src/internal/runtime/lifecycle/run-to-completion.ts
2803
+ var run_to_completion_exports = {};
2804
+ __export(run_to_completion_exports, {
2805
+ classifyRound: () => classifyRound,
2806
+ runToCompletionImpl: () => runToCompletionImpl
2807
+ });
2808
+ function isEmptyRound(result) {
2809
+ return (result.result ?? "").trim() === "";
2810
+ }
2811
+ function classifyRound(result, round, maxRounds, emptyStreak) {
2812
+ if (result.stoppedAtIterationLimit !== true) return "done";
2813
+ if (isEmptyRound(result) && emptyStreak >= 1) return "no_progress";
2814
+ if (round >= maxRounds) return "step_limit";
2815
+ return "continue";
2816
+ }
2817
+ function addUsage(acc, u) {
2818
+ if (u === void 0) return acc;
2819
+ const inputTokens = (acc?.inputTokens ?? 0) + u.inputTokens;
2820
+ const outputTokens = (acc?.outputTokens ?? 0) + u.outputTokens;
2821
+ const sumOpt = (a, b) => a === void 0 && b === void 0 ? void 0 : (a ?? 0) + (b ?? 0);
2822
+ return {
2823
+ inputTokens,
2824
+ outputTokens,
2825
+ totalTokens: inputTokens + outputTokens,
2826
+ cacheReadTokens: sumOpt(acc?.cacheReadTokens, u.cacheReadTokens),
2827
+ cacheWriteTokens: sumOpt(acc?.cacheWriteTokens, u.cacheWriteTokens),
2828
+ reasoningTokens: sumOpt(acc?.reasoningTokens, u.reasoningTokens)
2829
+ };
2830
+ }
2831
+ function buildResult(terminal, rounds, lastResult, usage) {
2832
+ return { terminal, rounds, lastResult, ...usage !== void 0 ? { usage } : {} };
2833
+ }
2834
+ async function stepRound(agent, prompt, sendOptions, round, maxRounds, state4) {
2835
+ const run = await agent.send(prompt, sendOptions);
2836
+ const result = await run.wait();
2837
+ const usage = addUsage(state4.usage, result.usage);
2838
+ const decision = classifyRound(result, round, maxRounds, state4.emptyStreak);
2839
+ if (decision !== "continue") return { terminal: buildResult(decision, round, result, usage) };
2840
+ const emptyStreak = isEmptyRound(result) ? state4.emptyStreak + 1 : 0;
2841
+ return { next: { usage, emptyStreak }, lastResult: result };
2842
+ }
2843
+ async function runToCompletionImpl(agent, message, options) {
2844
+ const maxRounds = options?.maxRounds ?? DEFAULT_MAX_ROUNDS;
2845
+ const continuationPrompt = options?.continuationPrompt ?? DEFAULT_CONTINUATION_PROMPT;
2846
+ const { onTruncated, signal, sendOptions } = options ?? {};
2847
+ let state4 = { usage: void 0, emptyStreak: 0 };
2848
+ for (let round = 0; ; round += 1) {
2849
+ const prompt = round === 0 ? message : continuationPrompt;
2850
+ const outcome = await stepRound(agent, prompt, sendOptions, round, maxRounds, state4);
2851
+ if ("terminal" in outcome) return outcome.terminal;
2852
+ state4 = outcome.next;
2853
+ await onTruncated?.({ round });
2854
+ if (signal?.aborted === true) {
2855
+ return buildResult("step_limit", round, outcome.lastResult, state4.usage);
2856
+ }
2857
+ }
2858
+ }
2859
+ var DEFAULT_MAX_ROUNDS, DEFAULT_CONTINUATION_PROMPT;
2860
+ var init_run_to_completion = __esm({
2861
+ "src/internal/runtime/lifecycle/run-to-completion.ts"() {
2862
+ DEFAULT_MAX_ROUNDS = 5;
2863
+ DEFAULT_CONTINUATION_PROMPT = "Continue from where you left off and finish the task. If it is already complete, give the final answer.";
2864
+ }
2865
+ });
2866
+
2802
2867
  // src/internal/runtime/lifecycle/fork-agent.ts
2803
2868
  var fork_agent_exports = {};
2804
2869
  __export(fork_agent_exports, {
@@ -2887,10 +2952,10 @@ var RingBuffer;
2887
2952
  var init_ring_buffer = __esm({
2888
2953
  "src/internal/task/ring-buffer.ts"() {
2889
2954
  RingBuffer = class {
2890
- constructor(cap) {
2891
- this.cap = cap;
2892
- if (!Number.isInteger(cap) || cap < 1) {
2893
- throw new Error(`RingBuffer capacity must be a positive integer, got ${cap}`);
2955
+ constructor(cap2) {
2956
+ this.cap = cap2;
2957
+ if (!Number.isInteger(cap2) || cap2 < 1) {
2958
+ throw new Error(`RingBuffer capacity must be a positive integer, got ${cap2}`);
2894
2959
  }
2895
2960
  }
2896
2961
  cap;
@@ -7354,6 +7419,18 @@ var CloudAgent = class {
7354
7419
  "fork"
7355
7420
  );
7356
7421
  }
7422
+ /**
7423
+ * The continuation driver re-sends against a stateful local session; the
7424
+ * cloud runtime manages its own continuation policy server-side (M1 Phase 3).
7425
+ *
7426
+ * @public
7427
+ */
7428
+ runToCompletion() {
7429
+ throw new exports.UnsupportedRunOperationError(
7430
+ "Agent.runToCompletion() is not supported on cloud agents. Cloud runtime manages continuation server-side. Use a local agent.",
7431
+ "runToCompletion"
7432
+ );
7433
+ }
7357
7434
  /**
7358
7435
  * Personality presets require consistent server-side enforcement that
7359
7436
  * the cloud runtime (pre-release) does not yet provide. Reject explicitly
@@ -8882,6 +8959,8 @@ function parseSubagentMarkdown(raw, filename) {
8882
8959
  if (fields.model !== void 0) {
8883
8960
  definition.model = fields.model === "inherit" ? "inherit" : { id: fields.model };
8884
8961
  }
8962
+ const tools = fields.tools?.split(/[\s,]+/).map((t) => t.trim()).filter((t) => t.length > 0);
8963
+ if (tools !== void 0 && tools.length > 0) definition.tools = tools;
8885
8964
  return { name, definition };
8886
8965
  }
8887
8966
  function splitFrontmatter2(raw, filename) {
@@ -9045,21 +9124,24 @@ ${lines.join("\n")}
9045
9124
  }
9046
9125
  };
9047
9126
 
9127
+ // src/internal/runtime/skills/skills-block.ts
9128
+ function buildSkillsBlock(skills) {
9129
+ if (skills.length === 0) return void 0;
9130
+ const lines = skills.map(
9131
+ (skill) => ` - ${escapeBlockBody(skill.name)}: ${escapeBlockBody(skill.description)}`
9132
+ );
9133
+ return `<skills>
9134
+ ${lines.join("\n")}
9135
+ </skills>`;
9136
+ }
9137
+
9048
9138
  // src/internal/runtime/system-prompt/sources/skills-provider.ts
9049
9139
  var SkillsPromptProvider = class {
9050
9140
  id = "skills";
9051
9141
  priority = 20;
9052
9142
  contribute(ctx) {
9053
9143
  if (ctx.skillsAutoInject === false) return Promise.resolve(void 0);
9054
- if (ctx.skills.length === 0) return Promise.resolve(void 0);
9055
- const lines = ctx.skills.map((skill) => {
9056
- const name = escapeBlockBody(skill.name);
9057
- const description = escapeBlockBody(skill.description);
9058
- return ` - ${name}: ${description}`;
9059
- });
9060
- return Promise.resolve(`<skills>
9061
- ${lines.join("\n")}
9062
- </skills>`);
9144
+ return Promise.resolve(buildSkillsBlock(ctx.skills));
9063
9145
  }
9064
9146
  };
9065
9147
 
@@ -10125,7 +10207,7 @@ async function loadPluginManifestFromJson(manifestPath, folderName) {
10125
10207
  const record = parsed;
10126
10208
  const name = typeof record.name === "string" ? record.name : folderName;
10127
10209
  const version = typeof record.version === "string" ? record.version : "0.0.0";
10128
- const capabilities = Array.isArray(record.capabilities) ? record.capabilities.filter((cap) => typeof cap === "string") : [];
10210
+ const capabilities = Array.isArray(record.capabilities) ? record.capabilities.filter((cap2) => typeof cap2 === "string") : [];
10129
10211
  const source = manifestPath.slice(manifestPath.indexOf(".theokit/"));
10130
10212
  const metadata = { name, version, capabilities, source };
10131
10213
  if (typeof record.entry === "string") metadata.entry = record.entry;
@@ -10168,7 +10250,7 @@ async function loadPluginManifestFromMarkdown(pluginsRoot, folderName) {
10168
10250
  return metadata;
10169
10251
  }
10170
10252
 
10171
- // src/internal/runtime/skills/skills-manager.ts
10253
+ // src/internal/runtime/skills/discover-skills.ts
10172
10254
  init_errors();
10173
10255
  init_path_guard();
10174
10256
 
@@ -10241,6 +10323,61 @@ function hasContent(value) {
10241
10323
  return value !== void 0 && value.trim().length > 0;
10242
10324
  }
10243
10325
 
10326
+ // src/internal/runtime/skills/discover-skills.ts
10327
+ async function discoverSkills(dir, options) {
10328
+ let entries;
10329
+ try {
10330
+ entries = await readWorkspaceDir(dir, "skills_read_error", "skills directory");
10331
+ } catch {
10332
+ return [];
10333
+ }
10334
+ const skills = [];
10335
+ for (const entry of entries) {
10336
+ if (!entry.isDirectory()) continue;
10337
+ let skillDir;
10338
+ try {
10339
+ skillDir = safePathJoin(dir, entry.name);
10340
+ assertNoSymlinkEscape(skillDir, dir);
10341
+ } catch {
10342
+ continue;
10343
+ }
10344
+ const skillPath = path.join(skillDir, "SKILL.md");
10345
+ let raw;
10346
+ try {
10347
+ raw = await promises.readFile(skillPath, "utf8");
10348
+ } catch {
10349
+ continue;
10350
+ }
10351
+ const skill = tryParseSkill(raw, entry.name, skillPath, options);
10352
+ if (skill !== void 0) skills.push(skill);
10353
+ }
10354
+ return skills;
10355
+ }
10356
+ function tryParseSkill(raw, fallbackName, source, options) {
10357
+ try {
10358
+ const frontmatter = parseSkillFrontmatter(raw, fallbackName);
10359
+ const skill = {
10360
+ name: frontmatter.name,
10361
+ description: frontmatter.description,
10362
+ source
10363
+ };
10364
+ if (frontmatter.category !== void 0) skill.category = frontmatter.category;
10365
+ if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
10366
+ return skill;
10367
+ } catch (cause) {
10368
+ if (cause instanceof exports.ConfigurationError) {
10369
+ options?.onInvalidSkill?.({
10370
+ name: fallbackName,
10371
+ source,
10372
+ code: cause.code ?? "unknown",
10373
+ message: cause.message
10374
+ });
10375
+ return void 0;
10376
+ }
10377
+ throw cause;
10378
+ }
10379
+ }
10380
+
10244
10381
  // src/internal/runtime/skills/skills-manager.ts
10245
10382
  var SkillsManager = class {
10246
10383
  constructor(cwd, _enabled, settingSourcesIncludeProject) {
@@ -10258,56 +10395,20 @@ var SkillsManager = class {
10258
10395
  await this.refresh();
10259
10396
  }
10260
10397
  async refresh() {
10261
- this.skills = [];
10262
10398
  const skillsRoot = path.join(this.cwd, ".theokit", "skills");
10263
- const entries = await readWorkspaceDir(skillsRoot, "skills_read_error", "skills directory");
10264
- for (const entry of entries) {
10265
- if (!entry.isDirectory()) continue;
10266
- let skillDir;
10267
- try {
10268
- skillDir = safePathJoin(skillsRoot, entry.name);
10269
- assertNoSymlinkEscape(skillDir, skillsRoot);
10270
- } catch {
10271
- continue;
10272
- }
10273
- const skillPath = path.join(skillDir, "SKILL.md");
10274
- let raw;
10275
- try {
10276
- raw = await promises.readFile(skillPath, "utf8");
10277
- } catch {
10278
- continue;
10399
+ this.skills = await discoverSkills(skillsRoot, {
10400
+ onInvalidSkill: (info) => {
10401
+ process.stderr.write(
10402
+ `[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
10403
+ `
10404
+ );
10279
10405
  }
10280
- const metadata = tryParseSkill(raw, entry.name, skillPath);
10281
- if (metadata !== void 0) this.skills.push(metadata);
10282
- }
10406
+ });
10283
10407
  }
10284
10408
  list() {
10285
10409
  return Promise.resolve(this.skills);
10286
10410
  }
10287
10411
  };
10288
- function tryParseSkill(raw, fallbackName, source) {
10289
- try {
10290
- const frontmatter = parseSkillFrontmatter(raw, fallbackName);
10291
- const metadata = {
10292
- name: frontmatter.name,
10293
- description: frontmatter.description,
10294
- source
10295
- };
10296
- if (frontmatter.category !== void 0) metadata.category = frontmatter.category;
10297
- if (frontmatter.dependencies !== void 0) metadata.dependencies = frontmatter.dependencies;
10298
- return metadata;
10299
- } catch (cause) {
10300
- if (cause instanceof exports.ConfigurationError) {
10301
- const code = cause.code ?? "unknown";
10302
- process.stderr.write(
10303
- `[theokit-sdk] skill ${fallbackName} skipped (${code}): ${cause.message}
10304
- `
10305
- );
10306
- return void 0;
10307
- }
10308
- throw cause;
10309
- }
10310
- }
10311
10412
 
10312
10413
  // src/internal/runtime/local-agent/local-agent-bootstrap.ts
10313
10414
  function registerLocalAgent(args) {
@@ -10720,6 +10821,7 @@ async function initLoopContext(inputs) {
10720
10821
  finalStatus: "finished",
10721
10822
  usage: new UsageAccumulator(),
10722
10823
  nudgeAttempts: 0,
10824
+ stopFeedbackAttempts: 0,
10723
10825
  ...memoryProviderHandle !== void 0 ? { memoryProviderHandle } : {},
10724
10826
  ...memorySystemPromptAdditions !== void 0 ? { memorySystemPromptAdditions } : {}
10725
10827
  };
@@ -10864,8 +10966,9 @@ function registerLoopError(ctx, cause) {
10864
10966
  if (ctx.error !== void 0) return;
10865
10967
  const rawMessage = cause?.message;
10866
10968
  const message = typeof rawMessage === "string" ? rawMessage : cause instanceof Error ? cause.message : String(cause);
10969
+ const metaCode = cause?.metadata?.code;
10867
10970
  const rawCode = cause?.code;
10868
- const code = typeof rawCode === "string" ? rawCode : void 0;
10971
+ const code = typeof metaCode === "string" ? metaCode : typeof rawCode === "string" ? rawCode : void 0;
10869
10972
  ctx.error = code !== void 0 ? { message, code, cause } : { message, cause };
10870
10973
  }
10871
10974
  async function runCollectorLoop(generator, inputs, ctx) {
@@ -11661,6 +11764,7 @@ function computeUsageCost(inputs, usage) {
11661
11764
 
11662
11765
  // src/internal/agent-loop/loop.ts
11663
11766
  var MAX_NUDGE_ATTEMPTS = 2;
11767
+ var MAX_STOP_FEEDBACK_ATTEMPTS = 2;
11664
11768
  async function runAgentLoop(inputs) {
11665
11769
  const sendSpan = inputs.telemetry?.startSpan("agent.send", {
11666
11770
  agentId: inputs.agentId,
@@ -11792,8 +11896,8 @@ function handleToolErrorContinuation(inputs, ctx, toolResults) {
11792
11896
  const hasError = toolResults.some((part) => part.type === "tool_result" && part.isError === true);
11793
11897
  if (hasError) {
11794
11898
  ctx._consecutiveToolErrors = (ctx._consecutiveToolErrors ?? 0) + 1;
11795
- const cap = inputs.maxConsecutiveToolErrors ?? 3;
11796
- if (ctx._consecutiveToolErrors >= cap) return "error";
11899
+ const cap2 = inputs.maxConsecutiveToolErrors ?? 3;
11900
+ if (ctx._consecutiveToolErrors >= cap2) return "error";
11797
11901
  return "continue";
11798
11902
  }
11799
11903
  ctx._consecutiveToolErrors = 0;
@@ -11818,6 +11922,28 @@ function shouldNudgeAndContinue(ctx, llmOutput) {
11818
11922
  });
11819
11923
  return true;
11820
11924
  }
11925
+ async function reflectAfterStop(inputs, ctx) {
11926
+ const result = await inputs.hooks.run({
11927
+ event: "stop",
11928
+ agentId: inputs.agentId,
11929
+ runId: inputs.runId
11930
+ });
11931
+ if (result.blocked) return false;
11932
+ if (ctx.stopFeedbackAttempts >= MAX_STOP_FEEDBACK_ATTEMPTS) return false;
11933
+ const feedback = result.decisions.find(
11934
+ (d) => d.decision === "feedback" && (d.feedback ?? "").length > 0
11935
+ )?.feedback;
11936
+ if (feedback === void 0) return false;
11937
+ ctx.stopFeedbackAttempts += 1;
11938
+ ctx.messages.push({ role: "user", content: [{ type: "text", text: feedback }] });
11939
+ return true;
11940
+ }
11941
+ async function finishOrReflect(inputs, ctx, llmOutput) {
11942
+ if (shouldNudgeAndContinue(ctx, llmOutput)) return "continue";
11943
+ if (await reflectAfterStop(inputs, ctx)) return "continue";
11944
+ ctx.finalStatus = "finished";
11945
+ return "done";
11946
+ }
11821
11947
  async function runIteration(inputs, ctx) {
11822
11948
  const llmOutput = await streamLlmTurn(inputs, ctx);
11823
11949
  accumulateUsage(ctx.usage, llmOutput);
@@ -11851,9 +11977,7 @@ async function continueOrTerminate(inputs, ctx, llmOutput) {
11851
11977
  await emitAssistantTextStep(inputs, ctx, llmOutput.text);
11852
11978
  }
11853
11979
  if (llmOutput.stopReason !== "tool_use" || llmOutput.toolCalls.length === 0) {
11854
- if (shouldNudgeAndContinue(ctx, llmOutput)) return "continue";
11855
- ctx.finalStatus = "finished";
11856
- return "done";
11980
+ return finishOrReflect(inputs, ctx, llmOutput);
11857
11981
  }
11858
11982
  ctx.messages.push(buildAssistantTurn(llmOutput.text, llmOutput.toolCalls));
11859
11983
  const toolResults = await dispatchTools(inputs, ctx.tools, llmOutput.toolCalls, ctx.events);
@@ -15287,7 +15411,7 @@ var MEMORY_GET_SCHEMA = {
15287
15411
  };
15288
15412
  var DEFAULT_MAX_TOTAL_CHARS = 16384;
15289
15413
  function createMemorySearchTool(opts) {
15290
- const cap = opts.maxTotalChars ?? DEFAULT_MAX_TOTAL_CHARS;
15414
+ const cap2 = opts.maxTotalChars ?? DEFAULT_MAX_TOTAL_CHARS;
15291
15415
  return {
15292
15416
  name: "memory_search",
15293
15417
  description: SEARCH_DESCRIPTION,
@@ -15304,7 +15428,7 @@ function createMemorySearchTool(opts) {
15304
15428
  ...sources !== void 0 ? { sources } : {}
15305
15429
  };
15306
15430
  const hits = await opts.index.search(query, searchOptions);
15307
- return JSON.stringify(capByTotalChars(hits, cap));
15431
+ return JSON.stringify(capByTotalChars(hits, cap2));
15308
15432
  }
15309
15433
  };
15310
15434
  }
@@ -15872,6 +15996,13 @@ function localAgentRunUntil(agent, goal, options) {
15872
15996
  }
15873
15997
  return wrap();
15874
15998
  }
15999
+ function localAgentRunToCompletion(agent, message, options) {
16000
+ async function run() {
16001
+ const { runToCompletionImpl: runToCompletionImpl2 } = await Promise.resolve().then(() => (init_run_to_completion(), run_to_completion_exports));
16002
+ return runToCompletionImpl2({ send: (m, o) => agent.send(m, o) }, message, options);
16003
+ }
16004
+ return run();
16005
+ }
15875
16006
  async function localAgentFork(parent, options) {
15876
16007
  const { forkAgentImpl: forkAgentImpl2 } = await Promise.resolve().then(() => (init_fork_agent(), fork_agent_exports));
15877
16008
  const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
@@ -15935,8 +16066,8 @@ async function applyPreUserSendHook(args) {
15935
16066
  ...args.options.memoryContext !== void 0 ? { memoryContext: args.options.memoryContext } : {},
15936
16067
  ...args.sendOptions.signal !== void 0 ? { signal: args.sendOptions.signal } : {}
15937
16068
  };
15938
- const cap = args.options.maxRecallContextBytes ?? DEFAULT_MAX_RECALL_BYTES;
15939
- const recalled = await args.pluginManager.runPreUserSendHooks(ctx, cap);
16069
+ const cap2 = args.options.maxRecallContextBytes ?? DEFAULT_MAX_RECALL_BYTES;
16070
+ const recalled = await args.pluginManager.runPreUserSendHooks(ctx, cap2);
15940
16071
  if (recalled === void 0 || recalled.length === 0) return args.original;
15941
16072
  const wrapped = `<memory-context>
15942
16073
  ${recalled}
@@ -16412,6 +16543,10 @@ var LocalAgent = class {
16412
16543
  fork(options) {
16413
16544
  return localAgentFork({ agentId: this.agentId, options: this.options, personalitySlugSnapshot: this.personalityStore.active(this.agentId) }, options);
16414
16545
  }
16546
+ // biome-ignore format: G8 budget — see runUntil comment above.
16547
+ runToCompletion(message, options) {
16548
+ return localAgentRunToCompletion(this, message, options);
16549
+ }
16415
16550
  };
16416
16551
  function resolveCwd(cwd) {
16417
16552
  return (Array.isArray(cwd) ? cwd[0] : cwd) ?? process.cwd();
@@ -17927,6 +18062,77 @@ function createCounterBudgetTracker(options = {}) {
17927
18062
  };
17928
18063
  }
17929
18064
 
18065
+ // src/internal/runtime/context/replay-history.ts
18066
+ var CHARS_PER_TOKEN = 4;
18067
+ var DEFAULT_RESERVE_TOKENS = 8e3;
18068
+ function finiteOr(value, fallback) {
18069
+ return Number.isFinite(value) ? value : fallback;
18070
+ }
18071
+ function charBudget(options) {
18072
+ const window = finiteOr(options.contextWindowTokens, 0);
18073
+ const reserve = finiteOr(options.reserveTokens ?? DEFAULT_RESERVE_TOKENS, DEFAULT_RESERVE_TOKENS);
18074
+ return Math.max(0, window - reserve) * CHARS_PER_TOKEN;
18075
+ }
18076
+ function assistantText2(event) {
18077
+ return event.message.content.filter((block) => block.type === "text").map((block) => block.text).join("");
18078
+ }
18079
+ function stringifyPayload(value) {
18080
+ if (value === void 0) return "";
18081
+ return typeof value === "string" ? value : JSON.stringify(value) ?? "";
18082
+ }
18083
+ function cap(content, perItemCap) {
18084
+ return truncateWithMarker(content, Math.max(0, perItemCap)).finalContent;
18085
+ }
18086
+ function mapEvent(event, perItemCap) {
18087
+ if (event.type === "assistant") {
18088
+ const text = assistantText2(event);
18089
+ return text.length > 0 ? { message: { role: "assistant", content: cap(text, perItemCap) } } : null;
18090
+ }
18091
+ if (event.type === "tool_call") {
18092
+ if (event.status === "running") {
18093
+ const content2 = cap(`[tool_call ${event.name}] ${stringifyPayload(event.args)}`, perItemCap);
18094
+ return { message: { role: "tool_call", content: content2 }, pairId: event.call_id };
18095
+ }
18096
+ const content = cap(
18097
+ `[tool_result ${event.name}] ${stringifyPayload(event.result)}`,
18098
+ perItemCap
18099
+ );
18100
+ return { message: { role: "tool_result", content }, pairId: event.call_id };
18101
+ }
18102
+ return null;
18103
+ }
18104
+ function evictionIndices(turns) {
18105
+ const head = turns[0];
18106
+ if (head?.pairId === void 0) return [0];
18107
+ const indices = [];
18108
+ for (let i = 0; i < turns.length; i += 1) {
18109
+ if (turns[i]?.pairId === head.pairId) indices.push(i);
18110
+ }
18111
+ return indices;
18112
+ }
18113
+ function totalChars(turns) {
18114
+ return turns.reduce((n, t) => n + t.message.content.length, 0);
18115
+ }
18116
+ function trimToBudget(turns, budgetChars) {
18117
+ const kept = [...turns];
18118
+ while (kept.length > 1 && totalChars(kept) > budgetChars) {
18119
+ const evict = evictionIndices(kept);
18120
+ if (kept.length - evict.length < 1) break;
18121
+ for (const idx of evict.sort((a, b) => b - a)) kept.splice(idx, 1);
18122
+ }
18123
+ return kept;
18124
+ }
18125
+ function buildReplayHistory(base, events, options) {
18126
+ const budgetChars = charBudget(options);
18127
+ const perItemCap = Math.max(0, options.perItemCap ?? Math.floor(budgetChars / 2));
18128
+ const turns = base.map((message) => ({ message }));
18129
+ for (const event of events) {
18130
+ const turn = mapEvent(event, perItemCap);
18131
+ if (turn !== null) turns.push(turn);
18132
+ }
18133
+ return trimToBudget(turns, budgetChars).map((t) => t.message);
18134
+ }
18135
+
17930
18136
  // src/internal/runtime/memory/memory-provider-noop.ts
17931
18137
  var NOOP_ADAPTER_ID = "noop";
17932
18138
  var NOOP_CAPABILITIES = {
@@ -19311,6 +19517,7 @@ exports.Security = Security;
19311
19517
  exports.Task = Task;
19312
19518
  exports.Theokit = Theokit;
19313
19519
  exports.UsageAccumulator = UsageAccumulator;
19520
+ exports.buildReplayHistory = buildReplayHistory;
19314
19521
  exports.chargeAndCheckThresholds = chargeAndCheckThresholds;
19315
19522
  exports.computeCost = computeCost;
19316
19523
  exports.createAgentFactory = createAgentFactory;