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