@vincemakes/kiso-runtime 0.1.31 → 0.1.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/compose.d.ts CHANGED
@@ -3,8 +3,10 @@
3
3
  * from session.ts: the extension system-prompt appends, the extension
4
4
  * hook composition (the existing come first), and the loop's microcompact config lookup.
5
5
  */
6
- import type { HookHost, KisoExtension } from "@vincemakes/kiso-core";
6
+ import type { ApprovalChain, HookHost, KisoExtension, ToolRegistry } from "@vincemakes/kiso-core";
7
7
  import type { SessionConfig } from "./session.js";
8
+ /** The table, or "" when the registry is empty (no vocabulary, no tools). */
9
+ export declare function composeToolTable(registry: ToolRegistry): string;
8
10
  /**
9
11
  * E2: the session's systemPrompt plus every extension's append, in LOAD
10
12
  * order, \n\n-joined — deterministic (same extension list → same prompt).
@@ -30,3 +32,23 @@ export declare function microcompactFor(config: SessionConfig): {
30
32
  readonly thresholdTokens: number;
31
33
  readonly keepResults?: number;
32
34
  } | undefined;
35
+ /**
36
+ * E1 (W21/R3 — moved out of the kernel by the 2026-08-09 corrective
37
+ * action; the composition is extension wiring, the same category as
38
+ * composeHooks): compose the extensions' approval policies into ONE
39
+ * chain — the kernel's gate. deny > allow > ask: any deny wins (the
40
+ * FIRST denial's reason), then ANY allow (a LATER allow beats an
41
+ * EARLIER ask: the allow-only dont-ask-again extension must override a
42
+ * mode tier's ask — the old ask-wins chain left it structurally dead),
43
+ * and an ask falls into the kernel's human flow (its speaker = the
44
+ * first non-abstain — the panel's why-asked line). Only an ask-free
45
+ * chain auto-approves: decidedBy = the deciding extension (the FIRST
46
+ * allow — the symmetry of the first denial; an every-speaker-allows
47
+ * chain records the first speaker). An all-abstain chain (ADR-0042)
48
+ * ASKS — no opinion is never a silent allow; absent a channel the
49
+ * kernel's honest denial. A policy that throws counts as ask — it
50
+ * speaks, never silently. No policies → undefined (no chain: the
51
+ * kernel's plain flow — the all-abstain ask exists only where a chain
52
+ * does).
53
+ */
54
+ export declare function composeApprovalChain(extensions: readonly KisoExtension[]): ApprovalChain | undefined;
package/dist/compose.js CHANGED
@@ -3,6 +3,42 @@
3
3
  * from session.ts: the extension system-prompt appends, the extension
4
4
  * hook composition (the existing come first), and the loop's microcompact config lookup.
5
5
  */
6
+ /**
7
+ * 0.1.40 (R-C item 1) — the tool substitution table: the fixed vocabulary
8
+ * (the reference implementation's content in kiso's voice, each line bound
9
+ * to the tool that makes
10
+ * it true) filtered to the ACTIVE tool set + each active tool's ONE-line
11
+ * snippet + its guideline bullets. The full descriptions NEVER enter the
12
+ * system prompt — the provider transmits them in the JSON schema anyway
13
+ * (never pay twice). Deterministic: same registry → same table.
14
+ */
15
+ const TOOL_RULES = [
16
+ { tool: "read_file", line: "read files with read_file, never shell cat/head/tail" },
17
+ { tool: "search_text", line: "search with search_text, never shell grep/rg" },
18
+ { tool: "list_dir", line: "list with list_dir, never ls" },
19
+ { tool: "shell", line: "reserve shell for real system commands" },
20
+ ];
21
+ /** The table, or "" when the registry is empty (no vocabulary, no tools). */
22
+ export function composeToolTable(registry) {
23
+ const tools = registry.list();
24
+ if (tools.length === 0)
25
+ return "";
26
+ const active = new Set(tools.map((t) => t.name));
27
+ const lines = [
28
+ "Tool use:",
29
+ ...TOOL_RULES.filter((r) => active.has(r.tool)).map((r) => `- ${r.line}`),
30
+ // the parallel directive: the window applies to every active turn.
31
+ "- batch independent tool calls into one reply — they run in parallel",
32
+ // D1: a tool result is evidence, not an answer — the turn ends with
33
+ // the findings that make the evidence useful to the human.
34
+ "- end your turn with your findings — never end on a bare tool result",
35
+ ...tools.flatMap((t) => (t.promptSnippet === undefined ? [] : [`- ${t.promptSnippet}`])),
36
+ ];
37
+ const guidelines = tools.flatMap((t) => (t.promptGuidelines ?? []).map((g) => `- ${t.name}: ${g}`));
38
+ if (guidelines.length > 0)
39
+ lines.push("Active tool guidelines:", ...guidelines);
40
+ return lines.join("\n");
41
+ }
6
42
  /**
7
43
  * E2: the session's systemPrompt plus every extension's append, in LOAD
8
44
  * order, \n\n-joined — deterministic (same extension list → same prompt).
@@ -115,3 +151,81 @@ export function microcompactFor(config) {
115
151
  }
116
152
  return undefined;
117
153
  }
154
+ /**
155
+ * E1 (W21/R3 — moved out of the kernel by the 2026-08-09 corrective
156
+ * action; the composition is extension wiring, the same category as
157
+ * composeHooks): compose the extensions' approval policies into ONE
158
+ * chain — the kernel's gate. deny > allow > ask: any deny wins (the
159
+ * FIRST denial's reason), then ANY allow (a LATER allow beats an
160
+ * EARLIER ask: the allow-only dont-ask-again extension must override a
161
+ * mode tier's ask — the old ask-wins chain left it structurally dead),
162
+ * and an ask falls into the kernel's human flow (its speaker = the
163
+ * first non-abstain — the panel's why-asked line). Only an ask-free
164
+ * chain auto-approves: decidedBy = the deciding extension (the FIRST
165
+ * allow — the symmetry of the first denial; an every-speaker-allows
166
+ * chain records the first speaker). An all-abstain chain (ADR-0042)
167
+ * ASKS — no opinion is never a silent allow; absent a channel the
168
+ * kernel's honest denial. A policy that throws counts as ask — it
169
+ * speaks, never silently. No policies → undefined (no chain: the
170
+ * kernel's plain flow — the all-abstain ask exists only where a chain
171
+ * does).
172
+ */
173
+ export function composeApprovalChain(extensions) {
174
+ const policies = extensions.flatMap((e) => (e.approvals ?? []).map((policy) => ({ extension: e.name, policy })));
175
+ if (policies.length === 0)
176
+ return undefined;
177
+ return {
178
+ async decide(payload, ctx) {
179
+ let chainVerdict;
180
+ let deniedReason;
181
+ let deniedBy;
182
+ let allowedBy; // the FIRST allowing extension (the composition's decider for an allow)
183
+ let firstSpeaker; // the first non-abstain verdict's extension
184
+ let anySpoke = false;
185
+ for (const { extension, policy } of policies) {
186
+ let v;
187
+ try {
188
+ v = await Promise.resolve(policy.decide(payload, ctx));
189
+ }
190
+ catch {
191
+ v = { action: "ask" }; // a throwing policy counts as ask — it speaks, never silently
192
+ }
193
+ if (v.action === "abstain")
194
+ continue; // no opinion — not a verdict
195
+ anySpoke = true;
196
+ firstSpeaker ??= extension;
197
+ if (v.action === "deny") {
198
+ deniedBy ??= extension;
199
+ deniedReason ??= v.reason; // the FIRST denial's reason
200
+ }
201
+ else if (v.action === "allow") {
202
+ // deny > allow > ask — the allow overrides any EARLIER
203
+ // ask in the chain (the allow-only dont-ask-again
204
+ // extension after a mode tier that asked). The first
205
+ // allow is the deciding one — the symmetry of deniedBy.
206
+ allowedBy ??= extension;
207
+ chainVerdict = { action: "allow" };
208
+ }
209
+ else if (chainVerdict === undefined) {
210
+ chainVerdict = { action: "ask" }; // recorded — a later allow overrides it
211
+ }
212
+ }
213
+ if (deniedBy !== undefined) {
214
+ return { action: "deny", reason: deniedReason ?? "denied", decidedBy: deniedBy };
215
+ }
216
+ if (allowedBy !== undefined) {
217
+ return { action: "allow", decidedBy: allowedBy }; // an allow beat any earlier ask
218
+ }
219
+ if (chainVerdict === undefined && anySpoke) {
220
+ return { action: "allow", decidedBy: firstSpeaker }; // every speaker allows
221
+ }
222
+ if (chainVerdict === undefined) {
223
+ // an all-abstain (ADR-0042): NO policy speaks — the call falls
224
+ // to the ask flow, never to a silent auto-approve. The human
225
+ // decides; absent a channel, the kernel's honest denial.
226
+ return { action: "ask" };
227
+ }
228
+ return { action: "ask", ...(firstSpeaker !== undefined ? { speaker: firstSpeaker } : {}) };
229
+ },
230
+ };
231
+ }
package/dist/run.js CHANGED
@@ -5,7 +5,8 @@
5
5
  */
6
6
  import { denialResult, loop } from "@vincemakes/kiso-core";
7
7
  import { ABORTED, MergedSignal, abortable, openRunId } from "./recovery.js";
8
- import { composeSystemPrompt, microcompactFor } from "./compose.js";
8
+ import { composeApprovalChain, composeSystemPrompt, composeToolTable, microcompactFor } from "./compose.js";
9
+ import { truncationGuard } from "./truncation-guard.js";
9
10
  import { ResumeBlockedError } from "./session.js";
10
11
  /**
11
12
  * A single turn. Async-iterable, so `for await (const ev of session.run(x))`
@@ -56,12 +57,24 @@ export class Run {
56
57
  // E2: the session's own microcompact wins; otherwise the FIRST
57
58
  // extension providing a compaction config supplies it.
58
59
  const microcompact = microcompactFor(this.#config);
60
+ // 0.1.40 (R-C item 1): the tool substitution table — the ACTIVE tool
61
+ // set's vocabulary, snippets, and guidelines — sits BETWEEN the
62
+ // session's base prompt and the extension appends: generated
63
+ // machinery never outranks the deliberate extension text (the E2
64
+ // "append lands at the END" contract holds). "" when empty.
65
+ const toolTable = composeToolTable(this.#config.registry);
66
+ const basePrompt = toolTable === "" ? this.#config.systemPrompt
67
+ : this.#config.systemPrompt === undefined ? toolTable
68
+ : `${this.#config.systemPrompt}\n\n${toolTable}`;
59
69
  // E2: the session's own systemPrompt first, then every extension
60
70
  // append in LOAD order — deterministic (same extensions → same
61
71
  // prompt); no appends → byte-identical to the extension-less run.
62
- const systemPrompt = composeSystemPrompt(this.#config.systemPrompt, this.#config.extensions ?? []);
72
+ const systemPrompt = composeSystemPrompt(basePrompt, this.#config.extensions ?? []);
73
+ const approvalChain = composeApprovalChain(this.#config.extensions ?? []);
63
74
  const loopConfig = () => ({
64
- adapter: this.#adapter,
75
+ // 0.1.40 (R-C item 3): the truncation guard gates the model
76
+ // stream — a truncated turn's tool batch never executes.
77
+ adapter: truncationGuard(this.#adapter),
65
78
  model: this.#config.model,
66
79
  sessionId: this.#session.id, // P3: tools see their session (ToolContext.sessionId)
67
80
  ...(systemPrompt !== undefined ? { systemPrompt } : {}),
@@ -73,7 +86,9 @@ export class Run {
73
86
  ...(this.#config.compaction !== undefined ? { compaction: this.#config.compaction } : {}),
74
87
  ...(microcompact !== undefined ? { microcompact } : {}),
75
88
  ...(this.#config.maxRetries !== undefined ? { maxRetries: this.#config.maxRetries } : {}),
76
- approvalPolicies: (this.#config.extensions ?? []).flatMap((e) => (e.approvals ?? []).map((policy) => ({ extension: e.name, policy }))),
89
+ // E1: the composed approval chain the extensions'
90
+ // policies composed into ONE gate (deny > allow > ask).
91
+ ...(approvalChain !== undefined ? { approvalPolicy: approvalChain } : {}),
77
92
  log,
78
93
  signal,
79
94
  resolveApproval: (decisionId) => new Promise((resolve) => {
package/dist/session.d.ts CHANGED
@@ -61,6 +61,16 @@ export interface SummarizeResult {
61
61
  /** The estimated tokens the compression saved (chars/4 proxy). */
62
62
  readonly savedTokens: number;
63
63
  }
64
+ /** W18: the knowable pre-call data, surfaced through onStart — everything
65
+ * the indicator's indeterminate row shows (rounds, the token estimate)
66
+ * is computed locally BEFORE the one adapter call; no fraction exists. */
67
+ export interface CompactInfo {
68
+ readonly coversToSeq: number;
69
+ /** The covered user rounds — the inputs in (previous summary point, boundary]. */
70
+ readonly rounds: number;
71
+ /** The covered content's estimated tokens (the chars/4 proxy). */
72
+ readonly tokens: number;
73
+ }
64
74
  export declare class AgentSession {
65
75
  #private;
66
76
  readonly id: string;
@@ -112,6 +122,7 @@ export declare class AgentSession {
112
122
  summarize(options?: {
113
123
  keepRounds?: number;
114
124
  signal?: AbortSignalLike;
125
+ onStart?: (info: CompactInfo) => void;
115
126
  }): Promise<SummarizeResult | null>;
116
127
  /**
117
128
  * Pauses that still await a human decision (durable, survives restart).
@@ -128,8 +139,11 @@ export declare class AgentSession {
128
139
  * next resume applies it without re-asking. The crash window between a
129
140
  * resolve and the run's write is benign: nothing has executed yet, so a
130
141
  * lost decision only re-presents the request.
142
+ * W21: an optional reason rides a DENIAL (the panel's feedback — the
143
+ * tool_result carries `[Permission denied] <the words>`); allow reasons
144
+ * are never persisted (the words ride the next user turn instead).
131
145
  */
132
- approve(decisionId: string, allow: boolean): Promise<void>;
146
+ approve(decisionId: string, allow: boolean, reason?: string): Promise<void>;
133
147
  /** Executions that started but never reported a result (crash window). */
134
148
  uncertainExecutions(): import("@vincemakes/kiso-core").ExecutionRecord[];
135
149
  /**
package/dist/session.js CHANGED
@@ -30,6 +30,7 @@
30
30
  import { EventLog, executionLedger, projectMessages, } from "@vincemakes/kiso-core";
31
31
  import { denialResult } from "@vincemakes/kiso-core";
32
32
  import { estimateSummarySavings, KEEP_RECENT_ROUNDS, lastSummaryPoint, summarizeConversation, summaryBoundarySeq, } from "./summarize.js";
33
+ import { estimateTokens } from "@vincemakes/kiso-core";
33
34
  import { StaleWriterError } from "./store.js";
34
35
  import { composeHooks } from "./compose.js";
35
36
  import { Run } from "./run.js";
@@ -181,18 +182,39 @@ export class AgentSession {
181
182
  async summarize(options = {}) {
182
183
  this.ensureHealthy();
183
184
  const keepRounds = options.keepRounds ?? KEEP_RECENT_ROUNDS;
185
+ // W18: the signal is observed at EVERY phase boundary — the cancel
186
+ // affordance works for the whole call (local work included), never
187
+ // just the adapter's wait. The abort error is the honest "nothing
188
+ // happened" outcome (ADR-0044 crash semantics).
189
+ const cancelled = () => new Error("the compaction was cancelled");
190
+ if (options.signal !== undefined && options.signal.aborted)
191
+ throw cancelled();
184
192
  const events = this.log.all;
185
193
  const boundary = summaryBoundarySeq(events, keepRounds);
186
194
  if (boundary === undefined)
187
195
  return null;
188
196
  const prevPoint = lastSummaryPoint(events);
189
197
  const covered = projectMessages(events.filter((e) => e.seq > prevPoint && e.seq <= boundary && e.type !== "summarized"));
198
+ // W18: the indicator's pre-call data — rounds + the token estimate
199
+ // are knowable BEFORE the adapter call; the summary itself is ONE
200
+ // call with no fraction (kiso never invents a percentage here).
201
+ if (options.signal !== undefined && options.signal.aborted)
202
+ throw cancelled();
203
+ options.onStart?.({
204
+ coversToSeq: boundary,
205
+ rounds: events.filter((e) => e.type === "user_input" && e.seq > prevPoint && e.seq <= boundary).length,
206
+ tokens: estimateTokens(covered),
207
+ });
190
208
  const summary = await summarizeConversation({
191
209
  adapter: this.#adapter,
192
210
  model: this.#config.model,
193
211
  messages: covered,
194
212
  ...(options.signal !== undefined ? { signal: options.signal } : {}),
195
213
  });
214
+ // The post-call boundary check: an abort that landed while the
215
+ // adapter returned must NOT persist — "nothing happened".
216
+ if (options.signal !== undefined && options.signal.aborted)
217
+ throw cancelled();
196
218
  const full = this.log.append({ type: "summarized", coversToSeq: boundary, summary });
197
219
  // The record rides the LAST recorded run's id — a summarized fact
198
220
  // must never open a run of its own: the open-run gate keys on
@@ -248,8 +270,11 @@ export class AgentSession {
248
270
  * next resume applies it without re-asking. The crash window between a
249
271
  * resolve and the run's write is benign: nothing has executed yet, so a
250
272
  * lost decision only re-presents the request.
273
+ * W21: an optional reason rides a DENIAL (the panel's feedback — the
274
+ * tool_result carries `[Permission denied] <the words>`); allow reasons
275
+ * are never persisted (the words ride the next user turn instead).
251
276
  */
252
- async approve(decisionId, allow) {
277
+ async approve(decisionId, allow, reason) {
253
278
  // round 4: a poisoned session may not mutate the log — checked before
254
279
  // anything is recorded.
255
280
  this.ensureHealthy();
@@ -284,7 +309,10 @@ export class AgentSession {
284
309
  // cannot issue while awaiting approve().)
285
310
  this.#pendingDurableApprovals.set(decisionId, allow);
286
311
  this.#pendingResolvers.delete(decisionId);
287
- resolver(allow ? { action: "allow" } : { action: "deny", reason: "denied by user" });
312
+ // W21: the panel's feedback rides the denial the tool_result
313
+ // carries `[Permission denied] <the words>` (the rejection
314
+ // asymmetry: words keep the run alive).
315
+ resolver(allow ? { action: "allow" } : { action: "deny", reason: reason ?? "denied by user" });
288
316
  return;
289
317
  }
290
318
  const runId = request?.runId ?? "approval";
@@ -293,7 +321,7 @@ export class AgentSession {
293
321
  decisionId,
294
322
  ...(request !== undefined ? { callId: request.event.callId } : {}),
295
323
  decision: allow ? "approved" : "denied",
296
- ...(allow ? {} : { reason: "denied by user" }),
324
+ ...(allow ? {} : { reason: reason ?? "denied by user" }),
297
325
  });
298
326
  await this.persist(runId, decided);
299
327
  }
@@ -51,8 +51,8 @@ export declare function lastSummaryPoint(events: readonly Event[]): number;
51
51
  * a message. Returns undefined when fewer than keepRounds+1 uncovered
52
52
  * rounds exist (nothing worth covering yet).
53
53
  *
54
- * ⑥ (todo round): a tool result tagged do-not-compact is DURABLE work
55
- * memory (the todo_set echo) — the summary must never cover its round,
54
+ * ⑥ (task round): a tool result tagged do-not-compact is DURABLE work
55
+ * memory (the task_set echo) — the summary must never cover its round,
56
56
  * or the model loses the current list. When the base boundary would
57
57
  * cover such a result, the boundary pulls back to just before the round
58
58
  * containing the LATEST one (still a turn boundary). A protected round
package/dist/summarize.js CHANGED
@@ -85,8 +85,8 @@ export function lastSummaryPoint(events) {
85
85
  * a message. Returns undefined when fewer than keepRounds+1 uncovered
86
86
  * rounds exist (nothing worth covering yet).
87
87
  *
88
- * ⑥ (todo round): a tool result tagged do-not-compact is DURABLE work
89
- * memory (the todo_set echo) — the summary must never cover its round,
88
+ * ⑥ (task round): a tool result tagged do-not-compact is DURABLE work
89
+ * memory (the task_set echo) — the summary must never cover its round,
90
90
  * or the model loses the current list. When the base boundary would
91
91
  * cover such a result, the boundary pulls back to just before the round
92
92
  * containing the LATEST one (still a turn boundary). A protected round
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 0.1.40 (R-C item 3) — the truncation guard: a runtime adapter wrapper.
3
+ *
4
+ * The reference implementation's protection: a truncated stream (stopReason
5
+ * max_tokens/length) can
6
+ * yield tool args that parse and validate but are silently incomplete —
7
+ * executing them is the destructive-bug class. The provider adapters already
8
+ * see the stop reason; the RUNTIME vetoes execution of the whole batch:
9
+ *
10
+ * - tool_call_end events are held per turn (the deltas pass through live —
11
+ * the UI still shows the calls building, only the COMPLETION is gated);
12
+ * - a compatible stop flushes the held calls in order, then the stop — the
13
+ * kernel launches them exactly as before (the parallel window survives;
14
+ * only the 0.1.26 mid-stream launch timing is gone — the cost of the
15
+ * guarantee: the turn's truncated intent is never half-executed);
16
+ * - a truncation stop flushes the held calls with input: null — the
17
+ * kernel's EXISTING invalid-input denial fails the whole batch without
18
+ * executing anything (the same honest null the adapters already emit
19
+ * for unparseable partials — zero new protocol surface), and the turn
20
+ * still ends with the max_tokens terminal (the loop's voided settle).
21
+ *
22
+ * The kernel machinery (the streaming launch, the window, the voided
23
+ * settle) is untouched — the gate lives at the adapter boundary, where the
24
+ * stop reason is already known.
25
+ */
26
+ import type { Adapter } from "@vincemakes/kiso-core";
27
+ /** Wrap the adapter so a truncated turn's tool batch can never execute. */
28
+ export declare function truncationGuard(adapter: Adapter): Adapter;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * 0.1.40 (R-C item 3) — the truncation guard: a runtime adapter wrapper.
3
+ *
4
+ * The reference implementation's protection: a truncated stream (stopReason
5
+ * max_tokens/length) can
6
+ * yield tool args that parse and validate but are silently incomplete —
7
+ * executing them is the destructive-bug class. The provider adapters already
8
+ * see the stop reason; the RUNTIME vetoes execution of the whole batch:
9
+ *
10
+ * - tool_call_end events are held per turn (the deltas pass through live —
11
+ * the UI still shows the calls building, only the COMPLETION is gated);
12
+ * - a compatible stop flushes the held calls in order, then the stop — the
13
+ * kernel launches them exactly as before (the parallel window survives;
14
+ * only the 0.1.26 mid-stream launch timing is gone — the cost of the
15
+ * guarantee: the turn's truncated intent is never half-executed);
16
+ * - a truncation stop flushes the held calls with input: null — the
17
+ * kernel's EXISTING invalid-input denial fails the whole batch without
18
+ * executing anything (the same honest null the adapters already emit
19
+ * for unparseable partials — zero new protocol surface), and the turn
20
+ * still ends with the max_tokens terminal (the loop's voided settle).
21
+ *
22
+ * The kernel machinery (the streaming launch, the window, the voided
23
+ * settle) is untouched — the gate lives at the adapter boundary, where the
24
+ * stop reason is already known.
25
+ */
26
+ /** Wrap the adapter so a truncated turn's tool batch can never execute. */
27
+ export function truncationGuard(adapter) {
28
+ return {
29
+ stream(options) {
30
+ return guardStream(adapter.stream(options));
31
+ },
32
+ };
33
+ }
34
+ async function* guardStream(stream) {
35
+ const held = [];
36
+ for await (const ev of stream) {
37
+ if (ev.type === "tool_call_end") {
38
+ held.push(ev);
39
+ continue; // held — emitted at the stop, complete or nulled
40
+ }
41
+ if (ev.type === "stop") {
42
+ const truncated = ev.reason === "max_tokens";
43
+ for (const call of held) {
44
+ // truncation: null input — the kernel's denial path fails the
45
+ // call without executing it; otherwise: untouched, in order.
46
+ yield truncated ? { ...call, input: null } : call;
47
+ }
48
+ held.length = 0;
49
+ }
50
+ yield ev;
51
+ }
52
+ // A stream that ends WITHOUT a stop drops the held ends — the kernel
53
+ // already voids the malformed turn (invalid_request); the dangling
54
+ // deltas are the pre-existing malformed-stream shape.
55
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-runtime",
3
- "version": "0.1.31",
3
+ "version": "0.1.33",
4
4
  "description": "kiso runtime — durable multi-turn agent sessions: AgentDefinition, AgentRuntime, AgentSession, Run, append-only JSONL store.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -21,11 +21,11 @@
21
21
  "test": "vitest run"
22
22
  },
23
23
  "dependencies": {
24
- "@vincemakes/kiso-core": "0.1.30"
24
+ "@vincemakes/kiso-core": "0.1.32"
25
25
  },
26
26
  "peerDependencies": {
27
- "@vincemakes/kiso-provider-anthropic": "0.1.31",
28
- "@vincemakes/kiso-provider-openai": "0.1.31"
27
+ "@vincemakes/kiso-provider-anthropic": "0.1.33",
28
+ "@vincemakes/kiso-provider-openai": "0.1.33"
29
29
  },
30
30
  "peerDependenciesMeta": {
31
31
  "@vincemakes/kiso-provider-anthropic": {
@@ -36,7 +36,7 @@
36
36
  }
37
37
  },
38
38
  "devDependencies": {
39
- "@vincemakes/kiso-evals": "0.1.31",
39
+ "@vincemakes/kiso-evals": "0.1.33",
40
40
  "@types/node": "^26.1.2",
41
41
  "typescript": "^5.7.2",
42
42
  "vitest": "^3.0.0"