@vincemakes/kiso-runtime 0.38.0 → 0.39.1

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.
@@ -124,9 +124,21 @@ export interface SummarizeConversationResult {
124
124
  readonly usage: RawUsage | null;
125
125
  }
126
126
  /**
127
- * The one-shot summary call. Collects the adapter's text deltas into the
128
- * summary; usage/stop pass through untouched. Throws when the model
129
- * produced no text — the caller reports it and nothing is persisted.
127
+ * The summary call, with ONE retry.
128
+ *
129
+ * 0.39.1: `/compact` had no retry at all. The kernel owns retries
130
+ * (ADR-0005) and this path does not go through the kernel — it calls the
131
+ * adapter directly — so a gateway that drops a 95k-token summary stream
132
+ * failed `/compact` every single time, with an honest message and no way
133
+ * forward. The adapter classifies that as a retryable `network` failure
134
+ * (the transport-failure-after-headers class); here is the only place
135
+ * that can act on it.
136
+ *
137
+ * ONE retry, not a loop, and not the kernel's budget: a summary re-pays
138
+ * its whole input, which on the sessions that need compacting is the
139
+ * most expensive request the session makes. A permanent error still
140
+ * throws on the first attempt — the retry is keyed on the classification
141
+ * the adapter already made, never on the fact that something failed.
130
142
  */
131
143
  export declare function summarizeConversation(options: SummarizeConversationOptions): Promise<SummarizeConversationResult>;
132
144
  /** E6 — the crux-experiment drop arm: the covered turns are replaced by
package/dist/summarize.js CHANGED
@@ -188,12 +188,69 @@ export function validateSummary(text) {
188
188
  }
189
189
  return null;
190
190
  }
191
+ /** A thrown value the adapter CLASSIFIED — `{ code, retryable, message }`
192
+ * (ADR-0005 rule 1). The core's own guard is private, and this asks a
193
+ * narrower question than that one: is this a failure someone already
194
+ * decided is worth trying again. A validation rejection below is a plain
195
+ * `Error` and can never match, which is the separation E6 (b) wants —
196
+ * "the model wrote a bad summary" is not retried, ever. */
197
+ function retryableStructured(err) {
198
+ if (err === null || typeof err !== "object")
199
+ return false;
200
+ const e = err;
201
+ return typeof e.code === "string" && typeof e.message === "string" && e.retryable === true;
202
+ }
203
+ /** How long to wait before the one retry. The provider's own ask when it
204
+ * made one and it is short enough to be worth honouring; otherwise a
205
+ * token pause — the failure this exists for is a dropped stream, not a
206
+ * rate limit, and an immediate second attempt is the right response to
207
+ * a socket that died. */
208
+ function retryWaitMs(err) {
209
+ const asked = err.retryAfterMs;
210
+ return typeof asked === "number" && Number.isFinite(asked) && asked >= 0 && asked <= 60_000 ? asked : 250;
211
+ }
191
212
  /**
192
- * The one-shot summary call. Collects the adapter's text deltas into the
193
- * summary; usage/stop pass through untouched. Throws when the model
194
- * produced no text — the caller reports it and nothing is persisted.
213
+ * The summary call, with ONE retry.
214
+ *
215
+ * 0.39.1: `/compact` had no retry at all. The kernel owns retries
216
+ * (ADR-0005) and this path does not go through the kernel — it calls the
217
+ * adapter directly — so a gateway that drops a 95k-token summary stream
218
+ * failed `/compact` every single time, with an honest message and no way
219
+ * forward. The adapter classifies that as a retryable `network` failure
220
+ * (the transport-failure-after-headers class); here is the only place
221
+ * that can act on it.
222
+ *
223
+ * ONE retry, not a loop, and not the kernel's budget: a summary re-pays
224
+ * its whole input, which on the sessions that need compacting is the
225
+ * most expensive request the session makes. A permanent error still
226
+ * throws on the first attempt — the retry is keyed on the classification
227
+ * the adapter already made, never on the fact that something failed.
195
228
  */
196
229
  export async function summarizeConversation(options) {
230
+ // Asked as a CALL, twice, because `aborted` is a readonly property and
231
+ // the narrowing from the first read would otherwise be carried across
232
+ // the await — where the whole point is that it can have changed.
233
+ const aborted = () => options.signal?.aborted === true;
234
+ try {
235
+ return await summaryAttempt(options);
236
+ }
237
+ catch (err) {
238
+ // The caller's cancel is the caller's: an aborted `/compact` must
239
+ // not spend a second call on its way out.
240
+ if (!retryableStructured(err) || aborted())
241
+ throw err;
242
+ await new Promise((r) => setTimeout(r, retryWaitMs(err)));
243
+ if (aborted())
244
+ throw err;
245
+ return await summaryAttempt(options);
246
+ }
247
+ }
248
+ /**
249
+ * ONE attempt. Collects the adapter's text deltas into the summary;
250
+ * usage/stop pass through untouched. Throws when the model produced no
251
+ * text — the caller reports it and nothing is persisted.
252
+ */
253
+ async function summaryAttempt(options) {
197
254
  const { adapter, model, messages } = options;
198
255
  let text = "";
199
256
  let usage = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-runtime",
3
- "version": "0.38.0",
3
+ "version": "0.39.1",
4
4
  "description": "kiso runtime \u2014 durable multi-turn agent sessions: AgentDefinition, AgentRuntime, AgentSession, Run, append-only JSONL store.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -25,12 +25,12 @@
25
25
  "test": "vitest run"
26
26
  },
27
27
  "dependencies": {
28
- "@vincemakes/kiso-core": "0.38.0"
28
+ "@vincemakes/kiso-core": "0.39.1"
29
29
  },
30
30
  "peerDependencies": {
31
- "@vincemakes/kiso-provider-anthropic": "0.38.0",
32
- "@vincemakes/kiso-provider-openai": "0.38.0",
33
- "@vincemakes/kiso-provider-openai-responses": "0.38.0"
31
+ "@vincemakes/kiso-provider-anthropic": "0.39.1",
32
+ "@vincemakes/kiso-provider-openai": "0.39.1",
33
+ "@vincemakes/kiso-provider-openai-responses": "0.39.1"
34
34
  },
35
35
  "peerDependenciesMeta": {
36
36
  "@vincemakes/kiso-provider-anthropic": {
@@ -44,7 +44,7 @@
44
44
  }
45
45
  },
46
46
  "devDependencies": {
47
- "@vincemakes/kiso-evals": "0.38.0",
47
+ "@vincemakes/kiso-evals": "0.39.1",
48
48
  "@types/node": "^26.1.2",
49
49
  "typescript": "^5.7.2",
50
50
  "vitest": "^3.0.0"