agents-can-communicate 0.1.0 → 0.1.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 (23) hide show
  1. package/node_modules/@agents-can-communicate/adapter-claude-code/package.json +1 -1
  2. package/node_modules/@agents-can-communicate/adapter-claude-code/plugin/.claude-plugin/plugin.json +1 -1
  3. package/node_modules/@agents-can-communicate/adapter-codex/package.json +1 -1
  4. package/node_modules/@agents-can-communicate/adapter-codex/plugin/.codex-plugin/plugin.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-kimi/package.json +1 -1
  8. package/node_modules/@agents-can-communicate/adapter-kimi/plugin/.kimi-plugin/plugin.json +1 -1
  9. package/node_modules/@agents-can-communicate/adapter-sdk/package.json +1 -1
  10. package/node_modules/@agents-can-communicate/adapter-sdk/src/config-merge.mjs +16 -1
  11. package/node_modules/@agents-can-communicate/adapter-sdk/src/index.mjs +1 -0
  12. package/node_modules/@agents-can-communicate/adapter-sdk/src/json-text.mjs +195 -0
  13. package/node_modules/@agents-can-communicate/cli/package.json +1 -1
  14. package/node_modules/@agents-can-communicate/cli/src/args.mjs +4 -1
  15. package/node_modules/@agents-can-communicate/cli/src/install-command.mjs +24 -3
  16. package/node_modules/@agents-can-communicate/core/package.json +1 -1
  17. package/node_modules/@agents-can-communicate/hook-runner/package.json +1 -1
  18. package/node_modules/@agents-can-communicate/installer/package.json +1 -1
  19. package/node_modules/@agents-can-communicate/installer/src/plan.mjs +28 -5
  20. package/node_modules/@agents-can-communicate/mcp-server/package.json +1 -1
  21. package/node_modules/@agents-can-communicate/protocol/package.json +1 -1
  22. package/node_modules/@agents-can-communicate/storage-filesystem/package.json +1 -1
  23. package/package.json +4 -4
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/adapter-claude-code",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "agents-can-communicate",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Coordinate this Claude Code session with other AI agent sessions working in the same workspace: shared presence, resource claims, typed messages, and handoffs."
5
5
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/adapter-codex",
3
- "version": "0.1.0",
3
+ "version": "0.1.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.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Coordinate this Codex session with other AI agent sessions working in the same workspace.",
5
5
  "license": "UNLICENSED",
6
6
  "keywords": ["coordination", "multi-agent", "claims", "handoff"],
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-can-communicate",
3
- "version": "0.1.0",
3
+ "version": "0.1.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.1.0",
3
+ "version": "0.1.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.1.0",
3
+ "version": "0.1.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.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Coordinate this Kimi Code session with other AI agent sessions working in the same workspace: shared presence, resource claims, typed messages, and handoffs.",
5
5
  "skills": "./skills/",
6
6
  "sessionStart": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/adapter-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,5 +1,7 @@
1
1
  import path from "node:path";
2
2
 
3
+ import { editJson } from "./json-text.mjs";
4
+
3
5
  const MARKER = "acc:owned";
4
6
  // Ownership of single entries inside a container someone else also writes to.
5
7
  // `enabledPlugins` in a Claude Code settings file holds every plugin the user
@@ -150,10 +152,23 @@ export function jsonStyleOf(text) {
150
152
  * Unchanged content is not rewritten at all, so a second install touches
151
153
  * nothing. A file that does not exist yet is ACC's to create, and gets the
152
154
  * conventional trailing newline.
155
+ *
156
+ * What is there is edited rather than re-emitted. Reading the style back out of
157
+ * the file kept the indentation, and still reformatted everything the style
158
+ * could not describe: a nested object a person had written on one line came
159
+ * back as three, and a blank line between sections was gone. The bytes are
160
+ * theirs, and the diff ACC leaves should be of what it changed.
153
161
  */
154
162
  export async function writeForeignJson(file, value, { readFile, writeFile, mkdir }) {
155
163
  const current = await readFile(file, "utf8").catch(() => null);
156
- const text = formatJsonAs(value, jsonStyleOf(current));
164
+ const style = jsonStyleOf(current);
165
+ // Null when the original cannot be read, or when the edit came back meaning
166
+ // something other than it was asked to write. Then this is the whole-file
167
+ // re-emit it has always been.
168
+ const spliced = typeof current === "string" ? editJson(current, value, style.indent) : null;
169
+ const text = spliced === null
170
+ ? formatJsonAs(value, style)
171
+ : (style.trailingNewline === false ? spliced : `${spliced}\n`);
157
172
  if (current === text) return false;
158
173
  await mkdir(path.dirname(file), { recursive: true });
159
174
  await writeFile(file, text);
@@ -8,6 +8,7 @@ export { assertRunner, bakeSkillCommand, defaultCli, defaultRunner, removeInstal
8
8
  export { BEGIN, END, removeTomlBlock, renderBlock, stripBlock, tomlString, writeTomlBlock }
9
9
  from "./toml-block.mjs";
10
10
  export { projectContext } from "./context-projector.mjs";
11
+ export { editJson, readJson } from "./json-text.mjs";
11
12
  export { formatJsonAs, jsonStyleOf, mergeOwnedConfig, mergeOwnedEntries, ownedEntries, ownedKeys,
12
13
  acccreatedFile, removeIfEmpty, removeOwnedConfig, removeOwnedEntries, writeForeignJson,
13
14
  blankJson, blankText } from "./config-merge.mjs";
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Edit a JSON document as text, so what was not changed is not rewritten.
3
+ *
4
+ * `JSON.parse` then `JSON.stringify` re-emits every byte of a file, which
5
+ * reformats the parts ACC was not asked to touch: a nested object a person kept
6
+ * on one line comes back as three, and a blank line between sections is gone.
7
+ * The bytes are the user's, and a tool that edits their settings should leave a
8
+ * diff of what it changed rather than of how it prints.
9
+ *
10
+ * So the original text is kept and spliced. Anything whose value is unchanged is
11
+ * copied across verbatim - not re-serialised and hoped to match - and only a
12
+ * member that was added, removed or replaced is written fresh.
13
+ *
14
+ * The result is parsed back and compared to the value it was asked to write. A
15
+ * splice that would change meaning is discarded rather than written, and the
16
+ * caller falls back to plain `JSON.stringify`: the worst this can do is what
17
+ * was already being done.
18
+ */
19
+
20
+ const WHITESPACE = " \t\n\r";
21
+ const same = (left, right) => JSON.stringify(left) === JSON.stringify(right);
22
+
23
+ const isObject = value =>
24
+ value !== null && typeof value === "object" && !Array.isArray(value);
25
+
26
+ /**
27
+ * Read a JSON document into a tree that remembers where everything was.
28
+ *
29
+ * @returns the root node, or null for anything this cannot read - which the
30
+ * caller treats the same way as a file it must not touch.
31
+ */
32
+ export function readJson(text) {
33
+ if (typeof text !== "string") return null;
34
+ let at = 0;
35
+
36
+ const skip = () => { while (at < text.length && WHITESPACE.includes(text[at])) at += 1; };
37
+ const fail = () => { throw new SyntaxError(`unreadable JSON at ${at}`); };
38
+ const expect = character => { if (text[at] !== character) fail(); at += 1; };
39
+
40
+ const readString = () => {
41
+ expect('"');
42
+ while (at < text.length) {
43
+ if (text[at] === "\\") { at += 2; continue; }
44
+ if (text[at] === '"') { at += 1; return; }
45
+ at += 1;
46
+ }
47
+ fail();
48
+ };
49
+
50
+ const readValue = () => {
51
+ skip();
52
+ const start = at;
53
+ if (text[at] === "{") return readObject(start);
54
+ if (text[at] === "[") return readArray(start);
55
+ if (text[at] === '"') { readString(); }
56
+ else {
57
+ // Numbers, true, false, null: read to the next structural character and
58
+ // let `JSON.parse` below be the judge of what was read.
59
+ while (at < text.length && !",}]".includes(text[at]) && !WHITESPACE.includes(text[at])) {
60
+ at += 1;
61
+ }
62
+ if (at === start) fail();
63
+ }
64
+ const slice = text.slice(start, at);
65
+ return { kind: "scalar", start, end: at, value: JSON.parse(slice) };
66
+ };
67
+
68
+ function readObject(start) {
69
+ expect("{");
70
+ const members = [];
71
+ const value = {};
72
+ for (;;) {
73
+ // Everything between the previous member and this one - the comma, the
74
+ // newline, the indentation - is kept as it was written.
75
+ const gapStart = at;
76
+ skip();
77
+ if (text[at] === "}") { at += 1; break; }
78
+ if (members.length > 0) { expect(","); skip(); }
79
+ if (text[at] === "}") { at += 1; break; }
80
+ const keyStart = at;
81
+ readString();
82
+ const key = JSON.parse(text.slice(keyStart, at));
83
+ skip();
84
+ expect(":");
85
+ const node = readValue();
86
+ members.push({ key, gapStart, keyStart, valueStart: node.start, end: node.end, node });
87
+ // Defined rather than assigned: `value.__proto__ = …` sets the prototype
88
+ // of an ordinary object instead of adding a key to it, so a config with
89
+ // that key read back without it - and the comparison that decides whether
90
+ // a subtree changed would be answering about a different document than
91
+ // the one on disk. This is what `JSON.parse` does with the same input.
92
+ Object.defineProperty(value, key,
93
+ { value: node.value, writable: true, enumerable: true, configurable: true });
94
+ }
95
+ return { kind: "object", start, end: at, value, members };
96
+ }
97
+
98
+ function readArray(start) {
99
+ expect("[");
100
+ const items = [];
101
+ const value = [];
102
+ for (;;) {
103
+ skip();
104
+ if (text[at] === "]") { at += 1; break; }
105
+ if (items.length > 0) { expect(","); skip(); }
106
+ if (text[at] === "]") { at += 1; break; }
107
+ const node = readValue();
108
+ items.push(node);
109
+ value.push(node.value);
110
+ }
111
+ return { kind: "array", start, end: at, value, items };
112
+ }
113
+
114
+ try {
115
+ const root = readValue();
116
+ skip();
117
+ // Trailing content means this is not the document it appears to be.
118
+ return at === text.length ? root : null;
119
+ } catch {
120
+ return null;
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Write `value` into `text`, changing only what differs.
126
+ *
127
+ * @returns the edited document, or null when it cannot be done safely - an
128
+ * unreadable original, or a splice that came back meaning something else.
129
+ */
130
+ export function editJson(text, value, indent) {
131
+ const root = readJson(text);
132
+ if (root === null) return null;
133
+
134
+ const unit = typeof indent === "number" ? " ".repeat(indent) : (indent ?? " ");
135
+ const pad = depth => unit.repeat(depth);
136
+ const broken = unit !== "";
137
+
138
+ // A value with no original to preserve: printed the way this file prints,
139
+ // then moved to the depth it sits at.
140
+ const fresh = (subject, depth) => {
141
+ const printed = JSON.stringify(subject, null, unit);
142
+ return broken ? printed.split("\n").join(`\n${pad(depth)}`) : printed;
143
+ };
144
+
145
+ const render = (node, subject, depth) => {
146
+ if (node !== null && same(node.value, subject)) return text.slice(node.start, node.end);
147
+ if (node?.kind === "object" && isObject(subject)) return spliceObject(node, subject, depth);
148
+ return fresh(subject, depth);
149
+ };
150
+
151
+ function spliceObject(node, subject, depth) {
152
+ const byKey = new Map(node.members.map(member => [member.key, member]));
153
+ const pieces = [];
154
+
155
+ for (const key of Object.keys(subject)) {
156
+ const member = byKey.get(key);
157
+ if (member === undefined) {
158
+ // New: written in this file's own shape rather than copied from nowhere.
159
+ pieces.push(broken
160
+ ? `\n${pad(depth + 1)}${JSON.stringify(key)}: ${fresh(subject[key], depth + 1)}`
161
+ : `${JSON.stringify(key)}:${fresh(subject[key], depth + 1)}`);
162
+ continue;
163
+ }
164
+ // The separator that preceded it, the key as it was spelled, and the
165
+ // colon and spacing after it: all of it is the user's, and none of it is
166
+ // what changed.
167
+ const separator = text.slice(member.gapStart, member.keyStart);
168
+ const label = text.slice(member.keyStart, member.valueStart);
169
+ pieces.push(separator.replace(",", "") + label + render(member.node, subject[key], depth + 1));
170
+ }
171
+
172
+ // The comma belongs between members, so it is placed rather than copied:
173
+ // a member that used to be first no longer is, and one that is now first
174
+ // must not arrive with the comma it used to carry.
175
+ const body = pieces.join(",");
176
+ // What sat between the last member and the brace, when the last member is
177
+ // still the one that was there; otherwise this file's own closing shape.
178
+ const last = node.members.at(-1);
179
+ const closing = last !== undefined && Object.keys(subject).at(-1) === last.key
180
+ ? text.slice(last.end, node.end - 1)
181
+ : (broken ? `\n${pad(depth)}` : "");
182
+ if (pieces.length === 0) return "{}";
183
+ return `{${body}${closing}}`;
184
+ }
185
+
186
+ const edited = render(root, value, 0);
187
+ // The safety net. A splice that parses to something else is not written.
188
+ let read;
189
+ try {
190
+ read = JSON.parse(edited);
191
+ } catch {
192
+ return null;
193
+ }
194
+ return same(read, value) ? edited : null;
195
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -57,7 +57,10 @@ export const COMMANDS = Object.freeze({
57
57
  config: { required: [], optional: [], flags: ["yes", "force"],
58
58
  subcommands: ["init", "validate"] },
59
59
  install: { required: [], optional: ["adapter", "home"], flags: ["dry-run", "yes"] },
60
- uninstall: { required: [], optional: ["adapter", "home"], flags: ["yes"] },
60
+ // `--dry-run` on both, because the preview was computed for either action and
61
+ // only `install` could ask for it. Removal is the side that reaches into a
62
+ // client's configuration - including a client that has left the machine.
63
+ uninstall: { required: [], optional: ["adapter", "home"], flags: ["dry-run", "yes"] },
61
64
  // The two things a person types first after installing from a registry. The
62
65
  // CLI answered neither: `acc --version` and `acc --help` were both "unknown
63
66
  // command", and `acc` on its own asked for a command without naming one.
@@ -5,7 +5,7 @@ import { createClaudeCodeAdapter } from "@agents-can-communicate/adapter-claude-
5
5
  import { createCodexAdapter } from "@agents-can-communicate/adapter-codex";
6
6
  import { createGeminiCliAdapter } from "@agents-can-communicate/adapter-gemini-cli";
7
7
  import { createKimiAdapter } from "@agents-can-communicate/adapter-kimi";
8
- import { applyPlan, detectInstallation, planInstallation }
8
+ import { applyPlan, detectInstallation, loadOwnership, planInstallation }
9
9
  from "@agents-can-communicate/installer";
10
10
  import { AccError, EXIT } from "@agents-can-communicate/protocol";
11
11
 
@@ -80,6 +80,21 @@ export function failureOf({ action, acted, failed = [] }) {
80
80
  describeOutcome({ action, acted, failed }), { failed });
81
81
  }
82
82
 
83
+ /**
84
+ * How many adapters this actually did something to.
85
+ *
86
+ * `applied` means the adapter's own step ran, which on an uninstall is true of
87
+ * every client on the machine whether ACC had ever written to it or not. So
88
+ * `uninstalled 3 adapter(s)` was the report on a machine where ACC had installed
89
+ * nothing at all - printed by the same run that skipped the one client it had
90
+ * actually written to.
91
+ */
92
+ export function actedOn(result) {
93
+ return result.operations.filter(operation => operation.applied
94
+ && (result.action === "install"
95
+ || (operation.removed?.length ?? 0) + (operation.changes?.length ?? 0) > 0)).length;
96
+ }
97
+
83
98
  export async function runInstallCommand({ options, runtime, action = "install" }) {
84
99
  const adapters = selectAdapters(options.adapter);
85
100
  const home = options.home ?? runtime.env?.HOME ?? homedir();
@@ -88,12 +103,18 @@ export async function runInstallCommand({ options, runtime, action = "install" }
88
103
  env: runtime.env ?? {} });
89
104
 
90
105
  const detected = await detectInstallation({ adapters, context });
91
- const plan = planInstallation({ adapters, detected, context, action });
106
+ // An uninstall is planned from what ACC recorded writing, not only from what
107
+ // is on the machine now. A client can be removed after ACC installed into it,
108
+ // and its configuration directory - with ACC's files in it - stays behind.
109
+ const recorded = action === "uninstall"
110
+ ? (await loadOwnership({ dataHome })).installs
111
+ : [];
112
+ const plan = planInstallation({ adapters, detected, context, action, recorded });
92
113
 
93
114
  const dryRun = options.dryRun === true;
94
115
  const result = await applyPlan({ plan, adapters, context, dataHome, dryRun });
95
116
 
96
- const acted = result.operations.filter(operation => operation.applied).length;
117
+ const acted = actedOn(result);
97
118
  if (dryRun) {
98
119
  return { data: { ...result, plan, dataHome },
99
120
  text: [`would ${action}:`, ...plan.operations.flatMap(operation => operation.summary),
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.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.1.0",
3
+ "version": "0.1.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.1.0",
3
+ "version": "0.1.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": { ".": "./src/index.mjs" },
@@ -7,11 +7,16 @@ import { AccError, EXIT } from "@agents-can-communicate/protocol";
7
7
  * makes `--dry-run` worth reading - a plan computed differently from the thing
8
8
  * it previews is a decoration, and the operator would find out only afterwards.
9
9
  */
10
- export function planInstallation({ adapters, detected, context, action = "install" }) {
10
+ export function planInstallation({ adapters, detected, context, action = "install",
11
+ recorded = [] }) {
11
12
  if (!["install", "uninstall"].includes(action)) {
12
13
  throw new AccError(EXIT.USAGE, `unknown installation action: ${action}`, { action });
13
14
  }
14
15
  const byId = new Map(adapters.map(adapter => [adapter.id, adapter]));
16
+ // What ACC recorded writing, by client. For an uninstall this is the
17
+ // authority rather than detection: the record is the only account of what was
18
+ // written, and a client's configuration directory outlives the client.
19
+ const recordedById = new Map(recorded.map(install => [install.adapterId, install]));
15
20
  const operations = [];
16
21
  const skipped = [];
17
22
 
@@ -24,20 +29,32 @@ export function planInstallation({ adapters, detected, context, action = "instal
24
29
  skipped.push({ adapterId: entry.adapterId, reason: "no adapter for this client" });
25
30
  continue;
26
31
  }
27
- if (!entry.present) {
32
+ // A client that has left the machine is still worth visiting when ACC wrote
33
+ // to it. Skipping it made that install permanently unremovable: `acc
34
+ // uninstall` reported success and exit 0, left ACC's tree in the client's
35
+ // configuration directory and ACC's entries in the user's own settings
36
+ // file, and said the same thing on every run afterwards.
37
+ const record = action === "uninstall" && !entry.present
38
+ ? recordedById.get(entry.adapterId)
39
+ : undefined;
40
+
41
+ if (!entry.present && record === undefined) {
28
42
  // Named rather than dropped: "nothing happened" and "that client is not
29
43
  // installed on this machine" look the same in an empty list.
30
44
  skipped.push({ adapterId: entry.adapterId,
31
45
  reason: `${entry.displayName ?? entry.adapterId} is not installed on this machine` });
32
46
  continue;
33
47
  }
34
- if (typeof adapter.planInstall !== "function") {
48
+ if (record === undefined && typeof adapter.planInstall !== "function") {
35
49
  skipped.push({ adapterId: entry.adapterId,
36
50
  reason: "this adapter cannot describe what it would write" });
37
51
  continue;
38
52
  }
39
53
 
40
- const artifacts = adapter.planInstall(context)
54
+ // From the record when the client is gone, because that is what was written
55
+ // and so what will be removed. Asking the adapter instead would describe an
56
+ // install for a machine this one no longer is.
57
+ const artifacts = (record?.artifacts ?? adapter.planInstall(context))
41
58
  .map(artifact => ({ path: artifact.path, kind: artifact.kind ?? "file" }))
42
59
  .sort((a, b) => a.path.localeCompare(b.path));
43
60
 
@@ -45,12 +62,18 @@ export function planInstallation({ adapters, detected, context, action = "instal
45
62
  adapterId: adapter.id,
46
63
  displayName: adapter.displayName,
47
64
  action,
48
- clientVersion: entry.version ?? null,
65
+ clientVersion: entry.version ?? record?.version ?? null,
66
+ // "Remove these files for a client that is not here" is a different thing
67
+ // to approve than an ordinary uninstall, so it is said rather than left
68
+ // to be inferred from a client version that is null.
69
+ clientPresent: entry.present === true,
49
70
  alreadyInstalled: entry.installed === true,
50
71
  artifacts,
51
72
  // Said in the operator's terms, not in paths: which files ACC creates
52
73
  // outright and which belong to the user and are only edited.
53
74
  summary: [
75
+ ...(entry.present ? [] : [`${adapter.displayName ?? adapter.id} is no longer on `
76
+ + "this machine; removing what ACC recorded writing"]),
54
77
  ...artifacts.filter(a => a.kind === "tree")
55
78
  .map(a => `${action === "install" ? "create" : "remove"} ${a.path}`),
56
79
  ...artifacts.filter(a => a.kind === "merge")
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/mcp-server",
3
- "version": "0.1.0",
3
+ "version": "0.1.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.1.0",
3
+ "version": "0.1.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.1.0",
3
+ "version": "0.1.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-can-communicate",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "description": "Model- and harness-agnostic coordination for independent AI agent sessions.",
6
6
  "keywords": [
@@ -36,9 +36,9 @@
36
36
  "node": ">=24"
37
37
  },
38
38
  "bin": {
39
- "acc": "./bin/acc.mjs",
40
- "acc-mcp": "./bin/acc-mcp.mjs",
41
- "acc-hook": "./bin/acc-hook.mjs"
39
+ "acc": "bin/acc.mjs",
40
+ "acc-mcp": "bin/acc-mcp.mjs",
41
+ "acc-hook": "bin/acc-hook.mjs"
42
42
  },
43
43
  "files": [
44
44
  "bin/",