@theokit/sdk 4.16.3 → 4.16.4

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/index.cjs CHANGED
@@ -1761,6 +1761,78 @@ var init_session_summary_writer = __esm({
1761
1761
  }
1762
1762
  });
1763
1763
 
1764
+ // src/internal/session/agent-session-store.ts
1765
+ function seedTranscript(prior, opts) {
1766
+ return SessionTranscript.fromRecords(prior, opts);
1767
+ }
1768
+ function mapAgentTurn(steps) {
1769
+ const assistant = {};
1770
+ const toolResults = [];
1771
+ const toolCalls = [];
1772
+ for (const step of steps) {
1773
+ if (step.type === "thinkingMessage") assistant.thinking = step.message.text;
1774
+ else if (step.type === "assistantMessage") assistant.text = step.message.text;
1775
+ else if (step.type === "toolCall")
1776
+ toolCalls.push({
1777
+ id: step.message.callId,
1778
+ name: step.message.name,
1779
+ input: step.message.args ?? {}
1780
+ });
1781
+ else
1782
+ toolResults.push({
1783
+ toolUseId: step.message.callId,
1784
+ content: step.message.result,
1785
+ isError: step.message.isError
1786
+ });
1787
+ }
1788
+ if (toolCalls.length > 0) assistant.toolCalls = toolCalls;
1789
+ return { assistant, toolResults };
1790
+ }
1791
+ function hasAssistantContent(a) {
1792
+ return a.text !== void 0 || a.thinking !== void 0 || (a.toolCalls?.length ?? 0) > 0;
1793
+ }
1794
+ function appendConversation(transcript, conversation) {
1795
+ for (const ct of conversation) {
1796
+ if (ct.type !== "agentConversationTurn") continue;
1797
+ const { assistant, toolResults } = mapAgentTurn(ct.turn.steps);
1798
+ if (hasAssistantContent(assistant)) transcript.appendAssistantTurn(assistant);
1799
+ if (toolResults.length > 0) transcript.appendToolResults(toolResults);
1800
+ }
1801
+ }
1802
+ async function readSessionMessages(store, agentId) {
1803
+ const records = await store.readRecords(agentId);
1804
+ return reconstructMessages(records).map(narrowToSessionMessage);
1805
+ }
1806
+ function partToText(p) {
1807
+ if (p.type === "text") return p.text ?? "";
1808
+ if (p.type === "tool_use") return `[tool call] ${p.name ?? ""}`;
1809
+ if (p.type === "tool_result") {
1810
+ const body = typeof p.content === "string" ? p.content : JSON.stringify(p.content);
1811
+ return `[tool result] ${body}`;
1812
+ }
1813
+ return "";
1814
+ }
1815
+ function narrowToSessionMessage(m) {
1816
+ const role = m.role === "user" ? "user" : "assistant";
1817
+ const text = m.content.map(partToText).filter((s) => s.length > 0).join("\n");
1818
+ return { role, text };
1819
+ }
1820
+ function deltaRecords(transcript, priorLength) {
1821
+ return transcript.records().slice(priorLength);
1822
+ }
1823
+ async function persistTurn(store, loc, sessionId, turn) {
1824
+ const prior = await store.readRecords(loc.agentId);
1825
+ const transcript = seedTranscript(prior, { cwd: loc.cwd, sessionId, model: loc.model });
1826
+ transcript.appendUserTurn(turn.userText);
1827
+ appendConversation(transcript, turn.conversation);
1828
+ await store.appendRecords(loc.agentId, deltaRecords(transcript, prior.length));
1829
+ }
1830
+ var init_agent_session_store = __esm({
1831
+ "src/internal/session/agent-session-store.ts"() {
1832
+ init_session_transcript();
1833
+ }
1834
+ });
1835
+
1764
1836
  // src/compaction.ts
1765
1837
  function estimateTokens(text) {
1766
1838
  return Math.ceil(text.length / 4);
@@ -1964,6 +2036,10 @@ function getProviderProfile(name) {
1964
2036
  function listProviders() {
1965
2037
  return Array.from(REGISTRY.values());
1966
2038
  }
2039
+ function _resetProvidersForTests() {
2040
+ REGISTRY.clear();
2041
+ ALIASES.clear();
2042
+ }
1967
2043
  var REGISTRY, ALIASES;
1968
2044
  var init_registry = __esm({
1969
2045
  "src/internal/providers/registry.ts"() {
@@ -2896,6 +2972,9 @@ function registerBuiltins() {
2896
2972
  registerProvider(CEREBRAS);
2897
2973
  registerCatalogProviders();
2898
2974
  }
2975
+ function _resetBuiltinsRegistered() {
2976
+ _registeredState.done = false;
2977
+ }
2899
2978
  var _registeredState;
2900
2979
  var init_builtin = __esm({
2901
2980
  "src/internal/providers/builtin/index.ts"() {
@@ -3022,6 +3101,9 @@ async function loadOne(dir, entryName) {
3022
3101
  }
3023
3102
  }
3024
3103
  }
3104
+ function _resetDiscovery() {
3105
+ discoveryState.done = false;
3106
+ }
3025
3107
  var discoveryState;
3026
3108
  var init_discovery = __esm({
3027
3109
  "src/internal/providers/discovery.ts"() {
@@ -3033,6 +3115,21 @@ var init_discovery = __esm({
3033
3115
  });
3034
3116
 
3035
3117
  // src/internal/providers/index.ts
3118
+ var providers_exports = {};
3119
+ __export(providers_exports, {
3120
+ ANTHROPIC: () => ANTHROPIC,
3121
+ GEMINI: () => GEMINI,
3122
+ OPENAI: () => OPENAI,
3123
+ OPENROUTER: () => OPENROUTER,
3124
+ _resetBuiltinsRegistered: () => _resetBuiltinsRegistered,
3125
+ _resetDiscovery: () => _resetDiscovery,
3126
+ _resetProvidersForTests: () => _resetProvidersForTests,
3127
+ discoverProviderPlugins: () => discoverProviderPlugins,
3128
+ getProviderProfile: () => getProviderProfile,
3129
+ listProviders: () => listProviders,
3130
+ registerBuiltins: () => registerBuiltins,
3131
+ registerProvider: () => registerProvider
3132
+ });
3036
3133
  var init_providers = __esm({
3037
3134
  "src/internal/providers/index.ts"() {
3038
3135
  init_builtin();
@@ -6095,7 +6192,14 @@ async function compactSessionTranscript(opts) {
6095
6192
  const m = compressible[i];
6096
6193
  if (m === void 0 || m.role !== "user" || isCompactSummary(m.content)) continue;
6097
6194
  const cost = estimateTokens(m.content);
6098
- if (budget + cost > COMPACT_USER_MESSAGE_MAX_TOKENS) break;
6195
+ if (budget + cost > COMPACT_USER_MESSAGE_MAX_TOKENS) {
6196
+ const remaining = COMPACT_USER_MESSAGE_MAX_TOKENS - budget;
6197
+ if (remaining > 50) {
6198
+ preserved.unshift(`${m.content.slice(0, remaining * 4)}
6199
+ [...truncated for compaction...]`);
6200
+ }
6201
+ break;
6202
+ }
6099
6203
  budget += cost;
6100
6204
  preserved.unshift(m.content);
6101
6205
  }
@@ -6111,6 +6215,8 @@ ${summaryBody}`;
6111
6215
  transcript.appendUserTurn(summary);
6112
6216
  const delta = transcript.records().slice(prior.length);
6113
6217
  await opts.store.appendRecords(opts.loc.agentId, delta);
6218
+ const { invalidateSessionCache: invalidateSessionCache2 } = await Promise.resolve().then(() => (init_agent_session(), agent_session_exports));
6219
+ invalidateSessionCache2(opts.loc.cwd, opts.loc.agentId);
6114
6220
  const postTokens = estimateTokens([...preserved, summary].join("\n"));
6115
6221
  return { preTokens, postTokens };
6116
6222
  }
@@ -6122,7 +6228,10 @@ function buildDefaultSummarizer(opts) {
6122
6228
  const { inferProviderFromApiKey: inferProviderFromApiKey2, detectPrimaryProvider: detectPrimaryProvider2 } = await Promise.resolve().then(() => (init_real_local_run_provider(), real_local_run_provider_exports));
6123
6229
  const keyProvider = inferProviderFromApiKey2(opts.apiKey);
6124
6230
  const modelPrefix = opts.agentModel.includes("/") ? opts.agentModel.slice(0, opts.agentModel.indexOf("/")) : void 0;
6125
- const provider = keyProvider ?? detectPrimaryProvider2();
6231
+ const { registerBuiltins: registerBuiltins2, getProviderProfile: getProviderProfile2 } = await Promise.resolve().then(() => (init_providers(), providers_exports));
6232
+ registerBuiltins2();
6233
+ const prefixProfile = modelPrefix !== void 0 ? getProviderProfile2(modelPrefix) : void 0;
6234
+ const provider = prefixProfile !== void 0 ? modelPrefix : keyProvider ?? detectPrimaryProvider2();
6126
6235
  let model;
6127
6236
  if (provider !== modelPrefix) {
6128
6237
  model = opts.agentModel;
@@ -6199,6 +6308,122 @@ var init_compact_session = __esm({
6199
6308
  })();
6200
6309
  }
6201
6310
  });
6311
+
6312
+ // src/internal/session/agent-session.ts
6313
+ var agent_session_exports = {};
6314
+ __export(agent_session_exports, {
6315
+ appendSessionMessage: () => appendSessionMessage,
6316
+ clearAllSessions: () => clearAllSessions,
6317
+ clearSession: () => clearSession,
6318
+ enqueueSessionWrite: () => enqueueSessionWrite,
6319
+ flushSessionWrites: () => flushSessionWrites,
6320
+ getSessionMessages: () => getSessionMessages,
6321
+ hydrateSession: () => hydrateSession,
6322
+ invalidateSessionCache: () => invalidateSessionCache,
6323
+ persistTurnToTranscript: () => persistTurnToTranscript
6324
+ });
6325
+ function transcriptKey(cwd, agentId) {
6326
+ return `${cwd}::${agentId}`;
6327
+ }
6328
+ function appendSessionMessage(agentId, message) {
6329
+ const existing = sessions.get(agentId) ?? [];
6330
+ existing.push(message);
6331
+ sessions.set(agentId, existing);
6332
+ }
6333
+ function getSessionMessages(agentId) {
6334
+ return sessions.get(agentId) ?? [];
6335
+ }
6336
+ function persistTurnToTranscript(store, loc, sessionId, turn, onCompact) {
6337
+ const key2 = transcriptKey(loc.cwd, loc.agentId);
6338
+ const chained = (pendingWrites.get(key2) ?? Promise.resolve()).then(async () => {
6339
+ try {
6340
+ await persistTurn(store, loc, sessionId, turn);
6341
+ const count = (recordCounts.get(key2) ?? 0) + 1;
6342
+ recordCounts.set(key2, count);
6343
+ if (turn.autoCompact !== void 0) {
6344
+ const { autoCompactIfNeeded: autoCompactIfNeeded2 } = await Promise.resolve().then(() => (init_compact_session(), compact_session_exports));
6345
+ const fired = await autoCompactIfNeeded2({
6346
+ store,
6347
+ loc,
6348
+ sessionId,
6349
+ usageTotal: turn.autoCompact.usageTotal,
6350
+ contextWindow: turn.autoCompact.contextWindow,
6351
+ turnCount: count,
6352
+ summarize: turn.autoCompact.summarize
6353
+ });
6354
+ if (fired) onCompact?.();
6355
+ }
6356
+ } catch (cause) {
6357
+ const msg = cause instanceof Error ? cause.message : String(cause);
6358
+ process.stderr.write(
6359
+ `[theokit-sdk] session transcript write failed (${loc.agentId}): ${msg}
6360
+ `
6361
+ );
6362
+ }
6363
+ });
6364
+ pendingWrites.set(
6365
+ key2,
6366
+ chained.then(
6367
+ () => void 0,
6368
+ () => void 0
6369
+ )
6370
+ );
6371
+ }
6372
+ async function hydrateSession(agentId, loc) {
6373
+ const key2 = transcriptKey(loc.cwd, agentId);
6374
+ if (hydratedKeys.has(key2)) return;
6375
+ hydratedKeys.add(key2);
6376
+ const persisted = await readSessionMessages(loc.store, agentId);
6377
+ if (persisted.length === 0) return;
6378
+ if (!sessions.has(agentId) || sessions.get(agentId)?.length === 0) {
6379
+ sessions.set(agentId, persisted);
6380
+ }
6381
+ }
6382
+ async function flushSessionWrites() {
6383
+ while (pendingWrites.size > 0) {
6384
+ const all = Array.from(pendingWrites.values());
6385
+ pendingWrites.clear();
6386
+ await Promise.all(all);
6387
+ }
6388
+ }
6389
+ function clearSession(agentId) {
6390
+ sessions.delete(agentId);
6391
+ }
6392
+ function invalidateSessionCache(cwd, agentId) {
6393
+ sessions.delete(agentId);
6394
+ hydratedKeys.delete(transcriptKey(cwd, agentId));
6395
+ }
6396
+ function enqueueSessionWrite(cwd, agentId, fn) {
6397
+ const key2 = transcriptKey(cwd, agentId);
6398
+ const prior = pendingWrites.get(key2) ?? Promise.resolve();
6399
+ const result = prior.then(fn);
6400
+ pendingWrites.set(
6401
+ key2,
6402
+ result.then(
6403
+ () => void 0,
6404
+ () => void 0
6405
+ )
6406
+ );
6407
+ return result;
6408
+ }
6409
+ function clearAllSessions() {
6410
+ sessions.clear();
6411
+ hydratedKeys.clear();
6412
+ recordCounts.clear();
6413
+ const g = globalThis;
6414
+ const sym = /* @__PURE__ */ Symbol.for("theokit-sdk.session.auto-compact-attempts");
6415
+ g[sym]?.clear();
6416
+ }
6417
+ var sessions, hydratedKeys, pendingWrites, recordCounts;
6418
+ var init_agent_session = __esm({
6419
+ "src/internal/session/agent-session.ts"() {
6420
+ init_agent_session_store();
6421
+ sessions = /* @__PURE__ */ new Map();
6422
+ hydratedKeys = /* @__PURE__ */ new Set();
6423
+ pendingWrites = /* @__PURE__ */ new Map();
6424
+ recordCounts = /* @__PURE__ */ new Map();
6425
+ }
6426
+ });
6202
6427
  async function withToolWhitelist(whitelist, fn) {
6203
6428
  return toolWhitelistStore.run(whitelist, fn);
6204
6429
  }
@@ -13019,147 +13244,6 @@ function parseDecisionFromStdout(stdout) {
13019
13244
  init_run_events();
13020
13245
  init_session_summary_writer();
13021
13246
 
13022
- // src/internal/session/agent-session-store.ts
13023
- init_session_transcript();
13024
- function seedTranscript(prior, opts) {
13025
- return SessionTranscript.fromRecords(prior, opts);
13026
- }
13027
- function mapAgentTurn(steps) {
13028
- const assistant = {};
13029
- const toolResults = [];
13030
- const toolCalls = [];
13031
- for (const step of steps) {
13032
- if (step.type === "thinkingMessage") assistant.thinking = step.message.text;
13033
- else if (step.type === "assistantMessage") assistant.text = step.message.text;
13034
- else if (step.type === "toolCall")
13035
- toolCalls.push({
13036
- id: step.message.callId,
13037
- name: step.message.name,
13038
- input: step.message.args ?? {}
13039
- });
13040
- else
13041
- toolResults.push({
13042
- toolUseId: step.message.callId,
13043
- content: step.message.result,
13044
- isError: step.message.isError
13045
- });
13046
- }
13047
- if (toolCalls.length > 0) assistant.toolCalls = toolCalls;
13048
- return { assistant, toolResults };
13049
- }
13050
- function hasAssistantContent(a) {
13051
- return a.text !== void 0 || a.thinking !== void 0 || (a.toolCalls?.length ?? 0) > 0;
13052
- }
13053
- function appendConversation(transcript, conversation) {
13054
- for (const ct of conversation) {
13055
- if (ct.type !== "agentConversationTurn") continue;
13056
- const { assistant, toolResults } = mapAgentTurn(ct.turn.steps);
13057
- if (hasAssistantContent(assistant)) transcript.appendAssistantTurn(assistant);
13058
- if (toolResults.length > 0) transcript.appendToolResults(toolResults);
13059
- }
13060
- }
13061
- async function readSessionMessages(store, agentId) {
13062
- const records = await store.readRecords(agentId);
13063
- return reconstructMessages(records).map(narrowToSessionMessage);
13064
- }
13065
- function partToText(p) {
13066
- if (p.type === "text") return p.text ?? "";
13067
- if (p.type === "tool_use") return `[tool call] ${p.name ?? ""}`;
13068
- if (p.type === "tool_result") {
13069
- const body = typeof p.content === "string" ? p.content : JSON.stringify(p.content);
13070
- return `[tool result] ${body}`;
13071
- }
13072
- return "";
13073
- }
13074
- function narrowToSessionMessage(m) {
13075
- const role = m.role === "user" ? "user" : "assistant";
13076
- const text = m.content.map(partToText).filter((s) => s.length > 0).join("\n");
13077
- return { role, text };
13078
- }
13079
- function deltaRecords(transcript, priorLength) {
13080
- return transcript.records().slice(priorLength);
13081
- }
13082
- async function persistTurn(store, loc, sessionId, turn) {
13083
- const prior = await store.readRecords(loc.agentId);
13084
- const transcript = seedTranscript(prior, { cwd: loc.cwd, sessionId, model: loc.model });
13085
- transcript.appendUserTurn(turn.userText);
13086
- appendConversation(transcript, turn.conversation);
13087
- await store.appendRecords(loc.agentId, deltaRecords(transcript, prior.length));
13088
- }
13089
-
13090
- // src/internal/session/agent-session.ts
13091
- var sessions = /* @__PURE__ */ new Map();
13092
- var hydratedKeys = /* @__PURE__ */ new Set();
13093
- var pendingWrites = /* @__PURE__ */ new Map();
13094
- var recordCounts = /* @__PURE__ */ new Map();
13095
- function transcriptKey(cwd, agentId) {
13096
- return `${cwd}::${agentId}`;
13097
- }
13098
- function appendSessionMessage(agentId, message) {
13099
- const existing = sessions.get(agentId) ?? [];
13100
- existing.push(message);
13101
- sessions.set(agentId, existing);
13102
- }
13103
- function getSessionMessages(agentId) {
13104
- return sessions.get(agentId) ?? [];
13105
- }
13106
- function persistTurnToTranscript(store, loc, sessionId, turn, onCompact) {
13107
- const key2 = transcriptKey(loc.cwd, loc.agentId);
13108
- const chained = (pendingWrites.get(key2) ?? Promise.resolve()).then(async () => {
13109
- try {
13110
- await persistTurn(store, loc, sessionId, turn);
13111
- const count = (recordCounts.get(key2) ?? 0) + 1;
13112
- recordCounts.set(key2, count);
13113
- if (turn.autoCompact !== void 0) {
13114
- const { autoCompactIfNeeded: autoCompactIfNeeded2 } = await Promise.resolve().then(() => (init_compact_session(), compact_session_exports));
13115
- const fired = await autoCompactIfNeeded2({
13116
- store,
13117
- loc,
13118
- sessionId,
13119
- usageTotal: turn.autoCompact.usageTotal,
13120
- contextWindow: turn.autoCompact.contextWindow,
13121
- turnCount: count,
13122
- summarize: turn.autoCompact.summarize
13123
- });
13124
- if (fired) onCompact?.();
13125
- }
13126
- } catch (cause) {
13127
- const msg = cause instanceof Error ? cause.message : String(cause);
13128
- process.stderr.write(
13129
- `[theokit-sdk] session transcript write failed (${loc.agentId}): ${msg}
13130
- `
13131
- );
13132
- }
13133
- });
13134
- pendingWrites.set(
13135
- key2,
13136
- chained.then(
13137
- () => void 0,
13138
- () => void 0
13139
- )
13140
- );
13141
- }
13142
- async function hydrateSession(agentId, loc) {
13143
- const key2 = transcriptKey(loc.cwd, agentId);
13144
- if (hydratedKeys.has(key2)) return;
13145
- hydratedKeys.add(key2);
13146
- const persisted = await readSessionMessages(loc.store, agentId);
13147
- if (persisted.length === 0) return;
13148
- if (!sessions.has(agentId) || sessions.get(agentId)?.length === 0) {
13149
- sessions.set(agentId, persisted);
13150
- }
13151
- }
13152
- async function flushSessionWrites() {
13153
- while (pendingWrites.size > 0) {
13154
- const all = Array.from(pendingWrites.values());
13155
- pendingWrites.clear();
13156
- await Promise.all(all);
13157
- }
13158
- }
13159
- function clearSession(agentId) {
13160
- sessions.delete(agentId);
13161
- }
13162
-
13163
13247
  // src/internal/runtime/memory/memory-path-selector.ts
13164
13248
  var PORT_MEMORY_PATH_ENV_VAR = "THEOKIT_PORT_MEMORY_PATH";
13165
13249
  function shouldUsePortMemoryPath() {
@@ -13210,6 +13294,20 @@ async function runPostRunLifecycle(inputs) {
13210
13294
  const { getCatalogModelInfo: getCatalogModelInfo2 } = await Promise.resolve().then(() => (init_catalog_loader(), catalog_loader_exports));
13211
13295
  const { buildDefaultSummarizer: buildDefaultSummarizer2 } = await Promise.resolve().then(() => (init_compact_session(), compact_session_exports));
13212
13296
  const contextWindow = getCatalogModelInfo2(model)?.limit?.context;
13297
+ if (contextWindow === void 0) {
13298
+ const g = globalThis;
13299
+ const sym = /* @__PURE__ */ Symbol.for("theokit-sdk.compact.no-cw-warned");
13300
+ const warned3 = g[sym] ??= /* @__PURE__ */ new Set();
13301
+ if (!warned3.has(model)) {
13302
+ warned3.add(model);
13303
+ process.stderr.write(
13304
+ `[theokit-sdk] auto-compaction disabled: model "${model}" has no context-window entry in the catalog
13305
+ `
13306
+ );
13307
+ }
13308
+ }
13309
+ const lastRequestUsage = result.usage?.requests?.at(-1)?.totalTokens;
13310
+ const usageForTrigger = lastRequestUsage ?? result.usage?.totalTokens;
13213
13311
  persistTurnToTranscript(
13214
13312
  sessionStore,
13215
13313
  { cwd: workspaceCwd, agentId, model },
@@ -13218,7 +13316,7 @@ async function runPostRunLifecycle(inputs) {
13218
13316
  userText,
13219
13317
  conversation,
13220
13318
  autoCompact: {
13221
- usageTotal: result.usage?.totalTokens,
13319
+ usageTotal: usageForTrigger,
13222
13320
  contextWindow,
13223
13321
  summarize: buildDefaultSummarizer2({
13224
13322
  agentModel: model,
@@ -21517,7 +21615,8 @@ var Agent = class _Agent {
21517
21615
  const { defaultBaseDir: defaultBaseDir2, expandTilde: expandTilde2 } = await Promise.resolve().then(() => (init_session_transcript(), session_transcript_exports));
21518
21616
  const baseDir = reg.options.local?.baseDir !== void 0 ? expandTilde2(reg.options.local.baseDir) : defaultBaseDir2();
21519
21617
  const store = new FsSessionStore2({ baseDir, cwd });
21520
- return compactSessionTranscript2({
21618
+ const { enqueueSessionWrite: enqueueSessionWrite2 } = await Promise.resolve().then(() => (init_agent_session(), agent_session_exports));
21619
+ return enqueueSessionWrite2(cwd, agentId, () => compactSessionTranscript2({
21521
21620
  store,
21522
21621
  loc: { cwd, agentId, model },
21523
21622
  sessionId: agentId,
@@ -21526,7 +21625,7 @@ var Agent = class _Agent {
21526
21625
  agentModel: model,
21527
21626
  ...reg.options.apiKey !== void 0 ? { apiKey: reg.options.apiKey } : {}
21528
21627
  })
21529
- });
21628
+ }));
21530
21629
  }
21531
21630
  /**
21532
21631
  * Permanently delete a cloud agent.