agents-can-communicate 0.7.0 → 0.8.0
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.
- package/README.md +3 -1
- package/bin/entrypoints/acc-bootstrap.mjs +6 -48
- package/bin/entrypoints/acc-claude-channel.mjs +47 -157
- package/docs/ADAPTER_AUTHORING.md +41 -10
- package/docs/ARCHITECTURE.md +28 -13
- package/docs/CAPABILITIES.md +19 -16
- package/docs/CLI.md +60 -14
- package/docs/CONCEPTS.md +12 -4
- package/docs/CONFIGURATION.md +18 -11
- package/docs/GETTING_STARTED.md +15 -12
- package/docs/GLOSSARY.md +2 -1
- package/docs/HOW_IT_WORKS.md +8 -4
- package/docs/PROTOCOL.md +56 -6
- package/docs/RELEASING.md +3 -2
- package/docs/SECURITY_MODEL.md +14 -1
- package/docs/TROUBLESHOOTING.md +64 -27
- package/docs/UPGRADING.md +49 -8
- package/docs/WHY_ACC.md +5 -3
- package/node_modules/@agents-can-communicate/adapter-antigravity/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-antigravity/plugin/plugin.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-antigravity/plugin/skills/acc/SKILL.md +8 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/certification.json +14 -73
- package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/certification-provenance.json +29 -71
- package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/delivery/claude-code-2.1.282-product-evidence.json +161 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/delivery/claude-code-2.1.282.json +28 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/inbox-wake-2.1.282.json +44 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/package.json +5 -2
- package/node_modules/@agents-can-communicate/adapter-claude-code/plugin/skills/acc/SKILL.md +8 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/adapter.mjs +25 -30
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/hooks.mjs +6 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-contract.mjs +10 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-delivery.mjs +254 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-endpoint.mjs +166 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-registry.mjs +71 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-settings.mjs +109 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/install.mjs +25 -31
- package/node_modules/@agents-can-communicate/adapter-codex/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-codex/plugin/skills/acc/SKILL.md +8 -0
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/extension/gemini-extension.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/extension/skills/acc/SKILL.md +8 -0
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-grok/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-grok/plugin/skills/acc/SKILL.md +8 -0
- package/node_modules/@agents-can-communicate/adapter-kimi/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-kimi/plugin/skills/acc/SKILL.md +8 -0
- package/node_modules/@agents-can-communicate/adapter-sdk/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-sdk/src/context-projector.mjs +15 -2
- package/node_modules/@agents-can-communicate/adapter-sdk/src/events.mjs +16 -3
- package/node_modules/@agents-can-communicate/adapter-sdk/src/hook-shim.mjs +4 -3
- package/node_modules/@agents-can-communicate/adapter-sdk/src/index.mjs +1 -1
- package/node_modules/@agents-can-communicate/adapter-sdk/src/native-activation.mjs +4 -14
- package/node_modules/@agents-can-communicate/adapter-sdk/src/native-delivery.mjs +23 -11
- package/node_modules/@agents-can-communicate/adapter-sdk/src/native-vocabulary.mjs +5 -1
- package/node_modules/@agents-can-communicate/cli/package.json +1 -1
- package/node_modules/@agents-can-communicate/cli/src/doctor-command.mjs +8 -6
- package/node_modules/@agents-can-communicate/cli/src/install-command.mjs +8 -23
- package/node_modules/@agents-can-communicate/cli/src/install-delivery-consent.mjs +3 -4
- package/node_modules/@agents-can-communicate/cli/src/main.mjs +39 -10
- package/node_modules/@agents-can-communicate/cli/src/managed-runtime/entry.mjs +7 -43
- package/node_modules/@agents-can-communicate/cli/src/managed-runtime/launchers.mjs +5 -3
- package/node_modules/@agents-can-communicate/cli/src/managed-runtime/refresh.mjs +3 -4
- package/node_modules/@agents-can-communicate/cli/src/native-delivery-status.mjs +2 -2
- package/node_modules/@agents-can-communicate/core/package.json +1 -1
- package/node_modules/@agents-can-communicate/core/src/conversations.mjs +2 -2
- package/node_modules/@agents-can-communicate/core/src/next-turn-delivery.mjs +21 -4
- package/node_modules/@agents-can-communicate/core/src/receipts.mjs +66 -10
- package/node_modules/@agents-can-communicate/core/src/sessions.mjs +25 -2
- package/node_modules/@agents-can-communicate/core/src/status.mjs +38 -1
- package/node_modules/@agents-can-communicate/core/src/sync.mjs +11 -2
- package/node_modules/@agents-can-communicate/delivery-router/package.json +1 -1
- package/node_modules/@agents-can-communicate/delivery-router/src/router.mjs +24 -7
- package/node_modules/@agents-can-communicate/hook-runner/package.json +1 -1
- package/node_modules/@agents-can-communicate/hook-runner/src/native-attempt.mjs +6 -8
- package/node_modules/@agents-can-communicate/hook-runner/src/native-binding.mjs +24 -11
- package/node_modules/@agents-can-communicate/hook-runner/src/runner.mjs +21 -12
- package/node_modules/@agents-can-communicate/installer/package.json +1 -1
- package/node_modules/@agents-can-communicate/installer/src/apply.mjs +19 -5
- package/node_modules/@agents-can-communicate/installer/src/detect.mjs +3 -7
- package/node_modules/@agents-can-communicate/installer/src/index.mjs +4 -7
- package/node_modules/@agents-can-communicate/installer/src/native-activation.mjs +23 -61
- package/node_modules/@agents-can-communicate/installer/src/ownership.mjs +7 -1
- package/node_modules/@agents-can-communicate/installer/src/plan.mjs +15 -5
- package/node_modules/@agents-can-communicate/installer/src/shell-bootstrap.mjs +10 -133
- package/node_modules/@agents-can-communicate/mcp-server/package.json +1 -1
- package/node_modules/@agents-can-communicate/mcp-server/src/tools.mjs +5 -3
- package/node_modules/@agents-can-communicate/protocol/package.json +1 -1
- package/node_modules/@agents-can-communicate/storage-filesystem/package.json +1 -1
- package/node_modules/@agents-can-communicate/storage-filesystem/src/atomic-json.mjs +6 -1
- package/package.json +1 -1
- package/bin/acc-bootstrap.mjs +0 -7
- package/bin/acc-claude-channel.mjs +0 -10
- package/bin/entrypoints/claude-channel-binding.mjs +0 -46
- package/bin/entrypoints/claude-channel-stdio.mjs +0 -29
- package/node_modules/@agents-can-communicate/adapter-claude-code/plugin/.mcp.json +0 -8
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/channel.mjs +0 -381
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/native-delivery.mjs +0 -232
- package/node_modules/@agents-can-communicate/installer/src/bootstrap-runtime.mjs +0 -150
|
@@ -2,7 +2,7 @@ import { describeInstallDelivery } from "./delivery-diagnostics.mjs";
|
|
|
2
2
|
|
|
3
3
|
import { AccError, EXIT } from "@agents-can-communicate/protocol";
|
|
4
4
|
|
|
5
|
-
import { LIVE_POLICIES, describeActivation, describeDeactivation, planActivationRetirements
|
|
5
|
+
import { LIVE_POLICIES, describeActivation, describeDeactivation, planActivationRetirements }
|
|
6
6
|
from "./native-activation.mjs";
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -122,8 +122,18 @@ export function planInstallation({ adapters, detected, context, action = "instal
|
|
|
122
122
|
&& native.activationPlan?.eligible === true;
|
|
123
123
|
const effectiveLivePolicy = liveDeliverySupported ? delivery : "off";
|
|
124
124
|
const previous = recordedById.get(entry.adapterId)?.nativeActivation ?? null;
|
|
125
|
+
// What a failed readiness probe may keep. Not a shell bootstrap: no adapter
|
|
126
|
+
// can plan one any more, so keeping it would keep a launch path nothing
|
|
127
|
+
// maintains - the 0.7.x `claude` shim. Not an activation recorded under a
|
|
128
|
+
// contract the adapter no longer declares: it describes a transport that is
|
|
129
|
+
// gone, the Claude Channel among them.
|
|
130
|
+
const declaredContracts = new Set((adapter.nativeDelivery?.anchors ?? [])
|
|
131
|
+
.map(anchor => anchor.protocolContract));
|
|
132
|
+
const retainable = previous !== null && declaredContracts.has(previous.protocolContract)
|
|
133
|
+
? { ...previous, mechanisms: (previous.mechanisms ?? []).filter(item => item.kind !== "shell-bootstrap") }
|
|
134
|
+
: null;
|
|
125
135
|
const retainedActivation = action === "install" && delivery !== "off"
|
|
126
|
-
&& !liveDeliverySupported &&
|
|
136
|
+
&& !liveDeliverySupported && retainable?.livePolicy === delivery ? retainable : null;
|
|
127
137
|
const configuredLivePolicy = retainedActivation ? delivery : effectiveLivePolicy;
|
|
128
138
|
const deliveryDiagnostic = action === "install" && delivery !== "off"
|
|
129
139
|
&& !liveDeliverySupported
|
|
@@ -144,13 +154,13 @@ export function planInstallation({ adapters, detected, context, action = "instal
|
|
|
144
154
|
// creates one.
|
|
145
155
|
const nativeActivation = action === "install" && effectiveLivePolicy !== "off"
|
|
146
156
|
? { livePolicy: effectiveLivePolicy, protocolContract: native.eligibility.protocolContract,
|
|
147
|
-
shell: context?.shell ?? null, rcFile: rcFileFor(context?.home, context?.shell),
|
|
148
|
-
shimDir: typeof context?.stateRoot === "string" ? shimDirFor(context.stateRoot) : null,
|
|
149
157
|
mechanisms: native.activationPlan.mechanisms }
|
|
150
158
|
: null;
|
|
151
159
|
// A failed readiness probe is not revocation. Keep existing guarded launch
|
|
152
160
|
// setup without applying service commands or claiming it is available.
|
|
153
|
-
const retirements = retainedActivation
|
|
161
|
+
const retirements = retainedActivation
|
|
162
|
+
? (previous.mechanisms ?? []).filter(item => item.kind === "shell-bootstrap")
|
|
163
|
+
: planActivationRetirements({ previous, desired: nativeActivation });
|
|
154
164
|
const deactivation = retirements.length > 0 ? { ...previous, mechanisms: retirements } : null;
|
|
155
165
|
const artifacts = (record?.artifacts ?? adapter.planInstall(installContext))
|
|
156
166
|
.map(artifact => ({ path: artifact.path, kind: artifact.kind ?? "file" }))
|
|
@@ -1,115 +1,19 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { chmod,
|
|
2
|
+
import { chmod, readdir, readFile, rename, rm, rmdir, stat, writeFile } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// replaces itself with the real vendor executable through `exec`; ACC is never
|
|
11
|
-
// the parent of a model session. Every byte ACC writes is recorded with its
|
|
12
|
-
// hash so uninstall removes only what is still ACC's and refuses a block or
|
|
13
|
-
// shim someone has edited.
|
|
5
|
+
// Retirement of the shell half of 0.7.x native delivery: one marked PATH block
|
|
6
|
+
// in the user's zsh rc and one `claude` shim in an ACC-owned directory. ACC no
|
|
7
|
+
// longer writes either; `acc install`, `acc update` and `acc uninstall` remove
|
|
8
|
+
// what an older version wrote. Every byte was recorded with its hash, so only
|
|
9
|
+
// what is still ACC's is removed, and an edited block or shim is kept.
|
|
14
10
|
|
|
15
11
|
export const BLOCK_BEGIN = "# >>> agents-can-communicate native delivery >>>";
|
|
16
12
|
export const BLOCK_END = "# <<< agents-can-communicate native delivery <<<";
|
|
17
13
|
export const SHIM_MARKER = "# agents-can-communicate native delivery shim";
|
|
18
|
-
export const SUPPORTED_SHELLS = Object.freeze(["zsh"]);
|
|
19
|
-
export const SHIM_POLICIES = Object.freeze(["actionable", "all"]);
|
|
20
|
-
const COMMAND_NAME = /^[a-z][a-z0-9_.-]*$/;
|
|
21
14
|
|
|
22
|
-
const usage = (message, details = {}) => { throw new AccError(EXIT.USAGE, message, details); };
|
|
23
15
|
const sha256 = text => createHash("sha256").update(text).digest("hex");
|
|
24
|
-
|
|
25
|
-
// byte of a path or argument is ever interpreted by the shell.
|
|
26
|
-
export const shellLiteral = value => `'${String(value).replaceAll("'", "'\\''")}'`;
|
|
27
|
-
const isAbsolute = value => typeof value === "string" && path.isAbsolute(value);
|
|
28
|
-
const inside = (root, candidate) => {
|
|
29
|
-
const relative = path.relative(root, candidate);
|
|
30
|
-
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export function renderPathBlock(shimDir) {
|
|
34
|
-
return `${BLOCK_BEGIN}\nexport PATH=${shellLiteral(shimDir)}:"$PATH"\n${BLOCK_END}\n`;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function validateShimEntry(entry) {
|
|
38
|
-
if (entry === null || typeof entry !== "object") usage("a shim entry must be an object");
|
|
39
|
-
for (const key of Object.keys(entry)) {
|
|
40
|
-
if (!["adapterId", "command", "realExecutable", "prefixArgs", "livePolicy"].includes(key)) {
|
|
41
|
-
usage(`unknown shim entry field ${key}`, { key });
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
assertPortableId(entry.adapterId, "shim adapter id");
|
|
45
|
-
if (typeof entry.command !== "string" || !COMMAND_NAME.test(entry.command)) {
|
|
46
|
-
usage("a shim command must be a bare command name", { command: entry.command });
|
|
47
|
-
}
|
|
48
|
-
if (!isAbsolute(entry.realExecutable)) usage("a shim realExecutable must be an absolute path");
|
|
49
|
-
if (!Array.isArray(entry.prefixArgs) || entry.prefixArgs.some(arg => typeof arg !== "string"
|
|
50
|
-
|| arg === "" || /[\0\n]/.test(arg))) {
|
|
51
|
-
usage("shim prefixArgs must be non-empty argument strings without NUL or newline");
|
|
52
|
-
}
|
|
53
|
-
if (!SHIM_POLICIES.includes(entry.livePolicy)) {
|
|
54
|
-
usage("a shim livePolicy must be actionable or all; off means no shim", { livePolicy: entry.livePolicy });
|
|
55
|
-
}
|
|
56
|
-
return Object.freeze({ ...entry, prefixArgs: Object.freeze([...entry.prefixArgs]) });
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function renderCommandShim({ node, bootstrap, dataHome, entry }) {
|
|
60
|
-
const shim = validateShimEntry(entry);
|
|
61
|
-
for (const [name, value] of Object.entries({ node, bootstrap, dataHome })) {
|
|
62
|
-
if (!isAbsolute(value)) usage(`shim ${name} must be an absolute path`, { [name]: value });
|
|
63
|
-
}
|
|
64
|
-
const real = shellLiteral(shim.realExecutable);
|
|
65
|
-
const check = [node, bootstrap, "--adapter", shim.adapterId, "--real-executable",
|
|
66
|
-
shim.realExecutable, "--data-home", dataHome].map(shellLiteral).join(" ");
|
|
67
|
-
const prefix = shim.prefixArgs.map(shellLiteral).join(" ");
|
|
68
|
-
return [
|
|
69
|
-
"#!/bin/sh",
|
|
70
|
-
`${SHIM_MARKER} for ${shellLiteral(shim.command)}. Generated; do not edit.`,
|
|
71
|
-
"# ACC_BYPASS=1 runs the vendor command untouched. A failed or missing check",
|
|
72
|
-
"# does the same: the vendor command is never blocked on ACC.",
|
|
73
|
-
'if [ "${ACC_BYPASS-}" = "1" ]; then',
|
|
74
|
-
" unset ACC_NATIVE_DELIVERY_POLICY",
|
|
75
|
-
` exec ${real} "$@"`,
|
|
76
|
-
"fi",
|
|
77
|
-
`if ${check} </dev/null >/dev/null 2>&1; then`,
|
|
78
|
-
` ACC_NATIVE_DELIVERY_POLICY=${shellLiteral(shim.livePolicy)}`,
|
|
79
|
-
" export ACC_NATIVE_DELIVERY_POLICY",
|
|
80
|
-
` exec ${real}${prefix === "" ? "" : ` ${prefix}`} "$@"`,
|
|
81
|
-
"fi",
|
|
82
|
-
"unset ACC_NATIVE_DELIVERY_POLICY",
|
|
83
|
-
`exec ${real} "$@"`,
|
|
84
|
-
"",
|
|
85
|
-
].join("\n");
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export function planShellBootstrap({ shell, rcFile, shimDir, entries = [], runtime = null }) {
|
|
89
|
-
if (!SUPPORTED_SHELLS.includes(shell)) {
|
|
90
|
-
return Object.freeze({ eligible: false, reasonCode: "unsupported_shell", shell: shell ?? null,
|
|
91
|
-
rcFile: null, shimDir: null, block: null, shims: Object.freeze([]), runtime: null });
|
|
92
|
-
}
|
|
93
|
-
if (!isAbsolute(rcFile) || !isAbsolute(shimDir)) usage("rcFile and shimDir must be absolute");
|
|
94
|
-
const validated = entries.map(validateShimEntry);
|
|
95
|
-
const commands = new Set();
|
|
96
|
-
for (const entry of validated) {
|
|
97
|
-
if (commands.has(entry.command)) usage(`duplicate shim command ${entry.command}`);
|
|
98
|
-
commands.add(entry.command);
|
|
99
|
-
// A shim that resolved to itself would loop forever; the real executable
|
|
100
|
-
// is resolved before the shim directory is ever on PATH.
|
|
101
|
-
if (inside(shimDir, entry.realExecutable)) {
|
|
102
|
-
usage("a shim realExecutable cannot live inside the shim directory",
|
|
103
|
-
{ realExecutable: entry.realExecutable });
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return Object.freeze({ eligible: true, reasonCode: null, shell, rcFile, shimDir,
|
|
107
|
-
block: renderPathBlock(shimDir), runtime,
|
|
108
|
-
shims: Object.freeze(validated.map(entry => Object.freeze({
|
|
109
|
-
path: path.join(shimDir, entry.command), entry }))) });
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const defaultIo = Object.freeze({ readFile, writeFile, mkdir, chmod, rename, rm, rmdir, readdir });
|
|
16
|
+
const defaultIo = Object.freeze({ readFile, writeFile, chmod, rename, rm, rmdir, readdir, stat });
|
|
113
17
|
|
|
114
18
|
async function readText(io, file) {
|
|
115
19
|
try {
|
|
@@ -139,35 +43,6 @@ export function locateBlock(text) {
|
|
|
139
43
|
return { start: begin, end: end === -1 ? text.length : end + 1 };
|
|
140
44
|
}
|
|
141
45
|
|
|
142
|
-
export async function installShellBootstrap({ plan, io = defaultIo }) {
|
|
143
|
-
if (!plan?.eligible) return { ok: false, reasonCode: plan?.reasonCode ?? "unsupported_shell" };
|
|
144
|
-
const { node, bootstrap, dataHome } = plan.runtime ?? {};
|
|
145
|
-
const current = await readText(io, plan.rcFile);
|
|
146
|
-
const span = locateBlock(current);
|
|
147
|
-
const existing = span === null ? null : current.slice(span.start, span.end);
|
|
148
|
-
if (existing !== null && existing !== plan.block) {
|
|
149
|
-
return { ok: false, reasonCode: "rc_block_modified", rcFile: plan.rcFile };
|
|
150
|
-
}
|
|
151
|
-
await io.mkdir(plan.shimDir, { recursive: true, mode: 0o700 });
|
|
152
|
-
await io.chmod(plan.shimDir, 0o700);
|
|
153
|
-
const shims = [];
|
|
154
|
-
for (const shim of plan.shims) {
|
|
155
|
-
const content = renderCommandShim({ node, bootstrap, dataHome, entry: shim.entry });
|
|
156
|
-
await writeAtomic(io, shim.path, content, 0o700);
|
|
157
|
-
shims.push({ path: shim.path, command: shim.entry.command, sha256: sha256(content) });
|
|
158
|
-
}
|
|
159
|
-
let appended = false;
|
|
160
|
-
if (existing === null) {
|
|
161
|
-
const base = current ?? "";
|
|
162
|
-
const separator = base === "" || base.endsWith("\n") ? "" : "\n";
|
|
163
|
-
await writeAtomic(io, plan.rcFile, `${base}${separator}${plan.block}`, 0o600);
|
|
164
|
-
appended = true;
|
|
165
|
-
}
|
|
166
|
-
return { ok: true, reasonCode: null, shell: plan.shell, shimDir: plan.shimDir,
|
|
167
|
-
rcFile: { path: plan.rcFile, blockSha256: sha256(plan.block), appended },
|
|
168
|
-
shims };
|
|
169
|
-
}
|
|
170
|
-
|
|
171
46
|
export async function uninstallShellBootstrap({ ownership, io = defaultIo }) {
|
|
172
47
|
const result = { ok: true, reasonCode: null, removedShims: [], keptShims: [],
|
|
173
48
|
missingShims: [], rcBlock: "absent" };
|
|
@@ -199,7 +74,9 @@ export async function uninstallShellBootstrap({ ownership, io = defaultIo }) {
|
|
|
199
74
|
} else if (remaining.length > 0) {
|
|
200
75
|
result.rcBlock = "kept";
|
|
201
76
|
} else {
|
|
202
|
-
|
|
77
|
+
// The user's file keeps the permissions it has now.
|
|
78
|
+
const mode = ((await io.stat?.(rcFile.path).catch(() => null))?.mode ?? 0o600) & 0o777;
|
|
79
|
+
await writeAtomic(io, rcFile.path, text.slice(0, span.start) + text.slice(span.end), mode);
|
|
203
80
|
result.rcBlock = "removed";
|
|
204
81
|
}
|
|
205
82
|
}
|
|
@@ -23,15 +23,17 @@ const stringList = description => ({ type: "array", items: { type: "string" }, d
|
|
|
23
23
|
export const PUBLIC_TOOLS = Object.freeze([
|
|
24
24
|
{
|
|
25
25
|
name: "acc_status",
|
|
26
|
-
description: `Read who is here, current intents and claims,
|
|
27
|
-
+ `protection level
|
|
26
|
+
description: `Read who is here, current intents and claims, the workspace's real `
|
|
27
|
+
+ `protection level, and how many messages each participant has not fetched `
|
|
28
|
+
+ `(offered is not read). ${POLLED}`,
|
|
28
29
|
inputSchema: object({}),
|
|
29
30
|
},
|
|
30
31
|
{
|
|
31
32
|
name: "acc_sync",
|
|
32
33
|
description: `Read coordination state for this workspace: roster, attention items, and `
|
|
33
34
|
+ `events since a cursor. Use scope "history" for bounded message summaries, then `
|
|
34
|
-
+ `messageId to read one complete historical message
|
|
35
|
+
+ `messageId to read one complete historical message, with every recipient's `
|
|
36
|
+
+ `receipt state, without changing receipts. `
|
|
35
37
|
+ `Scope "full" is an unbounded forensic workspace snapshot. Use acc_inbox for `
|
|
36
38
|
+ `your addressed messages. ${POLLED}`,
|
|
37
39
|
inputSchema: object({
|
|
@@ -72,11 +72,16 @@ export async function publishAtomic(destination, bytes,
|
|
|
72
72
|
// active-journal.mjs defaults tmpDir, so every caller keeps working.
|
|
73
73
|
stageDir = stageDir ?? path.join(root, "stage");
|
|
74
74
|
const destinationDir = path.dirname(destination);
|
|
75
|
-
|
|
75
|
+
// Every check settles before a refusal is reported: Promise.all would reject
|
|
76
|
+
// on the first one while the others still create directories under a root
|
|
77
|
+
// the caller may already be removing.
|
|
78
|
+
const prepared = await Promise.allSettled([
|
|
76
79
|
ensureManagedDirectory(root, tmpDir),
|
|
77
80
|
ensureManagedDirectory(root, stageDir),
|
|
78
81
|
ensureManagedDirectory(root, destinationDir),
|
|
79
82
|
]);
|
|
83
|
+
const refused = prepared.find(result => result.status === "rejected");
|
|
84
|
+
if (refused) throw refused.reason;
|
|
80
85
|
if (!replace) {
|
|
81
86
|
const existing = await bytesIfPresent(destination, root);
|
|
82
87
|
if (existing !== null) {
|
package/package.json
CHANGED
package/bin/acc-bootstrap.mjs
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { fileURLToPath } from "node:url";
|
|
3
|
-
import { invokedDirectly, runEntry } from "@agents-can-communicate/cli/managed-entry";
|
|
4
|
-
|
|
5
|
-
if (invokedDirectly(import.meta.url)) await runEntry({
|
|
6
|
-
kind: "acc-bootstrap", packageRoot: fileURLToPath(new URL("..", import.meta.url)),
|
|
7
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { fileURLToPath } from "node:url";
|
|
3
|
-
import { invokedDirectly, runEntry } from "@agents-can-communicate/cli/managed-entry";
|
|
4
|
-
export const resolveSession = async options => (await import("./entrypoints/acc-claude-channel.mjs")).resolveSession(options);
|
|
5
|
-
export const ownClient = async options => (await import("./entrypoints/acc-claude-channel.mjs")).ownClient(options);
|
|
6
|
-
export const resolveWithin = async options => (await import("./entrypoints/acc-claude-channel.mjs")).resolveWithin(options);
|
|
7
|
-
|
|
8
|
-
if (invokedDirectly(import.meta.url)) await runEntry({
|
|
9
|
-
kind: "acc-claude-channel", packageRoot: fileURLToPath(new URL("..", import.meta.url)),
|
|
10
|
-
});
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { createClaudeCodeAdapter } from "@agents-can-communicate/adapter-claude-code";
|
|
2
|
-
import { loadSessionBinding, storeNativeAttempt } from "@agents-can-communicate/adapter-sdk";
|
|
3
|
-
import { createCoordinationService } from "@agents-can-communicate/core";
|
|
4
|
-
import { establishNativeBinding, livePolicyFrom } from "@agents-can-communicate/hook-runner/native-binding";
|
|
5
|
-
import { withSessionLifecycle } from "@agents-can-communicate/hook-runner/session-lifecycle";
|
|
6
|
-
import { readInstalledLivePolicy } from "@agents-can-communicate/installer";
|
|
7
|
-
import { openFilesystemStore } from "@agents-can-communicate/storage-filesystem";
|
|
8
|
-
|
|
9
|
-
// SessionStart cannot wait for MCP indefinitely. The endpoint's owner completes
|
|
10
|
-
// the same handshake when it starts later, without a prompt or an LLM turn.
|
|
11
|
-
// Serialize with the hooks, then reread ownership: a queued startup must never
|
|
12
|
-
// publish for a replaced/closed session or undo SessionEnd's retirement.
|
|
13
|
-
export async function activateClaudeChannel({ session, service, runtimeDir, dataHome, env,
|
|
14
|
-
deadlineAt = Date.now() + 5_000 }) {
|
|
15
|
-
if (typeof session.harnessSessionId !== "string") return null;
|
|
16
|
-
return withSessionLifecycle({ root: runtimeDir, sessionId: session.harnessSessionId,
|
|
17
|
-
clock: service.clock, deadlineAt }, async () => {
|
|
18
|
-
// A prior hook can die after committing its journal. Recover that close
|
|
19
|
-
// before reading ownership, just as the hook runner does under this lock.
|
|
20
|
-
const { clock, ids } = service;
|
|
21
|
-
const store = await openFilesystemStore({ root: runtimeDir, clock, ids,
|
|
22
|
-
workspaceId: service.store.workspaceId, deadlineAt });
|
|
23
|
-
service = createCoordinationService({ store, clock, ids });
|
|
24
|
-
const current = await loadSessionBinding({ runtimeDir,
|
|
25
|
-
harnessSessionId: session.harnessSessionId });
|
|
26
|
-
if (current?.accSessionId !== session.sessionId || current.generation !== session.generation
|
|
27
|
-
|| current.clientPid !== session.clientPid) return null;
|
|
28
|
-
const located = await service.locateSession(session.sessionId);
|
|
29
|
-
if (located?.record.state !== "open" || located.record.generation !== session.generation) return null;
|
|
30
|
-
const policy = livePolicyFrom(env);
|
|
31
|
-
if (policy === "off" || await readInstalledLivePolicy({ dataHome,
|
|
32
|
-
adapterId: "claude_code" }) === "off") return null;
|
|
33
|
-
if (Date.now() >= deadlineAt) return null;
|
|
34
|
-
const result = await establishNativeBinding({ adapter: createClaudeCodeAdapter(),
|
|
35
|
-
event: { kind: "channelReady", sessionId: session.harnessSessionId },
|
|
36
|
-
hookBinding: current, clientVersion: current.clientVersion, platform: current.platform,
|
|
37
|
-
livePolicy: policy, service, runtimeDir, clock: service.clock, env,
|
|
38
|
-
timeoutMs: Math.max(1, Math.min(750, deadlineAt - Date.now())) });
|
|
39
|
-
await storeNativeAttempt({ runtimeDir, harnessSessionId: session.harnessSessionId,
|
|
40
|
-
accSessionId: session.sessionId, generation: session.generation, deadlineAt,
|
|
41
|
-
nativeAttempt: { at: service.clock.now(), event: "channelReady", state: result.state,
|
|
42
|
-
reasonCode: result.reasonCode, policy, policySource: "bootstrap-environment",
|
|
43
|
-
policyStatus: "enabled", clientProcess: "identified" } });
|
|
44
|
-
return result;
|
|
45
|
-
});
|
|
46
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// Workspace-free MCP fallback shared by composition and managed admission failure.
|
|
2
|
-
import { createInertChannel } from "@agents-can-communicate/adapter-claude-code/channel";
|
|
3
|
-
|
|
4
|
-
export function startInertChannel({ write = payload => process.stdout.write(JSON.stringify(payload) + "\n") } = {}) {
|
|
5
|
-
const inert = createInertChannel({ write });
|
|
6
|
-
pump(inert.handleLine, () => process.exit(0));
|
|
7
|
-
return inert;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/** One line-delimited JSON pump, for the bound server and the unbound one alike. */
|
|
11
|
-
export function pump(handleLine, shutdown) {
|
|
12
|
-
let buffer = "";
|
|
13
|
-
process.stdin.setEncoding("utf8");
|
|
14
|
-
process.stdin.on("data", async chunk => {
|
|
15
|
-
buffer += chunk;
|
|
16
|
-
let newline = buffer.indexOf("\n");
|
|
17
|
-
while (newline !== -1) {
|
|
18
|
-
const line = buffer.slice(0, newline).trim();
|
|
19
|
-
buffer = buffer.slice(newline + 1);
|
|
20
|
-
newline = buffer.indexOf("\n");
|
|
21
|
-
if (line !== "") await handleLine(line);
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
process.stdin.on("end", shutdown);
|
|
25
|
-
process.once("SIGTERM", shutdown);
|
|
26
|
-
process.once("SIGINT", shutdown);
|
|
27
|
-
// Keeps the child answerable for as long as Claude holds the transport open.
|
|
28
|
-
process.stdin.resume();
|
|
29
|
-
}
|