@theokit/sdk 4.22.0 → 4.23.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 (58) hide show
  1. package/dist/compaction.cjs +31 -0
  2. package/dist/compaction.cjs.map +1 -1
  3. package/dist/compaction.d.cts +79 -0
  4. package/dist/compaction.d.ts +79 -0
  5. package/dist/compaction.js +28 -1
  6. package/dist/compaction.js.map +1 -1
  7. package/dist/{cron-Bhdyjl0B.d.ts → cron-B_NkE_VM.d.ts} +15 -1
  8. package/dist/{cron-M2Xz7lq2.d.cts → cron-x3muPNgg.d.cts} +15 -1
  9. package/dist/cron.cjs +461 -332
  10. package/dist/cron.cjs.map +1 -1
  11. package/dist/cron.d.cts +2 -2
  12. package/dist/cron.d.ts +2 -2
  13. package/dist/cron.js +461 -332
  14. package/dist/cron.js.map +1 -1
  15. package/dist/{errors-gE8612p9.d.cts → errors-BdL-buYn.d.cts} +1 -1
  16. package/dist/{errors-CG2RpeW-.d.ts → errors-DHZtSNnj.d.ts} +1 -1
  17. package/dist/errors.d.cts +2 -2
  18. package/dist/eval.cjs +461 -332
  19. package/dist/eval.cjs.map +1 -1
  20. package/dist/eval.js +461 -332
  21. package/dist/eval.js.map +1 -1
  22. package/dist/index.cjs +634 -503
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +21 -12
  25. package/dist/index.d.ts +21 -12
  26. package/dist/index.js +634 -503
  27. package/dist/index.js.map +1 -1
  28. package/dist/internal/global-singleton.d.ts +13 -0
  29. package/dist/internal/llm/openai-messages.d.ts +2 -0
  30. package/dist/internal/local-agent/mcp-pool.d.ts +41 -0
  31. package/dist/internal/local-agent/real-local-run.d.ts +2 -0
  32. package/dist/internal/persistence/index.cjs +3 -1
  33. package/dist/internal/persistence/index.cjs.map +1 -1
  34. package/dist/internal/persistence/index.js +3 -1
  35. package/dist/internal/persistence/index.js.map +1 -1
  36. package/dist/internal/providers/registry.d.ts +1 -0
  37. package/dist/internal/runtime/lifecycle/context-budget-event.d.ts +25 -0
  38. package/dist/internal/runtime/lifecycle/goal-marker.d.ts +13 -0
  39. package/dist/internal/runtime/lifecycle/run-until.d.ts +0 -1
  40. package/dist/internal/session/agent-session.d.ts +1 -1
  41. package/dist/internal/session/session-cache.d.ts +20 -0
  42. package/dist/models.cjs +11 -15
  43. package/dist/models.cjs.map +1 -1
  44. package/dist/models.js +11 -15
  45. package/dist/models.js.map +1 -1
  46. package/dist/persistence.cjs +3 -1
  47. package/dist/persistence.cjs.map +1 -1
  48. package/dist/persistence.js +3 -1
  49. package/dist/persistence.js.map +1 -1
  50. package/dist/provider-catalog.json +144 -469
  51. package/dist/{run-DFM1H2jW.d.cts → run-OJbGyweZ.d.cts} +20 -1
  52. package/dist/{run-DFM1H2jW.d.ts → run-OJbGyweZ.d.ts} +20 -1
  53. package/dist/types/agent.d.ts +14 -0
  54. package/dist/types/run-events.d.ts +20 -1
  55. package/dist/workflow.cjs.map +1 -1
  56. package/dist/workflow.js.map +1 -1
  57. package/package.json +2 -2
  58. package/dist/goal-loop.d.ts +0 -35
package/dist/cron.cjs CHANGED
@@ -1598,6 +1598,44 @@ var init_plugin_guards = __esm({
1598
1598
  }
1599
1599
  });
1600
1600
 
1601
+ // src/compaction.ts
1602
+ function resolveEffectiveContextWindow(input) {
1603
+ if (!(input.margin > 0) || input.margin > 1) {
1604
+ throw new ContextWindowMarginError(input.margin);
1605
+ }
1606
+ const withMargin = (raw) => Math.floor(raw * input.margin);
1607
+ if (input.override !== void 0) {
1608
+ const clamped = input.catalog !== void 0 && input.override > input.catalog;
1609
+ const raw = clamped ? input.catalog : input.override;
1610
+ return { window: withMargin(raw), source: "override", clamped };
1611
+ }
1612
+ if (input.catalog !== void 0) {
1613
+ return { window: withMargin(input.catalog), source: "catalog", clamped: false };
1614
+ }
1615
+ return { window: withMargin(input.floor ?? 0), source: "fallback", clamped: false };
1616
+ }
1617
+ function estimateTokens(text) {
1618
+ return Math.ceil(text.length / 4);
1619
+ }
1620
+ var ContextWindowMarginError, CONTEXT_WINDOW_MARGIN, CONTEXT_WINDOW_FLOOR;
1621
+ var init_compaction = __esm({
1622
+ "src/compaction.ts"() {
1623
+ init_errors();
1624
+ ContextWindowMarginError = class extends TheokitAgentError {
1625
+ constructor(margin) {
1626
+ super(
1627
+ `context-window margin must be in (0, 1], got ${String(margin)}. A margin above 1 grows the assumed window and delays compaction past the real limit.`,
1628
+ { code: "invalid_context_window_margin" }
1629
+ );
1630
+ this.margin = margin;
1631
+ }
1632
+ margin;
1633
+ };
1634
+ CONTEXT_WINDOW_MARGIN = 0.95;
1635
+ CONTEXT_WINDOW_FLOOR = 128e3;
1636
+ }
1637
+ });
1638
+
1601
1639
  // src/types/run-events.ts
1602
1640
  function emitRunEvent(sink, event) {
1603
1641
  if (sink === void 0) return;
@@ -1610,6 +1648,18 @@ var init_run_events = __esm({
1610
1648
  "src/types/run-events.ts"() {
1611
1649
  }
1612
1650
  });
1651
+
1652
+ // src/internal/global-singleton.ts
1653
+ function globalSingleton(key, create) {
1654
+ const g = globalThis;
1655
+ const sym = Symbol.for(key);
1656
+ if (g[sym] === void 0) g[sym] = create();
1657
+ return g[sym];
1658
+ }
1659
+ var init_global_singleton = __esm({
1660
+ "src/internal/global-singleton.ts"() {
1661
+ }
1662
+ });
1613
1663
  var MODALITIES, costSchema, limitSchema, modalitiesSchema, catalogModelSchema;
1614
1664
  var init_catalog_schema = __esm({
1615
1665
  "src/internal/providers/catalog-schema.ts"() {
@@ -1650,12 +1700,6 @@ var init_catalog_schema = __esm({
1650
1700
  });
1651
1701
 
1652
1702
  // src/internal/providers/registry.ts
1653
- function globalSingleton(key, create) {
1654
- const g = globalThis;
1655
- const sym = Symbol.for(key);
1656
- if (g[sym] === void 0) g[sym] = create();
1657
- return g[sym];
1658
- }
1659
1703
  function registerProvider(profile) {
1660
1704
  if (REGISTRY.has(profile.name)) {
1661
1705
  process.stderr.write(`[theokit-sdk] Provider "${profile.name}" overridden by user plugin.
@@ -1680,6 +1724,7 @@ function getProviderProfile(name) {
1680
1724
  var REGISTRY, ALIASES;
1681
1725
  var init_registry = __esm({
1682
1726
  "src/internal/providers/registry.ts"() {
1727
+ init_global_singleton();
1683
1728
  REGISTRY = globalSingleton(
1684
1729
  "theokit-sdk.providers.registry",
1685
1730
  () => /* @__PURE__ */ new Map()
@@ -1687,12 +1732,6 @@ var init_registry = __esm({
1687
1732
  ALIASES = globalSingleton("theokit-sdk.providers.aliases", () => /* @__PURE__ */ new Map());
1688
1733
  }
1689
1734
  });
1690
- function globalSingleton2(key, create) {
1691
- const g = globalThis;
1692
- const sym = Symbol.for(key);
1693
- if (g[sym] === void 0) g[sym] = create();
1694
- return g[sym];
1695
- }
1696
1735
  function getCatalogModelInfo(key) {
1697
1736
  ensureModelIndexLoaded();
1698
1737
  return modelInfoIndex.get(key);
@@ -1781,32 +1820,24 @@ function registerCatalogProviders(opts) {
1781
1820
  var __dirname_resolved, modelInfoIndex, patchedModelKeys, indexState;
1782
1821
  var init_catalog_loader = __esm({
1783
1822
  "src/internal/providers/catalog-loader.ts"() {
1823
+ init_global_singleton();
1784
1824
  init_catalog_schema();
1785
1825
  init_registry();
1786
1826
  __dirname_resolved = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cron.cjs', document.baseURI).href))));
1787
- modelInfoIndex = globalSingleton2(
1827
+ modelInfoIndex = globalSingleton(
1788
1828
  "theokit-sdk.providers.model-info-index",
1789
1829
  () => /* @__PURE__ */ new Map()
1790
1830
  );
1791
- patchedModelKeys = globalSingleton2(
1831
+ patchedModelKeys = globalSingleton(
1792
1832
  "theokit-sdk.providers.model-info-patched",
1793
1833
  () => /* @__PURE__ */ new Set()
1794
1834
  );
1795
- indexState = globalSingleton2("theokit-sdk.providers.model-info-loaded", () => ({
1835
+ indexState = globalSingleton("theokit-sdk.providers.model-info-loaded", () => ({
1796
1836
  loaded: false
1797
1837
  }));
1798
1838
  }
1799
1839
  });
1800
1840
 
1801
- // src/compaction.ts
1802
- function estimateTokens(text) {
1803
- return Math.ceil(text.length / 4);
1804
- }
1805
- var init_compaction = __esm({
1806
- "src/compaction.ts"() {
1807
- }
1808
- });
1809
-
1810
1841
  // src/internal/providers/builtin/anthropic.ts
1811
1842
  var ANTHROPIC;
1812
1843
  var init_anthropic = __esm({
@@ -2602,12 +2633,6 @@ var init_builtin = __esm({
2602
2633
  })();
2603
2634
  }
2604
2635
  });
2605
- function globalSingleton3(key, create) {
2606
- const g = globalThis;
2607
- const sym = Symbol.for(key);
2608
- if (g[sym] === void 0) g[sym] = create();
2609
- return g[sym];
2610
- }
2611
2636
  function pluginsRoot() {
2612
2637
  return path.join(os.homedir(), ".theokit", "plugins", "model-providers");
2613
2638
  }
@@ -2699,8 +2724,9 @@ async function loadOne(dir, entryName) {
2699
2724
  var discoveryState;
2700
2725
  var init_discovery = __esm({
2701
2726
  "src/internal/providers/discovery.ts"() {
2727
+ init_global_singleton();
2702
2728
  init_registry();
2703
- discoveryState = globalSingleton3("theokit-sdk.providers.discovered", () => ({
2729
+ discoveryState = globalSingleton("theokit-sdk.providers.discovered", () => ({
2704
2730
  done: false
2705
2731
  }));
2706
2732
  }
@@ -4376,6 +4402,68 @@ var init_hermes_tool_extract = __esm({
4376
4402
  }
4377
4403
  });
4378
4404
 
4405
+ // src/internal/llm/openai-messages.ts
4406
+ function toOpenAIMessages(message) {
4407
+ if (message.role === "system") return [systemMessage(message)];
4408
+ if (message.role === "user") return userOrToolMessages(message);
4409
+ return [assistantMessage(message)];
4410
+ }
4411
+ function systemMessage(message) {
4412
+ return { role: "system", content: joinTextParts2(message) };
4413
+ }
4414
+ function joinTextParts2(message) {
4415
+ return message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
4416
+ }
4417
+ function userOrToolMessages(message) {
4418
+ const out = [];
4419
+ for (const part of message.content) {
4420
+ if (part.type === "tool_result") {
4421
+ out.push({
4422
+ role: "tool",
4423
+ tool_call_id: part.toolUseId,
4424
+ // SE7 — this wire's tool role is string-only: text blocks flatten; an
4425
+ // image block fails fast (ConfigurationError).
4426
+ content: toStringToolResultContent(part.content, "openai")
4427
+ });
4428
+ }
4429
+ }
4430
+ const userText = joinTextParts2(message);
4431
+ const imageParts = message.content.filter(
4432
+ (p) => p.type === "image"
4433
+ );
4434
+ if (imageParts.length > 0) {
4435
+ const content = [];
4436
+ if (userText.length > 0) content.push({ type: "text", text: userText });
4437
+ for (const img of imageParts) {
4438
+ const url = img.source.type === "base64" ? `data:${img.source.media_type};base64,${img.source.data}` : img.source.url;
4439
+ content.push({ type: "image_url", image_url: { url } });
4440
+ }
4441
+ out.push({ role: "user", content });
4442
+ } else if (userText.length > 0) {
4443
+ out.push({ role: "user", content: userText });
4444
+ }
4445
+ return out;
4446
+ }
4447
+ function assistantMessage(message) {
4448
+ const text = joinTextParts2(message);
4449
+ const toolCalls = message.content.filter((part) => part.type === "tool_use").map((part) => {
4450
+ const tc = part;
4451
+ return {
4452
+ id: tc.id,
4453
+ type: "function",
4454
+ function: { name: tc.name, arguments: JSON.stringify(tc.input) }
4455
+ };
4456
+ });
4457
+ const result = { role: "assistant", content: text };
4458
+ if (toolCalls.length > 0) result.tool_calls = toolCalls;
4459
+ return result;
4460
+ }
4461
+ var init_openai_messages = __esm({
4462
+ "src/internal/llm/openai-messages.ts"() {
4463
+ init_tool_result_content();
4464
+ }
4465
+ });
4466
+
4379
4467
  // src/internal/llm/openai.ts
4380
4468
  function deriveChatPath(baseUrl) {
4381
4469
  try {
@@ -4437,61 +4525,6 @@ function encodeOpenAIResponseFormat(rf) {
4437
4525
  }
4438
4526
  };
4439
4527
  }
4440
- function toOpenAIMessages(message) {
4441
- if (message.role === "system") return [systemMessage(message)];
4442
- if (message.role === "user") return userOrToolMessages(message);
4443
- return [assistantMessage(message)];
4444
- }
4445
- function systemMessage(message) {
4446
- return { role: "system", content: joinTextParts2(message) };
4447
- }
4448
- function joinTextParts2(message) {
4449
- return message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
4450
- }
4451
- function userOrToolMessages(message) {
4452
- const out = [];
4453
- for (const part of message.content) {
4454
- if (part.type === "tool_result") {
4455
- out.push({
4456
- role: "tool",
4457
- tool_call_id: part.toolUseId,
4458
- // SE7 — this wire's tool role is string-only: text blocks flatten; an
4459
- // image block fails fast (ConfigurationError).
4460
- content: toStringToolResultContent(part.content, "openai")
4461
- });
4462
- }
4463
- }
4464
- const userText = joinTextParts2(message);
4465
- const imageParts = message.content.filter(
4466
- (p) => p.type === "image"
4467
- );
4468
- if (imageParts.length > 0) {
4469
- const content = [];
4470
- if (userText.length > 0) content.push({ type: "text", text: userText });
4471
- for (const img of imageParts) {
4472
- const url = img.source.type === "base64" ? `data:${img.source.media_type};base64,${img.source.data}` : img.source.url;
4473
- content.push({ type: "image_url", image_url: { url } });
4474
- }
4475
- out.push({ role: "user", content });
4476
- } else if (userText.length > 0) {
4477
- out.push({ role: "user", content: userText });
4478
- }
4479
- return out;
4480
- }
4481
- function assistantMessage(message) {
4482
- const text = joinTextParts2(message);
4483
- const toolCalls = message.content.filter((part) => part.type === "tool_use").map((part) => {
4484
- const tc = part;
4485
- return {
4486
- id: tc.id,
4487
- type: "function",
4488
- function: { name: tc.name, arguments: JSON.stringify(tc.input) }
4489
- };
4490
- });
4491
- const result = { role: "assistant", content: text };
4492
- if (toolCalls.length > 0) result.tool_calls = toolCalls;
4493
- return result;
4494
- }
4495
4528
  var OpenAIClient, OpenAIStreamAccumulator, openAISystemText;
4496
4529
  var init_openai2 = __esm({
4497
4530
  "src/internal/llm/openai.ts"() {
@@ -4500,8 +4533,8 @@ var init_openai2 = __esm({
4500
4533
  init_openai_compatible2();
4501
4534
  init_finish();
4502
4535
  init_hermes_tool_extract();
4536
+ init_openai_messages();
4503
4537
  init_sse();
4504
- init_tool_result_content();
4505
4538
  OpenAIClient = class {
4506
4539
  constructor(options) {
4507
4540
  this.options = options;
@@ -5590,6 +5623,14 @@ function selectTransport(profile, apiKey) {
5590
5623
  const ctx = { apiKey };
5591
5624
  return { fetch: profile.transform.fetch?.(ctx), headers: profile.transform.headers?.(ctx) };
5592
5625
  };
5626
+ const comTransform = (opts, criar) => {
5627
+ const t = applyTransform();
5628
+ assertOAuthResolved(t);
5629
+ if (t.fetch !== void 0) opts.fetch = t.fetch;
5630
+ const merged = profile.extraHeaders !== void 0 || t.headers !== void 0 ? { ...profile.extraHeaders, ...t.headers } : void 0;
5631
+ if (merged !== void 0) opts.extraHeaders = merged;
5632
+ return criar(opts);
5633
+ };
5593
5634
  const assertOAuthResolved = (t) => {
5594
5635
  if (apiKey !== "__oauth_lazy_token__") return;
5595
5636
  const auth = t.headers?.authorization ?? t.headers?.Authorization;
@@ -5618,12 +5659,7 @@ function selectTransport(profile, apiKey) {
5618
5659
  }
5619
5660
  const envOverride = resolveBaseUrlEnvOverride(profile.name);
5620
5661
  if (envOverride !== void 0) opts.baseUrl = envOverride;
5621
- const t = applyTransform();
5622
- assertOAuthResolved(t);
5623
- if (t.fetch !== void 0) opts.fetch = t.fetch;
5624
- const merged = profile.extraHeaders !== void 0 || t.headers !== void 0 ? { ...profile.extraHeaders, ...t.headers } : void 0;
5625
- if (merged !== void 0) opts.extraHeaders = merged;
5626
- return new OpenAIClient(opts);
5662
+ return comTransform(opts, (o) => new OpenAIClient(o));
5627
5663
  }
5628
5664
  if (profile.apiMode === "anthropic_messages") {
5629
5665
  if (profile.name === "vertex") {
@@ -5632,12 +5668,7 @@ function selectTransport(profile, apiKey) {
5632
5668
  }
5633
5669
  const opts = { apiKey };
5634
5670
  opts.baseUrl = process.env.ANTHROPIC_API_BASE_URL ?? profile.baseUrl;
5635
- const t = applyTransform();
5636
- assertOAuthResolved(t);
5637
- if (t.fetch !== void 0) opts.fetch = t.fetch;
5638
- const merged = profile.extraHeaders !== void 0 || t.headers !== void 0 ? { ...profile.extraHeaders, ...t.headers } : void 0;
5639
- if (merged !== void 0) opts.extraHeaders = merged;
5640
- return new AnthropicClient(opts);
5671
+ return comTransform(opts, (o) => new AnthropicClient(o));
5641
5672
  }
5642
5673
  if (profile.apiMode === "bedrock_anthropic") {
5643
5674
  const realKey = apiKey === "__bedrock_lazy_token__" ? void 0 : apiKey;
@@ -5794,202 +5825,52 @@ function buildCompressionPrompt(messages) {
5794
5825
 
5795
5826
  --- CONVERSATION TO SUMMARIZE ---
5796
5827
  ${formatted}
5797
- --- END ---`;
5798
- }
5799
- async function compressConversationWindow(opts) {
5800
- const userPrompt = buildCompressionPrompt(opts.messages);
5801
- let summary;
5802
- try {
5803
- summary = await opts.callLlm(opts.model, COMPRESSION_SYSTEM, userPrompt);
5804
- } catch (cause) {
5805
- throw new CompressionFailedError(
5806
- `Compression LLM call failed: ${cause instanceof Error ? cause.message : String(cause)}`,
5807
- { cause: cause instanceof Error ? cause : void 0 }
5808
- );
5809
- }
5810
- if (!summary || summary.trim().length === 0) {
5811
- throw new CompressionFailedError(
5812
- "Compression LLM returned empty summary \u2014 reduction ineffective."
5813
- );
5814
- }
5815
- return {
5816
- role: "system",
5817
- content: `[Compressed conversation summary]: ${summary.trim()}`
5818
- };
5819
- }
5820
- var CompressionFailedError, COMPRESSION_SYSTEM;
5821
- var init_compression_summarizer = __esm({
5822
- "src/internal/runtime/compression/compression-summarizer.ts"() {
5823
- CompressionFailedError = class extends Error {
5824
- name = "CompressionFailedError";
5825
- };
5826
- COMPRESSION_SYSTEM = "You are a conversation summarizer. Produce a concise factual summary. Preserve all decisions, preferences, code snippets, and action items. Do not add commentary or opinions. Output ONLY the summary text.";
5827
- }
5828
- });
5829
-
5830
- // src/internal/session/agent-session-store.ts
5831
- function seedTranscript(prior, opts) {
5832
- return SessionTranscript.fromRecords(prior, opts);
5833
- }
5834
- function mapAgentTurn(steps) {
5835
- const assistant = {};
5836
- const toolResults = [];
5837
- const toolCalls = [];
5838
- for (const step of steps) {
5839
- if (step.type === "thinkingMessage") assistant.thinking = step.message.text;
5840
- else if (step.type === "assistantMessage") assistant.text = step.message.text;
5841
- else if (step.type === "toolCall")
5842
- toolCalls.push({
5843
- id: step.message.callId,
5844
- name: step.message.name,
5845
- input: step.message.args ?? {}
5846
- });
5847
- else
5848
- toolResults.push({
5849
- toolUseId: step.message.callId,
5850
- content: step.message.result,
5851
- isError: step.message.isError
5852
- });
5853
- }
5854
- if (toolCalls.length > 0) assistant.toolCalls = toolCalls;
5855
- return { assistant, toolResults };
5856
- }
5857
- function hasAssistantContent(a) {
5858
- return a.text !== void 0 || a.thinking !== void 0 || (a.toolCalls?.length ?? 0) > 0;
5859
- }
5860
- function appendConversation(transcript, conversation) {
5861
- for (const ct of conversation) {
5862
- if (ct.type !== "agentConversationTurn") continue;
5863
- const { assistant, toolResults } = mapAgentTurn(ct.turn.steps);
5864
- if (hasAssistantContent(assistant)) transcript.appendAssistantTurn(assistant);
5865
- if (toolResults.length > 0) transcript.appendToolResults(toolResults);
5866
- }
5867
- }
5868
- async function readSessionMessages(store, agentId) {
5869
- const records = await store.readRecords(agentId);
5870
- return reconstructMessages(records).map(narrowToSessionMessage);
5871
- }
5872
- function partToText(p) {
5873
- if (p.type === "text") return p.text ?? "";
5874
- if (p.type === "tool_use") return `[tool call] ${p.name ?? ""}`;
5875
- if (p.type === "tool_result") {
5876
- const body = typeof p.content === "string" ? p.content : JSON.stringify(p.content);
5877
- return `[tool result] ${body}`;
5878
- }
5879
- return "";
5880
- }
5881
- function narrowToSessionMessage(m) {
5882
- const role = m.role === "user" ? "user" : "assistant";
5883
- const text = m.content.map(partToText).filter((s) => s.length > 0).join("\n");
5884
- return { role, text };
5885
- }
5886
- function deltaRecords(transcript, priorLength) {
5887
- return transcript.records().slice(priorLength);
5888
- }
5889
- async function persistTurn(store, loc, sessionId, turn) {
5890
- const prior = await store.readRecords(loc.agentId);
5891
- const transcript = seedTranscript(prior, { cwd: loc.cwd, sessionId, model: loc.model });
5892
- transcript.appendUserTurn(turn.userText);
5893
- appendConversation(transcript, turn.conversation);
5894
- await store.appendRecords(loc.agentId, deltaRecords(transcript, prior.length));
5895
- }
5896
- var init_agent_session_store = __esm({
5897
- "src/internal/session/agent-session-store.ts"() {
5898
- init_session_transcript();
5899
- }
5900
- });
5901
-
5902
- // src/internal/session/agent-session.ts
5903
- function transcriptKey(cwd, agentId) {
5904
- return `${cwd}::${agentId}`;
5905
- }
5906
- function appendSessionMessage(agentId, message) {
5907
- const existing = sessions.get(agentId) ?? [];
5908
- existing.push(message);
5909
- sessions.set(agentId, existing);
5910
- }
5911
- function getSessionMessages(agentId) {
5912
- return sessions.get(agentId) ?? [];
5913
- }
5914
- function persistTurnToTranscript(store, loc, sessionId, turn, onCompact) {
5915
- const key = transcriptKey(loc.cwd, loc.agentId);
5916
- const chained = (pendingWrites.get(key) ?? Promise.resolve()).then(async () => {
5917
- try {
5918
- await persistTurn(store, loc, sessionId, turn);
5919
- const count = (recordCounts.get(key) ?? 0) + 1;
5920
- recordCounts.set(key, count);
5921
- if (turn.autoCompact !== void 0) {
5922
- const { autoCompactIfNeeded: autoCompactIfNeeded2 } = await Promise.resolve().then(() => (init_compact_session(), compact_session_exports));
5923
- const fired = await autoCompactIfNeeded2({
5924
- store,
5925
- loc,
5926
- sessionId,
5927
- usageTotal: turn.autoCompact.usageTotal,
5928
- contextWindow: turn.autoCompact.contextWindow,
5929
- turnCount: count,
5930
- summarize: turn.autoCompact.summarize
5931
- });
5932
- if (fired) onCompact?.();
5933
- }
5934
- } catch (cause) {
5935
- const msg = cause instanceof Error ? cause.message : String(cause);
5936
- process.stderr.write(
5937
- `[theokit-sdk] session transcript write failed (${loc.agentId}): ${msg}
5938
- `
5939
- );
5940
- }
5941
- });
5942
- pendingWrites.set(
5943
- key,
5944
- chained.then(
5945
- () => void 0,
5946
- () => void 0
5947
- )
5948
- );
5949
- }
5950
- async function hydrateSession(agentId, loc) {
5951
- const key = transcriptKey(loc.cwd, agentId);
5952
- if (hydratedKeys.has(key)) return;
5953
- hydratedKeys.add(key);
5954
- const persisted = await readSessionMessages(loc.store, agentId);
5955
- if (persisted.length === 0) return;
5956
- sessions.set(agentId, persisted);
5957
- }
5958
- async function flushSessionWrites() {
5959
- while (pendingWrites.size > 0) {
5960
- const all = Array.from(pendingWrites.values());
5961
- pendingWrites.clear();
5962
- await Promise.all(all);
5828
+ --- END ---`;
5829
+ }
5830
+ async function compressConversationWindow(opts) {
5831
+ const userPrompt = buildCompressionPrompt(opts.messages);
5832
+ let summary;
5833
+ try {
5834
+ summary = await opts.callLlm(opts.model, COMPRESSION_SYSTEM, userPrompt);
5835
+ } catch (cause) {
5836
+ throw new CompressionFailedError(
5837
+ `Compression LLM call failed: ${cause instanceof Error ? cause.message : String(cause)}`,
5838
+ { cause: cause instanceof Error ? cause : void 0 }
5839
+ );
5840
+ }
5841
+ if (!summary || summary.trim().length === 0) {
5842
+ throw new CompressionFailedError(
5843
+ "Compression LLM returned empty summary \u2014 reduction ineffective."
5844
+ );
5963
5845
  }
5846
+ return {
5847
+ role: "system",
5848
+ content: `[Compressed conversation summary]: ${summary.trim()}`
5849
+ };
5964
5850
  }
5965
- function clearSession(agentId) {
5966
- sessions.delete(agentId);
5851
+ var CompressionFailedError, COMPRESSION_SYSTEM;
5852
+ var init_compression_summarizer = __esm({
5853
+ "src/internal/runtime/compression/compression-summarizer.ts"() {
5854
+ CompressionFailedError = class extends Error {
5855
+ name = "CompressionFailedError";
5856
+ };
5857
+ COMPRESSION_SYSTEM = "You are a conversation summarizer. Produce a concise factual summary. Preserve all decisions, preferences, code snippets, and action items. Do not add commentary or opinions. Output ONLY the summary text.";
5858
+ }
5859
+ });
5860
+
5861
+ // src/internal/session/session-cache.ts
5862
+ function transcriptKey(cwd, agentId) {
5863
+ return `${cwd}::${agentId}`;
5967
5864
  }
5968
5865
  function invalidateSessionCache(cwd, agentId) {
5969
5866
  sessions.delete(agentId);
5970
5867
  hydratedKeys.delete(transcriptKey(cwd, agentId));
5971
5868
  }
5972
- function enqueueSessionWrite(cwd, agentId, fn) {
5973
- const key = transcriptKey(cwd, agentId);
5974
- const prior = pendingWrites.get(key) ?? Promise.resolve();
5975
- const result = prior.then(fn);
5976
- pendingWrites.set(
5977
- key,
5978
- result.then(
5979
- () => void 0,
5980
- () => void 0
5981
- )
5982
- );
5983
- return result;
5984
- }
5985
- var sessions, hydratedKeys, pendingWrites, recordCounts;
5986
- var init_agent_session = __esm({
5987
- "src/internal/session/agent-session.ts"() {
5988
- init_agent_session_store();
5869
+ var sessions, hydratedKeys;
5870
+ var init_session_cache = __esm({
5871
+ "src/internal/session/session-cache.ts"() {
5989
5872
  sessions = /* @__PURE__ */ new Map();
5990
5873
  hydratedKeys = /* @__PURE__ */ new Set();
5991
- pendingWrites = /* @__PURE__ */ new Map();
5992
- recordCounts = /* @__PURE__ */ new Map();
5993
5874
  }
5994
5875
  });
5995
5876
 
@@ -6151,7 +6032,7 @@ var init_compact_session = __esm({
6151
6032
  init_providers();
6152
6033
  init_compression_model_registry();
6153
6034
  init_compression_summarizer();
6154
- init_agent_session();
6035
+ init_session_cache();
6155
6036
  COMPACT_SUMMARY_MARKER = "[[theokit:compact-summary]]";
6156
6037
  COMPACT_USER_MESSAGE_MAX_TOKENS = 2e4;
6157
6038
  autoCompactAttempts = (() => {
@@ -6162,6 +6043,165 @@ var init_compact_session = __esm({
6162
6043
  })();
6163
6044
  }
6164
6045
  });
6046
+
6047
+ // src/internal/session/agent-session-store.ts
6048
+ function seedTranscript(prior, opts) {
6049
+ return SessionTranscript.fromRecords(prior, opts);
6050
+ }
6051
+ function mapAgentTurn(steps) {
6052
+ const assistant = {};
6053
+ const toolResults = [];
6054
+ const toolCalls = [];
6055
+ for (const step of steps) {
6056
+ if (step.type === "thinkingMessage") assistant.thinking = step.message.text;
6057
+ else if (step.type === "assistantMessage") assistant.text = step.message.text;
6058
+ else if (step.type === "toolCall")
6059
+ toolCalls.push({
6060
+ id: step.message.callId,
6061
+ name: step.message.name,
6062
+ input: step.message.args ?? {}
6063
+ });
6064
+ else
6065
+ toolResults.push({
6066
+ toolUseId: step.message.callId,
6067
+ content: step.message.result,
6068
+ isError: step.message.isError
6069
+ });
6070
+ }
6071
+ if (toolCalls.length > 0) assistant.toolCalls = toolCalls;
6072
+ return { assistant, toolResults };
6073
+ }
6074
+ function hasAssistantContent(a) {
6075
+ return a.text !== void 0 || a.thinking !== void 0 || (a.toolCalls?.length ?? 0) > 0;
6076
+ }
6077
+ function appendConversation(transcript, conversation) {
6078
+ for (const ct of conversation) {
6079
+ if (ct.type !== "agentConversationTurn") continue;
6080
+ const { assistant, toolResults } = mapAgentTurn(ct.turn.steps);
6081
+ if (hasAssistantContent(assistant)) transcript.appendAssistantTurn(assistant);
6082
+ if (toolResults.length > 0) transcript.appendToolResults(toolResults);
6083
+ }
6084
+ }
6085
+ async function readSessionMessages(store, agentId) {
6086
+ const records = await store.readRecords(agentId);
6087
+ return reconstructMessages(records).map(narrowToSessionMessage);
6088
+ }
6089
+ function partToText(p) {
6090
+ if (p.type === "text") return p.text ?? "";
6091
+ if (p.type === "tool_use") return `[tool call] ${p.name ?? ""}`;
6092
+ if (p.type === "tool_result") {
6093
+ const body = typeof p.content === "string" ? p.content : JSON.stringify(p.content);
6094
+ return `[tool result] ${body}`;
6095
+ }
6096
+ return "";
6097
+ }
6098
+ function narrowToSessionMessage(m) {
6099
+ const role = m.role === "user" ? "user" : "assistant";
6100
+ const text = m.content.map(partToText).filter((s) => s.length > 0).join("\n");
6101
+ return { role, text };
6102
+ }
6103
+ function deltaRecords(transcript, priorLength) {
6104
+ return transcript.records().slice(priorLength);
6105
+ }
6106
+ async function persistTurn(store, loc, sessionId, turn) {
6107
+ const prior = await store.readRecords(loc.agentId);
6108
+ const transcript = seedTranscript(prior, { cwd: loc.cwd, sessionId, model: loc.model });
6109
+ transcript.appendUserTurn(turn.userText);
6110
+ appendConversation(transcript, turn.conversation);
6111
+ await store.appendRecords(loc.agentId, deltaRecords(transcript, prior.length));
6112
+ }
6113
+ var init_agent_session_store = __esm({
6114
+ "src/internal/session/agent-session-store.ts"() {
6115
+ init_session_transcript();
6116
+ }
6117
+ });
6118
+
6119
+ // src/internal/session/agent-session.ts
6120
+ function appendSessionMessage(agentId, message) {
6121
+ const existing = sessions.get(agentId) ?? [];
6122
+ existing.push(message);
6123
+ sessions.set(agentId, existing);
6124
+ }
6125
+ function getSessionMessages(agentId) {
6126
+ return sessions.get(agentId) ?? [];
6127
+ }
6128
+ function persistTurnToTranscript(store, loc, sessionId, turn, onCompact) {
6129
+ const key = transcriptKey(loc.cwd, loc.agentId);
6130
+ const chained = (pendingWrites.get(key) ?? Promise.resolve()).then(async () => {
6131
+ try {
6132
+ await persistTurn(store, loc, sessionId, turn);
6133
+ const count = (recordCounts.get(key) ?? 0) + 1;
6134
+ recordCounts.set(key, count);
6135
+ if (turn.autoCompact !== void 0) {
6136
+ const { autoCompactIfNeeded: autoCompactIfNeeded2 } = await Promise.resolve().then(() => (init_compact_session(), compact_session_exports));
6137
+ const fired = await autoCompactIfNeeded2({
6138
+ store,
6139
+ loc,
6140
+ sessionId,
6141
+ usageTotal: turn.autoCompact.usageTotal,
6142
+ contextWindow: turn.autoCompact.contextWindow,
6143
+ turnCount: count,
6144
+ summarize: turn.autoCompact.summarize
6145
+ });
6146
+ if (fired) onCompact?.();
6147
+ }
6148
+ } catch (cause) {
6149
+ const msg = cause instanceof Error ? cause.message : String(cause);
6150
+ process.stderr.write(
6151
+ `[theokit-sdk] session transcript write failed (${loc.agentId}): ${msg}
6152
+ `
6153
+ );
6154
+ }
6155
+ });
6156
+ pendingWrites.set(
6157
+ key,
6158
+ chained.then(
6159
+ () => void 0,
6160
+ () => void 0
6161
+ )
6162
+ );
6163
+ }
6164
+ async function hydrateSession(agentId, loc) {
6165
+ const key = transcriptKey(loc.cwd, agentId);
6166
+ if (hydratedKeys.has(key)) return;
6167
+ hydratedKeys.add(key);
6168
+ const persisted = await readSessionMessages(loc.store, agentId);
6169
+ if (persisted.length === 0) return;
6170
+ sessions.set(agentId, persisted);
6171
+ }
6172
+ async function flushSessionWrites() {
6173
+ while (pendingWrites.size > 0) {
6174
+ const all = Array.from(pendingWrites.values());
6175
+ pendingWrites.clear();
6176
+ await Promise.all(all);
6177
+ }
6178
+ }
6179
+ function clearSession(agentId) {
6180
+ sessions.delete(agentId);
6181
+ }
6182
+ function enqueueSessionWrite(cwd, agentId, fn) {
6183
+ const key = transcriptKey(cwd, agentId);
6184
+ const prior = pendingWrites.get(key) ?? Promise.resolve();
6185
+ const result = prior.then(fn);
6186
+ pendingWrites.set(
6187
+ key,
6188
+ result.then(
6189
+ () => void 0,
6190
+ () => void 0
6191
+ )
6192
+ );
6193
+ return result;
6194
+ }
6195
+ var pendingWrites, recordCounts;
6196
+ var init_agent_session = __esm({
6197
+ "src/internal/session/agent-session.ts"() {
6198
+ init_agent_session_store();
6199
+ init_session_cache();
6200
+ init_session_cache();
6201
+ pendingWrites = /* @__PURE__ */ new Map();
6202
+ recordCounts = /* @__PURE__ */ new Map();
6203
+ }
6204
+ });
6165
6205
  async function withToolWhitelist(whitelist, fn) {
6166
6206
  return toolWhitelistStore.run(whitelist, fn);
6167
6207
  }
@@ -6256,10 +6296,10 @@ var init_context = __esm({
6256
6296
  }
6257
6297
  });
6258
6298
 
6259
- // src/goal-loop.ts
6299
+ // src/internal/runtime/lifecycle/goal-marker.ts
6260
6300
  var GOAL_CONTINUATION_MARKER;
6261
- var init_goal_loop = __esm({
6262
- "src/goal-loop.ts"() {
6301
+ var init_goal_marker = __esm({
6302
+ "src/internal/runtime/lifecycle/goal-marker.ts"() {
6263
6303
  GOAL_CONTINUATION_MARKER = "[[theokit:goal-continuation]]";
6264
6304
  }
6265
6305
  });
@@ -6433,7 +6473,7 @@ ${lastResponse.slice(-1e3)}`
6433
6473
  }
6434
6474
  var init_run_until = __esm({
6435
6475
  "src/internal/runtime/lifecycle/run-until.ts"() {
6436
- init_goal_loop();
6476
+ init_goal_marker();
6437
6477
  }
6438
6478
  });
6439
6479
 
@@ -10608,6 +10648,7 @@ function parseDecisionFromStdout(stdout) {
10608
10648
  }
10609
10649
 
10610
10650
  // src/internal/runtime/lifecycle/post-run-lifecycle.ts
10651
+ init_compaction();
10611
10652
  init_run_events();
10612
10653
 
10613
10654
  // src/internal/memory/storage/session-summary-writer.ts
@@ -10677,6 +10718,12 @@ function resolveActiveMemorySummaryForSend(legacySummary, portPathEnabled) {
10677
10718
  return legacySummary;
10678
10719
  }
10679
10720
 
10721
+ // src/internal/runtime/lifecycle/context-budget-event.ts
10722
+ function buildContextBudgetEvent(model, resolved) {
10723
+ if (resolved.source !== "fallback") return void 0;
10724
+ return { type: "compaction_fallback", model, window: resolved.window };
10725
+ }
10726
+
10680
10727
  // src/internal/runtime/lifecycle/post-run-lifecycle.ts
10681
10728
  async function runPostRunLifecycle(inputs) {
10682
10729
  const {
@@ -10702,18 +10749,15 @@ async function runPostRunLifecycle(inputs) {
10702
10749
  appendSessionMessage(agentId, { role: "assistant", text: result.result });
10703
10750
  }
10704
10751
  const conversation = await safeConversation(run);
10705
- const contextWindow = getCatalogModelInfo(model)?.limit?.context;
10706
- if (contextWindow === void 0) {
10707
- const g = globalThis;
10708
- const sym = /* @__PURE__ */ Symbol.for("theokit-sdk.compact.no-cw-warned");
10709
- const warned3 = g[sym] ??= /* @__PURE__ */ new Set();
10710
- if (!warned3.has(model)) {
10711
- warned3.add(model);
10712
- process.stderr.write(
10713
- `[theokit-sdk] auto-compaction disabled: model "${model}" has no context-window entry in the catalog
10714
- `
10715
- );
10716
- }
10752
+ const resolvedWindow = resolveEffectiveContextWindow({
10753
+ catalog: getCatalogModelInfo(model)?.limit?.context,
10754
+ margin: CONTEXT_WINDOW_MARGIN,
10755
+ floor: CONTEXT_WINDOW_FLOOR
10756
+ });
10757
+ const contextWindow = resolvedWindow.window;
10758
+ const budgetEvent = buildContextBudgetEvent(model, resolvedWindow);
10759
+ if (budgetEvent !== void 0 && onRunEvent !== void 0) {
10760
+ emitRunEvent(onRunEvent, budgetEvent);
10717
10761
  }
10718
10762
  const lastRequestUsage = result.usage?.requests?.at(-1)?.totalTokens;
10719
10763
  const usageForTrigger = lastRequestUsage ?? result.usage?.totalTokens;
@@ -15685,6 +15729,71 @@ function registerPluginProviderProfiles(entries) {
15685
15729
 
15686
15730
  // src/internal/local-agent/real-local-run.ts
15687
15731
  init_async_local_storage();
15732
+
15733
+ // src/internal/local-agent/mcp-pool.ts
15734
+ var DEFAULT_IDLE_TTL_MS = 6e5;
15735
+ function configKey(config) {
15736
+ return JSON.stringify(
15737
+ config,
15738
+ (_k, v) => v !== null && typeof v === "object" && !Array.isArray(v) ? Object.fromEntries(
15739
+ Object.entries(v).sort(([a], [b]) => a < b ? -1 : 1)
15740
+ ) : v
15741
+ );
15742
+ }
15743
+ var McpClientPool = class {
15744
+ entries = /* @__PURE__ */ new Map();
15745
+ idleTtlMs;
15746
+ now;
15747
+ constructor(options = {}) {
15748
+ this.idleTtlMs = options.idleTtlMs ?? DEFAULT_IDLE_TTL_MS;
15749
+ this.now = options.now ?? Date.now;
15750
+ }
15751
+ /**
15752
+ * Return the pooled client for `(sessionId, serverName, config)`, creating it via `factory` on
15753
+ * first use. Every call refreshes idleness — the TTL measures time SINCE LAST USE, not age.
15754
+ *
15755
+ * Synchronous by design: `createMcpClient` is itself synchronous (the handshake happens later, on
15756
+ * `initialize`), so there is no `await` between the lookup and the insert and two concurrent runs
15757
+ * in the same session cannot both miss the cache.
15758
+ */
15759
+ acquire(sessionId, serverName, config, factory) {
15760
+ const key = `${sessionId}\0${serverName}\0${configKey(config)}`;
15761
+ const existing = this.entries.get(key);
15762
+ if (existing !== void 0) {
15763
+ existing.lastUsedAt = this.now();
15764
+ return existing.client;
15765
+ }
15766
+ const client = factory();
15767
+ this.entries.set(key, { client, sessionId, lastUsedAt: this.now() });
15768
+ return client;
15769
+ }
15770
+ /**
15771
+ * Close and forget every client of ONE session. Scoped deliberately: clearing the whole map would
15772
+ * tear down the servers of every concurrent conversation.
15773
+ */
15774
+ disposeSession(sessionId, close) {
15775
+ for (const [key, entry] of this.entries) {
15776
+ if (entry.sessionId !== sessionId) continue;
15777
+ close(entry.client);
15778
+ this.entries.delete(key);
15779
+ }
15780
+ }
15781
+ /** Close and forget every client idle for longer than the TTL. */
15782
+ reapIdle(close) {
15783
+ const cutoff = this.now() - this.idleTtlMs;
15784
+ for (const [key, entry] of this.entries) {
15785
+ if (entry.lastUsedAt > cutoff) continue;
15786
+ close(entry.client);
15787
+ this.entries.delete(key);
15788
+ }
15789
+ }
15790
+ /** Live pooled-client count — for observability and tests. */
15791
+ size() {
15792
+ return this.entries.size;
15793
+ }
15794
+ };
15795
+
15796
+ // src/internal/local-agent/real-local-run.ts
15688
15797
  init_real_local_run_provider();
15689
15798
 
15690
15799
  // src/a2a/subagent.ts
@@ -16103,12 +16212,23 @@ function buildLoopInputs(options, runId, userText, userImages) {
16103
16212
  ...options.agentOptions.memoryProvider !== void 0 ? { memoryProvider: options.agentOptions.memoryProvider } : {}
16104
16213
  };
16105
16214
  }
16215
+ var sessionMcpPool = new McpClientPool();
16216
+ function disposeSessionMcpClients(agentId) {
16217
+ sessionMcpPool.disposeSession(agentId, (client) => {
16218
+ void client.close();
16219
+ });
16220
+ }
16106
16221
  function buildMcpMap(options) {
16107
16222
  const map = /* @__PURE__ */ new Map();
16108
16223
  const inline = options.sendOptions.mcpServers ?? options.agentOptions.mcpServers;
16109
16224
  if (inline === void 0) return map;
16225
+ const pooled = options.agentOptions.mcpLifecycle === "session";
16226
+ if (pooled) sessionMcpPool.reapIdle((c) => void c.close());
16110
16227
  for (const [name, config] of Object.entries(inline)) {
16111
- map.set(name, createMcpClient(name, config));
16228
+ map.set(
16229
+ name,
16230
+ pooled ? sessionMcpPool.acquire(options.agentId, name, config, () => createMcpClient(name, config)) : createMcpClient(name, config)
16231
+ );
16112
16232
  }
16113
16233
  return map;
16114
16234
  }
@@ -17173,7 +17293,9 @@ async function loadDriver(filePath) {
17173
17293
  }
17174
17294
  try {
17175
17295
  const mod = await (driverLoaderOverrides?.nodeSqlite?.() ?? Promise.resolve(
17176
- process.getBuiltinModule?.("node:sqlite") ?? (() => {
17296
+ process.getBuiltinModule?.(
17297
+ "node:sqlite"
17298
+ ) ?? (() => {
17177
17299
  throw new Error("node:sqlite built-in unavailable (Node < 22.3)");
17178
17300
  })()
17179
17301
  ));
@@ -18223,7 +18345,8 @@ var LocalAgentMemory = class {
18223
18345
  const message = cause instanceof Error ? cause.message : String(cause);
18224
18346
  const g = globalThis;
18225
18347
  const sym = /* @__PURE__ */ Symbol.for("theokit-sdk.memory.warned");
18226
- const warned3 = g[sym] ??= /* @__PURE__ */ new Set();
18348
+ g[sym] ??= /* @__PURE__ */ new Set();
18349
+ const warned3 = g[sym];
18227
18350
  if (!warned3.has(message)) {
18228
18351
  warned3.add(message);
18229
18352
  process.stderr.write(`[theokit-sdk] memory tools unavailable: ${message}
@@ -19407,6 +19530,7 @@ var LocalAgent = class {
19407
19530
  liveAgentRegistry.forget(this.agentId);
19408
19531
  this.lifecycleAbortController.abort();
19409
19532
  await withCwdMutex(`agent-send:${this.agentId}`, () => Promise.resolve());
19533
+ disposeSessionMcpClients(this.agentId);
19410
19534
  await flushSessionWrites();
19411
19535
  await flushRegistrySaves(this.workspaceCwd);
19412
19536
  }
@@ -19707,8 +19831,8 @@ async function getRegisteredAgentOrThrow(agentId) {
19707
19831
  // src/agent.ts
19708
19832
  init_errors();
19709
19833
  init_discovery();
19710
- init_agent_session();
19711
19834
  init_agent_factory_registry();
19835
+ init_agent_session();
19712
19836
  var streamObjectImport;
19713
19837
  var Agent = class _Agent {
19714
19838
  constructor() {
@@ -20000,26 +20124,26 @@ var Agent = class _Agent {
20000
20124
  reg = getRegisteredAgent(agentId);
20001
20125
  }
20002
20126
  if (reg === void 0 || reg.runtime !== "local") {
20003
- throw new UnknownAgentError(`No local agent "${agentId}" registered \u2014 compact targets local sessions.`);
20127
+ throw new UnknownAgentError(
20128
+ `No local agent "${agentId}" registered \u2014 compact targets local sessions.`
20129
+ );
20004
20130
  }
20005
- const cwd = reg.cwd ?? process.cwd();
20006
- const optModel = reg.options.model;
20007
- const model = reg.model?.id ?? (typeof optModel === "string" ? optModel : optModel?.id) ?? "unknown";
20008
20131
  const { compactSessionTranscript: compactSessionTranscript2, buildDefaultSummarizer: buildDefaultSummarizer2 } = await Promise.resolve().then(() => (init_compact_session(), compact_session_exports));
20009
- const { FsSessionStore: FsSessionStore2 } = await Promise.resolve().then(() => (init_fs_session_store(), fs_session_store_exports));
20010
- const { defaultBaseDir: defaultBaseDir2, expandTilde: expandTilde2 } = await Promise.resolve().then(() => (init_session_transcript(), session_transcript_exports));
20011
- const baseDir = reg.options.local?.baseDir !== void 0 ? expandTilde2(reg.options.local.baseDir) : defaultBaseDir2();
20012
- const store = new FsSessionStore2({ baseDir, cwd });
20013
- return enqueueSessionWrite(cwd, agentId, () => compactSessionTranscript2({
20014
- store,
20015
- loc: { cwd, agentId, model },
20016
- sessionId: agentId,
20017
- trigger: options.trigger ?? "manual",
20018
- summarize: options.summarize ?? buildDefaultSummarizer2({
20019
- agentModel: model,
20020
- ...reg.options.apiKey !== void 0 ? { apiKey: reg.options.apiKey } : {}
20132
+ const { cwd, model, store } = await abrirStoreLocal(reg);
20133
+ return enqueueSessionWrite(
20134
+ cwd,
20135
+ agentId,
20136
+ () => compactSessionTranscript2({
20137
+ store,
20138
+ loc: { cwd, agentId, model },
20139
+ sessionId: agentId,
20140
+ trigger: options.trigger ?? "manual",
20141
+ summarize: options.summarize ?? buildDefaultSummarizer2({
20142
+ agentModel: model,
20143
+ ...reg.options.apiKey !== void 0 ? { apiKey: reg.options.apiKey } : {}
20144
+ })
20021
20145
  })
20022
- }));
20146
+ );
20023
20147
  }
20024
20148
  /**
20025
20149
  * M51 — inject a SYNTHETIC user+assistant pair into a LOCAL session's persisted transcript WITHOUT
@@ -20036,16 +20160,12 @@ var Agent = class _Agent {
20036
20160
  reg = getRegisteredAgent(agentId);
20037
20161
  }
20038
20162
  if (reg === void 0 || reg.runtime !== "local") {
20039
- throw new UnknownAgentError(`No local agent "${agentId}" registered \u2014 injectSessionTurn targets local sessions.`);
20163
+ throw new UnknownAgentError(
20164
+ `No local agent "${agentId}" registered \u2014 injectSessionTurn targets local sessions.`
20165
+ );
20040
20166
  }
20041
- const cwd = reg.cwd ?? process.cwd();
20042
- const optModel = reg.options.model;
20043
- const model = reg.model?.id ?? (typeof optModel === "string" ? optModel : optModel?.id) ?? "unknown";
20044
20167
  const { injectSessionTurn: injectSessionTurn2 } = await Promise.resolve().then(() => (init_inject_session(), inject_session_exports));
20045
- const { FsSessionStore: FsSessionStore2 } = await Promise.resolve().then(() => (init_fs_session_store(), fs_session_store_exports));
20046
- const { defaultBaseDir: defaultBaseDir2, expandTilde: expandTilde2 } = await Promise.resolve().then(() => (init_session_transcript(), session_transcript_exports));
20047
- const baseDir = reg.options.local?.baseDir !== void 0 ? expandTilde2(reg.options.local.baseDir) : defaultBaseDir2();
20048
- const store = new FsSessionStore2({ baseDir, cwd });
20168
+ const { cwd, model, store } = await abrirStoreLocal(reg);
20049
20169
  await injectSessionTurn2({
20050
20170
  store,
20051
20171
  loc: { cwd, agentId, model },
@@ -20087,6 +20207,15 @@ setAgentFacade({
20087
20207
  resume: (agentId, options) => Agent.resume(agentId, options),
20088
20208
  batch: (prompts, options) => Agent.batch(prompts, options)
20089
20209
  });
20210
+ async function abrirStoreLocal(reg) {
20211
+ const cwd = reg.cwd ?? process.cwd();
20212
+ const optModel = reg.options.model;
20213
+ const model = reg.model?.id ?? (typeof optModel === "string" ? optModel : optModel?.id) ?? "unknown";
20214
+ const { FsSessionStore: FsSessionStore2 } = await Promise.resolve().then(() => (init_fs_session_store(), fs_session_store_exports));
20215
+ const { defaultBaseDir: defaultBaseDir2, expandTilde: expandTilde2 } = await Promise.resolve().then(() => (init_session_transcript(), session_transcript_exports));
20216
+ const baseDir = reg.options.local?.baseDir !== void 0 ? expandTilde2(reg.options.local.baseDir) : defaultBaseDir2();
20217
+ return { cwd, model, store: new FsSessionStore2({ baseDir, cwd }) };
20218
+ }
20090
20219
 
20091
20220
  // src/cron.ts
20092
20221
  init_errors();