@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.js CHANGED
@@ -1595,6 +1595,44 @@ var init_plugin_guards = __esm({
1595
1595
  }
1596
1596
  });
1597
1597
 
1598
+ // src/compaction.ts
1599
+ function resolveEffectiveContextWindow(input) {
1600
+ if (!(input.margin > 0) || input.margin > 1) {
1601
+ throw new ContextWindowMarginError(input.margin);
1602
+ }
1603
+ const withMargin = (raw) => Math.floor(raw * input.margin);
1604
+ if (input.override !== void 0) {
1605
+ const clamped = input.catalog !== void 0 && input.override > input.catalog;
1606
+ const raw = clamped ? input.catalog : input.override;
1607
+ return { window: withMargin(raw), source: "override", clamped };
1608
+ }
1609
+ if (input.catalog !== void 0) {
1610
+ return { window: withMargin(input.catalog), source: "catalog", clamped: false };
1611
+ }
1612
+ return { window: withMargin(input.floor ?? 0), source: "fallback", clamped: false };
1613
+ }
1614
+ function estimateTokens(text) {
1615
+ return Math.ceil(text.length / 4);
1616
+ }
1617
+ var ContextWindowMarginError, CONTEXT_WINDOW_MARGIN, CONTEXT_WINDOW_FLOOR;
1618
+ var init_compaction = __esm({
1619
+ "src/compaction.ts"() {
1620
+ init_errors();
1621
+ ContextWindowMarginError = class extends TheokitAgentError {
1622
+ constructor(margin) {
1623
+ super(
1624
+ `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.`,
1625
+ { code: "invalid_context_window_margin" }
1626
+ );
1627
+ this.margin = margin;
1628
+ }
1629
+ margin;
1630
+ };
1631
+ CONTEXT_WINDOW_MARGIN = 0.95;
1632
+ CONTEXT_WINDOW_FLOOR = 128e3;
1633
+ }
1634
+ });
1635
+
1598
1636
  // src/types/run-events.ts
1599
1637
  function emitRunEvent(sink, event) {
1600
1638
  if (sink === void 0) return;
@@ -1607,6 +1645,18 @@ var init_run_events = __esm({
1607
1645
  "src/types/run-events.ts"() {
1608
1646
  }
1609
1647
  });
1648
+
1649
+ // src/internal/global-singleton.ts
1650
+ function globalSingleton(key, create) {
1651
+ const g = globalThis;
1652
+ const sym = Symbol.for(key);
1653
+ if (g[sym] === void 0) g[sym] = create();
1654
+ return g[sym];
1655
+ }
1656
+ var init_global_singleton = __esm({
1657
+ "src/internal/global-singleton.ts"() {
1658
+ }
1659
+ });
1610
1660
  var MODALITIES, costSchema, limitSchema, modalitiesSchema, catalogModelSchema;
1611
1661
  var init_catalog_schema = __esm({
1612
1662
  "src/internal/providers/catalog-schema.ts"() {
@@ -1647,12 +1697,6 @@ var init_catalog_schema = __esm({
1647
1697
  });
1648
1698
 
1649
1699
  // src/internal/providers/registry.ts
1650
- function globalSingleton(key, create) {
1651
- const g = globalThis;
1652
- const sym = Symbol.for(key);
1653
- if (g[sym] === void 0) g[sym] = create();
1654
- return g[sym];
1655
- }
1656
1700
  function registerProvider(profile) {
1657
1701
  if (REGISTRY.has(profile.name)) {
1658
1702
  process.stderr.write(`[theokit-sdk] Provider "${profile.name}" overridden by user plugin.
@@ -1677,6 +1721,7 @@ function getProviderProfile(name) {
1677
1721
  var REGISTRY, ALIASES;
1678
1722
  var init_registry = __esm({
1679
1723
  "src/internal/providers/registry.ts"() {
1724
+ init_global_singleton();
1680
1725
  REGISTRY = globalSingleton(
1681
1726
  "theokit-sdk.providers.registry",
1682
1727
  () => /* @__PURE__ */ new Map()
@@ -1684,12 +1729,6 @@ var init_registry = __esm({
1684
1729
  ALIASES = globalSingleton("theokit-sdk.providers.aliases", () => /* @__PURE__ */ new Map());
1685
1730
  }
1686
1731
  });
1687
- function globalSingleton2(key, create) {
1688
- const g = globalThis;
1689
- const sym = Symbol.for(key);
1690
- if (g[sym] === void 0) g[sym] = create();
1691
- return g[sym];
1692
- }
1693
1732
  function getCatalogModelInfo(key) {
1694
1733
  ensureModelIndexLoaded();
1695
1734
  return modelInfoIndex.get(key);
@@ -1778,32 +1817,24 @@ function registerCatalogProviders(opts) {
1778
1817
  var __dirname_resolved, modelInfoIndex, patchedModelKeys, indexState;
1779
1818
  var init_catalog_loader = __esm({
1780
1819
  "src/internal/providers/catalog-loader.ts"() {
1820
+ init_global_singleton();
1781
1821
  init_catalog_schema();
1782
1822
  init_registry();
1783
1823
  __dirname_resolved = dirname(fileURLToPath(import.meta.url));
1784
- modelInfoIndex = globalSingleton2(
1824
+ modelInfoIndex = globalSingleton(
1785
1825
  "theokit-sdk.providers.model-info-index",
1786
1826
  () => /* @__PURE__ */ new Map()
1787
1827
  );
1788
- patchedModelKeys = globalSingleton2(
1828
+ patchedModelKeys = globalSingleton(
1789
1829
  "theokit-sdk.providers.model-info-patched",
1790
1830
  () => /* @__PURE__ */ new Set()
1791
1831
  );
1792
- indexState = globalSingleton2("theokit-sdk.providers.model-info-loaded", () => ({
1832
+ indexState = globalSingleton("theokit-sdk.providers.model-info-loaded", () => ({
1793
1833
  loaded: false
1794
1834
  }));
1795
1835
  }
1796
1836
  });
1797
1837
 
1798
- // src/compaction.ts
1799
- function estimateTokens(text) {
1800
- return Math.ceil(text.length / 4);
1801
- }
1802
- var init_compaction = __esm({
1803
- "src/compaction.ts"() {
1804
- }
1805
- });
1806
-
1807
1838
  // src/internal/providers/builtin/anthropic.ts
1808
1839
  var ANTHROPIC;
1809
1840
  var init_anthropic = __esm({
@@ -2599,12 +2630,6 @@ var init_builtin = __esm({
2599
2630
  })();
2600
2631
  }
2601
2632
  });
2602
- function globalSingleton3(key, create) {
2603
- const g = globalThis;
2604
- const sym = Symbol.for(key);
2605
- if (g[sym] === void 0) g[sym] = create();
2606
- return g[sym];
2607
- }
2608
2633
  function pluginsRoot() {
2609
2634
  return join(homedir(), ".theokit", "plugins", "model-providers");
2610
2635
  }
@@ -2696,8 +2721,9 @@ async function loadOne(dir, entryName) {
2696
2721
  var discoveryState;
2697
2722
  var init_discovery = __esm({
2698
2723
  "src/internal/providers/discovery.ts"() {
2724
+ init_global_singleton();
2699
2725
  init_registry();
2700
- discoveryState = globalSingleton3("theokit-sdk.providers.discovered", () => ({
2726
+ discoveryState = globalSingleton("theokit-sdk.providers.discovered", () => ({
2701
2727
  done: false
2702
2728
  }));
2703
2729
  }
@@ -4373,6 +4399,68 @@ var init_hermes_tool_extract = __esm({
4373
4399
  }
4374
4400
  });
4375
4401
 
4402
+ // src/internal/llm/openai-messages.ts
4403
+ function toOpenAIMessages(message) {
4404
+ if (message.role === "system") return [systemMessage(message)];
4405
+ if (message.role === "user") return userOrToolMessages(message);
4406
+ return [assistantMessage(message)];
4407
+ }
4408
+ function systemMessage(message) {
4409
+ return { role: "system", content: joinTextParts2(message) };
4410
+ }
4411
+ function joinTextParts2(message) {
4412
+ return message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
4413
+ }
4414
+ function userOrToolMessages(message) {
4415
+ const out = [];
4416
+ for (const part of message.content) {
4417
+ if (part.type === "tool_result") {
4418
+ out.push({
4419
+ role: "tool",
4420
+ tool_call_id: part.toolUseId,
4421
+ // SE7 — this wire's tool role is string-only: text blocks flatten; an
4422
+ // image block fails fast (ConfigurationError).
4423
+ content: toStringToolResultContent(part.content, "openai")
4424
+ });
4425
+ }
4426
+ }
4427
+ const userText = joinTextParts2(message);
4428
+ const imageParts = message.content.filter(
4429
+ (p) => p.type === "image"
4430
+ );
4431
+ if (imageParts.length > 0) {
4432
+ const content = [];
4433
+ if (userText.length > 0) content.push({ type: "text", text: userText });
4434
+ for (const img of imageParts) {
4435
+ const url = img.source.type === "base64" ? `data:${img.source.media_type};base64,${img.source.data}` : img.source.url;
4436
+ content.push({ type: "image_url", image_url: { url } });
4437
+ }
4438
+ out.push({ role: "user", content });
4439
+ } else if (userText.length > 0) {
4440
+ out.push({ role: "user", content: userText });
4441
+ }
4442
+ return out;
4443
+ }
4444
+ function assistantMessage(message) {
4445
+ const text = joinTextParts2(message);
4446
+ const toolCalls = message.content.filter((part) => part.type === "tool_use").map((part) => {
4447
+ const tc = part;
4448
+ return {
4449
+ id: tc.id,
4450
+ type: "function",
4451
+ function: { name: tc.name, arguments: JSON.stringify(tc.input) }
4452
+ };
4453
+ });
4454
+ const result = { role: "assistant", content: text };
4455
+ if (toolCalls.length > 0) result.tool_calls = toolCalls;
4456
+ return result;
4457
+ }
4458
+ var init_openai_messages = __esm({
4459
+ "src/internal/llm/openai-messages.ts"() {
4460
+ init_tool_result_content();
4461
+ }
4462
+ });
4463
+
4376
4464
  // src/internal/llm/openai.ts
4377
4465
  function deriveChatPath(baseUrl) {
4378
4466
  try {
@@ -4434,61 +4522,6 @@ function encodeOpenAIResponseFormat(rf) {
4434
4522
  }
4435
4523
  };
4436
4524
  }
4437
- function toOpenAIMessages(message) {
4438
- if (message.role === "system") return [systemMessage(message)];
4439
- if (message.role === "user") return userOrToolMessages(message);
4440
- return [assistantMessage(message)];
4441
- }
4442
- function systemMessage(message) {
4443
- return { role: "system", content: joinTextParts2(message) };
4444
- }
4445
- function joinTextParts2(message) {
4446
- return message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
4447
- }
4448
- function userOrToolMessages(message) {
4449
- const out = [];
4450
- for (const part of message.content) {
4451
- if (part.type === "tool_result") {
4452
- out.push({
4453
- role: "tool",
4454
- tool_call_id: part.toolUseId,
4455
- // SE7 — this wire's tool role is string-only: text blocks flatten; an
4456
- // image block fails fast (ConfigurationError).
4457
- content: toStringToolResultContent(part.content, "openai")
4458
- });
4459
- }
4460
- }
4461
- const userText = joinTextParts2(message);
4462
- const imageParts = message.content.filter(
4463
- (p) => p.type === "image"
4464
- );
4465
- if (imageParts.length > 0) {
4466
- const content = [];
4467
- if (userText.length > 0) content.push({ type: "text", text: userText });
4468
- for (const img of imageParts) {
4469
- const url = img.source.type === "base64" ? `data:${img.source.media_type};base64,${img.source.data}` : img.source.url;
4470
- content.push({ type: "image_url", image_url: { url } });
4471
- }
4472
- out.push({ role: "user", content });
4473
- } else if (userText.length > 0) {
4474
- out.push({ role: "user", content: userText });
4475
- }
4476
- return out;
4477
- }
4478
- function assistantMessage(message) {
4479
- const text = joinTextParts2(message);
4480
- const toolCalls = message.content.filter((part) => part.type === "tool_use").map((part) => {
4481
- const tc = part;
4482
- return {
4483
- id: tc.id,
4484
- type: "function",
4485
- function: { name: tc.name, arguments: JSON.stringify(tc.input) }
4486
- };
4487
- });
4488
- const result = { role: "assistant", content: text };
4489
- if (toolCalls.length > 0) result.tool_calls = toolCalls;
4490
- return result;
4491
- }
4492
4525
  var OpenAIClient, OpenAIStreamAccumulator, openAISystemText;
4493
4526
  var init_openai2 = __esm({
4494
4527
  "src/internal/llm/openai.ts"() {
@@ -4497,8 +4530,8 @@ var init_openai2 = __esm({
4497
4530
  init_openai_compatible2();
4498
4531
  init_finish();
4499
4532
  init_hermes_tool_extract();
4533
+ init_openai_messages();
4500
4534
  init_sse();
4501
- init_tool_result_content();
4502
4535
  OpenAIClient = class {
4503
4536
  constructor(options) {
4504
4537
  this.options = options;
@@ -5587,6 +5620,14 @@ function selectTransport(profile, apiKey) {
5587
5620
  const ctx = { apiKey };
5588
5621
  return { fetch: profile.transform.fetch?.(ctx), headers: profile.transform.headers?.(ctx) };
5589
5622
  };
5623
+ const comTransform = (opts, criar) => {
5624
+ const t = applyTransform();
5625
+ assertOAuthResolved(t);
5626
+ if (t.fetch !== void 0) opts.fetch = t.fetch;
5627
+ const merged = profile.extraHeaders !== void 0 || t.headers !== void 0 ? { ...profile.extraHeaders, ...t.headers } : void 0;
5628
+ if (merged !== void 0) opts.extraHeaders = merged;
5629
+ return criar(opts);
5630
+ };
5590
5631
  const assertOAuthResolved = (t) => {
5591
5632
  if (apiKey !== "__oauth_lazy_token__") return;
5592
5633
  const auth = t.headers?.authorization ?? t.headers?.Authorization;
@@ -5615,12 +5656,7 @@ function selectTransport(profile, apiKey) {
5615
5656
  }
5616
5657
  const envOverride = resolveBaseUrlEnvOverride(profile.name);
5617
5658
  if (envOverride !== void 0) opts.baseUrl = envOverride;
5618
- const t = applyTransform();
5619
- assertOAuthResolved(t);
5620
- if (t.fetch !== void 0) opts.fetch = t.fetch;
5621
- const merged = profile.extraHeaders !== void 0 || t.headers !== void 0 ? { ...profile.extraHeaders, ...t.headers } : void 0;
5622
- if (merged !== void 0) opts.extraHeaders = merged;
5623
- return new OpenAIClient(opts);
5659
+ return comTransform(opts, (o) => new OpenAIClient(o));
5624
5660
  }
5625
5661
  if (profile.apiMode === "anthropic_messages") {
5626
5662
  if (profile.name === "vertex") {
@@ -5629,12 +5665,7 @@ function selectTransport(profile, apiKey) {
5629
5665
  }
5630
5666
  const opts = { apiKey };
5631
5667
  opts.baseUrl = process.env.ANTHROPIC_API_BASE_URL ?? profile.baseUrl;
5632
- const t = applyTransform();
5633
- assertOAuthResolved(t);
5634
- if (t.fetch !== void 0) opts.fetch = t.fetch;
5635
- const merged = profile.extraHeaders !== void 0 || t.headers !== void 0 ? { ...profile.extraHeaders, ...t.headers } : void 0;
5636
- if (merged !== void 0) opts.extraHeaders = merged;
5637
- return new AnthropicClient(opts);
5668
+ return comTransform(opts, (o) => new AnthropicClient(o));
5638
5669
  }
5639
5670
  if (profile.apiMode === "bedrock_anthropic") {
5640
5671
  const realKey = apiKey === "__bedrock_lazy_token__" ? void 0 : apiKey;
@@ -5791,202 +5822,52 @@ function buildCompressionPrompt(messages) {
5791
5822
 
5792
5823
  --- CONVERSATION TO SUMMARIZE ---
5793
5824
  ${formatted}
5794
- --- END ---`;
5795
- }
5796
- async function compressConversationWindow(opts) {
5797
- const userPrompt = buildCompressionPrompt(opts.messages);
5798
- let summary;
5799
- try {
5800
- summary = await opts.callLlm(opts.model, COMPRESSION_SYSTEM, userPrompt);
5801
- } catch (cause) {
5802
- throw new CompressionFailedError(
5803
- `Compression LLM call failed: ${cause instanceof Error ? cause.message : String(cause)}`,
5804
- { cause: cause instanceof Error ? cause : void 0 }
5805
- );
5806
- }
5807
- if (!summary || summary.trim().length === 0) {
5808
- throw new CompressionFailedError(
5809
- "Compression LLM returned empty summary \u2014 reduction ineffective."
5810
- );
5811
- }
5812
- return {
5813
- role: "system",
5814
- content: `[Compressed conversation summary]: ${summary.trim()}`
5815
- };
5816
- }
5817
- var CompressionFailedError, COMPRESSION_SYSTEM;
5818
- var init_compression_summarizer = __esm({
5819
- "src/internal/runtime/compression/compression-summarizer.ts"() {
5820
- CompressionFailedError = class extends Error {
5821
- name = "CompressionFailedError";
5822
- };
5823
- 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.";
5824
- }
5825
- });
5826
-
5827
- // src/internal/session/agent-session-store.ts
5828
- function seedTranscript(prior, opts) {
5829
- return SessionTranscript.fromRecords(prior, opts);
5830
- }
5831
- function mapAgentTurn(steps) {
5832
- const assistant = {};
5833
- const toolResults = [];
5834
- const toolCalls = [];
5835
- for (const step of steps) {
5836
- if (step.type === "thinkingMessage") assistant.thinking = step.message.text;
5837
- else if (step.type === "assistantMessage") assistant.text = step.message.text;
5838
- else if (step.type === "toolCall")
5839
- toolCalls.push({
5840
- id: step.message.callId,
5841
- name: step.message.name,
5842
- input: step.message.args ?? {}
5843
- });
5844
- else
5845
- toolResults.push({
5846
- toolUseId: step.message.callId,
5847
- content: step.message.result,
5848
- isError: step.message.isError
5849
- });
5850
- }
5851
- if (toolCalls.length > 0) assistant.toolCalls = toolCalls;
5852
- return { assistant, toolResults };
5853
- }
5854
- function hasAssistantContent(a) {
5855
- return a.text !== void 0 || a.thinking !== void 0 || (a.toolCalls?.length ?? 0) > 0;
5856
- }
5857
- function appendConversation(transcript, conversation) {
5858
- for (const ct of conversation) {
5859
- if (ct.type !== "agentConversationTurn") continue;
5860
- const { assistant, toolResults } = mapAgentTurn(ct.turn.steps);
5861
- if (hasAssistantContent(assistant)) transcript.appendAssistantTurn(assistant);
5862
- if (toolResults.length > 0) transcript.appendToolResults(toolResults);
5863
- }
5864
- }
5865
- async function readSessionMessages(store, agentId) {
5866
- const records = await store.readRecords(agentId);
5867
- return reconstructMessages(records).map(narrowToSessionMessage);
5868
- }
5869
- function partToText(p) {
5870
- if (p.type === "text") return p.text ?? "";
5871
- if (p.type === "tool_use") return `[tool call] ${p.name ?? ""}`;
5872
- if (p.type === "tool_result") {
5873
- const body = typeof p.content === "string" ? p.content : JSON.stringify(p.content);
5874
- return `[tool result] ${body}`;
5875
- }
5876
- return "";
5877
- }
5878
- function narrowToSessionMessage(m) {
5879
- const role = m.role === "user" ? "user" : "assistant";
5880
- const text = m.content.map(partToText).filter((s) => s.length > 0).join("\n");
5881
- return { role, text };
5882
- }
5883
- function deltaRecords(transcript, priorLength) {
5884
- return transcript.records().slice(priorLength);
5885
- }
5886
- async function persistTurn(store, loc, sessionId, turn) {
5887
- const prior = await store.readRecords(loc.agentId);
5888
- const transcript = seedTranscript(prior, { cwd: loc.cwd, sessionId, model: loc.model });
5889
- transcript.appendUserTurn(turn.userText);
5890
- appendConversation(transcript, turn.conversation);
5891
- await store.appendRecords(loc.agentId, deltaRecords(transcript, prior.length));
5892
- }
5893
- var init_agent_session_store = __esm({
5894
- "src/internal/session/agent-session-store.ts"() {
5895
- init_session_transcript();
5896
- }
5897
- });
5898
-
5899
- // src/internal/session/agent-session.ts
5900
- function transcriptKey(cwd, agentId) {
5901
- return `${cwd}::${agentId}`;
5902
- }
5903
- function appendSessionMessage(agentId, message) {
5904
- const existing = sessions.get(agentId) ?? [];
5905
- existing.push(message);
5906
- sessions.set(agentId, existing);
5907
- }
5908
- function getSessionMessages(agentId) {
5909
- return sessions.get(agentId) ?? [];
5910
- }
5911
- function persistTurnToTranscript(store, loc, sessionId, turn, onCompact) {
5912
- const key = transcriptKey(loc.cwd, loc.agentId);
5913
- const chained = (pendingWrites.get(key) ?? Promise.resolve()).then(async () => {
5914
- try {
5915
- await persistTurn(store, loc, sessionId, turn);
5916
- const count = (recordCounts.get(key) ?? 0) + 1;
5917
- recordCounts.set(key, count);
5918
- if (turn.autoCompact !== void 0) {
5919
- const { autoCompactIfNeeded: autoCompactIfNeeded2 } = await Promise.resolve().then(() => (init_compact_session(), compact_session_exports));
5920
- const fired = await autoCompactIfNeeded2({
5921
- store,
5922
- loc,
5923
- sessionId,
5924
- usageTotal: turn.autoCompact.usageTotal,
5925
- contextWindow: turn.autoCompact.contextWindow,
5926
- turnCount: count,
5927
- summarize: turn.autoCompact.summarize
5928
- });
5929
- if (fired) onCompact?.();
5930
- }
5931
- } catch (cause) {
5932
- const msg = cause instanceof Error ? cause.message : String(cause);
5933
- process.stderr.write(
5934
- `[theokit-sdk] session transcript write failed (${loc.agentId}): ${msg}
5935
- `
5936
- );
5937
- }
5938
- });
5939
- pendingWrites.set(
5940
- key,
5941
- chained.then(
5942
- () => void 0,
5943
- () => void 0
5944
- )
5945
- );
5946
- }
5947
- async function hydrateSession(agentId, loc) {
5948
- const key = transcriptKey(loc.cwd, agentId);
5949
- if (hydratedKeys.has(key)) return;
5950
- hydratedKeys.add(key);
5951
- const persisted = await readSessionMessages(loc.store, agentId);
5952
- if (persisted.length === 0) return;
5953
- sessions.set(agentId, persisted);
5954
- }
5955
- async function flushSessionWrites() {
5956
- while (pendingWrites.size > 0) {
5957
- const all = Array.from(pendingWrites.values());
5958
- pendingWrites.clear();
5959
- await Promise.all(all);
5825
+ --- END ---`;
5826
+ }
5827
+ async function compressConversationWindow(opts) {
5828
+ const userPrompt = buildCompressionPrompt(opts.messages);
5829
+ let summary;
5830
+ try {
5831
+ summary = await opts.callLlm(opts.model, COMPRESSION_SYSTEM, userPrompt);
5832
+ } catch (cause) {
5833
+ throw new CompressionFailedError(
5834
+ `Compression LLM call failed: ${cause instanceof Error ? cause.message : String(cause)}`,
5835
+ { cause: cause instanceof Error ? cause : void 0 }
5836
+ );
5837
+ }
5838
+ if (!summary || summary.trim().length === 0) {
5839
+ throw new CompressionFailedError(
5840
+ "Compression LLM returned empty summary \u2014 reduction ineffective."
5841
+ );
5960
5842
  }
5843
+ return {
5844
+ role: "system",
5845
+ content: `[Compressed conversation summary]: ${summary.trim()}`
5846
+ };
5961
5847
  }
5962
- function clearSession(agentId) {
5963
- sessions.delete(agentId);
5848
+ var CompressionFailedError, COMPRESSION_SYSTEM;
5849
+ var init_compression_summarizer = __esm({
5850
+ "src/internal/runtime/compression/compression-summarizer.ts"() {
5851
+ CompressionFailedError = class extends Error {
5852
+ name = "CompressionFailedError";
5853
+ };
5854
+ 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.";
5855
+ }
5856
+ });
5857
+
5858
+ // src/internal/session/session-cache.ts
5859
+ function transcriptKey(cwd, agentId) {
5860
+ return `${cwd}::${agentId}`;
5964
5861
  }
5965
5862
  function invalidateSessionCache(cwd, agentId) {
5966
5863
  sessions.delete(agentId);
5967
5864
  hydratedKeys.delete(transcriptKey(cwd, agentId));
5968
5865
  }
5969
- function enqueueSessionWrite(cwd, agentId, fn) {
5970
- const key = transcriptKey(cwd, agentId);
5971
- const prior = pendingWrites.get(key) ?? Promise.resolve();
5972
- const result = prior.then(fn);
5973
- pendingWrites.set(
5974
- key,
5975
- result.then(
5976
- () => void 0,
5977
- () => void 0
5978
- )
5979
- );
5980
- return result;
5981
- }
5982
- var sessions, hydratedKeys, pendingWrites, recordCounts;
5983
- var init_agent_session = __esm({
5984
- "src/internal/session/agent-session.ts"() {
5985
- init_agent_session_store();
5866
+ var sessions, hydratedKeys;
5867
+ var init_session_cache = __esm({
5868
+ "src/internal/session/session-cache.ts"() {
5986
5869
  sessions = /* @__PURE__ */ new Map();
5987
5870
  hydratedKeys = /* @__PURE__ */ new Set();
5988
- pendingWrites = /* @__PURE__ */ new Map();
5989
- recordCounts = /* @__PURE__ */ new Map();
5990
5871
  }
5991
5872
  });
5992
5873
 
@@ -6148,7 +6029,7 @@ var init_compact_session = __esm({
6148
6029
  init_providers();
6149
6030
  init_compression_model_registry();
6150
6031
  init_compression_summarizer();
6151
- init_agent_session();
6032
+ init_session_cache();
6152
6033
  COMPACT_SUMMARY_MARKER = "[[theokit:compact-summary]]";
6153
6034
  COMPACT_USER_MESSAGE_MAX_TOKENS = 2e4;
6154
6035
  autoCompactAttempts = (() => {
@@ -6159,6 +6040,165 @@ var init_compact_session = __esm({
6159
6040
  })();
6160
6041
  }
6161
6042
  });
6043
+
6044
+ // src/internal/session/agent-session-store.ts
6045
+ function seedTranscript(prior, opts) {
6046
+ return SessionTranscript.fromRecords(prior, opts);
6047
+ }
6048
+ function mapAgentTurn(steps) {
6049
+ const assistant = {};
6050
+ const toolResults = [];
6051
+ const toolCalls = [];
6052
+ for (const step of steps) {
6053
+ if (step.type === "thinkingMessage") assistant.thinking = step.message.text;
6054
+ else if (step.type === "assistantMessage") assistant.text = step.message.text;
6055
+ else if (step.type === "toolCall")
6056
+ toolCalls.push({
6057
+ id: step.message.callId,
6058
+ name: step.message.name,
6059
+ input: step.message.args ?? {}
6060
+ });
6061
+ else
6062
+ toolResults.push({
6063
+ toolUseId: step.message.callId,
6064
+ content: step.message.result,
6065
+ isError: step.message.isError
6066
+ });
6067
+ }
6068
+ if (toolCalls.length > 0) assistant.toolCalls = toolCalls;
6069
+ return { assistant, toolResults };
6070
+ }
6071
+ function hasAssistantContent(a) {
6072
+ return a.text !== void 0 || a.thinking !== void 0 || (a.toolCalls?.length ?? 0) > 0;
6073
+ }
6074
+ function appendConversation(transcript, conversation) {
6075
+ for (const ct of conversation) {
6076
+ if (ct.type !== "agentConversationTurn") continue;
6077
+ const { assistant, toolResults } = mapAgentTurn(ct.turn.steps);
6078
+ if (hasAssistantContent(assistant)) transcript.appendAssistantTurn(assistant);
6079
+ if (toolResults.length > 0) transcript.appendToolResults(toolResults);
6080
+ }
6081
+ }
6082
+ async function readSessionMessages(store, agentId) {
6083
+ const records = await store.readRecords(agentId);
6084
+ return reconstructMessages(records).map(narrowToSessionMessage);
6085
+ }
6086
+ function partToText(p) {
6087
+ if (p.type === "text") return p.text ?? "";
6088
+ if (p.type === "tool_use") return `[tool call] ${p.name ?? ""}`;
6089
+ if (p.type === "tool_result") {
6090
+ const body = typeof p.content === "string" ? p.content : JSON.stringify(p.content);
6091
+ return `[tool result] ${body}`;
6092
+ }
6093
+ return "";
6094
+ }
6095
+ function narrowToSessionMessage(m) {
6096
+ const role = m.role === "user" ? "user" : "assistant";
6097
+ const text = m.content.map(partToText).filter((s) => s.length > 0).join("\n");
6098
+ return { role, text };
6099
+ }
6100
+ function deltaRecords(transcript, priorLength) {
6101
+ return transcript.records().slice(priorLength);
6102
+ }
6103
+ async function persistTurn(store, loc, sessionId, turn) {
6104
+ const prior = await store.readRecords(loc.agentId);
6105
+ const transcript = seedTranscript(prior, { cwd: loc.cwd, sessionId, model: loc.model });
6106
+ transcript.appendUserTurn(turn.userText);
6107
+ appendConversation(transcript, turn.conversation);
6108
+ await store.appendRecords(loc.agentId, deltaRecords(transcript, prior.length));
6109
+ }
6110
+ var init_agent_session_store = __esm({
6111
+ "src/internal/session/agent-session-store.ts"() {
6112
+ init_session_transcript();
6113
+ }
6114
+ });
6115
+
6116
+ // src/internal/session/agent-session.ts
6117
+ function appendSessionMessage(agentId, message) {
6118
+ const existing = sessions.get(agentId) ?? [];
6119
+ existing.push(message);
6120
+ sessions.set(agentId, existing);
6121
+ }
6122
+ function getSessionMessages(agentId) {
6123
+ return sessions.get(agentId) ?? [];
6124
+ }
6125
+ function persistTurnToTranscript(store, loc, sessionId, turn, onCompact) {
6126
+ const key = transcriptKey(loc.cwd, loc.agentId);
6127
+ const chained = (pendingWrites.get(key) ?? Promise.resolve()).then(async () => {
6128
+ try {
6129
+ await persistTurn(store, loc, sessionId, turn);
6130
+ const count = (recordCounts.get(key) ?? 0) + 1;
6131
+ recordCounts.set(key, count);
6132
+ if (turn.autoCompact !== void 0) {
6133
+ const { autoCompactIfNeeded: autoCompactIfNeeded2 } = await Promise.resolve().then(() => (init_compact_session(), compact_session_exports));
6134
+ const fired = await autoCompactIfNeeded2({
6135
+ store,
6136
+ loc,
6137
+ sessionId,
6138
+ usageTotal: turn.autoCompact.usageTotal,
6139
+ contextWindow: turn.autoCompact.contextWindow,
6140
+ turnCount: count,
6141
+ summarize: turn.autoCompact.summarize
6142
+ });
6143
+ if (fired) onCompact?.();
6144
+ }
6145
+ } catch (cause) {
6146
+ const msg = cause instanceof Error ? cause.message : String(cause);
6147
+ process.stderr.write(
6148
+ `[theokit-sdk] session transcript write failed (${loc.agentId}): ${msg}
6149
+ `
6150
+ );
6151
+ }
6152
+ });
6153
+ pendingWrites.set(
6154
+ key,
6155
+ chained.then(
6156
+ () => void 0,
6157
+ () => void 0
6158
+ )
6159
+ );
6160
+ }
6161
+ async function hydrateSession(agentId, loc) {
6162
+ const key = transcriptKey(loc.cwd, agentId);
6163
+ if (hydratedKeys.has(key)) return;
6164
+ hydratedKeys.add(key);
6165
+ const persisted = await readSessionMessages(loc.store, agentId);
6166
+ if (persisted.length === 0) return;
6167
+ sessions.set(agentId, persisted);
6168
+ }
6169
+ async function flushSessionWrites() {
6170
+ while (pendingWrites.size > 0) {
6171
+ const all = Array.from(pendingWrites.values());
6172
+ pendingWrites.clear();
6173
+ await Promise.all(all);
6174
+ }
6175
+ }
6176
+ function clearSession(agentId) {
6177
+ sessions.delete(agentId);
6178
+ }
6179
+ function enqueueSessionWrite(cwd, agentId, fn) {
6180
+ const key = transcriptKey(cwd, agentId);
6181
+ const prior = pendingWrites.get(key) ?? Promise.resolve();
6182
+ const result = prior.then(fn);
6183
+ pendingWrites.set(
6184
+ key,
6185
+ result.then(
6186
+ () => void 0,
6187
+ () => void 0
6188
+ )
6189
+ );
6190
+ return result;
6191
+ }
6192
+ var pendingWrites, recordCounts;
6193
+ var init_agent_session = __esm({
6194
+ "src/internal/session/agent-session.ts"() {
6195
+ init_agent_session_store();
6196
+ init_session_cache();
6197
+ init_session_cache();
6198
+ pendingWrites = /* @__PURE__ */ new Map();
6199
+ recordCounts = /* @__PURE__ */ new Map();
6200
+ }
6201
+ });
6162
6202
  async function withToolWhitelist(whitelist, fn) {
6163
6203
  return toolWhitelistStore.run(whitelist, fn);
6164
6204
  }
@@ -6253,10 +6293,10 @@ var init_context = __esm({
6253
6293
  }
6254
6294
  });
6255
6295
 
6256
- // src/goal-loop.ts
6296
+ // src/internal/runtime/lifecycle/goal-marker.ts
6257
6297
  var GOAL_CONTINUATION_MARKER;
6258
- var init_goal_loop = __esm({
6259
- "src/goal-loop.ts"() {
6298
+ var init_goal_marker = __esm({
6299
+ "src/internal/runtime/lifecycle/goal-marker.ts"() {
6260
6300
  GOAL_CONTINUATION_MARKER = "[[theokit:goal-continuation]]";
6261
6301
  }
6262
6302
  });
@@ -6430,7 +6470,7 @@ ${lastResponse.slice(-1e3)}`
6430
6470
  }
6431
6471
  var init_run_until = __esm({
6432
6472
  "src/internal/runtime/lifecycle/run-until.ts"() {
6433
- init_goal_loop();
6473
+ init_goal_marker();
6434
6474
  }
6435
6475
  });
6436
6476
 
@@ -10605,6 +10645,7 @@ function parseDecisionFromStdout(stdout) {
10605
10645
  }
10606
10646
 
10607
10647
  // src/internal/runtime/lifecycle/post-run-lifecycle.ts
10648
+ init_compaction();
10608
10649
  init_run_events();
10609
10650
 
10610
10651
  // src/internal/memory/storage/session-summary-writer.ts
@@ -10674,6 +10715,12 @@ function resolveActiveMemorySummaryForSend(legacySummary, portPathEnabled) {
10674
10715
  return legacySummary;
10675
10716
  }
10676
10717
 
10718
+ // src/internal/runtime/lifecycle/context-budget-event.ts
10719
+ function buildContextBudgetEvent(model, resolved) {
10720
+ if (resolved.source !== "fallback") return void 0;
10721
+ return { type: "compaction_fallback", model, window: resolved.window };
10722
+ }
10723
+
10677
10724
  // src/internal/runtime/lifecycle/post-run-lifecycle.ts
10678
10725
  async function runPostRunLifecycle(inputs) {
10679
10726
  const {
@@ -10699,18 +10746,15 @@ async function runPostRunLifecycle(inputs) {
10699
10746
  appendSessionMessage(agentId, { role: "assistant", text: result.result });
10700
10747
  }
10701
10748
  const conversation = await safeConversation(run);
10702
- const contextWindow = getCatalogModelInfo(model)?.limit?.context;
10703
- if (contextWindow === void 0) {
10704
- const g = globalThis;
10705
- const sym = /* @__PURE__ */ Symbol.for("theokit-sdk.compact.no-cw-warned");
10706
- const warned3 = g[sym] ??= /* @__PURE__ */ new Set();
10707
- if (!warned3.has(model)) {
10708
- warned3.add(model);
10709
- process.stderr.write(
10710
- `[theokit-sdk] auto-compaction disabled: model "${model}" has no context-window entry in the catalog
10711
- `
10712
- );
10713
- }
10749
+ const resolvedWindow = resolveEffectiveContextWindow({
10750
+ catalog: getCatalogModelInfo(model)?.limit?.context,
10751
+ margin: CONTEXT_WINDOW_MARGIN,
10752
+ floor: CONTEXT_WINDOW_FLOOR
10753
+ });
10754
+ const contextWindow = resolvedWindow.window;
10755
+ const budgetEvent = buildContextBudgetEvent(model, resolvedWindow);
10756
+ if (budgetEvent !== void 0 && onRunEvent !== void 0) {
10757
+ emitRunEvent(onRunEvent, budgetEvent);
10714
10758
  }
10715
10759
  const lastRequestUsage = result.usage?.requests?.at(-1)?.totalTokens;
10716
10760
  const usageForTrigger = lastRequestUsage ?? result.usage?.totalTokens;
@@ -15682,6 +15726,71 @@ function registerPluginProviderProfiles(entries) {
15682
15726
 
15683
15727
  // src/internal/local-agent/real-local-run.ts
15684
15728
  init_async_local_storage();
15729
+
15730
+ // src/internal/local-agent/mcp-pool.ts
15731
+ var DEFAULT_IDLE_TTL_MS = 6e5;
15732
+ function configKey(config) {
15733
+ return JSON.stringify(
15734
+ config,
15735
+ (_k, v) => v !== null && typeof v === "object" && !Array.isArray(v) ? Object.fromEntries(
15736
+ Object.entries(v).sort(([a], [b]) => a < b ? -1 : 1)
15737
+ ) : v
15738
+ );
15739
+ }
15740
+ var McpClientPool = class {
15741
+ entries = /* @__PURE__ */ new Map();
15742
+ idleTtlMs;
15743
+ now;
15744
+ constructor(options = {}) {
15745
+ this.idleTtlMs = options.idleTtlMs ?? DEFAULT_IDLE_TTL_MS;
15746
+ this.now = options.now ?? Date.now;
15747
+ }
15748
+ /**
15749
+ * Return the pooled client for `(sessionId, serverName, config)`, creating it via `factory` on
15750
+ * first use. Every call refreshes idleness — the TTL measures time SINCE LAST USE, not age.
15751
+ *
15752
+ * Synchronous by design: `createMcpClient` is itself synchronous (the handshake happens later, on
15753
+ * `initialize`), so there is no `await` between the lookup and the insert and two concurrent runs
15754
+ * in the same session cannot both miss the cache.
15755
+ */
15756
+ acquire(sessionId, serverName, config, factory) {
15757
+ const key = `${sessionId}\0${serverName}\0${configKey(config)}`;
15758
+ const existing = this.entries.get(key);
15759
+ if (existing !== void 0) {
15760
+ existing.lastUsedAt = this.now();
15761
+ return existing.client;
15762
+ }
15763
+ const client = factory();
15764
+ this.entries.set(key, { client, sessionId, lastUsedAt: this.now() });
15765
+ return client;
15766
+ }
15767
+ /**
15768
+ * Close and forget every client of ONE session. Scoped deliberately: clearing the whole map would
15769
+ * tear down the servers of every concurrent conversation.
15770
+ */
15771
+ disposeSession(sessionId, close) {
15772
+ for (const [key, entry] of this.entries) {
15773
+ if (entry.sessionId !== sessionId) continue;
15774
+ close(entry.client);
15775
+ this.entries.delete(key);
15776
+ }
15777
+ }
15778
+ /** Close and forget every client idle for longer than the TTL. */
15779
+ reapIdle(close) {
15780
+ const cutoff = this.now() - this.idleTtlMs;
15781
+ for (const [key, entry] of this.entries) {
15782
+ if (entry.lastUsedAt > cutoff) continue;
15783
+ close(entry.client);
15784
+ this.entries.delete(key);
15785
+ }
15786
+ }
15787
+ /** Live pooled-client count — for observability and tests. */
15788
+ size() {
15789
+ return this.entries.size;
15790
+ }
15791
+ };
15792
+
15793
+ // src/internal/local-agent/real-local-run.ts
15685
15794
  init_real_local_run_provider();
15686
15795
 
15687
15796
  // src/a2a/subagent.ts
@@ -16100,12 +16209,23 @@ function buildLoopInputs(options, runId, userText, userImages) {
16100
16209
  ...options.agentOptions.memoryProvider !== void 0 ? { memoryProvider: options.agentOptions.memoryProvider } : {}
16101
16210
  };
16102
16211
  }
16212
+ var sessionMcpPool = new McpClientPool();
16213
+ function disposeSessionMcpClients(agentId) {
16214
+ sessionMcpPool.disposeSession(agentId, (client) => {
16215
+ void client.close();
16216
+ });
16217
+ }
16103
16218
  function buildMcpMap(options) {
16104
16219
  const map = /* @__PURE__ */ new Map();
16105
16220
  const inline = options.sendOptions.mcpServers ?? options.agentOptions.mcpServers;
16106
16221
  if (inline === void 0) return map;
16222
+ const pooled = options.agentOptions.mcpLifecycle === "session";
16223
+ if (pooled) sessionMcpPool.reapIdle((c) => void c.close());
16107
16224
  for (const [name, config] of Object.entries(inline)) {
16108
- map.set(name, createMcpClient(name, config));
16225
+ map.set(
16226
+ name,
16227
+ pooled ? sessionMcpPool.acquire(options.agentId, name, config, () => createMcpClient(name, config)) : createMcpClient(name, config)
16228
+ );
16109
16229
  }
16110
16230
  return map;
16111
16231
  }
@@ -17170,7 +17290,9 @@ async function loadDriver(filePath) {
17170
17290
  }
17171
17291
  try {
17172
17292
  const mod = await (driverLoaderOverrides?.nodeSqlite?.() ?? Promise.resolve(
17173
- process.getBuiltinModule?.("node:sqlite") ?? (() => {
17293
+ process.getBuiltinModule?.(
17294
+ "node:sqlite"
17295
+ ) ?? (() => {
17174
17296
  throw new Error("node:sqlite built-in unavailable (Node < 22.3)");
17175
17297
  })()
17176
17298
  ));
@@ -18220,7 +18342,8 @@ var LocalAgentMemory = class {
18220
18342
  const message = cause instanceof Error ? cause.message : String(cause);
18221
18343
  const g = globalThis;
18222
18344
  const sym = /* @__PURE__ */ Symbol.for("theokit-sdk.memory.warned");
18223
- const warned3 = g[sym] ??= /* @__PURE__ */ new Set();
18345
+ g[sym] ??= /* @__PURE__ */ new Set();
18346
+ const warned3 = g[sym];
18224
18347
  if (!warned3.has(message)) {
18225
18348
  warned3.add(message);
18226
18349
  process.stderr.write(`[theokit-sdk] memory tools unavailable: ${message}
@@ -19404,6 +19527,7 @@ var LocalAgent = class {
19404
19527
  liveAgentRegistry.forget(this.agentId);
19405
19528
  this.lifecycleAbortController.abort();
19406
19529
  await withCwdMutex(`agent-send:${this.agentId}`, () => Promise.resolve());
19530
+ disposeSessionMcpClients(this.agentId);
19407
19531
  await flushSessionWrites();
19408
19532
  await flushRegistrySaves(this.workspaceCwd);
19409
19533
  }
@@ -19704,8 +19828,8 @@ async function getRegisteredAgentOrThrow(agentId) {
19704
19828
  // src/agent.ts
19705
19829
  init_errors();
19706
19830
  init_discovery();
19707
- init_agent_session();
19708
19831
  init_agent_factory_registry();
19832
+ init_agent_session();
19709
19833
  var streamObjectImport;
19710
19834
  var Agent = class _Agent {
19711
19835
  constructor() {
@@ -19997,26 +20121,26 @@ var Agent = class _Agent {
19997
20121
  reg = getRegisteredAgent(agentId);
19998
20122
  }
19999
20123
  if (reg === void 0 || reg.runtime !== "local") {
20000
- throw new UnknownAgentError(`No local agent "${agentId}" registered \u2014 compact targets local sessions.`);
20124
+ throw new UnknownAgentError(
20125
+ `No local agent "${agentId}" registered \u2014 compact targets local sessions.`
20126
+ );
20001
20127
  }
20002
- const cwd = reg.cwd ?? process.cwd();
20003
- const optModel = reg.options.model;
20004
- const model = reg.model?.id ?? (typeof optModel === "string" ? optModel : optModel?.id) ?? "unknown";
20005
20128
  const { compactSessionTranscript: compactSessionTranscript2, buildDefaultSummarizer: buildDefaultSummarizer2 } = await Promise.resolve().then(() => (init_compact_session(), compact_session_exports));
20006
- const { FsSessionStore: FsSessionStore2 } = await Promise.resolve().then(() => (init_fs_session_store(), fs_session_store_exports));
20007
- const { defaultBaseDir: defaultBaseDir2, expandTilde: expandTilde2 } = await Promise.resolve().then(() => (init_session_transcript(), session_transcript_exports));
20008
- const baseDir = reg.options.local?.baseDir !== void 0 ? expandTilde2(reg.options.local.baseDir) : defaultBaseDir2();
20009
- const store = new FsSessionStore2({ baseDir, cwd });
20010
- return enqueueSessionWrite(cwd, agentId, () => compactSessionTranscript2({
20011
- store,
20012
- loc: { cwd, agentId, model },
20013
- sessionId: agentId,
20014
- trigger: options.trigger ?? "manual",
20015
- summarize: options.summarize ?? buildDefaultSummarizer2({
20016
- agentModel: model,
20017
- ...reg.options.apiKey !== void 0 ? { apiKey: reg.options.apiKey } : {}
20129
+ const { cwd, model, store } = await abrirStoreLocal(reg);
20130
+ return enqueueSessionWrite(
20131
+ cwd,
20132
+ agentId,
20133
+ () => compactSessionTranscript2({
20134
+ store,
20135
+ loc: { cwd, agentId, model },
20136
+ sessionId: agentId,
20137
+ trigger: options.trigger ?? "manual",
20138
+ summarize: options.summarize ?? buildDefaultSummarizer2({
20139
+ agentModel: model,
20140
+ ...reg.options.apiKey !== void 0 ? { apiKey: reg.options.apiKey } : {}
20141
+ })
20018
20142
  })
20019
- }));
20143
+ );
20020
20144
  }
20021
20145
  /**
20022
20146
  * M51 — inject a SYNTHETIC user+assistant pair into a LOCAL session's persisted transcript WITHOUT
@@ -20033,16 +20157,12 @@ var Agent = class _Agent {
20033
20157
  reg = getRegisteredAgent(agentId);
20034
20158
  }
20035
20159
  if (reg === void 0 || reg.runtime !== "local") {
20036
- throw new UnknownAgentError(`No local agent "${agentId}" registered \u2014 injectSessionTurn targets local sessions.`);
20160
+ throw new UnknownAgentError(
20161
+ `No local agent "${agentId}" registered \u2014 injectSessionTurn targets local sessions.`
20162
+ );
20037
20163
  }
20038
- const cwd = reg.cwd ?? process.cwd();
20039
- const optModel = reg.options.model;
20040
- const model = reg.model?.id ?? (typeof optModel === "string" ? optModel : optModel?.id) ?? "unknown";
20041
20164
  const { injectSessionTurn: injectSessionTurn2 } = await Promise.resolve().then(() => (init_inject_session(), inject_session_exports));
20042
- const { FsSessionStore: FsSessionStore2 } = await Promise.resolve().then(() => (init_fs_session_store(), fs_session_store_exports));
20043
- const { defaultBaseDir: defaultBaseDir2, expandTilde: expandTilde2 } = await Promise.resolve().then(() => (init_session_transcript(), session_transcript_exports));
20044
- const baseDir = reg.options.local?.baseDir !== void 0 ? expandTilde2(reg.options.local.baseDir) : defaultBaseDir2();
20045
- const store = new FsSessionStore2({ baseDir, cwd });
20165
+ const { cwd, model, store } = await abrirStoreLocal(reg);
20046
20166
  await injectSessionTurn2({
20047
20167
  store,
20048
20168
  loc: { cwd, agentId, model },
@@ -20084,6 +20204,15 @@ setAgentFacade({
20084
20204
  resume: (agentId, options) => Agent.resume(agentId, options),
20085
20205
  batch: (prompts, options) => Agent.batch(prompts, options)
20086
20206
  });
20207
+ async function abrirStoreLocal(reg) {
20208
+ const cwd = reg.cwd ?? process.cwd();
20209
+ const optModel = reg.options.model;
20210
+ const model = reg.model?.id ?? (typeof optModel === "string" ? optModel : optModel?.id) ?? "unknown";
20211
+ const { FsSessionStore: FsSessionStore2 } = await Promise.resolve().then(() => (init_fs_session_store(), fs_session_store_exports));
20212
+ const { defaultBaseDir: defaultBaseDir2, expandTilde: expandTilde2 } = await Promise.resolve().then(() => (init_session_transcript(), session_transcript_exports));
20213
+ const baseDir = reg.options.local?.baseDir !== void 0 ? expandTilde2(reg.options.local.baseDir) : defaultBaseDir2();
20214
+ return { cwd, model, store: new FsSessionStore2({ baseDir, cwd }) };
20215
+ }
20087
20216
 
20088
20217
  // src/cron.ts
20089
20218
  init_errors();