@theokit/sdk 2.13.1 → 2.15.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 +12 -0
- package/dist/a2a/index.cjs +242 -3
- package/dist/a2a/index.cjs.map +1 -1
- package/dist/a2a/index.js +242 -3
- package/dist/a2a/index.js.map +1 -1
- package/dist/{cron-CpxLdAXc.d.cts → cron-BxLSz1UH.d.cts} +1 -1
- package/dist/{cron-CL_9nfhQ.d.ts → cron-DcaoP7aW.d.ts} +1 -1
- package/dist/cron.cjs +225 -3
- package/dist/cron.cjs.map +1 -1
- package/dist/cron.d.cts +2 -2
- package/dist/cron.d.ts +2 -2
- package/dist/cron.js +225 -3
- package/dist/cron.js.map +1 -1
- package/dist/define-tool.d.ts +8 -0
- package/dist/{errors-9yw4UQwX.d.cts → errors-Bart0ptP.d.cts} +1 -1
- package/dist/{errors-DFiY-NHK.d.ts → errors-DJuuubJK.d.ts} +1 -1
- package/dist/errors.d.cts +2 -2
- package/dist/eval.cjs +228 -6
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +228 -6
- package/dist/eval.js.map +1 -1
- package/dist/index.cjs +230 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -6
- package/dist/index.d.ts +41 -6
- package/dist/index.js +230 -4
- package/dist/index.js.map +1 -1
- package/dist/internal/agent-loop/doom-loop-tracker.d.ts +22 -0
- package/dist/internal/agent-loop/loop-types.d.ts +6 -0
- package/dist/internal/llm/hermes-tool-extract.d.ts +1 -0
- package/dist/{run-TMdc7gmo.d.cts → run-DXy_MVwz.d.cts} +29 -1
- package/dist/{run-TMdc7gmo.d.ts → run-DXy_MVwz.d.ts} +29 -1
- package/dist/sanitize/coerce.d.cts +1 -0
- package/dist/sanitize/coerce.d.ts +1 -0
- package/dist/sanitize/index.cjs +119 -0
- package/dist/sanitize/index.cjs.map +1 -0
- package/dist/sanitize/index.d.cts +9 -0
- package/dist/sanitize/index.d.ts +9 -0
- package/dist/sanitize/index.js +116 -0
- package/dist/sanitize/index.js.map +1 -0
- package/dist/sanitize/sanitize-tool-input.d.cts +11 -0
- package/dist/sanitize/sanitize-tool-input.d.ts +11 -0
- package/dist/sanitize/types.d.cts +39 -0
- package/dist/sanitize/types.d.ts +39 -0
- package/dist/types/run.d.ts +28 -0
- package/package.json +13 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as CustomTool, M as ModelSelection,
|
|
1
|
+
import { C as CustomTool, M as ModelSelection, G as SDKUserMessage, J as SendOptions, b as Run, r as RunToCompletionOptions, s as RunToCompletionResult, S as SDKMessage, U as StreamToCompletionResult, a as McpServerConfig } from './run-DXy_MVwz.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Fork primitive public type contracts (T1.2, ADRs D110-D114).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as CustomTool, M as ModelSelection,
|
|
1
|
+
import { C as CustomTool, M as ModelSelection, G as SDKUserMessage, J as SendOptions, b as Run, r as RunToCompletionOptions, s as RunToCompletionResult, S as SDKMessage, U as StreamToCompletionResult, a as McpServerConfig } from './run-DXy_MVwz.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Fork primitive public type contracts (T1.2, ADRs D110-D114).
|
package/dist/cron.cjs
CHANGED
|
@@ -1458,6 +1458,7 @@ function isEmptyRound(result) {
|
|
|
1458
1458
|
return (result.result ?? "").trim() === "";
|
|
1459
1459
|
}
|
|
1460
1460
|
function classifyRound(result, round, maxRounds, emptyStreak) {
|
|
1461
|
+
if (result.stoppedByDoomLoop === true) return "no_progress";
|
|
1461
1462
|
if (result.stoppedAtIterationLimit !== true) return "done";
|
|
1462
1463
|
if (isEmptyRound(result) && emptyStreak >= 1) return "no_progress";
|
|
1463
1464
|
if (round >= maxRounds) return "step_limit";
|
|
@@ -4495,6 +4496,7 @@ function applyScriptMetrics(base, script) {
|
|
|
4495
4496
|
if (script.usage !== void 0) base.usage = script.usage;
|
|
4496
4497
|
if (script.cost !== void 0) base.cost = script.cost;
|
|
4497
4498
|
if (script.stoppedAtIterationLimit === true) base.stoppedAtIterationLimit = true;
|
|
4499
|
+
if (script.stoppedByDoomLoop === true) base.stoppedByDoomLoop = true;
|
|
4498
4500
|
}
|
|
4499
4501
|
|
|
4500
4502
|
// src/internal/runtime/cloud/cloud-run.ts
|
|
@@ -8276,6 +8278,93 @@ function evaluateBudgetGate(tracker) {
|
|
|
8276
8278
|
}
|
|
8277
8279
|
}
|
|
8278
8280
|
|
|
8281
|
+
// src/internal/agent-loop/doom-loop-tracker.ts
|
|
8282
|
+
init_errors();
|
|
8283
|
+
function createDoomLoopTracker(option) {
|
|
8284
|
+
if (option === false) return void 0;
|
|
8285
|
+
return new DoomLoopTracker(option);
|
|
8286
|
+
}
|
|
8287
|
+
var DEFAULT_CONFIG = { softThreshold: 3, hardThreshold: 5 };
|
|
8288
|
+
function assertValidThresholds(soft, hard) {
|
|
8289
|
+
for (const [label, value] of [
|
|
8290
|
+
["softThreshold", soft],
|
|
8291
|
+
["hardThreshold", hard]
|
|
8292
|
+
]) {
|
|
8293
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
8294
|
+
throw new ConfigurationError(
|
|
8295
|
+
`doomLoop.${label} must be a positive integer (received ${value}).`,
|
|
8296
|
+
{ code: "invalid_doom_loop_threshold" }
|
|
8297
|
+
);
|
|
8298
|
+
}
|
|
8299
|
+
}
|
|
8300
|
+
}
|
|
8301
|
+
function sortKeys(value) {
|
|
8302
|
+
if (value === null || typeof value !== "object") return value;
|
|
8303
|
+
if (Array.isArray(value)) return value.map(sortKeys);
|
|
8304
|
+
const out = {};
|
|
8305
|
+
for (const key of Object.keys(value).sort()) {
|
|
8306
|
+
out[key] = sortKeys(value[key]);
|
|
8307
|
+
}
|
|
8308
|
+
return out;
|
|
8309
|
+
}
|
|
8310
|
+
function signatureOf(call) {
|
|
8311
|
+
const { input } = call;
|
|
8312
|
+
let inputSig;
|
|
8313
|
+
if (input === null || input === void 0) inputSig = "null";
|
|
8314
|
+
else if (typeof input !== "object") inputSig = String(input);
|
|
8315
|
+
else {
|
|
8316
|
+
try {
|
|
8317
|
+
inputSig = JSON.stringify(sortKeys(input)) ?? "null";
|
|
8318
|
+
} catch {
|
|
8319
|
+
inputSig = String(input);
|
|
8320
|
+
}
|
|
8321
|
+
}
|
|
8322
|
+
return `${call.name}\0${inputSig}`;
|
|
8323
|
+
}
|
|
8324
|
+
var DoomLoopTracker = class {
|
|
8325
|
+
#config;
|
|
8326
|
+
#lastSignature = "";
|
|
8327
|
+
#count = 0;
|
|
8328
|
+
constructor(config) {
|
|
8329
|
+
const softThreshold = config?.softThreshold ?? DEFAULT_CONFIG.softThreshold;
|
|
8330
|
+
const hardThreshold = config?.hardThreshold ?? DEFAULT_CONFIG.hardThreshold;
|
|
8331
|
+
assertValidThresholds(softThreshold, hardThreshold);
|
|
8332
|
+
this.#config = { softThreshold, hardThreshold };
|
|
8333
|
+
}
|
|
8334
|
+
inspect(call) {
|
|
8335
|
+
const signature = signatureOf(call);
|
|
8336
|
+
this.#count = signature === this.#lastSignature ? this.#count + 1 : 1;
|
|
8337
|
+
this.#lastSignature = signature;
|
|
8338
|
+
const count = this.#count;
|
|
8339
|
+
if (count >= this.#config.hardThreshold) {
|
|
8340
|
+
return {
|
|
8341
|
+
kind: "hard",
|
|
8342
|
+
message: `Detected ${count} consecutive identical calls to \`${call.name}\`; stopping to avoid a loop.`
|
|
8343
|
+
};
|
|
8344
|
+
}
|
|
8345
|
+
if (count === this.#config.softThreshold) {
|
|
8346
|
+
return {
|
|
8347
|
+
kind: "soft",
|
|
8348
|
+
message: `Detected ${count} consecutive identical calls to \`${call.name}\`; try a different approach.`
|
|
8349
|
+
};
|
|
8350
|
+
}
|
|
8351
|
+
return { kind: "ok" };
|
|
8352
|
+
}
|
|
8353
|
+
reset() {
|
|
8354
|
+
this.#lastSignature = "";
|
|
8355
|
+
this.#count = 0;
|
|
8356
|
+
}
|
|
8357
|
+
};
|
|
8358
|
+
function firstDoomLoopVerdict(tracker, calls) {
|
|
8359
|
+
let escalation = { kind: "ok" };
|
|
8360
|
+
for (const call of calls) {
|
|
8361
|
+
const v = tracker.inspect(call);
|
|
8362
|
+
if (v.kind === "hard") return v;
|
|
8363
|
+
if (v.kind === "soft" && escalation.kind === "ok") escalation = v;
|
|
8364
|
+
}
|
|
8365
|
+
return escalation;
|
|
8366
|
+
}
|
|
8367
|
+
|
|
8279
8368
|
// src/internal/budget/usage-accumulator.ts
|
|
8280
8369
|
var UsageAccumulator = class {
|
|
8281
8370
|
input = 0;
|
|
@@ -8456,6 +8545,7 @@ async function initLoopContext(inputs) {
|
|
|
8456
8545
|
tools,
|
|
8457
8546
|
finalText: "",
|
|
8458
8547
|
finalStatus: "finished",
|
|
8548
|
+
doomLoop: createDoomLoopTracker(inputs.doomLoop),
|
|
8459
8549
|
usage: new UsageAccumulator(),
|
|
8460
8550
|
nudgeAttempts: 0,
|
|
8461
8551
|
stopFeedbackAttempts: 0,
|
|
@@ -9480,6 +9570,7 @@ async function runAgentLoop(inputs) {
|
|
|
9480
9570
|
ctx.finalStatus = "error";
|
|
9481
9571
|
}
|
|
9482
9572
|
sendSpan?.setAttribute("status", ctx.finalStatus);
|
|
9573
|
+
if (ctx.stoppedByDoomLoop === true) sendSpan?.setAttribute("stoppedByDoomLoop", true);
|
|
9483
9574
|
if (inputs.telemetry?.includeContent === true && ctx.finalText.length > 0) {
|
|
9484
9575
|
sendSpan?.addEvent("response", { content: ctx.finalText });
|
|
9485
9576
|
}
|
|
@@ -9506,7 +9597,8 @@ async function runAgentLoop(inputs) {
|
|
|
9506
9597
|
...usage !== void 0 ? { usage } : {},
|
|
9507
9598
|
...cost !== void 0 ? { cost } : {},
|
|
9508
9599
|
...ctx.error !== void 0 ? { error: ctx.error } : {},
|
|
9509
|
-
...ctx.stoppedAtIterationLimit === true ? { stoppedAtIterationLimit: true } : {}
|
|
9600
|
+
...ctx.stoppedAtIterationLimit === true ? { stoppedAtIterationLimit: true } : {},
|
|
9601
|
+
...ctx.stoppedByDoomLoop === true ? { stoppedByDoomLoop: true } : {}
|
|
9510
9602
|
};
|
|
9511
9603
|
} finally {
|
|
9512
9604
|
if (ctxRef !== void 0 && ctxRef.memoryProviderHandle !== void 0 && inputs.memoryProvider !== void 0) {
|
|
@@ -9665,8 +9757,26 @@ async function continueOrTerminate(inputs, ctx, llmOutput) {
|
|
|
9665
9757
|
}
|
|
9666
9758
|
}
|
|
9667
9759
|
pushToolConversationSteps(ctx, llmOutput.toolCalls, toolResults);
|
|
9760
|
+
if (await inspectDoomLoop(inputs, ctx, llmOutput.toolCalls) === "stop") return "done";
|
|
9668
9761
|
return handleToolErrorContinuation(inputs, ctx, toolResults);
|
|
9669
9762
|
}
|
|
9763
|
+
async function inspectDoomLoop(inputs, ctx, toolCalls) {
|
|
9764
|
+
if (ctx.doomLoop === void 0) return "continue";
|
|
9765
|
+
const verdict = firstDoomLoopVerdict(ctx.doomLoop, toolCalls);
|
|
9766
|
+
if (verdict.kind === "hard") {
|
|
9767
|
+
ctx.stoppedByDoomLoop = true;
|
|
9768
|
+
await emitAssistantTextStep(
|
|
9769
|
+
inputs,
|
|
9770
|
+
ctx,
|
|
9771
|
+
verdict.message ?? "Stopped: repeated identical tool calls made no progress."
|
|
9772
|
+
);
|
|
9773
|
+
return "stop";
|
|
9774
|
+
}
|
|
9775
|
+
if (verdict.kind === "soft") {
|
|
9776
|
+
ctx.messages.push({ role: "user", content: [{ type: "text", text: verdict.message ?? "" }] });
|
|
9777
|
+
}
|
|
9778
|
+
return "continue";
|
|
9779
|
+
}
|
|
9670
9780
|
|
|
9671
9781
|
// src/internal/llm/fallback-client.ts
|
|
9672
9782
|
init_errors();
|
|
@@ -10955,6 +11065,115 @@ function toOllamaTools(tools) {
|
|
|
10955
11065
|
}
|
|
10956
11066
|
}));
|
|
10957
11067
|
}
|
|
11068
|
+
var cachedJsonrepair;
|
|
11069
|
+
function loadJsonrepair() {
|
|
11070
|
+
if (cachedJsonrepair === void 0) {
|
|
11071
|
+
const req = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cron.cjs', document.baseURI).href)));
|
|
11072
|
+
cachedJsonrepair = req("jsonrepair").jsonrepair;
|
|
11073
|
+
}
|
|
11074
|
+
return cachedJsonrepair;
|
|
11075
|
+
}
|
|
11076
|
+
function isPlainObject(v) {
|
|
11077
|
+
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
11078
|
+
}
|
|
11079
|
+
function toFiniteNumber(raw) {
|
|
11080
|
+
if (raw === "") return void 0;
|
|
11081
|
+
const n = Number(raw);
|
|
11082
|
+
return Number.isFinite(n) && String(n) === raw ? n : void 0;
|
|
11083
|
+
}
|
|
11084
|
+
function tryJson(raw, repair) {
|
|
11085
|
+
const t = raw.trimStart();
|
|
11086
|
+
if (!(t.startsWith("{") || t.startsWith("["))) return void 0;
|
|
11087
|
+
try {
|
|
11088
|
+
return JSON.parse(repair ? loadJsonrepair()(t) : t);
|
|
11089
|
+
} catch {
|
|
11090
|
+
return void 0;
|
|
11091
|
+
}
|
|
11092
|
+
}
|
|
11093
|
+
function heuristicCoerce(raw, repairJson) {
|
|
11094
|
+
if (raw === "true") return true;
|
|
11095
|
+
if (raw === "false") return false;
|
|
11096
|
+
if (raw === "null") return null;
|
|
11097
|
+
const n = toFiniteNumber(raw);
|
|
11098
|
+
if (n !== void 0) return n;
|
|
11099
|
+
const json = tryJson(raw, false) ?? (repairJson ? tryJson(raw, true) : void 0);
|
|
11100
|
+
return json === void 0 ? raw : json;
|
|
11101
|
+
}
|
|
11102
|
+
function coerceCandidates(raw, repairJson) {
|
|
11103
|
+
const out = [];
|
|
11104
|
+
if (raw === "true") out.push(true);
|
|
11105
|
+
else if (raw === "false") out.push(false);
|
|
11106
|
+
else if (raw === "null") out.push(null);
|
|
11107
|
+
const n = toFiniteNumber(raw);
|
|
11108
|
+
if (n !== void 0) out.push(n);
|
|
11109
|
+
const json = tryJson(raw, false) ?? (repairJson ? tryJson(raw, true) : void 0);
|
|
11110
|
+
if (json !== void 0) out.push(json);
|
|
11111
|
+
out.push(raw);
|
|
11112
|
+
return out;
|
|
11113
|
+
}
|
|
11114
|
+
function objectShape(schema) {
|
|
11115
|
+
const shape = schema?.shape;
|
|
11116
|
+
return shape !== null && typeof shape === "object" ? shape : void 0;
|
|
11117
|
+
}
|
|
11118
|
+
|
|
11119
|
+
// src/sanitize/sanitize-tool-input.ts
|
|
11120
|
+
function applyTrim(key, value, ctx) {
|
|
11121
|
+
const trimmed = value.trim();
|
|
11122
|
+
if (trimmed !== value) ctx.notes.push(`trimmed "${key}"`);
|
|
11123
|
+
return trimmed;
|
|
11124
|
+
}
|
|
11125
|
+
function applyCoerce(key, raw, ctx) {
|
|
11126
|
+
const field = ctx.shape?.[key];
|
|
11127
|
+
let coerced = raw;
|
|
11128
|
+
if (field) {
|
|
11129
|
+
for (const candidate of coerceCandidates(raw, ctx.repairJson)) {
|
|
11130
|
+
if (field.safeParse(candidate).success) {
|
|
11131
|
+
coerced = candidate;
|
|
11132
|
+
break;
|
|
11133
|
+
}
|
|
11134
|
+
}
|
|
11135
|
+
} else {
|
|
11136
|
+
coerced = heuristicCoerce(raw, ctx.repairJson);
|
|
11137
|
+
}
|
|
11138
|
+
if (coerced !== raw) ctx.notes.push(`coerced "${key}"`);
|
|
11139
|
+
return coerced;
|
|
11140
|
+
}
|
|
11141
|
+
function applyRepair(key, value, ctx) {
|
|
11142
|
+
const repaired = tryJson(value, true);
|
|
11143
|
+
if (repaired === void 0) return value;
|
|
11144
|
+
ctx.notes.push(`repaired json "${key}"`);
|
|
11145
|
+
return repaired;
|
|
11146
|
+
}
|
|
11147
|
+
function sanitizeString(key, value, ctx) {
|
|
11148
|
+
let out = ctx.trim ? applyTrim(key, value, ctx) : value;
|
|
11149
|
+
if (ctx.coerce && typeof out === "string") out = applyCoerce(key, out, ctx);
|
|
11150
|
+
if (ctx.repairJson && !ctx.coerce && typeof out === "string") out = applyRepair(key, out, ctx);
|
|
11151
|
+
return out;
|
|
11152
|
+
}
|
|
11153
|
+
function walk(input, ctx, depth) {
|
|
11154
|
+
const out = {};
|
|
11155
|
+
for (const [key, value] of Object.entries(input)) {
|
|
11156
|
+
if (typeof value === "string") out[key] = sanitizeString(key, value, ctx);
|
|
11157
|
+
else if (ctx.deep && depth < ctx.maxDepth && isPlainObject(value))
|
|
11158
|
+
out[key] = walk(value, ctx, depth + 1);
|
|
11159
|
+
else out[key] = value;
|
|
11160
|
+
}
|
|
11161
|
+
return out;
|
|
11162
|
+
}
|
|
11163
|
+
function sanitizeToolInput(input, options) {
|
|
11164
|
+
if (!isPlainObject(input)) return { value: input, changed: false, notes: [] };
|
|
11165
|
+
const ctx = {
|
|
11166
|
+
trim: options?.trim,
|
|
11167
|
+
coerce: options?.coerce ?? false,
|
|
11168
|
+
repairJson: options?.repairJson ?? false,
|
|
11169
|
+
deep: options?.deep ?? false,
|
|
11170
|
+
maxDepth: options?.maxDepth ?? 8,
|
|
11171
|
+
shape: objectShape(options?.schema),
|
|
11172
|
+
notes: []
|
|
11173
|
+
};
|
|
11174
|
+
const value = walk(input, ctx, 0);
|
|
11175
|
+
return { value, changed: ctx.notes.length > 0, notes: ctx.notes };
|
|
11176
|
+
}
|
|
10958
11177
|
|
|
10959
11178
|
// src/internal/llm/hermes-tool-extract.ts
|
|
10960
11179
|
var HERMES_BLOCK = /<function=\s*([^>\s]+)\s*>([\s\S]*?)<\/tool_call>/g;
|
|
@@ -10980,9 +11199,9 @@ function parseHermesParams(inner) {
|
|
|
10980
11199
|
const key = param[1];
|
|
10981
11200
|
const value = param[2];
|
|
10982
11201
|
if (key === void 0 || value === void 0) continue;
|
|
10983
|
-
input[key.trim()] = value
|
|
11202
|
+
input[key.trim()] = value;
|
|
10984
11203
|
}
|
|
10985
|
-
return input;
|
|
11204
|
+
return sanitizeToolInput(input, { trim: true }).value;
|
|
10986
11205
|
}
|
|
10987
11206
|
|
|
10988
11207
|
// src/internal/llm/openai.ts
|
|
@@ -12102,6 +12321,8 @@ function buildLoopInputs(options, runId, userText) {
|
|
|
12102
12321
|
// M1-2: per-send iteration ceiling (validated above). The loop reads
|
|
12103
12322
|
// inputs.maxIterations (default 8 when unset).
|
|
12104
12323
|
...maxIterations !== void 0 ? { maxIterations } : {},
|
|
12324
|
+
// Doom-loop guard config (default on; `false` disables, object tunes thresholds).
|
|
12325
|
+
...options.sendOptions.doomLoop !== void 0 ? { doomLoop: options.sendOptions.doomLoop } : {},
|
|
12105
12326
|
// D315-D317 — tool lifecycle hooks (cost tracking + audit + retry/alert)
|
|
12106
12327
|
...options.agentOptions.onToolStart !== void 0 ? { onToolStart: options.agentOptions.onToolStart } : {},
|
|
12107
12328
|
...options.agentOptions.onToolEnd !== void 0 ? { onToolEnd: options.agentOptions.onToolEnd } : {},
|
|
@@ -12234,6 +12455,7 @@ var RealLocalRun = class extends FixtureRunBase {
|
|
|
12234
12455
|
if (output.usage !== void 0) this.script.usage = output.usage;
|
|
12235
12456
|
if (output.cost !== void 0) this.script.cost = output.cost;
|
|
12236
12457
|
if (output.stoppedAtIterationLimit === true) this.script.stoppedAtIterationLimit = true;
|
|
12458
|
+
if (output.stoppedByDoomLoop === true) this.script.stoppedByDoomLoop = true;
|
|
12237
12459
|
if (output.error !== void 0 && this.script.errorDetail === void 0) {
|
|
12238
12460
|
this.script.errorDetail = {
|
|
12239
12461
|
message: output.error.message,
|