@jskit-ai/assistant-core 0.1.229 → 0.1.230

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.
@@ -8,7 +8,7 @@
8
8
  "build": "vite build"
9
9
  },
10
10
  "dependencies": {
11
- "@jskit-ai/assistant-core": "0.1.229",
11
+ "@jskit-ai/assistant-core": "0.1.230",
12
12
  "@jskit-ai/http-runtime": "0.1.242",
13
13
  "@jskit-ai/kernel": "0.1.244",
14
14
  "@mdi/js": "^7.4.47",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/assistant-core",
3
- "version": "0.1.229",
3
+ "version": "0.1.230",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "test": "node --test --test-concurrency=1"
@@ -2,6 +2,7 @@ import { createHash, randomUUID } from "node:crypto";
2
2
  import { homedir } from "node:os";
3
3
  import path from "node:path";
4
4
  import { realpath } from "node:fs/promises";
5
+ import { isDeepStrictEqual } from "node:util";
5
6
  import { bindClaudeConversationAccount, claudeConnectionIdentity, claudeFlagSettings, claudeModelConfiguration, readClaudeCodeAuthStatus } from "../claudeProcess.js";
6
7
  import { nativeAiModel, nativeAiProvider } from "../../../shared/nativeProviders.js";
7
8
  import { requireClaudeSessionId, listClaudeConversationStorage } from "../claudeHistory.js";
@@ -107,7 +108,13 @@ export function createClaudeConversationDriver({ connections, host = {}, limits
107
108
  const store = {
108
109
  read(context) { return JSON.stringify({ executionId: context.binding.executionId, sent: context.binding.sent, pausedGoal: context.binding.pausedGoal, blockedGoal: context.binding.blockedGoal }); },
109
110
  async save(entry, { execution = false } = {}) {
110
- await entry.context.updateBinding({ pausedGoal: entry.pausedGoal, blockedGoal: entry.blockedGoal, ...(execution ? { executionId: entry.executionId } : {}) });
111
+ // Only execution and retained-goal changes belong to the binding. An
112
+ // unchanged save (such as opening a replacement successor before its
113
+ // owner commits) must not write through the provider's binding fence.
114
+ const { binding } = entry.context;
115
+ const goals = { pausedGoal: entry.pausedGoal ?? null, blockedGoal: entry.blockedGoal ?? null };
116
+ if (!execution && isDeepStrictEqual(goals, { pausedGoal: binding.pausedGoal ?? null, blockedGoal: binding.blockedGoal ?? null })) return;
117
+ await entry.context.updateBinding({ ...goals, ...(execution ? { executionId: entry.executionId } : {}) });
111
118
  },
112
119
  async releaseExecution(entry) {
113
120
  await entry.context.updateBinding({ executionId: "" });
@@ -1550,6 +1550,18 @@ for (const saveFails of [false, true]) test(`Claude retains failed-start custody
1550
1550
  }
1551
1551
  });
1552
1552
 
1553
+ test("opening an inert Claude successor binding does not write through the provider fence", async t => {
1554
+ const f = await fixture(t);
1555
+ await f.first.close();
1556
+ const driver = createClaudeConversationDriver(f.driverOptions);
1557
+ // A replacement opens its successor before the runtime commits the new owner.
1558
+ const writeBinding = () => { throw new Error("A retired provider cannot change a native binding."); };
1559
+ for (const binding of [await driver.createBinding(), { ...await driver.createBinding(), pausedGoal: null, blockedGoal: null }]) {
1560
+ const provider = await driver.open({ binding, writeBinding, onFailure() {} });
1561
+ await provider.dispose();
1562
+ }
1563
+ });
1564
+
1553
1565
  test("original scoped Claude history resumes from the authorized credential home while retaining its private scope", async t => {
1554
1566
  const f = await fixture(t);
1555
1567
  await f.first.close();