@theokit/sdk 2.0.1 → 2.1.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.
- package/CHANGELOG.md +18 -0
- package/dist/a2a/index.cjs +232 -171
- package/dist/a2a/index.cjs.map +1 -1
- package/dist/a2a/index.js +232 -171
- package/dist/a2a/index.js.map +1 -1
- package/dist/concurrency.cjs +86 -0
- package/dist/concurrency.cjs.map +1 -0
- package/dist/concurrency.d.cts +13 -0
- package/dist/concurrency.d.ts +13 -0
- package/dist/concurrency.js +83 -0
- package/dist/concurrency.js.map +1 -0
- package/dist/{cron-DFG9-W17.d.cts → cron-CSTqNZp9.d.cts} +1 -1
- package/dist/{cron-Bj8-Aq1O.d.ts → cron-Da6vF_2y.d.ts} +1 -1
- package/dist/cron.cjs +213 -169
- package/dist/cron.cjs.map +1 -1
- package/dist/cron.d.cts +1 -1
- package/dist/cron.d.ts +1 -1
- package/dist/cron.js +213 -169
- package/dist/cron.js.map +1 -1
- package/dist/{errors-DV9e0rcp.d.ts → errors--VP2qrGc.d.ts} +23 -1
- package/dist/{errors-ChqOmFH1.d.cts → errors-C9xkhNEF.d.cts} +23 -1
- package/dist/errors.cjs +17 -11
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +1 -1
- package/dist/errors.d.ts +22 -0
- package/dist/errors.js +17 -12
- package/dist/errors.js.map +1 -1
- package/dist/eval.cjs +213 -169
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +213 -169
- package/dist/eval.js.map +1 -1
- package/dist/index.cjs +231 -171
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +161 -119
- package/dist/index.d.ts +161 -119
- package/dist/index.js +231 -173
- package/dist/index.js.map +1 -1
- package/dist/internal/default-retriable.d.ts +1 -0
- package/dist/internal/persistence/index.cjs +75 -0
- package/dist/internal/persistence/index.cjs.map +1 -1
- package/dist/internal/persistence/index.d.cts +2 -0
- package/dist/internal/persistence/index.d.ts +2 -0
- package/dist/internal/persistence/index.js +74 -1
- package/dist/internal/persistence/index.js.map +1 -1
- package/dist/internal/persistence/sqlite-open.d.cts +47 -0
- package/dist/internal/persistence/sqlite-open.d.ts +47 -0
- package/dist/internal/providers/register-plugin-providers.d.ts +22 -0
- package/dist/internal/runtime/concurrency/map-with-concurrency.d.ts +28 -0
- package/dist/internal/runtime/retry/with-retry.d.ts +40 -0
- package/dist/internal/security/index.cjs +1 -0
- package/dist/internal/security/index.cjs.map +1 -1
- package/dist/internal/security/index.js +1 -0
- package/dist/internal/security/index.js.map +1 -1
- package/dist/path-safety.cjs +15 -0
- package/dist/path-safety.cjs.map +1 -1
- package/dist/path-safety.d.cts +1 -1
- package/dist/path-safety.d.ts +1 -1
- package/dist/path-safety.js +15 -1
- package/dist/path-safety.js.map +1 -1
- package/dist/retry.cjs +85 -0
- package/dist/retry.cjs.map +1 -0
- package/dist/retry.d.cts +9 -0
- package/dist/retry.d.ts +9 -0
- package/dist/retry.js +83 -0
- package/dist/retry.js.map +1 -0
- package/dist/server/errors-envelope.cjs +14 -12
- package/dist/server/errors-envelope.cjs.map +1 -1
- package/dist/server/errors-envelope.js +14 -12
- package/dist/server/errors-envelope.js.map +1 -1
- package/dist/subscription/index.cjs.map +1 -1
- package/dist/subscription/index.js.map +1 -1
- package/dist/task-store.cjs.map +1 -1
- package/dist/task-store.js.map +1 -1
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.js.map +1 -1
- package/package.json +21 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 7d53632: Custom LLM providers via the public Plugin protocol (plan `dev-friendly-custom-provider`).
|
|
8
|
+
|
|
9
|
+
- **Added** `defineProvider(profile, opts?)` — canonical factory (mirrors `defineTool`/`definePlugin`, Inviolable Rule 9) that wraps a data-only `ProviderProfile` into a `kind: "model-provider"` `Plugin`. Register any OpenAI-/Anthropic-compatible endpoint (Groq, Together, Fireworks, DeepInfra, a private gateway) with `Agent.create({ model: { id: "myprov/model" }, plugins: [defineProvider(profile)] })`, routed via the `provider/model` id prefix. Exported from `@theokit/sdk`.
|
|
10
|
+
- **Fixed** half-wired `kind: "model-provider"` plugin path: `PluginManager` aggregated provider profiles but nothing registered them, so `getProviderProfile`/`resolveProviderChain` never saw a plugin-contributed provider — a programmatic `model-provider` plugin was silently dropped. The local-agent run now registers plugin-contributed profiles before provider-chain resolution, so custom providers actually route.
|
|
11
|
+
- **Docs** new "Custom providers (`defineProvider`)" section in `docs.md` (field reference + `apiMode` table) and a worked `examples/custom-provider/`.
|
|
12
|
+
|
|
13
|
+
- 872c89e: M0 Foundation — expose already-existing internal primitives as public surfaces (plan `m0-foundation-expose-primitives`), so agent/code-assistant builders reuse battle-tested plumbing instead of re-implementing it.
|
|
14
|
+
|
|
15
|
+
- `isTransientError(err)` — public retryability predicate delegating to `TheokitAgentError.isRetryable` (T1.1).
|
|
16
|
+
- `safeFilenameForId(id, { maxLen })` — total id→filename helper via `@theokit/sdk/path-safety` (passthrough when safe, deterministic sha256 token otherwise); `sanitizeRunId` migrated to it (T2.1).
|
|
17
|
+
- `@theokit/sdk/concurrency` — public `createSemaphore` + new ordered, fail-fast `mapWithConcurrency`; two internal pooling clones deduplicated onto it (T3.1).
|
|
18
|
+
- `@theokit/sdk/retry` — generic `withRetry(fn, options)` (exponential backoff + full jitter, injectable sleep/rng, default `isRetryable = isTransientError`) (T4.1).
|
|
19
|
+
- `openSqliteResilient` (`@theokit/sdk/internal/persistence`, semver-exempt) — shared driver-load + WAL + corruption-recovery; both memory `index-db` copies deduplicated onto it (T5.1).
|
|
20
|
+
|
|
3
21
|
## 2.0.1
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/dist/a2a/index.cjs
CHANGED
|
@@ -132,6 +132,24 @@ var init_agent_builder = __esm({
|
|
|
132
132
|
}
|
|
133
133
|
});
|
|
134
134
|
|
|
135
|
+
// src/internal/default-retriable.ts
|
|
136
|
+
function defaultRetriableForCode(code) {
|
|
137
|
+
switch (code) {
|
|
138
|
+
case "rate_limit":
|
|
139
|
+
case "timeout":
|
|
140
|
+
case "server_error":
|
|
141
|
+
case "network":
|
|
142
|
+
case "provider_unreachable":
|
|
143
|
+
return true;
|
|
144
|
+
default:
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
var init_default_retriable = __esm({
|
|
149
|
+
"src/internal/default-retriable.ts"() {
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
135
153
|
// src/internal/security/redact.ts
|
|
136
154
|
function readEnvOnce() {
|
|
137
155
|
const raw = process.env.THEOKIT_REDACT_SECRETS;
|
|
@@ -282,7 +300,8 @@ __export(errors_exports, {
|
|
|
282
300
|
UnsupportedBudgetOperationError: () => UnsupportedBudgetOperationError,
|
|
283
301
|
UnsupportedRunOperationError: () => UnsupportedRunOperationError,
|
|
284
302
|
UnsupportedTaskOperationError: () => UnsupportedTaskOperationError,
|
|
285
|
-
coerceToKnownAgentRunErrorCode: () => coerceToKnownAgentRunErrorCode
|
|
303
|
+
coerceToKnownAgentRunErrorCode: () => coerceToKnownAgentRunErrorCode,
|
|
304
|
+
isTransientError: () => isTransientError
|
|
286
305
|
});
|
|
287
306
|
function coerceToKnownAgentRunErrorCode(code) {
|
|
288
307
|
if (code !== void 0 && KNOWN_AGENT_RUN_ERROR_CODES.has(code)) {
|
|
@@ -314,21 +333,13 @@ function safeStringify(value) {
|
|
|
314
333
|
return String(value);
|
|
315
334
|
}
|
|
316
335
|
}
|
|
317
|
-
function
|
|
318
|
-
|
|
319
|
-
case "rate_limit":
|
|
320
|
-
case "timeout":
|
|
321
|
-
case "server_error":
|
|
322
|
-
case "network":
|
|
323
|
-
case "provider_unreachable":
|
|
324
|
-
return true;
|
|
325
|
-
default:
|
|
326
|
-
return false;
|
|
327
|
-
}
|
|
336
|
+
function isTransientError(err) {
|
|
337
|
+
return err instanceof TheokitAgentError && err.isRetryable === true;
|
|
328
338
|
}
|
|
329
339
|
var KNOWN_AGENT_RUN_ERROR_CODES, TheokitAgentError, AuthenticationError, RateLimitError, ConfigurationError, IntegrationNotConnectedError, NetworkError, UnknownAgentError, AgentRunError, UnsupportedRunOperationError, CredentialPoolExhaustedError, MemoryAdapterError, InvalidTaskIdError, TaskNotFoundError, UnsupportedTaskOperationError, BudgetExceededError, AgentDisposedError, UnsupportedBudgetOperationError;
|
|
330
340
|
var init_errors = __esm({
|
|
331
341
|
"src/errors.ts"() {
|
|
342
|
+
init_default_retriable();
|
|
332
343
|
init_redact();
|
|
333
344
|
KNOWN_AGENT_RUN_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
334
345
|
"rate_limit",
|
|
@@ -1027,6 +1038,19 @@ function sanitizeIdentifier(input, options) {
|
|
|
1027
1038
|
}
|
|
1028
1039
|
return input.toLowerCase();
|
|
1029
1040
|
}
|
|
1041
|
+
function safeFilenameForId(id, options) {
|
|
1042
|
+
if (id.length === 0) {
|
|
1043
|
+
throw new ConfigurationError("Filename id must be a non-empty string", {
|
|
1044
|
+
code: "invalid_filename_id"
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
const maxLen = options?.maxLen;
|
|
1048
|
+
const lower = id.toLowerCase();
|
|
1049
|
+
if (lower.length <= maxLen && IDENTIFIER_PATTERN.test(lower)) {
|
|
1050
|
+
return lower;
|
|
1051
|
+
}
|
|
1052
|
+
return `h-${crypto.createHash("sha256").update(id).digest("hex").slice(0, 16)}`;
|
|
1053
|
+
}
|
|
1030
1054
|
var PathTraversalError, IDENTIFIER_PATTERN;
|
|
1031
1055
|
var init_path_guard = __esm({
|
|
1032
1056
|
"src/internal/security/path-guard.ts"() {
|
|
@@ -4243,10 +4267,7 @@ function sessionsDir(cwd) {
|
|
|
4243
4267
|
return path.join(memoryDir(cwd), "sessions");
|
|
4244
4268
|
}
|
|
4245
4269
|
function sessionSummaryPath(cwd, runId) {
|
|
4246
|
-
return path.join(sessionsDir(cwd), `${
|
|
4247
|
-
}
|
|
4248
|
-
function sanitizeRunId(runId) {
|
|
4249
|
-
return runId.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 128);
|
|
4270
|
+
return path.join(sessionsDir(cwd), `${safeFilenameForId(runId, { maxLen: 128 })}.md`);
|
|
4250
4271
|
}
|
|
4251
4272
|
function truncate(text) {
|
|
4252
4273
|
if (text.length <= MAX_TURN_CHARS) return text;
|
|
@@ -4282,6 +4303,7 @@ var MAX_TURN_CHARS;
|
|
|
4282
4303
|
var init_session_summary_writer = __esm({
|
|
4283
4304
|
"src/internal/memory/storage/session-summary-writer.ts"() {
|
|
4284
4305
|
init_atomic_write();
|
|
4306
|
+
init_path_guard();
|
|
4285
4307
|
init_types();
|
|
4286
4308
|
init_markdown_store();
|
|
4287
4309
|
MAX_TURN_CHARS = 2e3;
|
|
@@ -7112,6 +7134,75 @@ var init_async_local_storage = __esm({
|
|
|
7112
7134
|
}
|
|
7113
7135
|
});
|
|
7114
7136
|
|
|
7137
|
+
// src/internal/runtime/concurrency/async-semaphore.ts
|
|
7138
|
+
function createSemaphore(permits) {
|
|
7139
|
+
if (!Number.isInteger(permits) || permits < 1) {
|
|
7140
|
+
throw new ConfigurationError(
|
|
7141
|
+
`async-semaphore: permits must be a positive integer, got ${permits}`,
|
|
7142
|
+
{ code: "invalid_concurrency" }
|
|
7143
|
+
);
|
|
7144
|
+
}
|
|
7145
|
+
let active = 0;
|
|
7146
|
+
const queue = [];
|
|
7147
|
+
function tryGrant() {
|
|
7148
|
+
if (active < permits && queue.length > 0) {
|
|
7149
|
+
const resolve3 = queue.shift();
|
|
7150
|
+
if (resolve3 !== void 0) {
|
|
7151
|
+
active += 1;
|
|
7152
|
+
resolve3();
|
|
7153
|
+
}
|
|
7154
|
+
}
|
|
7155
|
+
}
|
|
7156
|
+
return {
|
|
7157
|
+
inFlight: () => active,
|
|
7158
|
+
pending: () => queue.length + active,
|
|
7159
|
+
async acquire() {
|
|
7160
|
+
await new Promise((resolve3) => {
|
|
7161
|
+
queue.push(resolve3);
|
|
7162
|
+
tryGrant();
|
|
7163
|
+
});
|
|
7164
|
+
let released = false;
|
|
7165
|
+
return () => {
|
|
7166
|
+
if (released) return;
|
|
7167
|
+
released = true;
|
|
7168
|
+
active -= 1;
|
|
7169
|
+
tryGrant();
|
|
7170
|
+
};
|
|
7171
|
+
}
|
|
7172
|
+
};
|
|
7173
|
+
}
|
|
7174
|
+
var init_async_semaphore = __esm({
|
|
7175
|
+
"src/internal/runtime/concurrency/async-semaphore.ts"() {
|
|
7176
|
+
init_errors();
|
|
7177
|
+
}
|
|
7178
|
+
});
|
|
7179
|
+
|
|
7180
|
+
// src/internal/runtime/concurrency/map-with-concurrency.ts
|
|
7181
|
+
async function mapWithConcurrency(items, concurrency, fn, options) {
|
|
7182
|
+
const semaphore = createSemaphore(concurrency);
|
|
7183
|
+
const signal = NEVER_ABORT;
|
|
7184
|
+
return Promise.all(
|
|
7185
|
+
items.map(async (item, index) => {
|
|
7186
|
+
const release = await semaphore.acquire();
|
|
7187
|
+
try {
|
|
7188
|
+
if (signal.aborted) {
|
|
7189
|
+
throw signal.reason instanceof Error ? signal.reason : new Error("mapWithConcurrency: aborted");
|
|
7190
|
+
}
|
|
7191
|
+
return await fn(item, index, signal);
|
|
7192
|
+
} finally {
|
|
7193
|
+
release();
|
|
7194
|
+
}
|
|
7195
|
+
})
|
|
7196
|
+
);
|
|
7197
|
+
}
|
|
7198
|
+
var NEVER_ABORT;
|
|
7199
|
+
var init_map_with_concurrency = __esm({
|
|
7200
|
+
"src/internal/runtime/concurrency/map-with-concurrency.ts"() {
|
|
7201
|
+
init_async_semaphore();
|
|
7202
|
+
NEVER_ABORT = new AbortController().signal;
|
|
7203
|
+
}
|
|
7204
|
+
});
|
|
7205
|
+
|
|
7115
7206
|
// src/internal/tool-dispatch/repair-middleware.ts
|
|
7116
7207
|
function repairToolCall(raw, registry) {
|
|
7117
7208
|
const repairs = [];
|
|
@@ -7301,38 +7392,12 @@ var init_tool_executors = __esm({
|
|
|
7301
7392
|
// src/internal/agent-loop/tool-dispatch.ts
|
|
7302
7393
|
async function dispatchTools(inputs, tools, toolCalls, events) {
|
|
7303
7394
|
const maxConcurrent = inputs.maxConcurrentTools ?? 4;
|
|
7304
|
-
return
|
|
7305
|
-
maxConcurrent,
|
|
7395
|
+
return mapWithConcurrency(
|
|
7306
7396
|
toolCalls,
|
|
7397
|
+
maxConcurrent,
|
|
7307
7398
|
(call) => dispatchSingleCall(inputs, tools, call, events)
|
|
7308
7399
|
);
|
|
7309
7400
|
}
|
|
7310
|
-
async function boundedParallel(max, items, fn) {
|
|
7311
|
-
let running = 0;
|
|
7312
|
-
const queue = [];
|
|
7313
|
-
async function acquire() {
|
|
7314
|
-
if (running < max) {
|
|
7315
|
-
running++;
|
|
7316
|
-
return;
|
|
7317
|
-
}
|
|
7318
|
-
await new Promise((resolve3) => queue.push(resolve3));
|
|
7319
|
-
running++;
|
|
7320
|
-
}
|
|
7321
|
-
function release() {
|
|
7322
|
-
running--;
|
|
7323
|
-
if (queue.length > 0) queue.shift()();
|
|
7324
|
-
}
|
|
7325
|
-
return Promise.all(
|
|
7326
|
-
items.map(async (item) => {
|
|
7327
|
-
await acquire();
|
|
7328
|
-
try {
|
|
7329
|
-
return await fn(item);
|
|
7330
|
-
} finally {
|
|
7331
|
-
release();
|
|
7332
|
-
}
|
|
7333
|
-
})
|
|
7334
|
-
);
|
|
7335
|
-
}
|
|
7336
7401
|
async function dispatchSingleCall(inputs, tools, call, events) {
|
|
7337
7402
|
const { call: workingCall, repairs } = applyRepairAndExtractCall(tools, call);
|
|
7338
7403
|
const callId = generateCallId();
|
|
@@ -7556,6 +7621,7 @@ var init_tool_dispatch = __esm({
|
|
|
7556
7621
|
"src/internal/agent-loop/tool-dispatch.ts"() {
|
|
7557
7622
|
init_ids();
|
|
7558
7623
|
init_async_local_storage();
|
|
7624
|
+
init_map_with_concurrency();
|
|
7559
7625
|
init_repair_middleware();
|
|
7560
7626
|
init_tool_executors();
|
|
7561
7627
|
}
|
|
@@ -10827,6 +10893,21 @@ var init_client = __esm({
|
|
|
10827
10893
|
}
|
|
10828
10894
|
});
|
|
10829
10895
|
|
|
10896
|
+
// src/internal/providers/register-plugin-providers.ts
|
|
10897
|
+
function registerPluginProviderProfiles(entries) {
|
|
10898
|
+
let registered4 = 0;
|
|
10899
|
+
for (const entry of entries) {
|
|
10900
|
+
registerProvider(entry.profile);
|
|
10901
|
+
registered4 += 1;
|
|
10902
|
+
}
|
|
10903
|
+
return registered4;
|
|
10904
|
+
}
|
|
10905
|
+
var init_register_plugin_providers = __esm({
|
|
10906
|
+
"src/internal/providers/register-plugin-providers.ts"() {
|
|
10907
|
+
init_registry();
|
|
10908
|
+
}
|
|
10909
|
+
});
|
|
10910
|
+
|
|
10830
10911
|
// src/internal/tool-registry/personality-filter.ts
|
|
10831
10912
|
function applyPersonalityFilter(exposedTools, whitelist, opts) {
|
|
10832
10913
|
if (whitelist === void 0) return exposedTools;
|
|
@@ -10907,12 +10988,26 @@ function createRealLocalRun(options) {
|
|
|
10907
10988
|
registerRun(handle);
|
|
10908
10989
|
return handle;
|
|
10909
10990
|
}
|
|
10910
|
-
function
|
|
10991
|
+
function resolveRunProvider(options) {
|
|
10911
10992
|
registerBuiltins();
|
|
10993
|
+
const profiles = options.pluginManager?.aggregated.providerProfiles ?? [];
|
|
10994
|
+
const registered4 = registerPluginProviderProfiles(profiles);
|
|
10995
|
+
if (registered4 > 0 && !pluginProvidersAnnounced) {
|
|
10996
|
+
pluginProvidersAnnounced = true;
|
|
10997
|
+
const names = profiles.map((e) => e.profile.name).join(", ");
|
|
10998
|
+
process.stderr.write(
|
|
10999
|
+
`[theokit-sdk] registered ${registered4} plugin provider profile(s): ${names}
|
|
11000
|
+
`
|
|
11001
|
+
);
|
|
11002
|
+
}
|
|
10912
11003
|
const parsedModel = parseModelId(options.model?.id);
|
|
10913
11004
|
const inferredProvider = parsedModel.provider !== void 0 && getProviderProfile(parsedModel.provider) !== void 0 ? parsedModel.provider : void 0;
|
|
10914
11005
|
const primary = options.agentOptions.providers?.routes?.[0]?.provider ?? inferredProvider ?? detectPrimaryProvider();
|
|
10915
11006
|
const effectiveModelId = inferredProvider !== void 0 ? parsedModel.name : options.model?.id ?? "claude-sonnet-4-6";
|
|
11007
|
+
return { primary, effectiveModelId };
|
|
11008
|
+
}
|
|
11009
|
+
function buildLoopInputs(options, runId, userText) {
|
|
11010
|
+
const { primary, effectiveModelId } = resolveRunProvider(options);
|
|
10916
11011
|
const fallback = options.agentOptions.providers?.fallback;
|
|
10917
11012
|
const apiKeys = options.agentOptions.providers?.apiKeys;
|
|
10918
11013
|
const credentialPoolStrategy = options.agentOptions.providers?.credentialPoolStrategy;
|
|
@@ -11006,7 +11101,7 @@ function buildMcpMap(options) {
|
|
|
11006
11101
|
}
|
|
11007
11102
|
return map;
|
|
11008
11103
|
}
|
|
11009
|
-
var RealLocalRun;
|
|
11104
|
+
var pluginProvidersAnnounced, RealLocalRun;
|
|
11010
11105
|
var init_real_local_run = __esm({
|
|
11011
11106
|
"src/internal/runtime/local-agent/real-local-run.ts"() {
|
|
11012
11107
|
init_loop();
|
|
@@ -11015,10 +11110,12 @@ var init_real_local_run = __esm({
|
|
|
11015
11110
|
init_router();
|
|
11016
11111
|
init_client();
|
|
11017
11112
|
init_providers();
|
|
11113
|
+
init_register_plugin_providers();
|
|
11018
11114
|
init_tracer();
|
|
11019
11115
|
init_personality_filter();
|
|
11020
11116
|
init_fixture_run_base();
|
|
11021
11117
|
init_run_registry();
|
|
11118
|
+
pluginProvidersAnnounced = false;
|
|
11022
11119
|
RealLocalRun = class extends FixtureRunBase {
|
|
11023
11120
|
buildInputs;
|
|
11024
11121
|
constructor(options, buildInputs) {
|
|
@@ -11570,7 +11667,7 @@ async function embedTexts(input) {
|
|
|
11570
11667
|
pending
|
|
11571
11668
|
});
|
|
11572
11669
|
}
|
|
11573
|
-
await
|
|
11670
|
+
await embedInBoundedBatches(input, pending, results);
|
|
11574
11671
|
return results.map((v) => v ?? new Array(dimension).fill(0));
|
|
11575
11672
|
}
|
|
11576
11673
|
function classifyEntry(args) {
|
|
@@ -11588,45 +11685,34 @@ function classifyEntry(args) {
|
|
|
11588
11685
|
args.stats.cacheMisses += 1;
|
|
11589
11686
|
args.pending.push({ index: args.index, text: args.text, key });
|
|
11590
11687
|
}
|
|
11591
|
-
async function
|
|
11688
|
+
async function embedInBoundedBatches(input, pending, results) {
|
|
11592
11689
|
const batches = [];
|
|
11593
11690
|
for (let offset = 0; offset < pending.length; offset += MAX_BATCH) {
|
|
11594
11691
|
batches.push(pending.slice(offset, offset + MAX_BATCH));
|
|
11595
11692
|
}
|
|
11596
|
-
|
|
11597
|
-
|
|
11598
|
-
|
|
11599
|
-
|
|
11600
|
-
|
|
11601
|
-
running++;
|
|
11602
|
-
}
|
|
11603
|
-
function release() {
|
|
11604
|
-
running--;
|
|
11605
|
-
if (queue.length > 0) queue.shift()();
|
|
11606
|
-
}
|
|
11693
|
+
await mapWithConcurrency(
|
|
11694
|
+
batches,
|
|
11695
|
+
MAX_CONCURRENT_BATCHES,
|
|
11696
|
+
(batch) => processBatch(input, batch, results)
|
|
11697
|
+
);
|
|
11607
11698
|
}
|
|
11608
|
-
async function processBatch(input, batch, results
|
|
11609
|
-
await
|
|
11610
|
-
|
|
11611
|
-
|
|
11612
|
-
|
|
11613
|
-
|
|
11614
|
-
|
|
11615
|
-
|
|
11616
|
-
|
|
11617
|
-
|
|
11618
|
-
|
|
11619
|
-
|
|
11620
|
-
|
|
11621
|
-
|
|
11622
|
-
|
|
11623
|
-
|
|
11624
|
-
|
|
11625
|
-
results[slot.index] = vector;
|
|
11626
|
-
input.cache.set(slot.key, vector);
|
|
11627
|
-
}
|
|
11628
|
-
} finally {
|
|
11629
|
-
release();
|
|
11699
|
+
async function processBatch(input, batch, results) {
|
|
11700
|
+
const vectors = await embedBatch({
|
|
11701
|
+
apiKey: input.apiKey,
|
|
11702
|
+
baseUrl: input.baseUrl,
|
|
11703
|
+
embeddingsPath: input.embeddingsPath,
|
|
11704
|
+
model: input.model,
|
|
11705
|
+
inputs: batch.map((b) => b.text),
|
|
11706
|
+
fetchImpl: input.fetchImpl,
|
|
11707
|
+
stats: input.stats,
|
|
11708
|
+
providerId: input.providerId
|
|
11709
|
+
});
|
|
11710
|
+
for (let j = 0; j < batch.length; j++) {
|
|
11711
|
+
const slot = batch[j];
|
|
11712
|
+
const vector = vectors[j];
|
|
11713
|
+
if (slot === void 0 || vector === void 0) continue;
|
|
11714
|
+
results[slot.index] = vector;
|
|
11715
|
+
input.cache.set(slot.key, vector);
|
|
11630
11716
|
}
|
|
11631
11717
|
}
|
|
11632
11718
|
async function embedBatch(opts) {
|
|
@@ -11700,6 +11786,7 @@ var init_openai_compatible2 = __esm({
|
|
|
11700
11786
|
"src/internal/memory/adapters/openai-compatible.ts"() {
|
|
11701
11787
|
init_errors();
|
|
11702
11788
|
init_openai_compatible();
|
|
11789
|
+
init_map_with_concurrency();
|
|
11703
11790
|
init_embedding_cache();
|
|
11704
11791
|
MAX_BATCH = 100;
|
|
11705
11792
|
MAX_RETRIES = 2;
|
|
@@ -12184,6 +12271,61 @@ var init_sqlite_wal = __esm({
|
|
|
12184
12271
|
warnedLabels = /* @__PURE__ */ new Set();
|
|
12185
12272
|
}
|
|
12186
12273
|
});
|
|
12274
|
+
async function openSqliteResilient(options) {
|
|
12275
|
+
await promises.mkdir(path.dirname(options.filePath), { recursive: true });
|
|
12276
|
+
try {
|
|
12277
|
+
return await openConcrete(options);
|
|
12278
|
+
} catch (cause) {
|
|
12279
|
+
if (options.recoverCorrupt !== false && isCorruptionError(cause)) {
|
|
12280
|
+
await renameAside(options.filePath, options.label ?? "sqlite");
|
|
12281
|
+
return await openConcrete(options);
|
|
12282
|
+
}
|
|
12283
|
+
throw cause;
|
|
12284
|
+
}
|
|
12285
|
+
}
|
|
12286
|
+
async function openConcrete(options) {
|
|
12287
|
+
const db = await loadDriver(options.filePath);
|
|
12288
|
+
applyWalWithFallback(db, options.label ?? "sqlite");
|
|
12289
|
+
await options.onOpen?.(db);
|
|
12290
|
+
return db;
|
|
12291
|
+
}
|
|
12292
|
+
async function loadDriver(filePath) {
|
|
12293
|
+
try {
|
|
12294
|
+
const mod = await import('better-sqlite3');
|
|
12295
|
+
const Ctor = mod.default ?? mod;
|
|
12296
|
+
if (typeof Ctor !== "function") {
|
|
12297
|
+
throw new Error(`better-sqlite3 export is not a constructor (got ${typeof Ctor})`);
|
|
12298
|
+
}
|
|
12299
|
+
return new Ctor(filePath);
|
|
12300
|
+
} catch (cause) {
|
|
12301
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
12302
|
+
throw new ConfigurationError(
|
|
12303
|
+
`Failed to load SQLite driver. Install \`better-sqlite3\` or run on Node 22.5+ for built-in \`node:sqlite\`. Cause: ${message}`,
|
|
12304
|
+
{ code: "sqlite_driver_unavailable", cause }
|
|
12305
|
+
);
|
|
12306
|
+
}
|
|
12307
|
+
}
|
|
12308
|
+
function isCorruptionError(cause) {
|
|
12309
|
+
if (!(cause instanceof Error)) return false;
|
|
12310
|
+
const msg = cause.message.toLowerCase();
|
|
12311
|
+
return msg.includes("malformed") || msg.includes("not a database") || msg.includes("encrypted") || msg.includes("disk image is malformed");
|
|
12312
|
+
}
|
|
12313
|
+
async function renameAside(filePath, label) {
|
|
12314
|
+
const asidePath = `${filePath}.corrupt-${Date.now()}`;
|
|
12315
|
+
await promises.rename(filePath, asidePath).catch(() => void 0);
|
|
12316
|
+
await promises.rename(`${filePath}-wal`, `${asidePath}-wal`).catch(() => void 0);
|
|
12317
|
+
await promises.rename(`${filePath}-shm`, `${asidePath}-shm`).catch(() => void 0);
|
|
12318
|
+
process.stderr.write(
|
|
12319
|
+
`[theokit-sdk] ${label} database corrupt; renamed aside to ${asidePath} and rebuilt schema
|
|
12320
|
+
`
|
|
12321
|
+
);
|
|
12322
|
+
}
|
|
12323
|
+
var init_sqlite_open = __esm({
|
|
12324
|
+
"src/internal/persistence/sqlite-open.ts"() {
|
|
12325
|
+
init_errors();
|
|
12326
|
+
init_sqlite_wal();
|
|
12327
|
+
}
|
|
12328
|
+
});
|
|
12187
12329
|
|
|
12188
12330
|
// src/internal/memory/index-schema.ts
|
|
12189
12331
|
var SCHEMA_STATEMENTS, PRAGMA_STATEMENTS;
|
|
@@ -12231,60 +12373,22 @@ var init_index_schema = __esm({
|
|
|
12231
12373
|
}
|
|
12232
12374
|
});
|
|
12233
12375
|
async function openMemoryDb(opts) {
|
|
12234
|
-
|
|
12235
|
-
|
|
12236
|
-
|
|
12237
|
-
|
|
12238
|
-
|
|
12239
|
-
|
|
12240
|
-
|
|
12376
|
+
return openSqliteResilient({
|
|
12377
|
+
filePath: opts.filePath,
|
|
12378
|
+
label: "memory-index",
|
|
12379
|
+
recoverCorrupt: opts.recoverCorrupt,
|
|
12380
|
+
onOpen: (db) => {
|
|
12381
|
+
for (const pragma of PRAGMA_STATEMENTS) db.exec(pragma);
|
|
12382
|
+
for (const stmt of SCHEMA_STATEMENTS) db.exec(stmt);
|
|
12241
12383
|
}
|
|
12242
|
-
|
|
12243
|
-
}
|
|
12244
|
-
}
|
|
12245
|
-
async function openConcrete(filePath) {
|
|
12246
|
-
const db = await loadDriver(filePath);
|
|
12247
|
-
applyWalWithFallback(db, "memory-index");
|
|
12248
|
-
for (const pragma of PRAGMA_STATEMENTS) db.exec(pragma);
|
|
12249
|
-
for (const stmt of SCHEMA_STATEMENTS) db.exec(stmt);
|
|
12250
|
-
return db;
|
|
12251
|
-
}
|
|
12252
|
-
async function loadDriver(filePath) {
|
|
12253
|
-
try {
|
|
12254
|
-
const mod = await import('better-sqlite3');
|
|
12255
|
-
const Ctor = mod.default ?? mod;
|
|
12256
|
-
const db = new Ctor(filePath);
|
|
12257
|
-
return db;
|
|
12258
|
-
} catch (cause) {
|
|
12259
|
-
const message = cause instanceof Error ? cause.message : String(cause);
|
|
12260
|
-
throw new ConfigurationError(
|
|
12261
|
-
`Failed to load SQLite driver. Install \`better-sqlite3\` or run on Node 22.5+ for built-in \`node:sqlite\`. Cause: ${message}`,
|
|
12262
|
-
{ code: "sqlite_driver_unavailable", cause }
|
|
12263
|
-
);
|
|
12264
|
-
}
|
|
12265
|
-
}
|
|
12266
|
-
function isCorruptionError(cause) {
|
|
12267
|
-
if (!(cause instanceof Error)) return false;
|
|
12268
|
-
const msg = cause.message.toLowerCase();
|
|
12269
|
-
return msg.includes("malformed") || msg.includes("not a database") || msg.includes("encrypted") || msg.includes("disk image is malformed");
|
|
12270
|
-
}
|
|
12271
|
-
async function renameAside(filePath) {
|
|
12272
|
-
const asidePath = `${filePath}.corrupt-${Date.now()}`;
|
|
12273
|
-
await promises.rename(filePath, asidePath).catch(() => void 0);
|
|
12274
|
-
await promises.rename(`${filePath}-wal`, `${asidePath}-wal`).catch(() => void 0);
|
|
12275
|
-
await promises.rename(`${filePath}-shm`, `${asidePath}-shm`).catch(() => void 0);
|
|
12276
|
-
process.stderr.write(
|
|
12277
|
-
`[theokit-sdk] memory index corrupt; renamed aside to ${asidePath} and rebuilt schema
|
|
12278
|
-
`
|
|
12279
|
-
);
|
|
12384
|
+
});
|
|
12280
12385
|
}
|
|
12281
12386
|
function defaultIndexPath(cwd) {
|
|
12282
12387
|
return path.join(cwd, ".theokit", "memory", ".index", "memory.sqlite");
|
|
12283
12388
|
}
|
|
12284
12389
|
var init_index_db = __esm({
|
|
12285
12390
|
"src/internal/memory/index-db.ts"() {
|
|
12286
|
-
|
|
12287
|
-
init_sqlite_wal();
|
|
12391
|
+
init_sqlite_open();
|
|
12288
12392
|
init_index_schema();
|
|
12289
12393
|
}
|
|
12290
12394
|
});
|
|
@@ -14347,49 +14451,6 @@ var init_task = __esm({
|
|
|
14347
14451
|
}
|
|
14348
14452
|
});
|
|
14349
14453
|
|
|
14350
|
-
// src/internal/runtime/concurrency/async-semaphore.ts
|
|
14351
|
-
function createSemaphore(permits) {
|
|
14352
|
-
if (!Number.isInteger(permits) || permits < 1) {
|
|
14353
|
-
throw new ConfigurationError(
|
|
14354
|
-
`async-semaphore: permits must be a positive integer, got ${permits}`,
|
|
14355
|
-
{ code: "invalid_concurrency" }
|
|
14356
|
-
);
|
|
14357
|
-
}
|
|
14358
|
-
let active = 0;
|
|
14359
|
-
const queue = [];
|
|
14360
|
-
function tryGrant() {
|
|
14361
|
-
if (active < permits && queue.length > 0) {
|
|
14362
|
-
const resolve3 = queue.shift();
|
|
14363
|
-
if (resolve3 !== void 0) {
|
|
14364
|
-
active += 1;
|
|
14365
|
-
resolve3();
|
|
14366
|
-
}
|
|
14367
|
-
}
|
|
14368
|
-
}
|
|
14369
|
-
return {
|
|
14370
|
-
inFlight: () => active,
|
|
14371
|
-
pending: () => queue.length + active,
|
|
14372
|
-
async acquire() {
|
|
14373
|
-
await new Promise((resolve3) => {
|
|
14374
|
-
queue.push(resolve3);
|
|
14375
|
-
tryGrant();
|
|
14376
|
-
});
|
|
14377
|
-
let released = false;
|
|
14378
|
-
return () => {
|
|
14379
|
-
if (released) return;
|
|
14380
|
-
released = true;
|
|
14381
|
-
active -= 1;
|
|
14382
|
-
tryGrant();
|
|
14383
|
-
};
|
|
14384
|
-
}
|
|
14385
|
-
};
|
|
14386
|
-
}
|
|
14387
|
-
var init_async_semaphore = __esm({
|
|
14388
|
-
"src/internal/runtime/concurrency/async-semaphore.ts"() {
|
|
14389
|
-
init_errors();
|
|
14390
|
-
}
|
|
14391
|
-
});
|
|
14392
|
-
|
|
14393
14454
|
// src/internal/task/ring-buffer.ts
|
|
14394
14455
|
var RingBuffer;
|
|
14395
14456
|
var init_ring_buffer = __esm({
|