@vincemakes/kiso-runtime 0.51.0 → 0.51.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.
@@ -183,6 +183,16 @@ function unavailable(err) {
183
183
  return new LockUnavailableError(`${e.code ?? "?"}: ${e.message}`);
184
184
  }
185
185
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
186
+ /**
187
+ * The tokens of the lock handles THIS process holds, or is in the middle of
188
+ * publishing. A lock naming our pid is a same-process writer's residue only
189
+ * when its token is in here; any other token was left by a PREVIOUS process
190
+ * that had the same pid — in a container node is pid 1, so a SIGKILLed
191
+ * container's lock names the next container's pid too. Kept on globalThis so
192
+ * a second copy of this module in the same process shares one answer.
193
+ */
194
+ const HELD_KEY = Symbol.for("kiso.lock-adapter.held-tokens");
195
+ const held = (globalThis[HELD_KEY] ??= new Set());
186
196
  class NativeLockHandle {
187
197
  pid;
188
198
  token;
@@ -205,6 +215,7 @@ class NativeLockHandle {
205
215
  if (this.#released)
206
216
  return;
207
217
  this.#released = true;
218
+ held.delete(this.token);
208
219
  try {
209
220
  renameSync(this.#lockPath, this.#tombstone);
210
221
  }
@@ -258,8 +269,20 @@ class NativeLockHandle {
258
269
  class NativeLock {
259
270
  name = "link-lock";
260
271
  async acquire(lockPath, sessionId, cancelled) {
261
- const pid = process.pid;
272
+ // Our token is registered before any file can name it; a handle's
273
+ // release drops it, and a failed acquire drops it here.
262
274
  const token = randomUUID();
275
+ held.add(token);
276
+ try {
277
+ return await this.#take(lockPath, sessionId, cancelled, token);
278
+ }
279
+ catch (err) {
280
+ held.delete(token);
281
+ throw err;
282
+ }
283
+ }
284
+ async #take(lockPath, sessionId, cancelled, token) {
285
+ const pid = process.pid;
263
286
  // The staging name is PER-ATTEMPT: a later rename-away in the same
264
287
  // acquire must never atomically overwrite an earlier attempt's
265
288
  // abandoned staging (that would clobber the displacement residue,
@@ -276,7 +299,11 @@ class NativeLock {
276
299
  cancelled();
277
300
  const staging = `${lockPath}.staging-${pid}-${token}-${attempt}`;
278
301
  const seen = readLockIdentity(lockPath);
279
- if (seen === null || seen.pid === undefined || !isAlive(seen.pid)) {
302
+ // A lock naming OUR pid with a token this process never issued is a
303
+ // previous process's (a killed container's node was pid 1 too): a
304
+ // dead holder, however alive the pid looks.
305
+ const stalePid = seen !== null && seen.pid === pid && seen.token !== undefined && !held.has(seen.token);
306
+ if (seen === null || seen.pid === undefined || stalePid || !isAlive(seen.pid)) {
280
307
  // Fresh path, dead holder, or stale residue — take it over
281
308
  // by identity confirmation: rename-away → verify → link.
282
309
  if (readyDir !== undefined)
@@ -366,8 +393,8 @@ class NativeLock {
366
393
  return new NativeLockHandle(lockPath, tombstone, { pid, token });
367
394
  }
368
395
  if (seen.pid === pid && seen.token !== undefined) {
369
- // Same-process writer's residue (round 5): another store in
370
- // THIS process holds the lock — it will release; retry until
396
+ // Same-process writer (round 5): another store in THIS process
397
+ // holds the lock (its token is in `held`) — it will release; retry until
371
398
  // it does (never a spurious self-conflict). A legacy
372
399
  // bare-pid lock naming our own process is refused like any
373
400
  // live foreign owner.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-runtime",
3
- "version": "0.51.0",
3
+ "version": "0.51.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.51.0"
28
+ "@vincemakes/kiso-core": "0.51.1"
29
29
  },
30
30
  "peerDependencies": {
31
- "@vincemakes/kiso-provider-anthropic": "0.51.0",
32
- "@vincemakes/kiso-provider-openai": "0.51.0",
33
- "@vincemakes/kiso-provider-openai-responses": "0.51.0"
31
+ "@vincemakes/kiso-provider-anthropic": "0.51.1",
32
+ "@vincemakes/kiso-provider-openai": "0.51.1",
33
+ "@vincemakes/kiso-provider-openai-responses": "0.51.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.51.0",
47
+ "@vincemakes/kiso-evals": "0.51.1",
48
48
  "@types/node": "^26.1.2",
49
49
  "typescript": "^5.7.2",
50
50
  "vitest": "^3.0.0"