@theokit/sdk 2.0.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/a2a/index.cjs +261 -174
  3. package/dist/a2a/index.cjs.map +1 -1
  4. package/dist/a2a/index.js +261 -174
  5. package/dist/a2a/index.js.map +1 -1
  6. package/dist/concurrency.cjs +86 -0
  7. package/dist/concurrency.cjs.map +1 -0
  8. package/dist/concurrency.d.cts +13 -0
  9. package/dist/concurrency.d.ts +13 -0
  10. package/dist/concurrency.js +83 -0
  11. package/dist/concurrency.js.map +1 -0
  12. package/dist/{cron-Bj8-Aq1O.d.ts → cron-Aksw2Hy4.d.ts} +10 -2
  13. package/dist/{cron-DFG9-W17.d.cts → cron-JSPSFczQ.d.cts} +10 -2
  14. package/dist/cron.cjs +244 -172
  15. package/dist/cron.cjs.map +1 -1
  16. package/dist/cron.d.cts +2 -2
  17. package/dist/cron.d.ts +2 -2
  18. package/dist/cron.js +244 -172
  19. package/dist/cron.js.map +1 -1
  20. package/dist/{errors-ChqOmFH1.d.cts → errors-Bcw_Pakm.d.ts} +24 -2
  21. package/dist/{errors-DV9e0rcp.d.ts → errors-Vhg6ZV4o.d.cts} +24 -2
  22. package/dist/errors.cjs +17 -11
  23. package/dist/errors.cjs.map +1 -1
  24. package/dist/errors.d.cts +2 -2
  25. package/dist/errors.d.ts +22 -0
  26. package/dist/errors.js +17 -12
  27. package/dist/errors.js.map +1 -1
  28. package/dist/eval.cjs +244 -172
  29. package/dist/eval.cjs.map +1 -1
  30. package/dist/eval.js +244 -172
  31. package/dist/eval.js.map +1 -1
  32. package/dist/index.cjs +262 -174
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +163 -121
  35. package/dist/index.d.ts +163 -121
  36. package/dist/index.js +262 -176
  37. package/dist/index.js.map +1 -1
  38. package/dist/internal/agent-loop/loop-types.d.ts +6 -0
  39. package/dist/internal/default-retriable.d.ts +1 -0
  40. package/dist/internal/persistence/index.cjs +75 -0
  41. package/dist/internal/persistence/index.cjs.map +1 -1
  42. package/dist/internal/persistence/index.d.cts +2 -0
  43. package/dist/internal/persistence/index.d.ts +2 -0
  44. package/dist/internal/persistence/index.js +74 -1
  45. package/dist/internal/persistence/index.js.map +1 -1
  46. package/dist/internal/persistence/sqlite-open.d.cts +47 -0
  47. package/dist/internal/persistence/sqlite-open.d.ts +47 -0
  48. package/dist/internal/providers/register-plugin-providers.d.ts +22 -0
  49. package/dist/internal/runtime/budget/budget-tracker.d.ts +8 -0
  50. package/dist/internal/runtime/concurrency/map-with-concurrency.d.ts +28 -0
  51. package/dist/internal/runtime/retry/with-retry.d.ts +40 -0
  52. package/dist/internal/security/index.cjs +1 -0
  53. package/dist/internal/security/index.cjs.map +1 -1
  54. package/dist/internal/security/index.js +1 -0
  55. package/dist/internal/security/index.js.map +1 -1
  56. package/dist/path-safety.cjs +15 -0
  57. package/dist/path-safety.cjs.map +1 -1
  58. package/dist/path-safety.d.cts +1 -1
  59. package/dist/path-safety.d.ts +1 -1
  60. package/dist/path-safety.js +15 -1
  61. package/dist/path-safety.js.map +1 -1
  62. package/dist/retry.cjs +85 -0
  63. package/dist/retry.cjs.map +1 -0
  64. package/dist/retry.d.cts +9 -0
  65. package/dist/retry.d.ts +9 -0
  66. package/dist/retry.js +83 -0
  67. package/dist/retry.js.map +1 -0
  68. package/dist/{run-DrwUpFxZ.d.cts → run-ekGKZlmg.d.cts} +20 -0
  69. package/dist/{run-DrwUpFxZ.d.ts → run-ekGKZlmg.d.ts} +20 -0
  70. package/dist/server/errors-envelope.cjs +14 -12
  71. package/dist/server/errors-envelope.cjs.map +1 -1
  72. package/dist/server/errors-envelope.js +14 -12
  73. package/dist/server/errors-envelope.js.map +1 -1
  74. package/dist/subscription/index.cjs.map +1 -1
  75. package/dist/subscription/index.js.map +1 -1
  76. package/dist/task-store.cjs.map +1 -1
  77. package/dist/task-store.js.map +1 -1
  78. package/dist/types/run.d.ts +20 -0
  79. package/dist/workflow.cjs.map +1 -1
  80. package/dist/workflow.js.map +1 -1
  81. package/package.json +21 -1
package/dist/a2a/index.js CHANGED
@@ -129,6 +129,24 @@ var init_agent_builder = __esm({
129
129
  }
130
130
  });
131
131
 
132
+ // src/internal/default-retriable.ts
133
+ function defaultRetriableForCode(code) {
134
+ switch (code) {
135
+ case "rate_limit":
136
+ case "timeout":
137
+ case "server_error":
138
+ case "network":
139
+ case "provider_unreachable":
140
+ return true;
141
+ default:
142
+ return false;
143
+ }
144
+ }
145
+ var init_default_retriable = __esm({
146
+ "src/internal/default-retriable.ts"() {
147
+ }
148
+ });
149
+
132
150
  // src/internal/security/redact.ts
133
151
  function readEnvOnce() {
134
152
  const raw = process.env.THEOKIT_REDACT_SECRETS;
@@ -279,7 +297,8 @@ __export(errors_exports, {
279
297
  UnsupportedBudgetOperationError: () => UnsupportedBudgetOperationError,
280
298
  UnsupportedRunOperationError: () => UnsupportedRunOperationError,
281
299
  UnsupportedTaskOperationError: () => UnsupportedTaskOperationError,
282
- coerceToKnownAgentRunErrorCode: () => coerceToKnownAgentRunErrorCode
300
+ coerceToKnownAgentRunErrorCode: () => coerceToKnownAgentRunErrorCode,
301
+ isTransientError: () => isTransientError
283
302
  });
284
303
  function coerceToKnownAgentRunErrorCode(code) {
285
304
  if (code !== void 0 && KNOWN_AGENT_RUN_ERROR_CODES.has(code)) {
@@ -311,21 +330,13 @@ function safeStringify(value) {
311
330
  return String(value);
312
331
  }
313
332
  }
314
- function defaultRetriableForCode(code) {
315
- switch (code) {
316
- case "rate_limit":
317
- case "timeout":
318
- case "server_error":
319
- case "network":
320
- case "provider_unreachable":
321
- return true;
322
- default:
323
- return false;
324
- }
333
+ function isTransientError(err) {
334
+ return err instanceof TheokitAgentError && err.isRetryable === true;
325
335
  }
326
336
  var KNOWN_AGENT_RUN_ERROR_CODES, TheokitAgentError, AuthenticationError, RateLimitError, ConfigurationError, IntegrationNotConnectedError, NetworkError, UnknownAgentError, AgentRunError, UnsupportedRunOperationError, CredentialPoolExhaustedError, MemoryAdapterError, InvalidTaskIdError, TaskNotFoundError, UnsupportedTaskOperationError, BudgetExceededError, AgentDisposedError, UnsupportedBudgetOperationError;
327
337
  var init_errors = __esm({
328
338
  "src/errors.ts"() {
339
+ init_default_retriable();
329
340
  init_redact();
330
341
  KNOWN_AGENT_RUN_ERROR_CODES = /* @__PURE__ */ new Set([
331
342
  "rate_limit",
@@ -1024,6 +1035,19 @@ function sanitizeIdentifier(input, options) {
1024
1035
  }
1025
1036
  return input.toLowerCase();
1026
1037
  }
1038
+ function safeFilenameForId(id, options) {
1039
+ if (id.length === 0) {
1040
+ throw new ConfigurationError("Filename id must be a non-empty string", {
1041
+ code: "invalid_filename_id"
1042
+ });
1043
+ }
1044
+ const maxLen = options?.maxLen;
1045
+ const lower = id.toLowerCase();
1046
+ if (lower.length <= maxLen && IDENTIFIER_PATTERN.test(lower)) {
1047
+ return lower;
1048
+ }
1049
+ return `h-${createHash("sha256").update(id).digest("hex").slice(0, 16)}`;
1050
+ }
1027
1051
  var PathTraversalError, IDENTIFIER_PATTERN;
1028
1052
  var init_path_guard = __esm({
1029
1053
  "src/internal/security/path-guard.ts"() {
@@ -2286,6 +2310,11 @@ function makeNotifier() {
2286
2310
  });
2287
2311
  return { promise, resolve: resolve3 };
2288
2312
  }
2313
+ function applyScriptMetrics(base, script) {
2314
+ if (script.usage !== void 0) base.usage = script.usage;
2315
+ if (script.cost !== void 0) base.cost = script.cost;
2316
+ if (script.stoppedAtIterationLimit === true) base.stoppedAtIterationLimit = true;
2317
+ }
2289
2318
  var FixtureRunBase;
2290
2319
  var init_fixture_run_base = __esm({
2291
2320
  "src/internal/runtime/fixtures/fixture-run-base.ts"() {
@@ -2392,8 +2421,7 @@ var init_fixture_run_base = __esm({
2392
2421
  if (status === "error" && this.script.errorDetail !== void 0) {
2393
2422
  base.error = this.script.errorDetail;
2394
2423
  }
2395
- if (this.script.usage !== void 0) base.usage = this.script.usage;
2396
- if (this.script.cost !== void 0) base.cost = this.script.cost;
2424
+ applyScriptMetrics(base, this.script);
2397
2425
  return this.extendRunResult(applyExtraRunFields(base, this.script));
2398
2426
  }
2399
2427
  /** Subclasses override to attach runtime-specific fields (e.g. cloud git info). */
@@ -4240,10 +4268,7 @@ function sessionsDir(cwd) {
4240
4268
  return join(memoryDir(cwd), "sessions");
4241
4269
  }
4242
4270
  function sessionSummaryPath(cwd, runId) {
4243
- return join(sessionsDir(cwd), `${sanitizeRunId(runId)}.md`);
4244
- }
4245
- function sanitizeRunId(runId) {
4246
- return runId.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 128);
4271
+ return join(sessionsDir(cwd), `${safeFilenameForId(runId, { maxLen: 128 })}.md`);
4247
4272
  }
4248
4273
  function truncate(text) {
4249
4274
  if (text.length <= MAX_TURN_CHARS) return text;
@@ -4279,6 +4304,7 @@ var MAX_TURN_CHARS;
4279
4304
  var init_session_summary_writer = __esm({
4280
4305
  "src/internal/memory/storage/session-summary-writer.ts"() {
4281
4306
  init_atomic_write();
4307
+ init_path_guard();
4282
4308
  init_types();
4283
4309
  init_markdown_store();
4284
4310
  MAX_TURN_CHARS = 2e3;
@@ -7109,6 +7135,75 @@ var init_async_local_storage = __esm({
7109
7135
  }
7110
7136
  });
7111
7137
 
7138
+ // src/internal/runtime/concurrency/async-semaphore.ts
7139
+ function createSemaphore(permits) {
7140
+ if (!Number.isInteger(permits) || permits < 1) {
7141
+ throw new ConfigurationError(
7142
+ `async-semaphore: permits must be a positive integer, got ${permits}`,
7143
+ { code: "invalid_concurrency" }
7144
+ );
7145
+ }
7146
+ let active = 0;
7147
+ const queue = [];
7148
+ function tryGrant() {
7149
+ if (active < permits && queue.length > 0) {
7150
+ const resolve3 = queue.shift();
7151
+ if (resolve3 !== void 0) {
7152
+ active += 1;
7153
+ resolve3();
7154
+ }
7155
+ }
7156
+ }
7157
+ return {
7158
+ inFlight: () => active,
7159
+ pending: () => queue.length + active,
7160
+ async acquire() {
7161
+ await new Promise((resolve3) => {
7162
+ queue.push(resolve3);
7163
+ tryGrant();
7164
+ });
7165
+ let released = false;
7166
+ return () => {
7167
+ if (released) return;
7168
+ released = true;
7169
+ active -= 1;
7170
+ tryGrant();
7171
+ };
7172
+ }
7173
+ };
7174
+ }
7175
+ var init_async_semaphore = __esm({
7176
+ "src/internal/runtime/concurrency/async-semaphore.ts"() {
7177
+ init_errors();
7178
+ }
7179
+ });
7180
+
7181
+ // src/internal/runtime/concurrency/map-with-concurrency.ts
7182
+ async function mapWithConcurrency(items, concurrency, fn, options) {
7183
+ const semaphore = createSemaphore(concurrency);
7184
+ const signal = NEVER_ABORT;
7185
+ return Promise.all(
7186
+ items.map(async (item, index) => {
7187
+ const release = await semaphore.acquire();
7188
+ try {
7189
+ if (signal.aborted) {
7190
+ throw signal.reason instanceof Error ? signal.reason : new Error("mapWithConcurrency: aborted");
7191
+ }
7192
+ return await fn(item, index, signal);
7193
+ } finally {
7194
+ release();
7195
+ }
7196
+ })
7197
+ );
7198
+ }
7199
+ var NEVER_ABORT;
7200
+ var init_map_with_concurrency = __esm({
7201
+ "src/internal/runtime/concurrency/map-with-concurrency.ts"() {
7202
+ init_async_semaphore();
7203
+ NEVER_ABORT = new AbortController().signal;
7204
+ }
7205
+ });
7206
+
7112
7207
  // src/internal/tool-dispatch/repair-middleware.ts
7113
7208
  function repairToolCall(raw, registry) {
7114
7209
  const repairs = [];
@@ -7298,38 +7393,12 @@ var init_tool_executors = __esm({
7298
7393
  // src/internal/agent-loop/tool-dispatch.ts
7299
7394
  async function dispatchTools(inputs, tools, toolCalls, events) {
7300
7395
  const maxConcurrent = inputs.maxConcurrentTools ?? 4;
7301
- return boundedParallel(
7302
- maxConcurrent,
7396
+ return mapWithConcurrency(
7303
7397
  toolCalls,
7398
+ maxConcurrent,
7304
7399
  (call) => dispatchSingleCall(inputs, tools, call, events)
7305
7400
  );
7306
7401
  }
7307
- async function boundedParallel(max, items, fn) {
7308
- let running = 0;
7309
- const queue = [];
7310
- async function acquire() {
7311
- if (running < max) {
7312
- running++;
7313
- return;
7314
- }
7315
- await new Promise((resolve3) => queue.push(resolve3));
7316
- running++;
7317
- }
7318
- function release() {
7319
- running--;
7320
- if (queue.length > 0) queue.shift()();
7321
- }
7322
- return Promise.all(
7323
- items.map(async (item) => {
7324
- await acquire();
7325
- try {
7326
- return await fn(item);
7327
- } finally {
7328
- release();
7329
- }
7330
- })
7331
- );
7332
- }
7333
7402
  async function dispatchSingleCall(inputs, tools, call, events) {
7334
7403
  const { call: workingCall, repairs } = applyRepairAndExtractCall(tools, call);
7335
7404
  const callId = generateCallId();
@@ -7553,6 +7622,7 @@ var init_tool_dispatch = __esm({
7553
7622
  "src/internal/agent-loop/tool-dispatch.ts"() {
7554
7623
  init_ids();
7555
7624
  init_async_local_storage();
7625
+ init_map_with_concurrency();
7556
7626
  init_repair_middleware();
7557
7627
  init_tool_executors();
7558
7628
  }
@@ -7939,6 +8009,7 @@ async function runAgentLoop(inputs) {
7939
8009
  const ctx = await initLoopContext(inputs);
7940
8010
  ctxRef = ctx;
7941
8011
  const budget = inputs.budget ?? new IterationBudget({ maxIterations: inputs.maxIterations ?? 8 });
8012
+ let lastTurnDecision;
7942
8013
  while (budget.shouldContinue()) {
7943
8014
  if (inputs.budgetTracker !== void 0) {
7944
8015
  const decision2 = evaluateBudgetGate(inputs.budgetTracker);
@@ -7947,18 +8018,26 @@ async function runAgentLoop(inputs) {
7947
8018
  if (decision2.detail !== void 0) {
7948
8019
  ctx.error = { message: decision2.detail, code: decision2.reason ?? "budget" };
7949
8020
  }
8021
+ if (decision2.reason === "iteration_limit") {
8022
+ ctx.stoppedAtIterationLimit = true;
8023
+ }
7950
8024
  break;
7951
8025
  }
7952
8026
  }
7953
8027
  const usingGrace = budget.remaining <= 0 && !budget.graceCallUsed;
7954
8028
  if (usingGrace) budget.useGraceCall();
7955
8029
  const decision = await runIteration(inputs, ctx);
8030
+ lastTurnDecision = decision;
7956
8031
  if (decision === "done") break;
7957
8032
  if (decision === "error") {
7958
8033
  ctx.finalStatus = "error";
7959
8034
  break;
7960
8035
  }
7961
8036
  budget.consume();
8037
+ inputs.budgetTracker?.nextIteration?.();
8038
+ }
8039
+ if (lastTurnDecision === "continue" && budget.shouldContinue() === false) {
8040
+ ctx.stoppedAtIterationLimit = true;
7962
8041
  }
7963
8042
  if (budget.shouldContinue() === false && ctx.finalStatus === "finished" && ctx.finalText === "") {
7964
8043
  ctx.finalStatus = "error";
@@ -7989,7 +8068,8 @@ async function runAgentLoop(inputs) {
7989
8068
  conversation: ctx.conversation,
7990
8069
  ...usage !== void 0 ? { usage } : {},
7991
8070
  ...cost !== void 0 ? { cost } : {},
7992
- ...ctx.error !== void 0 ? { error: ctx.error } : {}
8071
+ ...ctx.error !== void 0 ? { error: ctx.error } : {},
8072
+ ...ctx.stoppedAtIterationLimit === true ? { stoppedAtIterationLimit: true } : {}
7993
8073
  };
7994
8074
  } finally {
7995
8075
  if (ctxRef !== void 0 && ctxRef.memoryProviderHandle !== void 0 && inputs.memoryProvider !== void 0) {
@@ -10824,6 +10904,21 @@ var init_client = __esm({
10824
10904
  }
10825
10905
  });
10826
10906
 
10907
+ // src/internal/providers/register-plugin-providers.ts
10908
+ function registerPluginProviderProfiles(entries) {
10909
+ let registered4 = 0;
10910
+ for (const entry of entries) {
10911
+ registerProvider(entry.profile);
10912
+ registered4 += 1;
10913
+ }
10914
+ return registered4;
10915
+ }
10916
+ var init_register_plugin_providers = __esm({
10917
+ "src/internal/providers/register-plugin-providers.ts"() {
10918
+ init_registry();
10919
+ }
10920
+ });
10921
+
10827
10922
  // src/internal/tool-registry/personality-filter.ts
10828
10923
  function applyPersonalityFilter(exposedTools, whitelist, opts) {
10829
10924
  if (whitelist === void 0) return exposedTools;
@@ -10904,12 +10999,33 @@ function createRealLocalRun(options) {
10904
10999
  registerRun(handle);
10905
11000
  return handle;
10906
11001
  }
10907
- function buildLoopInputs(options, runId, userText) {
11002
+ function resolveRunProvider(options) {
10908
11003
  registerBuiltins();
11004
+ const profiles = options.pluginManager?.aggregated.providerProfiles ?? [];
11005
+ const registered4 = registerPluginProviderProfiles(profiles);
11006
+ if (registered4 > 0 && !pluginProvidersAnnounced) {
11007
+ pluginProvidersAnnounced = true;
11008
+ const names = profiles.map((e) => e.profile.name).join(", ");
11009
+ process.stderr.write(
11010
+ `[theokit-sdk] registered ${registered4} plugin provider profile(s): ${names}
11011
+ `
11012
+ );
11013
+ }
10909
11014
  const parsedModel = parseModelId(options.model?.id);
10910
11015
  const inferredProvider = parsedModel.provider !== void 0 && getProviderProfile(parsedModel.provider) !== void 0 ? parsedModel.provider : void 0;
10911
11016
  const primary = options.agentOptions.providers?.routes?.[0]?.provider ?? inferredProvider ?? detectPrimaryProvider();
10912
11017
  const effectiveModelId = inferredProvider !== void 0 ? parsedModel.name : options.model?.id ?? "claude-sonnet-4-6";
11018
+ return { primary, effectiveModelId };
11019
+ }
11020
+ function buildLoopInputs(options, runId, userText) {
11021
+ const maxIterations = options.sendOptions.maxIterations;
11022
+ if (maxIterations !== void 0 && (!Number.isInteger(maxIterations) || maxIterations < 1)) {
11023
+ throw new ConfigurationError(
11024
+ `SendOptions.maxIterations must be a positive integer, got ${maxIterations}`,
11025
+ { code: "invalid_max_iterations" }
11026
+ );
11027
+ }
11028
+ const { primary, effectiveModelId } = resolveRunProvider(options);
10913
11029
  const fallback = options.agentOptions.providers?.fallback;
10914
11030
  const apiKeys = options.agentOptions.providers?.apiKeys;
10915
11031
  const credentialPoolStrategy = options.agentOptions.providers?.credentialPoolStrategy;
@@ -10947,6 +11063,9 @@ function buildLoopInputs(options, runId, userText) {
10947
11063
  // D318 — forward SendOptions.signal to the agent loop so streamLlmTurn
10948
11064
  // can attach it to the LLM `fetch({ signal })` call.
10949
11065
  ...options.sendOptions.signal !== void 0 ? { signal: options.sendOptions.signal } : {},
11066
+ // M1-2: per-send iteration ceiling (validated above). The loop reads
11067
+ // inputs.maxIterations (default 8 when unset).
11068
+ ...maxIterations !== void 0 ? { maxIterations } : {},
10950
11069
  // D315-D317 — tool lifecycle hooks (cost tracking + audit + retry/alert)
10951
11070
  ...options.agentOptions.onToolStart !== void 0 ? { onToolStart: options.agentOptions.onToolStart } : {},
10952
11071
  ...options.agentOptions.onToolEnd !== void 0 ? { onToolEnd: options.agentOptions.onToolEnd } : {},
@@ -11003,19 +11122,22 @@ function buildMcpMap(options) {
11003
11122
  }
11004
11123
  return map;
11005
11124
  }
11006
- var RealLocalRun;
11125
+ var pluginProvidersAnnounced, RealLocalRun;
11007
11126
  var init_real_local_run = __esm({
11008
11127
  "src/internal/runtime/local-agent/real-local-run.ts"() {
11128
+ init_errors();
11009
11129
  init_loop();
11010
11130
  init_fallback_client();
11011
11131
  init_model_identifier();
11012
11132
  init_router();
11013
11133
  init_client();
11014
11134
  init_providers();
11135
+ init_register_plugin_providers();
11015
11136
  init_tracer();
11016
11137
  init_personality_filter();
11017
11138
  init_fixture_run_base();
11018
11139
  init_run_registry();
11140
+ pluginProvidersAnnounced = false;
11019
11141
  RealLocalRun = class extends FixtureRunBase {
11020
11142
  buildInputs;
11021
11143
  constructor(options, buildInputs) {
@@ -11091,6 +11213,7 @@ var init_real_local_run = __esm({
11091
11213
  if (output.result.length > 0) this.script.result = output.result;
11092
11214
  if (output.usage !== void 0) this.script.usage = output.usage;
11093
11215
  if (output.cost !== void 0) this.script.cost = output.cost;
11216
+ if (output.stoppedAtIterationLimit === true) this.script.stoppedAtIterationLimit = true;
11094
11217
  if (output.error !== void 0 && this.script.errorDetail === void 0) {
11095
11218
  this.script.errorDetail = {
11096
11219
  message: output.error.message,
@@ -11567,7 +11690,7 @@ async function embedTexts(input) {
11567
11690
  pending
11568
11691
  });
11569
11692
  }
11570
- await runBatches(input, pending, results);
11693
+ await embedInBoundedBatches(input, pending, results);
11571
11694
  return results.map((v) => v ?? new Array(dimension).fill(0));
11572
11695
  }
11573
11696
  function classifyEntry(args) {
@@ -11585,45 +11708,34 @@ function classifyEntry(args) {
11585
11708
  args.stats.cacheMisses += 1;
11586
11709
  args.pending.push({ index: args.index, text: args.text, key });
11587
11710
  }
11588
- async function runBatches(input, pending, results) {
11711
+ async function embedInBoundedBatches(input, pending, results) {
11589
11712
  const batches = [];
11590
11713
  for (let offset = 0; offset < pending.length; offset += MAX_BATCH) {
11591
11714
  batches.push(pending.slice(offset, offset + MAX_BATCH));
11592
11715
  }
11593
- let running = 0;
11594
- const queue = [];
11595
- await Promise.all(batches.map((batch) => processBatch(input, batch, results, acquire, release)));
11596
- async function acquire() {
11597
- if (running >= MAX_CONCURRENT_BATCHES) await new Promise((r) => queue.push(r));
11598
- running++;
11599
- }
11600
- function release() {
11601
- running--;
11602
- if (queue.length > 0) queue.shift()();
11603
- }
11716
+ await mapWithConcurrency(
11717
+ batches,
11718
+ MAX_CONCURRENT_BATCHES,
11719
+ (batch) => processBatch(input, batch, results)
11720
+ );
11604
11721
  }
11605
- async function processBatch(input, batch, results, acquire, release) {
11606
- await acquire();
11607
- try {
11608
- const vectors = await embedBatch({
11609
- apiKey: input.apiKey,
11610
- baseUrl: input.baseUrl,
11611
- embeddingsPath: input.embeddingsPath,
11612
- model: input.model,
11613
- inputs: batch.map((b) => b.text),
11614
- fetchImpl: input.fetchImpl,
11615
- stats: input.stats,
11616
- providerId: input.providerId
11617
- });
11618
- for (let j = 0; j < batch.length; j++) {
11619
- const slot = batch[j];
11620
- const vector = vectors[j];
11621
- if (slot === void 0 || vector === void 0) continue;
11622
- results[slot.index] = vector;
11623
- input.cache.set(slot.key, vector);
11624
- }
11625
- } finally {
11626
- release();
11722
+ async function processBatch(input, batch, results) {
11723
+ const vectors = await embedBatch({
11724
+ apiKey: input.apiKey,
11725
+ baseUrl: input.baseUrl,
11726
+ embeddingsPath: input.embeddingsPath,
11727
+ model: input.model,
11728
+ inputs: batch.map((b) => b.text),
11729
+ fetchImpl: input.fetchImpl,
11730
+ stats: input.stats,
11731
+ providerId: input.providerId
11732
+ });
11733
+ for (let j = 0; j < batch.length; j++) {
11734
+ const slot = batch[j];
11735
+ const vector = vectors[j];
11736
+ if (slot === void 0 || vector === void 0) continue;
11737
+ results[slot.index] = vector;
11738
+ input.cache.set(slot.key, vector);
11627
11739
  }
11628
11740
  }
11629
11741
  async function embedBatch(opts) {
@@ -11697,6 +11809,7 @@ var init_openai_compatible2 = __esm({
11697
11809
  "src/internal/memory/adapters/openai-compatible.ts"() {
11698
11810
  init_errors();
11699
11811
  init_openai_compatible();
11812
+ init_map_with_concurrency();
11700
11813
  init_embedding_cache();
11701
11814
  MAX_BATCH = 100;
11702
11815
  MAX_RETRIES = 2;
@@ -12181,6 +12294,61 @@ var init_sqlite_wal = __esm({
12181
12294
  warnedLabels = /* @__PURE__ */ new Set();
12182
12295
  }
12183
12296
  });
12297
+ async function openSqliteResilient(options) {
12298
+ await mkdir(dirname(options.filePath), { recursive: true });
12299
+ try {
12300
+ return await openConcrete(options);
12301
+ } catch (cause) {
12302
+ if (options.recoverCorrupt !== false && isCorruptionError(cause)) {
12303
+ await renameAside(options.filePath, options.label ?? "sqlite");
12304
+ return await openConcrete(options);
12305
+ }
12306
+ throw cause;
12307
+ }
12308
+ }
12309
+ async function openConcrete(options) {
12310
+ const db = await loadDriver(options.filePath);
12311
+ applyWalWithFallback(db, options.label ?? "sqlite");
12312
+ await options.onOpen?.(db);
12313
+ return db;
12314
+ }
12315
+ async function loadDriver(filePath) {
12316
+ try {
12317
+ const mod = await import('better-sqlite3');
12318
+ const Ctor = mod.default ?? mod;
12319
+ if (typeof Ctor !== "function") {
12320
+ throw new Error(`better-sqlite3 export is not a constructor (got ${typeof Ctor})`);
12321
+ }
12322
+ return new Ctor(filePath);
12323
+ } catch (cause) {
12324
+ const message = cause instanceof Error ? cause.message : String(cause);
12325
+ throw new ConfigurationError(
12326
+ `Failed to load SQLite driver. Install \`better-sqlite3\` or run on Node 22.5+ for built-in \`node:sqlite\`. Cause: ${message}`,
12327
+ { code: "sqlite_driver_unavailable", cause }
12328
+ );
12329
+ }
12330
+ }
12331
+ function isCorruptionError(cause) {
12332
+ if (!(cause instanceof Error)) return false;
12333
+ const msg = cause.message.toLowerCase();
12334
+ return msg.includes("malformed") || msg.includes("not a database") || msg.includes("encrypted") || msg.includes("disk image is malformed");
12335
+ }
12336
+ async function renameAside(filePath, label) {
12337
+ const asidePath = `${filePath}.corrupt-${Date.now()}`;
12338
+ await rename(filePath, asidePath).catch(() => void 0);
12339
+ await rename(`${filePath}-wal`, `${asidePath}-wal`).catch(() => void 0);
12340
+ await rename(`${filePath}-shm`, `${asidePath}-shm`).catch(() => void 0);
12341
+ process.stderr.write(
12342
+ `[theokit-sdk] ${label} database corrupt; renamed aside to ${asidePath} and rebuilt schema
12343
+ `
12344
+ );
12345
+ }
12346
+ var init_sqlite_open = __esm({
12347
+ "src/internal/persistence/sqlite-open.ts"() {
12348
+ init_errors();
12349
+ init_sqlite_wal();
12350
+ }
12351
+ });
12184
12352
 
12185
12353
  // src/internal/memory/index-schema.ts
12186
12354
  var SCHEMA_STATEMENTS, PRAGMA_STATEMENTS;
@@ -12228,60 +12396,22 @@ var init_index_schema = __esm({
12228
12396
  }
12229
12397
  });
12230
12398
  async function openMemoryDb(opts) {
12231
- await mkdir(dirname(opts.filePath), { recursive: true });
12232
- try {
12233
- return await openConcrete(opts.filePath);
12234
- } catch (cause) {
12235
- if (opts.recoverCorrupt !== false && isCorruptionError(cause)) {
12236
- await renameAside(opts.filePath);
12237
- return await openConcrete(opts.filePath);
12399
+ return openSqliteResilient({
12400
+ filePath: opts.filePath,
12401
+ label: "memory-index",
12402
+ recoverCorrupt: opts.recoverCorrupt,
12403
+ onOpen: (db) => {
12404
+ for (const pragma of PRAGMA_STATEMENTS) db.exec(pragma);
12405
+ for (const stmt of SCHEMA_STATEMENTS) db.exec(stmt);
12238
12406
  }
12239
- throw cause;
12240
- }
12241
- }
12242
- async function openConcrete(filePath) {
12243
- const db = await loadDriver(filePath);
12244
- applyWalWithFallback(db, "memory-index");
12245
- for (const pragma of PRAGMA_STATEMENTS) db.exec(pragma);
12246
- for (const stmt of SCHEMA_STATEMENTS) db.exec(stmt);
12247
- return db;
12248
- }
12249
- async function loadDriver(filePath) {
12250
- try {
12251
- const mod = await import('better-sqlite3');
12252
- const Ctor = mod.default ?? mod;
12253
- const db = new Ctor(filePath);
12254
- return db;
12255
- } catch (cause) {
12256
- const message = cause instanceof Error ? cause.message : String(cause);
12257
- throw new ConfigurationError(
12258
- `Failed to load SQLite driver. Install \`better-sqlite3\` or run on Node 22.5+ for built-in \`node:sqlite\`. Cause: ${message}`,
12259
- { code: "sqlite_driver_unavailable", cause }
12260
- );
12261
- }
12262
- }
12263
- function isCorruptionError(cause) {
12264
- if (!(cause instanceof Error)) return false;
12265
- const msg = cause.message.toLowerCase();
12266
- return msg.includes("malformed") || msg.includes("not a database") || msg.includes("encrypted") || msg.includes("disk image is malformed");
12267
- }
12268
- async function renameAside(filePath) {
12269
- const asidePath = `${filePath}.corrupt-${Date.now()}`;
12270
- await rename(filePath, asidePath).catch(() => void 0);
12271
- await rename(`${filePath}-wal`, `${asidePath}-wal`).catch(() => void 0);
12272
- await rename(`${filePath}-shm`, `${asidePath}-shm`).catch(() => void 0);
12273
- process.stderr.write(
12274
- `[theokit-sdk] memory index corrupt; renamed aside to ${asidePath} and rebuilt schema
12275
- `
12276
- );
12407
+ });
12277
12408
  }
12278
12409
  function defaultIndexPath(cwd) {
12279
12410
  return join(cwd, ".theokit", "memory", ".index", "memory.sqlite");
12280
12411
  }
12281
12412
  var init_index_db = __esm({
12282
12413
  "src/internal/memory/index-db.ts"() {
12283
- init_errors();
12284
- init_sqlite_wal();
12414
+ init_sqlite_open();
12285
12415
  init_index_schema();
12286
12416
  }
12287
12417
  });
@@ -14344,49 +14474,6 @@ var init_task = __esm({
14344
14474
  }
14345
14475
  });
14346
14476
 
14347
- // src/internal/runtime/concurrency/async-semaphore.ts
14348
- function createSemaphore(permits) {
14349
- if (!Number.isInteger(permits) || permits < 1) {
14350
- throw new ConfigurationError(
14351
- `async-semaphore: permits must be a positive integer, got ${permits}`,
14352
- { code: "invalid_concurrency" }
14353
- );
14354
- }
14355
- let active = 0;
14356
- const queue = [];
14357
- function tryGrant() {
14358
- if (active < permits && queue.length > 0) {
14359
- const resolve3 = queue.shift();
14360
- if (resolve3 !== void 0) {
14361
- active += 1;
14362
- resolve3();
14363
- }
14364
- }
14365
- }
14366
- return {
14367
- inFlight: () => active,
14368
- pending: () => queue.length + active,
14369
- async acquire() {
14370
- await new Promise((resolve3) => {
14371
- queue.push(resolve3);
14372
- tryGrant();
14373
- });
14374
- let released = false;
14375
- return () => {
14376
- if (released) return;
14377
- released = true;
14378
- active -= 1;
14379
- tryGrant();
14380
- };
14381
- }
14382
- };
14383
- }
14384
- var init_async_semaphore = __esm({
14385
- "src/internal/runtime/concurrency/async-semaphore.ts"() {
14386
- init_errors();
14387
- }
14388
- });
14389
-
14390
14477
  // src/internal/task/ring-buffer.ts
14391
14478
  var RingBuffer;
14392
14479
  var init_ring_buffer = __esm({