@deepstrike/sdk 0.2.51 → 0.2.52

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.
@@ -30,6 +30,10 @@ export interface CanonicalTransition {
30
30
  recordDigest: string;
31
31
  plannedStep: CanonicalPlannedStep;
32
32
  checkpointAdvice?: Record<string, unknown>;
33
+ /** Set when the advised §12.3 checkpoint failed AFTER this step was durably committed.
34
+ * The step itself is published and authoritative; the checkpoint is deferred
35
+ * housekeeping retried at the next advice or forced by the checkpoint_required gate. */
36
+ checkpointFailure?: string;
33
37
  replayed: boolean;
34
38
  }
35
39
  export declare function canonicalUnsupportedEffectResolution(effectId: string, effectKind: string): CanonicalKernelInput;
@@ -44,8 +48,13 @@ export declare class CanonicalKernelRejectedError extends Error {
44
48
  * is therefore a rebuild boundary, never an abort boundary.
45
49
  */
46
50
  export declare class CanonicalKernelRebuildRequiredError extends Error {
51
+ /** True when the runtime was already rebuilt from the journal with the durable record
52
+ * applied — the caller can resync and continue. False when the rebuild itself failed
53
+ * and the operation cannot proceed without journal repair. */
54
+ readonly rebuilt: boolean;
47
55
  constructor(message: string, options?: {
48
56
  cause?: unknown;
57
+ rebuilt?: boolean;
49
58
  });
50
59
  }
51
60
  /**
@@ -281,9 +281,14 @@ export class CanonicalKernelRejectedError extends Error {
281
281
  * is therefore a rebuild boundary, never an abort boundary.
282
282
  */
283
283
  export class CanonicalKernelRebuildRequiredError extends Error {
284
+ /** True when the runtime was already rebuilt from the journal with the durable record
285
+ * applied — the caller can resync and continue. False when the rebuild itself failed
286
+ * and the operation cannot proceed without journal repair. */
287
+ rebuilt;
284
288
  constructor(message, options) {
285
- super(message, options);
289
+ super(message, options?.cause !== undefined ? { cause: options.cause } : undefined);
286
290
  this.name = "CanonicalKernelRebuildRequiredError";
291
+ this.rebuilt = options?.rebuilt ?? false;
287
292
  }
288
293
  }
289
294
  function chainPosition(value, label) {
@@ -434,6 +439,7 @@ export class CanonicalKernelHost {
434
439
  }
435
440
  const stepSeq = chainPosition(preparation.stepSeq, "prepared stepSeq");
436
441
  let appended = false;
442
+ let transition;
437
443
  try {
438
444
  const receipt = await this.journal.compareAndAppend(this.operationId, preparation.expectedHead, {
439
445
  step_seq: stepSeq,
@@ -447,7 +453,7 @@ export class CanonicalKernelHost {
447
453
  throw new Error("canonical commit receipt disagrees with the durably appended record");
448
454
  }
449
455
  const checkpointAdvice = parseAdvice(committed.checkpointAdviceJson);
450
- const transition = {
456
+ transition = {
451
457
  inputJson,
452
458
  stepSeq,
453
459
  recordDigest: committed.recordDigest,
@@ -455,9 +461,6 @@ export class CanonicalKernelHost {
455
461
  ...(checkpointAdvice ? { checkpointAdvice } : {}),
456
462
  replayed: false,
457
463
  };
458
- if (checkpointAdvice)
459
- await this.checkpoint();
460
- return transition;
461
464
  }
462
465
  catch (error) {
463
466
  if (appended) {
@@ -467,7 +470,7 @@ export class CanonicalKernelHost {
467
470
  catch (restoreError) {
468
471
  throw new CanonicalKernelRebuildRequiredError("canonical record is durable, commit failed, and journal rebuild also failed", { cause: new AggregateError([error, restoreError]) });
469
472
  }
470
- throw new CanonicalKernelRebuildRequiredError("canonical record is durable but commit could not be published; runtime rebuilt from journal", { cause: error });
473
+ throw new CanonicalKernelRebuildRequiredError("canonical record is durable but commit could not be published; runtime rebuilt from journal", { cause: error, rebuilt: true });
471
474
  }
472
475
  try {
473
476
  this.kernel.abort(preparation.prepareToken);
@@ -481,6 +484,19 @@ export class CanonicalKernelHost {
481
484
  }
482
485
  throw error;
483
486
  }
487
+ // Past this point the step is durable AND committed. A failing advised checkpoint
488
+ // must not be misdiagnosed as a lost commit: it is deferred housekeeping — the next
489
+ // advice retries it, and the checkpoint_required prepare gate is the hard backstop.
490
+ if (transition.checkpointAdvice) {
491
+ try {
492
+ await this.checkpoint();
493
+ }
494
+ catch (checkpointError) {
495
+ transition.checkpointFailure =
496
+ checkpointError instanceof Error ? checkpointError.message : String(checkpointError);
497
+ }
498
+ }
499
+ return transition;
484
500
  }
485
501
  }
486
502
  function canonicalProviderMessage(raw) {
@@ -1100,22 +1116,45 @@ export class CanonicalRunnerRuntime {
1100
1116
  async commit(input) {
1101
1117
  let nextInput = input;
1102
1118
  for (;;) {
1103
- const transition = await this.host.transition(nextInput);
1104
- if (!transition.replayed) {
1105
- for (const raw of transition.plannedStep.observations ?? []) {
1106
- const kind = String(raw.kind ?? "");
1107
- if (!kind)
1108
- throw new Error("canonical observation is missing kind");
1109
- this.hostObservations.push({ ...raw, kind });
1110
- }
1111
- if (transition.checkpointAdvice) {
1112
- this.hostObservations.push({
1113
- kind: "checkpoint_advised",
1114
- ...transition.checkpointAdvice,
1115
- });
1119
+ let transition;
1120
+ try {
1121
+ transition = await this.host.transition(nextInput);
1122
+ }
1123
+ catch (error) {
1124
+ if (!(error instanceof CanonicalKernelRebuildRequiredError) || !error.rebuilt)
1125
+ throw error;
1126
+ // The input's record is durable and the kernel was rebuilt from the journal with it
1127
+ // applied; only that step's observations are lost (the crash-window cost). Resync and
1128
+ // publish the rebuilt kernel's pending work instead of failing a healthy run.
1129
+ const lifecycle = this.host.kernel.lifecycle();
1130
+ this.configured = lifecycle !== "created";
1131
+ this.started = !["created", "configured"].includes(lifecycle);
1132
+ this.hostObservations.push({ kind: "kernel_rebuilt", reason: error.message });
1133
+ this.lastAction = this.currentAction();
1134
+ }
1135
+ if (transition) {
1136
+ if (!transition.replayed) {
1137
+ for (const raw of transition.plannedStep.observations ?? []) {
1138
+ const kind = String(raw.kind ?? "");
1139
+ if (!kind)
1140
+ throw new Error("canonical observation is missing kind");
1141
+ this.hostObservations.push({ ...raw, kind });
1142
+ }
1143
+ if (transition.checkpointAdvice) {
1144
+ this.hostObservations.push({
1145
+ kind: "checkpoint_advised",
1146
+ ...transition.checkpointAdvice,
1147
+ });
1148
+ }
1149
+ if (transition.checkpointFailure) {
1150
+ this.hostObservations.push({
1151
+ kind: "checkpoint_deferred",
1152
+ reason: transition.checkpointFailure,
1153
+ });
1154
+ }
1116
1155
  }
1156
+ this.lastAction = canonicalActionFromPlannedStep(transition.plannedStep);
1117
1157
  }
1118
- this.lastAction = canonicalActionFromPlannedStep(transition.plannedStep);
1119
1158
  if (this.lastAction?.kind !== "unsupported_effect")
1120
1159
  return this.lastAction;
1121
1160
  nextInput = canonicalUnsupportedEffectResolution(this.lastAction.effectId, this.lastAction.effectKind);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepstrike/sdk",
3
- "version": "0.2.51",
3
+ "version": "0.2.52",
4
4
  "description": "DeepStrike Node.js SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -72,7 +72,7 @@
72
72
  },
73
73
  "dependencies": {
74
74
  "@anthropic-ai/sdk": "^0.99.0",
75
- "@deepstrike/core": "0.2.51",
75
+ "@deepstrike/core": "0.2.52",
76
76
  "@google/generative-ai": "^0.24.1",
77
77
  "openai": "^5.23.2"
78
78
  },