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