@theokit/sdk 2.1.0 → 2.3.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 +35 -0
- package/dist/a2a/index.cjs +117 -3
- package/dist/a2a/index.cjs.map +1 -1
- package/dist/a2a/index.js +117 -3
- package/dist/a2a/index.js.map +1 -1
- package/dist/{cron-Da6vF_2y.d.ts → cron-B_H8rn-j.d.cts} +28 -2
- package/dist/{cron-CSTqNZp9.d.cts → cron-DX6HbHxd.d.ts} +28 -2
- package/dist/cron.cjs +119 -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 +119 -3
- package/dist/cron.js.map +1 -1
- package/dist/{errors--VP2qrGc.d.ts → errors-DG_7CAUg.d.ts} +1 -1
- package/dist/{errors-C9xkhNEF.d.cts → errors-QDYUPABr.d.cts} +1 -1
- package/dist/errors.d.cts +2 -2
- package/dist/eval.cjs +119 -3
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +119 -3
- package/dist/eval.js.map +1 -1
- package/dist/index.cjs +202 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -7
- package/dist/index.d.ts +50 -7
- package/dist/index.js +202 -15
- package/dist/index.js.map +1 -1
- package/dist/internal/agent-loop/loop-types.d.ts +6 -0
- package/dist/internal/runtime/budget/budget-tracker.d.ts +8 -0
- package/dist/internal/runtime/lifecycle/run-to-completion.d.ts +22 -0
- package/dist/{run-DrwUpFxZ.d.cts → run-BPRYG1Id.d.cts} +75 -2
- package/dist/{run-DrwUpFxZ.d.ts → run-BPRYG1Id.d.ts} +75 -2
- package/dist/types/agent.d.ts +14 -0
- package/dist/types/conversation-storage.d.ts +5 -1
- package/dist/types/run.d.ts +74 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- d7d5215: M1-3 — `buildReplayHistory(base, events, options)` pure stateless continuation-history rebuild (plan `m1-continuation-history`).
|
|
8
|
+
|
|
9
|
+
The stateless complement to M1 Phase 3's `runToCompletion` (which covers the stateful-session path). For a server / serverless handler that re-runs an agent on a fresh request and must reconstruct working memory from persisted stream events, `buildReplayHistory` serializes a round's `SDKMessage[]` into a bounded `StoredMessage[]` you can replay as prior history:
|
|
10
|
+
|
|
11
|
+
- maps assistant text → `assistant`; tool `running` → `tool_call` (args); tool `completed`/`error` → `tool_result` (carrying the result content the continued model needs);
|
|
12
|
+
- drops the oldest turns — pair-safe (a `tool_call` and its `tool_result` are never split) — until the total fits a context-window-derived char budget, keeping ≥ 1;
|
|
13
|
+
- truncates an oversized single turn (reusing the SDK's `truncateWithMarker`) rather than dropping it;
|
|
14
|
+
- pure, synchronous, dependency-free; a non-finite `contextWindowTokens` collapses to budget 0 (never returns an unbounded history).
|
|
15
|
+
|
|
16
|
+
Exported from `@theokit/sdk` with `ReplayHistoryOptions`. Replaces the outer-loop history rebuild a code-assistant server otherwise hand-rolls.
|
|
17
|
+
|
|
18
|
+
- f218630: M1 Phase 3 — `agent.runToCompletion()` continuation driver (plan `m1-run-to-completion`).
|
|
19
|
+
|
|
20
|
+
Builds on M1-2's `RunResult.stoppedAtIterationLimit` signal: a single `agent.send()` truncates when the model still wants tools at the loop's iteration ceiling. `runToCompletion(message, options?)` re-sends a short continuation prompt — the agent's stateful session preserves the conversation — until a genuine terminal:
|
|
21
|
+
|
|
22
|
+
- `done` — a round finished without truncating.
|
|
23
|
+
- `step_limit` — `maxRounds` (default 5) exhausted, or aborted via `signal`, while still truncating.
|
|
24
|
+
- `no_progress` — two consecutive rounds produced empty output.
|
|
25
|
+
|
|
26
|
+
Returns `{ terminal, rounds, lastResult, usage }` with token usage summed across rounds. Options: `maxRounds`, `continuationPrompt`, `onTruncated`, `signal`, `sendOptions`. Local agents only — cloud agents throw `UnsupportedRunOperationError` (the cloud runtime manages continuation server-side). This replaces the outer continuation loop a code-assistant builder would otherwise hand-roll.
|
|
27
|
+
|
|
28
|
+
## 2.2.0
|
|
29
|
+
|
|
30
|
+
### Minor Changes
|
|
31
|
+
|
|
32
|
+
- efe183e: M1 Reliable harness — make the agent loop's iteration ceiling real (plan `m1-reliable-harness`).
|
|
33
|
+
|
|
34
|
+
- **M1-1:** the agent loop now calls `BudgetTracker.nextIteration?.()` once per completed turn, and `nextIteration?()` is an optional member of the `BudgetTracker` interface. `createCounterBudgetTracker({ maxIterations: N })` now actually halts the loop after N turns (it was dead — nothing called it). Additive and backward-compatible: trackers that only gate on tokens/USD omit the method.
|
|
35
|
+
- **M1-2 (knob):** `SendOptions.maxIterations` lets a builder raise/lower the loop's default 8-turn cap per `agent.send` call. Validated at the boundary (positive integer; invalid throws `ConfigurationError`). Default of 8 preserved when unset.
|
|
36
|
+
- **M1-2 (truncation signal):** `RunResult.stoppedAtIterationLimit` is `true` when the loop stopped at its iteration ceiling with tool work still pending (silent truncation) vs a clean `done` finish. Lets a caller/continuation driver detect and recover.
|
|
37
|
+
|
|
3
38
|
## 2.1.0
|
|
4
39
|
|
|
5
40
|
### Minor Changes
|
package/dist/a2a/index.cjs
CHANGED
|
@@ -2313,6 +2313,11 @@ function makeNotifier() {
|
|
|
2313
2313
|
});
|
|
2314
2314
|
return { promise, resolve: resolve3 };
|
|
2315
2315
|
}
|
|
2316
|
+
function applyScriptMetrics(base, script) {
|
|
2317
|
+
if (script.usage !== void 0) base.usage = script.usage;
|
|
2318
|
+
if (script.cost !== void 0) base.cost = script.cost;
|
|
2319
|
+
if (script.stoppedAtIterationLimit === true) base.stoppedAtIterationLimit = true;
|
|
2320
|
+
}
|
|
2316
2321
|
var FixtureRunBase;
|
|
2317
2322
|
var init_fixture_run_base = __esm({
|
|
2318
2323
|
"src/internal/runtime/fixtures/fixture-run-base.ts"() {
|
|
@@ -2419,8 +2424,7 @@ var init_fixture_run_base = __esm({
|
|
|
2419
2424
|
if (status === "error" && this.script.errorDetail !== void 0) {
|
|
2420
2425
|
base.error = this.script.errorDetail;
|
|
2421
2426
|
}
|
|
2422
|
-
|
|
2423
|
-
if (this.script.cost !== void 0) base.cost = this.script.cost;
|
|
2427
|
+
applyScriptMetrics(base, this.script);
|
|
2424
2428
|
return this.extendRunResult(applyExtraRunFields(base, this.script));
|
|
2425
2429
|
}
|
|
2426
2430
|
/** Subclasses override to attach runtime-specific fields (e.g. cloud git info). */
|
|
@@ -2999,6 +3003,18 @@ var init_cloud_agent = __esm({
|
|
|
2999
3003
|
"fork"
|
|
3000
3004
|
);
|
|
3001
3005
|
}
|
|
3006
|
+
/**
|
|
3007
|
+
* The continuation driver re-sends against a stateful local session; the
|
|
3008
|
+
* cloud runtime manages its own continuation policy server-side (M1 Phase 3).
|
|
3009
|
+
*
|
|
3010
|
+
* @public
|
|
3011
|
+
*/
|
|
3012
|
+
runToCompletion() {
|
|
3013
|
+
throw new UnsupportedRunOperationError(
|
|
3014
|
+
"Agent.runToCompletion() is not supported on cloud agents. Cloud runtime manages continuation server-side. Use a local agent.",
|
|
3015
|
+
"runToCompletion"
|
|
3016
|
+
);
|
|
3017
|
+
}
|
|
3002
3018
|
/**
|
|
3003
3019
|
* Personality presets require consistent server-side enforcement that
|
|
3004
3020
|
* the cloud runtime (pre-release) does not yet provide. Reject explicitly
|
|
@@ -8008,6 +8024,7 @@ async function runAgentLoop(inputs) {
|
|
|
8008
8024
|
const ctx = await initLoopContext(inputs);
|
|
8009
8025
|
ctxRef = ctx;
|
|
8010
8026
|
const budget = inputs.budget ?? new IterationBudget({ maxIterations: inputs.maxIterations ?? 8 });
|
|
8027
|
+
let lastTurnDecision;
|
|
8011
8028
|
while (budget.shouldContinue()) {
|
|
8012
8029
|
if (inputs.budgetTracker !== void 0) {
|
|
8013
8030
|
const decision2 = evaluateBudgetGate(inputs.budgetTracker);
|
|
@@ -8016,18 +8033,26 @@ async function runAgentLoop(inputs) {
|
|
|
8016
8033
|
if (decision2.detail !== void 0) {
|
|
8017
8034
|
ctx.error = { message: decision2.detail, code: decision2.reason ?? "budget" };
|
|
8018
8035
|
}
|
|
8036
|
+
if (decision2.reason === "iteration_limit") {
|
|
8037
|
+
ctx.stoppedAtIterationLimit = true;
|
|
8038
|
+
}
|
|
8019
8039
|
break;
|
|
8020
8040
|
}
|
|
8021
8041
|
}
|
|
8022
8042
|
const usingGrace = budget.remaining <= 0 && !budget.graceCallUsed;
|
|
8023
8043
|
if (usingGrace) budget.useGraceCall();
|
|
8024
8044
|
const decision = await runIteration(inputs, ctx);
|
|
8045
|
+
lastTurnDecision = decision;
|
|
8025
8046
|
if (decision === "done") break;
|
|
8026
8047
|
if (decision === "error") {
|
|
8027
8048
|
ctx.finalStatus = "error";
|
|
8028
8049
|
break;
|
|
8029
8050
|
}
|
|
8030
8051
|
budget.consume();
|
|
8052
|
+
inputs.budgetTracker?.nextIteration?.();
|
|
8053
|
+
}
|
|
8054
|
+
if (lastTurnDecision === "continue" && budget.shouldContinue() === false) {
|
|
8055
|
+
ctx.stoppedAtIterationLimit = true;
|
|
8031
8056
|
}
|
|
8032
8057
|
if (budget.shouldContinue() === false && ctx.finalStatus === "finished" && ctx.finalText === "") {
|
|
8033
8058
|
ctx.finalStatus = "error";
|
|
@@ -8058,7 +8083,8 @@ async function runAgentLoop(inputs) {
|
|
|
8058
8083
|
conversation: ctx.conversation,
|
|
8059
8084
|
...usage !== void 0 ? { usage } : {},
|
|
8060
8085
|
...cost !== void 0 ? { cost } : {},
|
|
8061
|
-
...ctx.error !== void 0 ? { error: ctx.error } : {}
|
|
8086
|
+
...ctx.error !== void 0 ? { error: ctx.error } : {},
|
|
8087
|
+
...ctx.stoppedAtIterationLimit === true ? { stoppedAtIterationLimit: true } : {}
|
|
8062
8088
|
};
|
|
8063
8089
|
} finally {
|
|
8064
8090
|
if (ctxRef !== void 0 && ctxRef.memoryProviderHandle !== void 0 && inputs.memoryProvider !== void 0) {
|
|
@@ -11007,6 +11033,13 @@ function resolveRunProvider(options) {
|
|
|
11007
11033
|
return { primary, effectiveModelId };
|
|
11008
11034
|
}
|
|
11009
11035
|
function buildLoopInputs(options, runId, userText) {
|
|
11036
|
+
const maxIterations = options.sendOptions.maxIterations;
|
|
11037
|
+
if (maxIterations !== void 0 && (!Number.isInteger(maxIterations) || maxIterations < 1)) {
|
|
11038
|
+
throw new ConfigurationError(
|
|
11039
|
+
`SendOptions.maxIterations must be a positive integer, got ${maxIterations}`,
|
|
11040
|
+
{ code: "invalid_max_iterations" }
|
|
11041
|
+
);
|
|
11042
|
+
}
|
|
11010
11043
|
const { primary, effectiveModelId } = resolveRunProvider(options);
|
|
11011
11044
|
const fallback = options.agentOptions.providers?.fallback;
|
|
11012
11045
|
const apiKeys = options.agentOptions.providers?.apiKeys;
|
|
@@ -11045,6 +11078,9 @@ function buildLoopInputs(options, runId, userText) {
|
|
|
11045
11078
|
// D318 — forward SendOptions.signal to the agent loop so streamLlmTurn
|
|
11046
11079
|
// can attach it to the LLM `fetch({ signal })` call.
|
|
11047
11080
|
...options.sendOptions.signal !== void 0 ? { signal: options.sendOptions.signal } : {},
|
|
11081
|
+
// M1-2: per-send iteration ceiling (validated above). The loop reads
|
|
11082
|
+
// inputs.maxIterations (default 8 when unset).
|
|
11083
|
+
...maxIterations !== void 0 ? { maxIterations } : {},
|
|
11048
11084
|
// D315-D317 — tool lifecycle hooks (cost tracking + audit + retry/alert)
|
|
11049
11085
|
...options.agentOptions.onToolStart !== void 0 ? { onToolStart: options.agentOptions.onToolStart } : {},
|
|
11050
11086
|
...options.agentOptions.onToolEnd !== void 0 ? { onToolEnd: options.agentOptions.onToolEnd } : {},
|
|
@@ -11104,6 +11140,7 @@ function buildMcpMap(options) {
|
|
|
11104
11140
|
var pluginProvidersAnnounced, RealLocalRun;
|
|
11105
11141
|
var init_real_local_run = __esm({
|
|
11106
11142
|
"src/internal/runtime/local-agent/real-local-run.ts"() {
|
|
11143
|
+
init_errors();
|
|
11107
11144
|
init_loop();
|
|
11108
11145
|
init_fallback_client();
|
|
11109
11146
|
init_model_identifier();
|
|
@@ -11191,6 +11228,7 @@ var init_real_local_run = __esm({
|
|
|
11191
11228
|
if (output.result.length > 0) this.script.result = output.result;
|
|
11192
11229
|
if (output.usage !== void 0) this.script.usage = output.usage;
|
|
11193
11230
|
if (output.cost !== void 0) this.script.cost = output.cost;
|
|
11231
|
+
if (output.stoppedAtIterationLimit === true) this.script.stoppedAtIterationLimit = true;
|
|
11194
11232
|
if (output.error !== void 0 && this.script.errorDetail === void 0) {
|
|
11195
11233
|
this.script.errorDetail = {
|
|
11196
11234
|
message: output.error.message,
|
|
@@ -14164,6 +14202,71 @@ var init_agent_factory_registry = __esm({
|
|
|
14164
14202
|
}
|
|
14165
14203
|
});
|
|
14166
14204
|
|
|
14205
|
+
// src/internal/runtime/lifecycle/run-to-completion.ts
|
|
14206
|
+
var run_to_completion_exports = {};
|
|
14207
|
+
__export(run_to_completion_exports, {
|
|
14208
|
+
classifyRound: () => classifyRound,
|
|
14209
|
+
runToCompletionImpl: () => runToCompletionImpl
|
|
14210
|
+
});
|
|
14211
|
+
function isEmptyRound(result) {
|
|
14212
|
+
return (result.result ?? "").trim() === "";
|
|
14213
|
+
}
|
|
14214
|
+
function classifyRound(result, round, maxRounds, emptyStreak) {
|
|
14215
|
+
if (result.stoppedAtIterationLimit !== true) return "done";
|
|
14216
|
+
if (isEmptyRound(result) && emptyStreak >= 1) return "no_progress";
|
|
14217
|
+
if (round >= maxRounds) return "step_limit";
|
|
14218
|
+
return "continue";
|
|
14219
|
+
}
|
|
14220
|
+
function addUsage(acc, u) {
|
|
14221
|
+
if (u === void 0) return acc;
|
|
14222
|
+
const inputTokens = (acc?.inputTokens ?? 0) + u.inputTokens;
|
|
14223
|
+
const outputTokens = (acc?.outputTokens ?? 0) + u.outputTokens;
|
|
14224
|
+
const sumOpt = (a, b) => a === void 0 && b === void 0 ? void 0 : (a ?? 0) + (b ?? 0);
|
|
14225
|
+
return {
|
|
14226
|
+
inputTokens,
|
|
14227
|
+
outputTokens,
|
|
14228
|
+
totalTokens: inputTokens + outputTokens,
|
|
14229
|
+
cacheReadTokens: sumOpt(acc?.cacheReadTokens, u.cacheReadTokens),
|
|
14230
|
+
cacheWriteTokens: sumOpt(acc?.cacheWriteTokens, u.cacheWriteTokens),
|
|
14231
|
+
reasoningTokens: sumOpt(acc?.reasoningTokens, u.reasoningTokens)
|
|
14232
|
+
};
|
|
14233
|
+
}
|
|
14234
|
+
function buildResult(terminal, rounds, lastResult, usage) {
|
|
14235
|
+
return { terminal, rounds, lastResult, ...usage !== void 0 ? { usage } : {} };
|
|
14236
|
+
}
|
|
14237
|
+
async function stepRound(agent, prompt, sendOptions, round, maxRounds, state2) {
|
|
14238
|
+
const run = await agent.send(prompt, sendOptions);
|
|
14239
|
+
const result = await run.wait();
|
|
14240
|
+
const usage = addUsage(state2.usage, result.usage);
|
|
14241
|
+
const decision = classifyRound(result, round, maxRounds, state2.emptyStreak);
|
|
14242
|
+
if (decision !== "continue") return { terminal: buildResult(decision, round, result, usage) };
|
|
14243
|
+
const emptyStreak = isEmptyRound(result) ? state2.emptyStreak + 1 : 0;
|
|
14244
|
+
return { next: { usage, emptyStreak }, lastResult: result };
|
|
14245
|
+
}
|
|
14246
|
+
async function runToCompletionImpl(agent, message, options) {
|
|
14247
|
+
const maxRounds = options?.maxRounds ?? DEFAULT_MAX_ROUNDS;
|
|
14248
|
+
const continuationPrompt = options?.continuationPrompt ?? DEFAULT_CONTINUATION_PROMPT;
|
|
14249
|
+
const { onTruncated, signal, sendOptions } = options ?? {};
|
|
14250
|
+
let state2 = { usage: void 0, emptyStreak: 0 };
|
|
14251
|
+
for (let round = 0; ; round += 1) {
|
|
14252
|
+
const prompt = round === 0 ? message : continuationPrompt;
|
|
14253
|
+
const outcome = await stepRound(agent, prompt, sendOptions, round, maxRounds, state2);
|
|
14254
|
+
if ("terminal" in outcome) return outcome.terminal;
|
|
14255
|
+
state2 = outcome.next;
|
|
14256
|
+
await onTruncated?.({ round });
|
|
14257
|
+
if (signal?.aborted === true) {
|
|
14258
|
+
return buildResult("step_limit", round, outcome.lastResult, state2.usage);
|
|
14259
|
+
}
|
|
14260
|
+
}
|
|
14261
|
+
}
|
|
14262
|
+
var DEFAULT_MAX_ROUNDS, DEFAULT_CONTINUATION_PROMPT;
|
|
14263
|
+
var init_run_to_completion = __esm({
|
|
14264
|
+
"src/internal/runtime/lifecycle/run-to-completion.ts"() {
|
|
14265
|
+
DEFAULT_MAX_ROUNDS = 5;
|
|
14266
|
+
DEFAULT_CONTINUATION_PROMPT = "Continue from where you left off and finish the task. If it is already complete, give the final answer.";
|
|
14267
|
+
}
|
|
14268
|
+
});
|
|
14269
|
+
|
|
14167
14270
|
// src/internal/runtime/lifecycle/fork-agent.ts
|
|
14168
14271
|
var fork_agent_exports = {};
|
|
14169
14272
|
__export(fork_agent_exports, {
|
|
@@ -14244,6 +14347,13 @@ function localAgentRunUntil(agent, goal, options) {
|
|
|
14244
14347
|
}
|
|
14245
14348
|
return wrap();
|
|
14246
14349
|
}
|
|
14350
|
+
function localAgentRunToCompletion(agent, message, options) {
|
|
14351
|
+
async function run() {
|
|
14352
|
+
const { runToCompletionImpl: runToCompletionImpl2 } = await Promise.resolve().then(() => (init_run_to_completion(), run_to_completion_exports));
|
|
14353
|
+
return runToCompletionImpl2({ send: (m, o) => agent.send(m, o) }, message, options);
|
|
14354
|
+
}
|
|
14355
|
+
return run();
|
|
14356
|
+
}
|
|
14247
14357
|
async function localAgentFork(parent, options) {
|
|
14248
14358
|
const { forkAgentImpl: forkAgentImpl2 } = await Promise.resolve().then(() => (init_fork_agent(), fork_agent_exports));
|
|
14249
14359
|
const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
|
|
@@ -15378,6 +15488,10 @@ var init_local_agent = __esm({
|
|
|
15378
15488
|
fork(options) {
|
|
15379
15489
|
return localAgentFork({ agentId: this.agentId, options: this.options, personalitySlugSnapshot: this.personalityStore.active(this.agentId) }, options);
|
|
15380
15490
|
}
|
|
15491
|
+
// biome-ignore format: G8 budget — see runUntil comment above.
|
|
15492
|
+
runToCompletion(message, options) {
|
|
15493
|
+
return localAgentRunToCompletion(this, message, options);
|
|
15494
|
+
}
|
|
15381
15495
|
};
|
|
15382
15496
|
}
|
|
15383
15497
|
});
|