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