agents-can-communicate 0.6.0 → 0.6.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.
Files changed (21) hide show
  1. package/node_modules/@agents-can-communicate/adapter-antigravity/package.json +1 -1
  2. package/node_modules/@agents-can-communicate/adapter-antigravity/plugin/plugin.json +1 -1
  3. package/node_modules/@agents-can-communicate/adapter-claude-code/package.json +1 -1
  4. package/node_modules/@agents-can-communicate/adapter-codex/package.json +1 -1
  5. package/node_modules/@agents-can-communicate/adapter-gemini-cli/extension/gemini-extension.json +1 -1
  6. package/node_modules/@agents-can-communicate/adapter-gemini-cli/package.json +1 -1
  7. package/node_modules/@agents-can-communicate/adapter-grok/package.json +1 -1
  8. package/node_modules/@agents-can-communicate/adapter-kimi/package.json +1 -1
  9. package/node_modules/@agents-can-communicate/adapter-sdk/package.json +1 -1
  10. package/node_modules/@agents-can-communicate/cli/package.json +1 -1
  11. package/node_modules/@agents-can-communicate/core/package.json +1 -1
  12. package/node_modules/@agents-can-communicate/core/src/sessions.mjs +1 -2
  13. package/node_modules/@agents-can-communicate/delivery-router/package.json +1 -1
  14. package/node_modules/@agents-can-communicate/hook-runner/package.json +1 -1
  15. package/node_modules/@agents-can-communicate/installer/package.json +1 -1
  16. package/node_modules/@agents-can-communicate/mcp-server/package.json +1 -1
  17. package/node_modules/@agents-can-communicate/protocol/package.json +1 -1
  18. package/node_modules/@agents-can-communicate/storage-filesystem/package.json +1 -1
  19. package/node_modules/@agents-can-communicate/storage-filesystem/src/retention.mjs +23 -13
  20. package/node_modules/@agents-can-communicate/storage-filesystem/src/store.mjs +18 -1
  21. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/adapter-antigravity",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "acc",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Coordinate this Antigravity CLI session with other AI agent sessions working in the same workspace."
5
5
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/adapter-claude-code",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/adapter-codex",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-can-communicate",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Coordinate this Gemini CLI session with other AI agent sessions working in the same workspace.",
5
5
  "contextFileName": "skills/acc/SKILL.md"
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/adapter-gemini-cli",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/adapter-grok",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/adapter-kimi",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/adapter-sdk",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/cli",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/core",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -58,8 +58,7 @@ export function createSessionService(ports) {
58
58
  const ephemeral = await store.ephemeral.get("session", sessionId);
59
59
  const resolved = workspaceId ?? store.workspaceId ?? ephemeral?.workspaceId;
60
60
  if (resolved === undefined) return null;
61
- const durable = (await store.snapshot(resolved, { kinds: ["session"] })).sessions
62
- .find(session => session.sessionId === sessionId) ?? null;
61
+ const durable = await store.stateRecord(resolved, "session", sessionId);
63
62
  if (durable !== null) return { record: durable, durable: true };
64
63
  return ephemeral !== null && ephemeral.workspaceId === resolved
65
64
  ? { record: ephemeral, durable: false } : null;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/delivery-router",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/hook-runner",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/installer",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/mcp-server",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/protocol",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/storage-filesystem",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -58,28 +58,34 @@ function ephemeralDirectory(paths, kind, id) {
58
58
  return path.join(paths.retained, "ephemeral", kind, id);
59
59
  }
60
60
 
61
+ // The newest marker decides a record's state, so only that one is read and
62
+ // checked. Every name is still validated first - an unparsable sequence fails
63
+ // closed before anything is selected - and names are ordered as numbers, since
64
+ // a sequence can outgrow its padding. Reading every marker made each lookup
65
+ // cost an open and a full ancestor check per marker ever written: thousands
66
+ // for a delivery binding renewed every forty seconds, and seconds for one
67
+ // status in a workspace that had been in use for weeks.
61
68
  async function latestEphemeralMarker(paths, root, kind, id) {
62
69
  const directory = ephemeralDirectory(paths, kind, id);
63
- const markers = [];
64
- for (const filePath of await listJsonFiles(directory, { root })) {
70
+ const named = (await listJsonFiles(directory, { root })).map(filePath => {
65
71
  const sequence = path.basename(filePath, ".json");
72
+ if (typeof sequence !== "string" || !/^\d+$/.test(sequence)
73
+ || BigInt(sequence) < 1n || sequence !== pad(BigInt(sequence))) {
74
+ data("invalid ephemeral retention marker", { filePath });
75
+ }
76
+ return { filePath, sequence, order: BigInt(sequence) };
77
+ }).sort((left, right) => (left.order < right.order ? 1 : left.order > right.order ? -1 : 0));
78
+ for (const { filePath, sequence } of named) {
66
79
  const found = await readJsonIfPresent(filePath, root);
67
80
  if (found === null) continue;
68
81
  const marker = found.value;
69
- if (typeof sequence !== "string" || !/^\d+$/.test(sequence)
70
- || BigInt(sequence) < 1n || sequence !== pad(BigInt(sequence))
71
- || !(marker?.state === "present" || marker?.state === "deleted")) {
82
+ if (!(marker?.state === "present" || marker?.state === "deleted")) {
72
83
  data("invalid ephemeral retention marker", { filePath });
73
84
  }
74
- assertMarker(found, { area: "ephemeral", kind, id, sequence, state: marker.state },
75
- filePath);
76
- markers.push(marker);
85
+ assertMarker(found, { area: "ephemeral", kind, id, sequence, state: marker.state }, filePath);
86
+ return marker;
77
87
  }
78
- return markers.sort((left, right) => {
79
- const leftSequence = BigInt(left.sequence);
80
- const rightSequence = BigInt(right.sequence);
81
- return leftSequence < rightSequence ? -1 : leftSequence > rightSequence ? 1 : 0;
82
- }).at(-1) ?? null;
88
+ return null;
83
89
  }
84
90
 
85
91
  export async function ephemeralIsDeleted(paths, root, kind, id) {
@@ -91,6 +97,10 @@ export async function markEphemeral(paths, options, kind, id, state) {
91
97
  data("invalid ephemeral retention state", { state });
92
98
  }
93
99
  const previous = await latestEphemeralMarker(paths, options.root, kind, id);
100
+ // A marker that repeats the current state changes nothing, and every renewal
101
+ // of a live record used to append one. History now grows only with a real
102
+ // change: published after a deletion, or deleted.
103
+ if (previous?.state === state) return previous;
94
104
  const sequence = pad(previous === null ? 1n : BigInt(previous.sequence) + 1n);
95
105
  const record = { retentionVersion: RETENTION_VERSION, area: "ephemeral", kind, id,
96
106
  sequence, state };
@@ -265,6 +265,23 @@ export async function openFilesystemStore({ root, clock, ids, workspaceId, failA
265
265
  * cost grow with the number of messages the workspace had ever carried, and
266
266
  * the hook budget is five seconds after which it allows the write.
267
267
  */
268
+ /**
269
+ * One state record by id, or null - the checks a listing applies to each
270
+ * record (the path names it, a deleted generation is absent, the record
271
+ * validates, it belongs to this workspace) without reading every other
272
+ * record of its kind. Looking one session up by listing them all cost a full
273
+ * pass over every session the workspace ever had, several times a hook.
274
+ */
275
+ async function stateRecord(workspace, kind, id) {
276
+ const filePath = statePath(paths, kind, id);
277
+ const found = await readJsonIfPresent(filePath, root);
278
+ if (found === null) return null;
279
+ const envelope = assertStateBinding(found.value, kind, id, filePath);
280
+ if (await stateGenerationIsDeleted(paths, root, kind, envelope.id, envelope.generation)) return null;
281
+ validateRecord(kind, envelope.record);
282
+ return envelope.record.workspaceId === workspace ? envelope.record : null;
283
+ }
284
+
268
285
  async function snapshot(workspace, { kinds } = {}) {
269
286
  const wanted = kinds === undefined ? null : new Set(kinds);
270
287
  const of = async kind => {
@@ -348,6 +365,6 @@ export async function openFilesystemStore({ root, clock, ids, workspaceId, failA
348
365
  },
349
366
  });
350
367
 
351
- return Object.freeze({ transaction, eventsSince, snapshot, ephemeral, paths, root,
368
+ return Object.freeze({ transaction, eventsSince, snapshot, stateRecord, ephemeral, paths, root,
352
369
  workspaceId });
353
370
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-can-communicate",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "accManagedUpdateProtocol": 2,
5
5
  "accStoreVersion": 6,
6
6
  "type": "module",