@theokit/sdk 4.16.3 → 4.16.5

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.
package/dist/cron.cjs CHANGED
@@ -1605,140 +1605,6 @@ var init_run_events = __esm({
1605
1605
  "src/types/run-events.ts"() {
1606
1606
  }
1607
1607
  });
1608
-
1609
- // src/compaction.ts
1610
- function estimateTokens(text) {
1611
- return Math.ceil(text.length / 4);
1612
- }
1613
- var init_compaction = __esm({
1614
- "src/compaction.ts"() {
1615
- }
1616
- });
1617
-
1618
- // src/internal/runtime/compression/compression-summarizer.ts
1619
- var compression_summarizer_exports = {};
1620
- __export(compression_summarizer_exports, {
1621
- CompressionFailedError: () => CompressionFailedError,
1622
- buildCompressionPrompt: () => buildCompressionPrompt,
1623
- compressConversationWindow: () => compressConversationWindow
1624
- });
1625
- function buildCompressionPrompt(messages) {
1626
- const formatted = messages.map((m) => `[${m.role}]: ${m.content}`).join("\n\n");
1627
- return `Summarize the following ${messages.length} conversation messages into a concise summary that preserves ALL facts, decisions, user preferences, and context needed for the conversation to continue naturally. The summary will replace these messages in the context window. Be thorough but concise.
1628
-
1629
- --- CONVERSATION TO SUMMARIZE ---
1630
- ${formatted}
1631
- --- END ---`;
1632
- }
1633
- async function compressConversationWindow(opts) {
1634
- const userPrompt = buildCompressionPrompt(opts.messages);
1635
- let summary;
1636
- try {
1637
- summary = await opts.callLlm(opts.model, COMPRESSION_SYSTEM, userPrompt);
1638
- } catch (cause) {
1639
- throw new CompressionFailedError(
1640
- `Compression LLM call failed: ${cause instanceof Error ? cause.message : String(cause)}`,
1641
- { cause: cause instanceof Error ? cause : void 0 }
1642
- );
1643
- }
1644
- if (!summary || summary.trim().length === 0) {
1645
- throw new CompressionFailedError(
1646
- "Compression LLM returned empty summary \u2014 reduction ineffective."
1647
- );
1648
- }
1649
- return {
1650
- role: "system",
1651
- content: `[Compressed conversation summary]: ${summary.trim()}`
1652
- };
1653
- }
1654
- var CompressionFailedError, COMPRESSION_SYSTEM;
1655
- var init_compression_summarizer = __esm({
1656
- "src/internal/runtime/compression/compression-summarizer.ts"() {
1657
- CompressionFailedError = class extends Error {
1658
- name = "CompressionFailedError";
1659
- };
1660
- 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.";
1661
- }
1662
- });
1663
-
1664
- // src/internal/runtime/compression/compression-model-registry.ts
1665
- var compression_model_registry_exports = {};
1666
- __export(compression_model_registry_exports, {
1667
- CompressionModelUnresolvedError: () => CompressionModelUnresolvedError,
1668
- resolveCompressionModel: () => resolveCompressionModel
1669
- });
1670
- function resolveCompressionModel(agentModel) {
1671
- const exact = EXACT_REGISTRY.get(agentModel);
1672
- if (exact !== void 0) return exact;
1673
- const wildcard = matchWildcard(agentModel);
1674
- if (wildcard !== null) return wildcard;
1675
- if (isNoAuthProvider(agentModel)) return agentModel;
1676
- throw new CompressionModelUnresolvedError(agentModel);
1677
- }
1678
- function matchWildcard(agentModel) {
1679
- for (const [pattern, replacement] of WILDCARD_REGISTRY) {
1680
- const prefix = pattern.endsWith("*") ? pattern.slice(0, -1) : pattern;
1681
- if (!agentModel.startsWith(prefix)) continue;
1682
- const suffix = agentModel.slice(prefix.length);
1683
- const replPrefix = replacement.endsWith("*") ? replacement.slice(0, -1) : replacement;
1684
- return `${replPrefix}${suffix}`;
1685
- }
1686
- return null;
1687
- }
1688
- function isNoAuthProvider(agentModel) {
1689
- const slashIdx = agentModel.indexOf("/");
1690
- if (slashIdx <= 0) return false;
1691
- return NO_AUTH_PROVIDERS.has(agentModel.slice(0, slashIdx));
1692
- }
1693
- var EXACT_REGISTRY, WILDCARD_REGISTRY, NO_AUTH_PROVIDERS, CompressionModelUnresolvedError;
1694
- var init_compression_model_registry = __esm({
1695
- "src/internal/runtime/compression/compression-model-registry.ts"() {
1696
- EXACT_REGISTRY = /* @__PURE__ */ new Map([
1697
- // OpenAI family
1698
- ["openai/gpt-4o", "openai/gpt-4o-mini"],
1699
- ["openai/gpt-4-turbo", "openai/gpt-4o-mini"],
1700
- ["openai/gpt-4", "openai/gpt-4o-mini"],
1701
- ["openai/o1-preview", "openai/gpt-4o-mini"],
1702
- ["openai/o1", "openai/gpt-4o-mini"],
1703
- ["openai/o3", "openai/gpt-4o-mini"],
1704
- ["openai/o3-mini", "openai/gpt-4o-mini"],
1705
- // Anthropic family
1706
- ["anthropic/claude-opus-4", "anthropic/claude-3-5-haiku-latest"],
1707
- ["anthropic/claude-sonnet-4", "anthropic/claude-3-5-haiku-latest"],
1708
- ["anthropic/claude-3-5-sonnet", "anthropic/claude-3-5-haiku-latest"],
1709
- ["anthropic/claude-3-5-sonnet-latest", "anthropic/claude-3-5-haiku-latest"],
1710
- ["anthropic/claude-3-opus", "anthropic/claude-3-haiku"],
1711
- ["anthropic/claude-3-sonnet", "anthropic/claude-3-haiku"],
1712
- // Vertex (Gemini + Anthropic-on-Vertex)
1713
- ["vertex/gemini-1.5-pro", "vertex/gemini-1.5-flash"],
1714
- ["vertex/gemini-2.0-pro", "vertex/gemini-1.5-flash"],
1715
- ["vertex/claude-3-5-sonnet", "vertex/claude-3-5-haiku"],
1716
- ["vertex/claude-3-opus", "vertex/claude-3-haiku"],
1717
- // OpenRouter (preserve openrouter prefix, swap tier within same vendor)
1718
- ["openrouter/openai/gpt-4o", "openrouter/openai/gpt-4o-mini"],
1719
- ["openrouter/openai/gpt-4-turbo", "openrouter/openai/gpt-4o-mini"],
1720
- ["openrouter/anthropic/claude-3-5-sonnet", "openrouter/anthropic/claude-3-5-haiku"],
1721
- ["openrouter/anthropic/claude-opus-4", "openrouter/anthropic/claude-3-5-haiku"]
1722
- ]);
1723
- WILDCARD_REGISTRY = [
1724
- // Bedrock Anthropic: us.anthropic.claude-sonnet-* → us.anthropic.claude-3-haiku-*
1725
- ["bedrock/anthropic.claude-sonnet*", "bedrock/anthropic.claude-3-haiku*"],
1726
- ["bedrock/anthropic.claude-opus*", "bedrock/anthropic.claude-3-haiku*"],
1727
- ["bedrock/anthropic.claude-3-5-sonnet*", "bedrock/anthropic.claude-3-5-haiku*"]
1728
- ];
1729
- NO_AUTH_PROVIDERS = /* @__PURE__ */ new Set(["ollama", "lmstudio", "llamacpp"]);
1730
- CompressionModelUnresolvedError = class extends Error {
1731
- name = "CompressionModelUnresolvedError";
1732
- agentModel;
1733
- constructor(agentModel) {
1734
- super(
1735
- `Could not resolve a same-family-cheaper-tier compression model for "${agentModel}". Provide Agent.create({compression: {model: "<your-cheaper-model>"}}) OR add "${agentModel}" to the compression-model-registry (see ADR D440).`
1736
- );
1737
- this.agentModel = agentModel;
1738
- }
1739
- };
1740
- }
1741
- });
1742
1608
  var MODALITIES, costSchema, limitSchema, modalitiesSchema, catalogModelSchema;
1743
1609
  var init_catalog_schema = __esm({
1744
1610
  "src/internal/providers/catalog-schema.ts"() {
@@ -1816,19 +1682,6 @@ var init_registry = __esm({
1816
1682
  ALIASES = globalSingleton("theokit-sdk.providers.aliases", () => /* @__PURE__ */ new Map());
1817
1683
  }
1818
1684
  });
1819
-
1820
- // src/internal/providers/catalog-loader.ts
1821
- var catalog_loader_exports = {};
1822
- __export(catalog_loader_exports, {
1823
- _resetModelInfoIndexForTests: () => _resetModelInfoIndexForTests,
1824
- getCatalogCapabilities: () => getCatalogCapabilities,
1825
- getCatalogModelInfo: () => getCatalogModelInfo,
1826
- isPatchedModelKey: () => isPatchedModelKey,
1827
- listModelInfoKeys: () => listModelInfoKeys,
1828
- loadProviderCatalog: () => loadProviderCatalog,
1829
- patchModelInfo: () => patchModelInfo,
1830
- registerCatalogProviders: () => registerCatalogProviders
1831
- });
1832
1685
  function globalSingleton2(key, create) {
1833
1686
  const g = globalThis;
1834
1687
  const sym = Symbol.for(key);
@@ -1842,16 +1695,6 @@ function getCatalogModelInfo(key) {
1842
1695
  function isPatchedModelKey(key) {
1843
1696
  return patchedModelKeys.has(key);
1844
1697
  }
1845
- function patchModelInfo(key, model) {
1846
- ensureModelIndexLoaded();
1847
- const existing = modelInfoIndex.get(key);
1848
- modelInfoIndex.set(key, existing === void 0 ? model : { ...existing, ...model });
1849
- patchedModelKeys.add(key);
1850
- }
1851
- function listModelInfoKeys() {
1852
- ensureModelIndexLoaded();
1853
- return [...modelInfoIndex.keys()];
1854
- }
1855
1698
  function ensureModelIndexLoaded() {
1856
1699
  if (indexState.loaded) return;
1857
1700
  indexState.loaded = true;
@@ -1885,11 +1728,6 @@ function indexEntryModels(entry) {
1885
1728
  }
1886
1729
  }
1887
1730
  }
1888
- function _resetModelInfoIndexForTests() {
1889
- modelInfoIndex.clear();
1890
- patchedModelKeys.clear();
1891
- indexState.loaded = false;
1892
- }
1893
1731
  function validateEntry(raw) {
1894
1732
  if (typeof raw.id !== "string" || typeof raw.displayName !== "string" || typeof raw.apiMode !== "string" || typeof raw.authType !== "string" || typeof raw.baseUrl !== "string" || !Array.isArray(raw.envVars) || !Array.isArray(raw.fallbackModels) || raw.capabilities == null || typeof raw.capabilities !== "object") {
1895
1733
  return null;
@@ -1900,12 +1738,6 @@ function loadProviderCatalog(opts) {
1900
1738
  const catalogPath = path.join(__dirname_resolved, "provider-catalog.json");
1901
1739
  const rawText = fs.readFileSync(catalogPath, "utf-8");
1902
1740
  let entries = JSON.parse(rawText);
1903
- if (opts?._testInjectMalformed) {
1904
- entries = [
1905
- ...entries,
1906
- { id: "malformed-provider", displayName: "Bad" }
1907
- ];
1908
- }
1909
1741
  const result = {};
1910
1742
  for (const raw of entries) {
1911
1743
  const validated = validateEntry(raw);
@@ -1920,21 +1752,8 @@ function loadProviderCatalog(opts) {
1920
1752
  }
1921
1753
  return result;
1922
1754
  }
1923
- function getCatalogCapabilities(providerId) {
1924
- if (_capabilitiesCache === null) {
1925
- const catalog = loadProviderCatalog();
1926
- _capabilitiesCache = {};
1927
- for (const entry of Object.values(catalog)) {
1928
- _capabilitiesCache[entry.id] = entry.capabilities;
1929
- for (const alias of entry.aliases ?? []) {
1930
- if (_capabilitiesCache[alias] === void 0) _capabilitiesCache[alias] = entry.capabilities;
1931
- }
1932
- }
1933
- }
1934
- return _capabilitiesCache[providerId];
1935
- }
1936
1755
  function registerCatalogProviders(opts) {
1937
- const catalog = loadProviderCatalog(opts);
1756
+ const catalog = loadProviderCatalog();
1938
1757
  for (const entry of Object.values(catalog)) {
1939
1758
  if (getProviderProfile(entry.id) !== void 0) continue;
1940
1759
  if (entry.aliases?.some((a) => getProviderProfile(a) !== void 0)) continue;
@@ -1954,7 +1773,7 @@ function registerCatalogProviders(opts) {
1954
1773
  registerProvider(profile);
1955
1774
  }
1956
1775
  }
1957
- var __dirname_resolved, modelInfoIndex, patchedModelKeys, indexState, _capabilitiesCache;
1776
+ var __dirname_resolved, modelInfoIndex, patchedModelKeys, indexState;
1958
1777
  var init_catalog_loader = __esm({
1959
1778
  "src/internal/providers/catalog-loader.ts"() {
1960
1779
  init_catalog_schema();
@@ -1971,7 +1790,15 @@ var init_catalog_loader = __esm({
1971
1790
  indexState = globalSingleton2("theokit-sdk.providers.model-info-loaded", () => ({
1972
1791
  loaded: false
1973
1792
  }));
1974
- _capabilitiesCache = null;
1793
+ }
1794
+ });
1795
+
1796
+ // src/compaction.ts
1797
+ function estimateTokens(text) {
1798
+ return Math.ceil(text.length / 4);
1799
+ }
1800
+ var init_compaction = __esm({
1801
+ "src/compaction.ts"() {
1975
1802
  }
1976
1803
  });
1977
1804
 
@@ -5618,12 +5445,6 @@ var init_vertex_router = __esm({
5618
5445
  });
5619
5446
 
5620
5447
  // src/internal/llm/router.ts
5621
- var router_exports = {};
5622
- __export(router_exports, {
5623
- _resetCredentialPoolWarnings: () => _resetCredentialPoolWarnings,
5624
- _resetNoAuthApiKeyWarnings: () => _resetNoAuthApiKeyWarnings,
5625
- resolveProviderChain: () => resolveProviderChain
5626
- });
5627
5448
  function resolveProviderChain(options) {
5628
5449
  registerBuiltins();
5629
5450
  return buildChain(options);
@@ -5721,9 +5542,6 @@ function warnNoAuthApiKeysIgnoredOnce(provider) {
5721
5542
  `
5722
5543
  );
5723
5544
  }
5724
- function _resetNoAuthApiKeyWarnings() {
5725
- warnedNoAuthApiKeys.clear();
5726
- }
5727
5545
  function sentinelForNoAuth(profile) {
5728
5546
  return profile.authType === "none" ? profile.name : void 0;
5729
5547
  }
@@ -5754,9 +5572,6 @@ function warnUnknownProvidersInApiKeys(apiKeys) {
5754
5572
  }
5755
5573
  }
5756
5574
  }
5757
- function _resetCredentialPoolWarnings() {
5758
- warnedProviders.clear();
5759
- }
5760
5575
  function resolveApiKey2(envVars) {
5761
5576
  for (const v of envVars) {
5762
5577
  const value = process.env[v];
@@ -5860,41 +5675,318 @@ var init_router = __esm({
5860
5675
  }
5861
5676
  });
5862
5677
 
5863
- // src/internal/local-agent/real-local-run-provider.ts
5864
- var real_local_run_provider_exports = {};
5865
- __export(real_local_run_provider_exports, {
5866
- detectPrimaryProvider: () => detectPrimaryProvider,
5867
- inferProviderFromApiKey: () => inferProviderFromApiKey
5868
- });
5869
- function inferProviderFromApiKey(apiKey) {
5870
- if (apiKey === void 0 || apiKey.length === 0) return void 0;
5871
- const byPrefix = [
5872
- { provider: "openrouter", prefix: "sk-or-" },
5873
- { provider: "anthropic", prefix: "sk-ant-" },
5874
- { provider: "openai", prefix: "sk-" }
5875
- ];
5876
- for (const { provider, prefix } of byPrefix) {
5877
- if (apiKey.startsWith(prefix) && getProviderProfile(provider) !== void 0) {
5878
- return provider;
5678
+ // src/internal/local-agent/real-local-run-provider.ts
5679
+ function inferProviderFromApiKey(apiKey) {
5680
+ if (apiKey === void 0 || apiKey.length === 0) return void 0;
5681
+ const byPrefix = [
5682
+ { provider: "openrouter", prefix: "sk-or-" },
5683
+ { provider: "anthropic", prefix: "sk-ant-" },
5684
+ { provider: "openai", prefix: "sk-" }
5685
+ ];
5686
+ for (const { provider, prefix } of byPrefix) {
5687
+ if (apiKey.startsWith(prefix) && getProviderProfile(provider) !== void 0) {
5688
+ return provider;
5689
+ }
5690
+ }
5691
+ return void 0;
5692
+ }
5693
+ function detectPrimaryProvider() {
5694
+ if (process.env.ANTHROPIC_API_KEY !== void 0 && process.env.ANTHROPIC_API_KEY.length > 0) {
5695
+ return "anthropic";
5696
+ }
5697
+ if (process.env.OPENAI_API_KEY !== void 0 && process.env.OPENAI_API_KEY.length > 0) {
5698
+ return "openai";
5699
+ }
5700
+ if (process.env.OPENROUTER_API_KEY !== void 0 && process.env.OPENROUTER_API_KEY.length > 0) {
5701
+ return "openrouter";
5702
+ }
5703
+ return "openai";
5704
+ }
5705
+ var init_real_local_run_provider = __esm({
5706
+ "src/internal/local-agent/real-local-run-provider.ts"() {
5707
+ init_providers();
5708
+ }
5709
+ });
5710
+
5711
+ // src/internal/runtime/compression/compression-model-registry.ts
5712
+ function resolveCompressionModel(agentModel) {
5713
+ const exact = EXACT_REGISTRY.get(agentModel);
5714
+ if (exact !== void 0) return exact;
5715
+ const wildcard = matchWildcard(agentModel);
5716
+ if (wildcard !== null) return wildcard;
5717
+ if (isNoAuthProvider(agentModel)) return agentModel;
5718
+ throw new CompressionModelUnresolvedError(agentModel);
5719
+ }
5720
+ function matchWildcard(agentModel) {
5721
+ for (const [pattern, replacement] of WILDCARD_REGISTRY) {
5722
+ const prefix = pattern.endsWith("*") ? pattern.slice(0, -1) : pattern;
5723
+ if (!agentModel.startsWith(prefix)) continue;
5724
+ const suffix = agentModel.slice(prefix.length);
5725
+ const replPrefix = replacement.endsWith("*") ? replacement.slice(0, -1) : replacement;
5726
+ return `${replPrefix}${suffix}`;
5727
+ }
5728
+ return null;
5729
+ }
5730
+ function isNoAuthProvider(agentModel) {
5731
+ const slashIdx = agentModel.indexOf("/");
5732
+ if (slashIdx <= 0) return false;
5733
+ return NO_AUTH_PROVIDERS.has(agentModel.slice(0, slashIdx));
5734
+ }
5735
+ var EXACT_REGISTRY, WILDCARD_REGISTRY, NO_AUTH_PROVIDERS, CompressionModelUnresolvedError;
5736
+ var init_compression_model_registry = __esm({
5737
+ "src/internal/runtime/compression/compression-model-registry.ts"() {
5738
+ EXACT_REGISTRY = /* @__PURE__ */ new Map([
5739
+ // OpenAI family
5740
+ ["openai/gpt-4o", "openai/gpt-4o-mini"],
5741
+ ["openai/gpt-4-turbo", "openai/gpt-4o-mini"],
5742
+ ["openai/gpt-4", "openai/gpt-4o-mini"],
5743
+ ["openai/o1-preview", "openai/gpt-4o-mini"],
5744
+ ["openai/o1", "openai/gpt-4o-mini"],
5745
+ ["openai/o3", "openai/gpt-4o-mini"],
5746
+ ["openai/o3-mini", "openai/gpt-4o-mini"],
5747
+ // Anthropic family
5748
+ ["anthropic/claude-opus-4", "anthropic/claude-3-5-haiku-latest"],
5749
+ ["anthropic/claude-sonnet-4", "anthropic/claude-3-5-haiku-latest"],
5750
+ ["anthropic/claude-3-5-sonnet", "anthropic/claude-3-5-haiku-latest"],
5751
+ ["anthropic/claude-3-5-sonnet-latest", "anthropic/claude-3-5-haiku-latest"],
5752
+ ["anthropic/claude-3-opus", "anthropic/claude-3-haiku"],
5753
+ ["anthropic/claude-3-sonnet", "anthropic/claude-3-haiku"],
5754
+ // Vertex (Gemini + Anthropic-on-Vertex)
5755
+ ["vertex/gemini-1.5-pro", "vertex/gemini-1.5-flash"],
5756
+ ["vertex/gemini-2.0-pro", "vertex/gemini-1.5-flash"],
5757
+ ["vertex/claude-3-5-sonnet", "vertex/claude-3-5-haiku"],
5758
+ ["vertex/claude-3-opus", "vertex/claude-3-haiku"],
5759
+ // OpenRouter (preserve openrouter prefix, swap tier within same vendor)
5760
+ ["openrouter/openai/gpt-4o", "openrouter/openai/gpt-4o-mini"],
5761
+ ["openrouter/openai/gpt-4-turbo", "openrouter/openai/gpt-4o-mini"],
5762
+ ["openrouter/anthropic/claude-3-5-sonnet", "openrouter/anthropic/claude-3-5-haiku"],
5763
+ ["openrouter/anthropic/claude-opus-4", "openrouter/anthropic/claude-3-5-haiku"]
5764
+ ]);
5765
+ WILDCARD_REGISTRY = [
5766
+ // Bedrock Anthropic: us.anthropic.claude-sonnet-* → us.anthropic.claude-3-haiku-*
5767
+ ["bedrock/anthropic.claude-sonnet*", "bedrock/anthropic.claude-3-haiku*"],
5768
+ ["bedrock/anthropic.claude-opus*", "bedrock/anthropic.claude-3-haiku*"],
5769
+ ["bedrock/anthropic.claude-3-5-sonnet*", "bedrock/anthropic.claude-3-5-haiku*"]
5770
+ ];
5771
+ NO_AUTH_PROVIDERS = /* @__PURE__ */ new Set(["ollama", "lmstudio", "llamacpp"]);
5772
+ CompressionModelUnresolvedError = class extends Error {
5773
+ name = "CompressionModelUnresolvedError";
5774
+ agentModel;
5775
+ constructor(agentModel) {
5776
+ super(
5777
+ `Could not resolve a same-family-cheaper-tier compression model for "${agentModel}". Provide Agent.create({compression: {model: "<your-cheaper-model>"}}) OR add "${agentModel}" to the compression-model-registry (see ADR D440).`
5778
+ );
5779
+ this.agentModel = agentModel;
5780
+ }
5781
+ };
5782
+ }
5783
+ });
5784
+
5785
+ // src/internal/runtime/compression/compression-summarizer.ts
5786
+ function buildCompressionPrompt(messages) {
5787
+ const formatted = messages.map((m) => `[${m.role}]: ${m.content}`).join("\n\n");
5788
+ return `Summarize the following ${messages.length} conversation messages into a concise summary that preserves ALL facts, decisions, user preferences, and context needed for the conversation to continue naturally. The summary will replace these messages in the context window. Be thorough but concise.
5789
+
5790
+ --- CONVERSATION TO SUMMARIZE ---
5791
+ ${formatted}
5792
+ --- END ---`;
5793
+ }
5794
+ async function compressConversationWindow(opts) {
5795
+ const userPrompt = buildCompressionPrompt(opts.messages);
5796
+ let summary;
5797
+ try {
5798
+ summary = await opts.callLlm(opts.model, COMPRESSION_SYSTEM, userPrompt);
5799
+ } catch (cause) {
5800
+ throw new CompressionFailedError(
5801
+ `Compression LLM call failed: ${cause instanceof Error ? cause.message : String(cause)}`,
5802
+ { cause: cause instanceof Error ? cause : void 0 }
5803
+ );
5804
+ }
5805
+ if (!summary || summary.trim().length === 0) {
5806
+ throw new CompressionFailedError(
5807
+ "Compression LLM returned empty summary \u2014 reduction ineffective."
5808
+ );
5809
+ }
5810
+ return {
5811
+ role: "system",
5812
+ content: `[Compressed conversation summary]: ${summary.trim()}`
5813
+ };
5814
+ }
5815
+ var CompressionFailedError, COMPRESSION_SYSTEM;
5816
+ var init_compression_summarizer = __esm({
5817
+ "src/internal/runtime/compression/compression-summarizer.ts"() {
5818
+ CompressionFailedError = class extends Error {
5819
+ name = "CompressionFailedError";
5820
+ };
5821
+ 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.";
5822
+ }
5823
+ });
5824
+
5825
+ // src/internal/session/agent-session-store.ts
5826
+ function seedTranscript(prior, opts) {
5827
+ return SessionTranscript.fromRecords(prior, opts);
5828
+ }
5829
+ function mapAgentTurn(steps) {
5830
+ const assistant = {};
5831
+ const toolResults = [];
5832
+ const toolCalls = [];
5833
+ for (const step of steps) {
5834
+ if (step.type === "thinkingMessage") assistant.thinking = step.message.text;
5835
+ else if (step.type === "assistantMessage") assistant.text = step.message.text;
5836
+ else if (step.type === "toolCall")
5837
+ toolCalls.push({
5838
+ id: step.message.callId,
5839
+ name: step.message.name,
5840
+ input: step.message.args ?? {}
5841
+ });
5842
+ else
5843
+ toolResults.push({
5844
+ toolUseId: step.message.callId,
5845
+ content: step.message.result,
5846
+ isError: step.message.isError
5847
+ });
5848
+ }
5849
+ if (toolCalls.length > 0) assistant.toolCalls = toolCalls;
5850
+ return { assistant, toolResults };
5851
+ }
5852
+ function hasAssistantContent(a) {
5853
+ return a.text !== void 0 || a.thinking !== void 0 || (a.toolCalls?.length ?? 0) > 0;
5854
+ }
5855
+ function appendConversation(transcript, conversation) {
5856
+ for (const ct of conversation) {
5857
+ if (ct.type !== "agentConversationTurn") continue;
5858
+ const { assistant, toolResults } = mapAgentTurn(ct.turn.steps);
5859
+ if (hasAssistantContent(assistant)) transcript.appendAssistantTurn(assistant);
5860
+ if (toolResults.length > 0) transcript.appendToolResults(toolResults);
5861
+ }
5862
+ }
5863
+ async function readSessionMessages(store, agentId) {
5864
+ const records = await store.readRecords(agentId);
5865
+ return reconstructMessages(records).map(narrowToSessionMessage);
5866
+ }
5867
+ function partToText(p) {
5868
+ if (p.type === "text") return p.text ?? "";
5869
+ if (p.type === "tool_use") return `[tool call] ${p.name ?? ""}`;
5870
+ if (p.type === "tool_result") {
5871
+ const body = typeof p.content === "string" ? p.content : JSON.stringify(p.content);
5872
+ return `[tool result] ${body}`;
5873
+ }
5874
+ return "";
5875
+ }
5876
+ function narrowToSessionMessage(m) {
5877
+ const role = m.role === "user" ? "user" : "assistant";
5878
+ const text = m.content.map(partToText).filter((s) => s.length > 0).join("\n");
5879
+ return { role, text };
5880
+ }
5881
+ function deltaRecords(transcript, priorLength) {
5882
+ return transcript.records().slice(priorLength);
5883
+ }
5884
+ async function persistTurn(store, loc, sessionId, turn) {
5885
+ const prior = await store.readRecords(loc.agentId);
5886
+ const transcript = seedTranscript(prior, { cwd: loc.cwd, sessionId, model: loc.model });
5887
+ transcript.appendUserTurn(turn.userText);
5888
+ appendConversation(transcript, turn.conversation);
5889
+ await store.appendRecords(loc.agentId, deltaRecords(transcript, prior.length));
5890
+ }
5891
+ var init_agent_session_store = __esm({
5892
+ "src/internal/session/agent-session-store.ts"() {
5893
+ init_session_transcript();
5894
+ }
5895
+ });
5896
+
5897
+ // src/internal/session/agent-session.ts
5898
+ function transcriptKey(cwd, agentId) {
5899
+ return `${cwd}::${agentId}`;
5900
+ }
5901
+ function appendSessionMessage(agentId, message) {
5902
+ const existing = sessions.get(agentId) ?? [];
5903
+ existing.push(message);
5904
+ sessions.set(agentId, existing);
5905
+ }
5906
+ function getSessionMessages(agentId) {
5907
+ return sessions.get(agentId) ?? [];
5908
+ }
5909
+ function persistTurnToTranscript(store, loc, sessionId, turn, onCompact) {
5910
+ const key = transcriptKey(loc.cwd, loc.agentId);
5911
+ const chained = (pendingWrites.get(key) ?? Promise.resolve()).then(async () => {
5912
+ try {
5913
+ await persistTurn(store, loc, sessionId, turn);
5914
+ const count = (recordCounts.get(key) ?? 0) + 1;
5915
+ recordCounts.set(key, count);
5916
+ if (turn.autoCompact !== void 0) {
5917
+ const { autoCompactIfNeeded: autoCompactIfNeeded2 } = await Promise.resolve().then(() => (init_compact_session(), compact_session_exports));
5918
+ const fired = await autoCompactIfNeeded2({
5919
+ store,
5920
+ loc,
5921
+ sessionId,
5922
+ usageTotal: turn.autoCompact.usageTotal,
5923
+ contextWindow: turn.autoCompact.contextWindow,
5924
+ turnCount: count,
5925
+ summarize: turn.autoCompact.summarize
5926
+ });
5927
+ if (fired) onCompact?.();
5928
+ }
5929
+ } catch (cause) {
5930
+ const msg = cause instanceof Error ? cause.message : String(cause);
5931
+ process.stderr.write(
5932
+ `[theokit-sdk] session transcript write failed (${loc.agentId}): ${msg}
5933
+ `
5934
+ );
5879
5935
  }
5880
- }
5881
- return void 0;
5936
+ });
5937
+ pendingWrites.set(
5938
+ key,
5939
+ chained.then(
5940
+ () => void 0,
5941
+ () => void 0
5942
+ )
5943
+ );
5882
5944
  }
5883
- function detectPrimaryProvider() {
5884
- if (process.env.ANTHROPIC_API_KEY !== void 0 && process.env.ANTHROPIC_API_KEY.length > 0) {
5885
- return "anthropic";
5886
- }
5887
- if (process.env.OPENAI_API_KEY !== void 0 && process.env.OPENAI_API_KEY.length > 0) {
5888
- return "openai";
5945
+ async function hydrateSession(agentId, loc) {
5946
+ const key = transcriptKey(loc.cwd, agentId);
5947
+ if (hydratedKeys.has(key)) return;
5948
+ hydratedKeys.add(key);
5949
+ const persisted = await readSessionMessages(loc.store, agentId);
5950
+ if (persisted.length === 0) return;
5951
+ if (!sessions.has(agentId) || sessions.get(agentId)?.length === 0) {
5952
+ sessions.set(agentId, persisted);
5889
5953
  }
5890
- if (process.env.OPENROUTER_API_KEY !== void 0 && process.env.OPENROUTER_API_KEY.length > 0) {
5891
- return "openrouter";
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);
5892
5960
  }
5893
- return "openai";
5894
5961
  }
5895
- var init_real_local_run_provider = __esm({
5896
- "src/internal/local-agent/real-local-run-provider.ts"() {
5897
- init_providers();
5962
+ function clearSession(agentId) {
5963
+ sessions.delete(agentId);
5964
+ }
5965
+ function invalidateSessionCache(cwd, agentId) {
5966
+ sessions.delete(agentId);
5967
+ hydratedKeys.delete(transcriptKey(cwd, agentId));
5968
+ }
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();
5986
+ sessions = /* @__PURE__ */ new Map();
5987
+ hydratedKeys = /* @__PURE__ */ new Set();
5988
+ pendingWrites = /* @__PURE__ */ new Map();
5989
+ recordCounts = /* @__PURE__ */ new Map();
5898
5990
  }
5899
5991
  });
5900
5992
 
@@ -5936,7 +6028,14 @@ async function compactSessionTranscript(opts) {
5936
6028
  const m = compressible[i];
5937
6029
  if (m === void 0 || m.role !== "user" || isCompactSummary(m.content)) continue;
5938
6030
  const cost = estimateTokens(m.content);
5939
- if (budget + cost > COMPACT_USER_MESSAGE_MAX_TOKENS) break;
6031
+ if (budget + cost > COMPACT_USER_MESSAGE_MAX_TOKENS) {
6032
+ const remaining = COMPACT_USER_MESSAGE_MAX_TOKENS - budget;
6033
+ if (remaining > 50) {
6034
+ preserved.unshift(`${m.content.slice(0, remaining * 4)}
6035
+ [...truncated for compaction...]`);
6036
+ }
6037
+ break;
6038
+ }
5940
6039
  budget += cost;
5941
6040
  preserved.unshift(m.content);
5942
6041
  }
@@ -5952,30 +6051,29 @@ ${summaryBody}`;
5952
6051
  transcript.appendUserTurn(summary);
5953
6052
  const delta = transcript.records().slice(prior.length);
5954
6053
  await opts.store.appendRecords(opts.loc.agentId, delta);
6054
+ invalidateSessionCache(opts.loc.cwd, opts.loc.agentId);
5955
6055
  const postTokens = estimateTokens([...preserved, summary].join("\n"));
5956
6056
  return { preTokens, postTokens };
5957
6057
  }
5958
6058
  function buildDefaultSummarizer(opts) {
5959
6059
  return async (messages) => {
5960
- const { compressConversationWindow: compressConversationWindow2 } = await Promise.resolve().then(() => (init_compression_summarizer(), compression_summarizer_exports));
5961
- const { resolveCompressionModel: resolveCompressionModel2 } = await Promise.resolve().then(() => (init_compression_model_registry(), compression_model_registry_exports));
5962
- const { resolveProviderChain: resolveProviderChain2 } = await Promise.resolve().then(() => (init_router(), router_exports));
5963
- const { inferProviderFromApiKey: inferProviderFromApiKey2, detectPrimaryProvider: detectPrimaryProvider2 } = await Promise.resolve().then(() => (init_real_local_run_provider(), real_local_run_provider_exports));
5964
- const keyProvider = inferProviderFromApiKey2(opts.apiKey);
6060
+ const keyProvider = inferProviderFromApiKey(opts.apiKey);
5965
6061
  const modelPrefix = opts.agentModel.includes("/") ? opts.agentModel.slice(0, opts.agentModel.indexOf("/")) : void 0;
5966
- const provider = keyProvider ?? detectPrimaryProvider2();
6062
+ registerBuiltins();
6063
+ const prefixProfile = modelPrefix !== void 0 ? getProviderProfile(modelPrefix) : void 0;
6064
+ const provider = prefixProfile !== void 0 ? modelPrefix : keyProvider ?? detectPrimaryProvider();
5967
6065
  let model;
5968
6066
  if (provider !== modelPrefix) {
5969
6067
  model = opts.agentModel;
5970
6068
  } else {
5971
6069
  try {
5972
- model = resolveCompressionModel2(opts.agentModel);
6070
+ model = resolveCompressionModel(opts.agentModel);
5973
6071
  } catch {
5974
6072
  model = opts.agentModel;
5975
6073
  }
5976
6074
  }
5977
6075
  const callLlm = async (m, system, user) => {
5978
- const chain = resolveProviderChain2({
6076
+ const chain = resolveProviderChain({
5979
6077
  primary: provider,
5980
6078
  ...opts.apiKey !== void 0 ? { apiKeys: { [provider]: [opts.apiKey] } } : {}
5981
6079
  });
@@ -5995,7 +6093,7 @@ function buildDefaultSummarizer(opts) {
5995
6093
  }
5996
6094
  return text;
5997
6095
  };
5998
- const summary = await compressConversationWindow2({ messages: [...messages], model, callLlm });
6096
+ const summary = await compressConversationWindow({ messages: [...messages], model, callLlm });
5999
6097
  return summary.content;
6000
6098
  };
6001
6099
  }
@@ -6029,6 +6127,12 @@ var COMPACT_SUMMARY_MARKER, COMPACT_USER_MESSAGE_MAX_TOKENS, autoCompactAttempts
6029
6127
  var init_compact_session = __esm({
6030
6128
  "src/internal/session/compact-session.ts"() {
6031
6129
  init_compaction();
6130
+ init_router();
6131
+ init_real_local_run_provider();
6132
+ init_providers();
6133
+ init_compression_model_registry();
6134
+ init_compression_summarizer();
6135
+ init_agent_session();
6032
6136
  init_session_transcript();
6033
6137
  COMPACT_SUMMARY_MARKER = "[[theokit:compact-summary]]";
6034
6138
  COMPACT_USER_MESSAGE_MAX_TOKENS = 2e4;
@@ -10419,146 +10523,9 @@ async function writeSessionSummary(input) {
10419
10523
  await replaceFileAtomic(path, body);
10420
10524
  }
10421
10525
 
10422
- // src/internal/session/agent-session-store.ts
10423
- init_session_transcript();
10424
- function seedTranscript(prior, opts) {
10425
- return SessionTranscript.fromRecords(prior, opts);
10426
- }
10427
- function mapAgentTurn(steps) {
10428
- const assistant = {};
10429
- const toolResults = [];
10430
- const toolCalls = [];
10431
- for (const step of steps) {
10432
- if (step.type === "thinkingMessage") assistant.thinking = step.message.text;
10433
- else if (step.type === "assistantMessage") assistant.text = step.message.text;
10434
- else if (step.type === "toolCall")
10435
- toolCalls.push({
10436
- id: step.message.callId,
10437
- name: step.message.name,
10438
- input: step.message.args ?? {}
10439
- });
10440
- else
10441
- toolResults.push({
10442
- toolUseId: step.message.callId,
10443
- content: step.message.result,
10444
- isError: step.message.isError
10445
- });
10446
- }
10447
- if (toolCalls.length > 0) assistant.toolCalls = toolCalls;
10448
- return { assistant, toolResults };
10449
- }
10450
- function hasAssistantContent(a) {
10451
- return a.text !== void 0 || a.thinking !== void 0 || (a.toolCalls?.length ?? 0) > 0;
10452
- }
10453
- function appendConversation(transcript, conversation) {
10454
- for (const ct of conversation) {
10455
- if (ct.type !== "agentConversationTurn") continue;
10456
- const { assistant, toolResults } = mapAgentTurn(ct.turn.steps);
10457
- if (hasAssistantContent(assistant)) transcript.appendAssistantTurn(assistant);
10458
- if (toolResults.length > 0) transcript.appendToolResults(toolResults);
10459
- }
10460
- }
10461
- async function readSessionMessages(store, agentId) {
10462
- const records = await store.readRecords(agentId);
10463
- return reconstructMessages(records).map(narrowToSessionMessage);
10464
- }
10465
- function partToText(p) {
10466
- if (p.type === "text") return p.text ?? "";
10467
- if (p.type === "tool_use") return `[tool call] ${p.name ?? ""}`;
10468
- if (p.type === "tool_result") {
10469
- const body = typeof p.content === "string" ? p.content : JSON.stringify(p.content);
10470
- return `[tool result] ${body}`;
10471
- }
10472
- return "";
10473
- }
10474
- function narrowToSessionMessage(m) {
10475
- const role = m.role === "user" ? "user" : "assistant";
10476
- const text = m.content.map(partToText).filter((s) => s.length > 0).join("\n");
10477
- return { role, text };
10478
- }
10479
- function deltaRecords(transcript, priorLength) {
10480
- return transcript.records().slice(priorLength);
10481
- }
10482
- async function persistTurn(store, loc, sessionId, turn) {
10483
- const prior = await store.readRecords(loc.agentId);
10484
- const transcript = seedTranscript(prior, { cwd: loc.cwd, sessionId, model: loc.model });
10485
- transcript.appendUserTurn(turn.userText);
10486
- appendConversation(transcript, turn.conversation);
10487
- await store.appendRecords(loc.agentId, deltaRecords(transcript, prior.length));
10488
- }
10489
-
10490
- // src/internal/session/agent-session.ts
10491
- var sessions = /* @__PURE__ */ new Map();
10492
- var hydratedKeys = /* @__PURE__ */ new Set();
10493
- var pendingWrites = /* @__PURE__ */ new Map();
10494
- var recordCounts = /* @__PURE__ */ new Map();
10495
- function transcriptKey(cwd, agentId) {
10496
- return `${cwd}::${agentId}`;
10497
- }
10498
- function appendSessionMessage(agentId, message) {
10499
- const existing = sessions.get(agentId) ?? [];
10500
- existing.push(message);
10501
- sessions.set(agentId, existing);
10502
- }
10503
- function getSessionMessages(agentId) {
10504
- return sessions.get(agentId) ?? [];
10505
- }
10506
- function persistTurnToTranscript(store, loc, sessionId, turn, onCompact) {
10507
- const key = transcriptKey(loc.cwd, loc.agentId);
10508
- const chained = (pendingWrites.get(key) ?? Promise.resolve()).then(async () => {
10509
- try {
10510
- await persistTurn(store, loc, sessionId, turn);
10511
- const count = (recordCounts.get(key) ?? 0) + 1;
10512
- recordCounts.set(key, count);
10513
- if (turn.autoCompact !== void 0) {
10514
- const { autoCompactIfNeeded: autoCompactIfNeeded2 } = await Promise.resolve().then(() => (init_compact_session(), compact_session_exports));
10515
- const fired = await autoCompactIfNeeded2({
10516
- store,
10517
- loc,
10518
- sessionId,
10519
- usageTotal: turn.autoCompact.usageTotal,
10520
- contextWindow: turn.autoCompact.contextWindow,
10521
- turnCount: count,
10522
- summarize: turn.autoCompact.summarize
10523
- });
10524
- if (fired) onCompact?.();
10525
- }
10526
- } catch (cause) {
10527
- const msg = cause instanceof Error ? cause.message : String(cause);
10528
- process.stderr.write(
10529
- `[theokit-sdk] session transcript write failed (${loc.agentId}): ${msg}
10530
- `
10531
- );
10532
- }
10533
- });
10534
- pendingWrites.set(
10535
- key,
10536
- chained.then(
10537
- () => void 0,
10538
- () => void 0
10539
- )
10540
- );
10541
- }
10542
- async function hydrateSession(agentId, loc) {
10543
- const key = transcriptKey(loc.cwd, agentId);
10544
- if (hydratedKeys.has(key)) return;
10545
- hydratedKeys.add(key);
10546
- const persisted = await readSessionMessages(loc.store, agentId);
10547
- if (persisted.length === 0) return;
10548
- if (!sessions.has(agentId) || sessions.get(agentId)?.length === 0) {
10549
- sessions.set(agentId, persisted);
10550
- }
10551
- }
10552
- async function flushSessionWrites() {
10553
- while (pendingWrites.size > 0) {
10554
- const all = Array.from(pendingWrites.values());
10555
- pendingWrites.clear();
10556
- await Promise.all(all);
10557
- }
10558
- }
10559
- function clearSession(agentId) {
10560
- sessions.delete(agentId);
10561
- }
10526
+ // src/internal/runtime/lifecycle/post-run-lifecycle.ts
10527
+ init_catalog_loader();
10528
+ init_compact_session();
10562
10529
 
10563
10530
  // src/internal/runtime/memory/memory-path-selector.ts
10564
10531
  var PORT_MEMORY_PATH_ENV_VAR = "THEOKIT_PORT_MEMORY_PATH";
@@ -10607,9 +10574,21 @@ async function runPostRunLifecycle(inputs) {
10607
10574
  appendSessionMessage(agentId, { role: "assistant", text: result.result });
10608
10575
  }
10609
10576
  const conversation = await safeConversation(run);
10610
- const { getCatalogModelInfo: getCatalogModelInfo2 } = await Promise.resolve().then(() => (init_catalog_loader(), catalog_loader_exports));
10611
- const { buildDefaultSummarizer: buildDefaultSummarizer2 } = await Promise.resolve().then(() => (init_compact_session(), compact_session_exports));
10612
- const contextWindow = getCatalogModelInfo2(model)?.limit?.context;
10577
+ const contextWindow = getCatalogModelInfo(model)?.limit?.context;
10578
+ if (contextWindow === void 0) {
10579
+ const g = globalThis;
10580
+ const sym = /* @__PURE__ */ Symbol.for("theokit-sdk.compact.no-cw-warned");
10581
+ const warned3 = g[sym] ??= /* @__PURE__ */ new Set();
10582
+ if (!warned3.has(model)) {
10583
+ warned3.add(model);
10584
+ process.stderr.write(
10585
+ `[theokit-sdk] auto-compaction disabled: model "${model}" has no context-window entry in the catalog
10586
+ `
10587
+ );
10588
+ }
10589
+ }
10590
+ const lastRequestUsage = result.usage?.requests?.at(-1)?.totalTokens;
10591
+ const usageForTrigger = lastRequestUsage ?? result.usage?.totalTokens;
10613
10592
  persistTurnToTranscript(
10614
10593
  sessionStore,
10615
10594
  { cwd: workspaceCwd, agentId, model },
@@ -10618,9 +10597,9 @@ async function runPostRunLifecycle(inputs) {
10618
10597
  userText,
10619
10598
  conversation,
10620
10599
  autoCompact: {
10621
- usageTotal: result.usage?.totalTokens,
10600
+ usageTotal: usageForTrigger,
10622
10601
  contextWindow,
10623
- summarize: buildDefaultSummarizer2({
10602
+ summarize: buildDefaultSummarizer({
10624
10603
  agentModel: model,
10625
10604
  ...inputs.apiKey !== void 0 ? { apiKey: inputs.apiKey } : {}
10626
10605
  })
@@ -19600,6 +19579,7 @@ async function getRegisteredAgentOrThrow(agentId) {
19600
19579
  // src/agent.ts
19601
19580
  init_errors();
19602
19581
  init_discovery();
19582
+ init_agent_session();
19603
19583
  init_agent_factory_registry();
19604
19584
  var streamObjectImport;
19605
19585
  var Agent = class _Agent {
@@ -19902,7 +19882,7 @@ var Agent = class _Agent {
19902
19882
  const { defaultBaseDir: defaultBaseDir2, expandTilde: expandTilde2 } = await Promise.resolve().then(() => (init_session_transcript(), session_transcript_exports));
19903
19883
  const baseDir = reg.options.local?.baseDir !== void 0 ? expandTilde2(reg.options.local.baseDir) : defaultBaseDir2();
19904
19884
  const store = new FsSessionStore2({ baseDir, cwd });
19905
- return compactSessionTranscript2({
19885
+ return enqueueSessionWrite(cwd, agentId, () => compactSessionTranscript2({
19906
19886
  store,
19907
19887
  loc: { cwd, agentId, model },
19908
19888
  sessionId: agentId,
@@ -19911,7 +19891,7 @@ var Agent = class _Agent {
19911
19891
  agentModel: model,
19912
19892
  ...reg.options.apiKey !== void 0 ? { apiKey: reg.options.apiKey } : {}
19913
19893
  })
19914
- });
19894
+ }));
19915
19895
  }
19916
19896
  /**
19917
19897
  * Permanently delete a cloud agent.