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