agents-can-communicate 0.4.1 → 0.4.3
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 +17 -4
- package/docs/ARCHITECTURE.md +7 -1
- package/docs/CLI.md +23 -3
- package/docs/CONFIGURATION.md +25 -0
- package/docs/GETTING_STARTED.md +17 -5
- package/docs/PROTOCOL.md +4 -0
- package/docs/RELEASING.md +1 -1
- package/docs/SECURITY_MODEL.md +7 -0
- package/docs/TROUBLESHOOTING.md +60 -7
- package/docs/UPGRADING.md +36 -19
- package/node_modules/@agents-can-communicate/adapter-claude-code/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/adapter.mjs +3 -3
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/channel.mjs +2 -4
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/install.mjs +10 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/native-delivery.mjs +3 -1
- package/node_modules/@agents-can-communicate/adapter-codex/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-codex/src/app-server-client.mjs +1 -1
- package/node_modules/@agents-can-communicate/adapter-codex/src/config-block.mjs +4 -88
- package/node_modules/@agents-can-communicate/adapter-codex/src/install.mjs +36 -15
- package/node_modules/@agents-can-communicate/adapter-codex/src/live-permissions.mjs +110 -0
- package/node_modules/@agents-can-communicate/adapter-codex/src/native-delivery.mjs +2 -1
- package/node_modules/@agents-can-communicate/adapter-codex/src/permission-ownership.mjs +109 -0
- package/node_modules/@agents-can-communicate/adapter-codex/src/toml-scan.mjs +99 -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/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-grok/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-kimi/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-sdk/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-sdk/src/channel-directory.mjs +8 -0
- package/node_modules/@agents-can-communicate/adapter-sdk/src/index.mjs +3 -0
- package/node_modules/@agents-can-communicate/adapter-sdk/src/native-attempt-writer.mjs +64 -0
- package/node_modules/@agents-can-communicate/adapter-sdk/src/native-attempt.mjs +65 -0
- package/node_modules/@agents-can-communicate/adapter-sdk/src/native-vocabulary.mjs +1 -0
- package/node_modules/@agents-can-communicate/cli/package.json +1 -1
- package/node_modules/@agents-can-communicate/cli/src/doctor-command.mjs +19 -52
- package/node_modules/@agents-can-communicate/cli/src/install-command.mjs +23 -45
- package/node_modules/@agents-can-communicate/cli/src/main.mjs +3 -1
- package/node_modules/@agents-can-communicate/cli/src/native-delivery-status.mjs +88 -0
- package/node_modules/@agents-can-communicate/cli/src/native-session-diagnostics.mjs +64 -0
- package/node_modules/@agents-can-communicate/core/package.json +1 -1
- package/node_modules/@agents-can-communicate/core/src/receipts.mjs +1 -0
- package/node_modules/@agents-can-communicate/delivery-router/package.json +1 -1
- package/node_modules/@agents-can-communicate/delivery-router/src/router.mjs +1 -1
- package/node_modules/@agents-can-communicate/hook-runner/package.json +1 -1
- package/node_modules/@agents-can-communicate/hook-runner/src/native-attempt.mjs +43 -0
- package/node_modules/@agents-can-communicate/hook-runner/src/runner.mjs +17 -27
- package/node_modules/@agents-can-communicate/installer/package.json +1 -1
- package/node_modules/@agents-can-communicate/installer/src/apply.mjs +2 -0
- package/node_modules/@agents-can-communicate/installer/src/delivery-diagnostics.mjs +36 -0
- package/node_modules/@agents-can-communicate/installer/src/detect.mjs +28 -12
- package/node_modules/@agents-can-communicate/installer/src/index.mjs +3 -1
- package/node_modules/@agents-can-communicate/installer/src/live-policy.mjs +10 -3
- package/node_modules/@agents-can-communicate/installer/src/plan.mjs +12 -2
- package/node_modules/@agents-can-communicate/mcp-server/package.json +1 -1
- package/node_modules/@agents-can-communicate/protocol/package.json +1 -1
- package/node_modules/@agents-can-communicate/storage-filesystem/package.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -65,6 +65,12 @@ then restart your clients from the project directory. In Codex, check `/plugins`
|
|
|
65
65
|
review the current ACC definitions in `/hooks`; changed hooks may need fresh trust.
|
|
66
66
|
[Getting started](docs/GETTING_STARTED.md) covers activation and preserved sandbox settings.
|
|
67
67
|
|
|
68
|
+
For Codex live delivery on Apple Silicon macOS, installation also configures outgoing
|
|
69
|
+
local socket access on Codex 0.153.4 or newer when using default workspace permissions.
|
|
70
|
+
Custom policies are preserved. If its local service is missing, doctor gives the command
|
|
71
|
+
`codex app-server daemon start`; then open a new Codex session. Doctor reports receiving
|
|
72
|
+
channel state and outgoing permission configuration separately.
|
|
73
|
+
|
|
68
74
|
Open two sessions and give them ordinary tasks, as above. Look for an agent discovering a
|
|
69
75
|
peer, checking who is changing a file, asking about a shared dependency, or replying to a
|
|
70
76
|
review request.
|
|
@@ -73,8 +79,8 @@ Run `acc doctor` from the project if a peer is missing. A directory containing A
|
|
|
73
79
|
state, commonly your home directory, cannot be used as a workspace; start the client in a
|
|
74
80
|
project directory. See [Troubleshooting](docs/TROUBLESHOOTING.md).
|
|
75
81
|
|
|
76
|
-
Already using ACC? Follow the [upgrade guide](docs/UPGRADING.md), including the 0.4.
|
|
77
|
-
0.4.
|
|
82
|
+
Already using ACC? Follow the [upgrade guide](docs/UPGRADING.md), including the 0.4.x →
|
|
83
|
+
0.4.3 update and the data-format boundary when moving from 0.3.1.
|
|
78
84
|
|
|
79
85
|
## When messages arrive
|
|
80
86
|
|
|
@@ -95,9 +101,16 @@ mutations. It adds no automatic peer-message injection or idle delivery. A reloc
|
|
|
95
101
|
**Optional live delivery can start a turn in an idle Codex or Claude Code session.** It is
|
|
96
102
|
experimental, off by default, and can spend model tokens. On Apple Silicon Macs, Codex
|
|
97
103
|
0.152.1 or newer requires an already-running LocalDaemon and a verified session;
|
|
98
|
-
Claude Code 2.1.258 or newer requires zsh and
|
|
99
|
-
startup
|
|
104
|
+
Claude Code 2.1.258 or newer requires zsh and client-side Channels activation; check its
|
|
105
|
+
startup notice for ACC and accept the development warning when shown. An MCP connection
|
|
106
|
+
alone does not verify inbound delivery. Messages arriving mid-turn wait for the turn to
|
|
107
|
+
finish. The receiving session's
|
|
100
108
|
opt-in policy and current reachability determine whether delivery can proceed.
|
|
109
|
+
`acc install` reports each client's delivery state and can save Codex consent before its
|
|
110
|
+
service is available. `acc doctor` also names each session’s last native binding result,
|
|
111
|
+
including missing launch consent, an unidentified client process or a failed handshake.
|
|
112
|
+
It distinguishes a disabled policy from an unavailable service or a missing live channel
|
|
113
|
+
in the current project.
|
|
101
114
|
|
|
102
115
|
A Codex thread retained by LocalDaemon can receive opted-in messages after its terminal
|
|
103
116
|
exits. Turning ACC delivery off prevents new native offers; already accepted queue entries
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -68,7 +68,13 @@ livePolicy · opaqueEndpointRef · leaseUntil
|
|
|
68
68
|
|
|
69
69
|
Core validates identity and expiry but never interprets the opaque endpoint. That remains
|
|
70
70
|
inside the owning adapter. `acc status` reports available modes, policy, reachability, and
|
|
71
|
-
lease without exposing the endpoint.
|
|
71
|
+
lease without exposing the endpoint. The hook runner also replaces one optional native
|
|
72
|
+
attempt diagnostic beside its session-owner file: closed policy/process/handshake
|
|
73
|
+
metadata with a timestamp, never vendor output. Doctor joins it only to the current open
|
|
74
|
+
generation and reports it separately from transport and receipt facts. It is not journalled
|
|
75
|
+
or projected into agent context; session restart replaces it and SessionEnd attempts bounded
|
|
76
|
+
cleanup. Doctor ignores closed or superseded generations even if cleanup could not finish. Diagnostic disk I/O runs in an
|
|
77
|
+
unreferenced worker, so a stalled write cannot hold the hook process open.
|
|
72
78
|
|
|
73
79
|
## Certified capability versus current reachability
|
|
74
80
|
|
package/docs/CLI.md
CHANGED
|
@@ -239,8 +239,9 @@ external AI client. An addressed handoff requires acknowledgement; a room handof
|
|
|
239
239
|
`--delivery off|actionable|all` is a per-client recipient policy request, not a capability
|
|
240
240
|
switch, and the default is `off`. `--adapter` is repeatable to name several clients. An
|
|
241
241
|
explicit `--delivery` applies uniformly and never prompts; omitting it on an interactive
|
|
242
|
-
terminal asks one default-No question per
|
|
243
|
-
|
|
242
|
+
terminal asks one default-No question per supported client. Codex can save consent while
|
|
243
|
+
its local service is unavailable or has no loaded session; this does not activate delivery.
|
|
244
|
+
A non-interactive run or a `--dry-run` keeps fresh clients off. A recorded opt-in is kept on upgrade. If the detected
|
|
244
245
|
client cannot receive native delivery - unsupported, below the captured minimum, a
|
|
245
246
|
prerelease, known-bad, a wrong platform, or an unsupported shell - installation keeps the
|
|
246
247
|
effective policy off and prints the reason. Claude Code shell activation writes an owned
|
|
@@ -248,7 +249,26 @@ zsh PATH block and a shim that `exec`s the real client; `ACC_BYPASS=1` bypasses
|
|
|
248
249
|
activation. Codex LocalDaemon delivery uses recorded installation consent without changing
|
|
249
250
|
ordinary launch arguments. Its opt-in remains active when shim variables are absent or
|
|
250
251
|
bypassed; `acc install --adapter codex --delivery off` disables new native offers. ACC never
|
|
251
|
-
starts or stops the vendor daemon.
|
|
252
|
+
starts or stops the vendor daemon. The install summary names each client's requested policy,
|
|
253
|
+
activation state and verified fallback. `doctor` separates protocol readiness, recorded
|
|
254
|
+
consent and a live channel in the current workspace, with a next step for missing activation.
|
|
255
|
+
A supported version or an installed plugin alone is not an active delivery channel.
|
|
256
|
+
`runtime: active` means ACC has a reachable local transport binding. Claude can still
|
|
257
|
+
block inbound Channels messages while its MCP server and tools remain connected;
|
|
258
|
+
doctor therefore also names the client-side startup check.
|
|
259
|
+
In doctor JSON, `nativeDelivery.activation` distinguishes missing launch setup from a
|
|
260
|
+
recorded setup (or `not_required` for a pre-existing service). `policy` is the installed
|
|
261
|
+
choice; `sessionPolicy` describes a native binding when one is visible. Existing Claude
|
|
262
|
+
sessions can retain their launch policy after a different choice is installed for new
|
|
263
|
+
sessions; Codex checks current recorded consent before new offers.
|
|
264
|
+
`nativeDelivery.sessions` lists each current session's identity, present transport state
|
|
265
|
+
and `lastAttempt`: timestamp, startup/turn event, effective policy and its source, whether
|
|
266
|
+
that policy was missing/invalid/off, whether a client process was identified, and the closed
|
|
267
|
+
handshake result/reason. `lastAttempt: null` means no usable attempt was observed for this
|
|
268
|
+
generation; it does not prove hooks are disabled. A past successful handshake is separate
|
|
269
|
+
from current transport reachability. ACC replaces this small diagnostic beside the
|
|
270
|
+
hook-owner file outside the repository; it never adds attempt history to agent context.
|
|
271
|
+
See [delivery consent](CONFIGURATION.md#keep-delivery-consent-user-owned).
|
|
252
272
|
|
|
253
273
|
An initial `acc install` enables automatic updates. Reinstalling preserves an explicit
|
|
254
274
|
`acc update --auto off` choice. A full uninstall pauses updates; reinstalling restores
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -144,6 +144,31 @@ consent from the installation record, not a shell-shim variable. Unavailable or
|
|
|
144
144
|
sessions retain durable inbox fallback. Use `acc install --adapter codex --delivery off`
|
|
145
145
|
to stop new native offers; bypassing a shim does not disable that recorded opt-in.
|
|
146
146
|
|
|
147
|
+
### Codex outgoing permissions
|
|
148
|
+
|
|
149
|
+
Receiving a native message and sending from the agent's sandbox are separate operations.
|
|
150
|
+
On Codex 0.153.4 or newer on macOS arm64, live opt-in also configures outgoing access
|
|
151
|
+
for default workspace permissions. This happens even when the daemon is not yet available.
|
|
152
|
+
Installation, its preview, and the interactive consent question disclose this change.
|
|
153
|
+
|
|
154
|
+
ACC selects a permission profile named `acc-workspace`, extending `:workspace`. It grants
|
|
155
|
+
write access to the ACC state directory and allows only the local ACC channel directory
|
|
156
|
+
(`/tmp/acc-ch-<uid>`) and the Codex home control socket. The profile enables networking
|
|
157
|
+
through `features.network_proxy = true`, with no external domains allowed. The proxy and
|
|
158
|
+
socket grants must stay together: enabling networking without the proxy changes its scope.
|
|
159
|
+
|
|
160
|
+
An existing legacy workspace-write configuration is migrated only when its sole writable
|
|
161
|
+
root is ACC's state directory. Custom permission/configuration profiles, additional roots,
|
|
162
|
+
inline settings and uncaptured clients are preserved and reported as unverified. ACC does
|
|
163
|
+
not merge arbitrary security policies or verify overrides in an already running session.
|
|
164
|
+
For a custom policy, grant the same state and socket access through the proxy in the
|
|
165
|
+
client's effective workspace profile; do not combine it with legacy sandbox settings.
|
|
166
|
+
|
|
167
|
+
Restart Codex after changing permissions. Explicit delivery `off` or uninstall restores
|
|
168
|
+
the previous configuration only while every generated permission component is unchanged.
|
|
169
|
+
If any component was edited or another setting depends on it, ACC preserves the entire
|
|
170
|
+
bundle and reports it for review. Plugin registration can still be removed independently.
|
|
171
|
+
|
|
147
172
|
## Override local paths and identity
|
|
148
173
|
|
|
149
174
|
Nothing in `acc.workspace.json` says where state is stored, and nothing there can — that is
|
package/docs/GETTING_STARTED.md
CHANGED
|
@@ -15,7 +15,7 @@ pair or session-bound ACC MCP tools. See [CLI ownership](CLI.md#coordinate-from-
|
|
|
15
15
|
|
|
16
16
|
ACC requires macOS or Linux and Node.js 24 or newer.
|
|
17
17
|
|
|
18
|
-
Already using ACC? Follow the [upgrade guide](UPGRADING.md) for the 0.4.
|
|
18
|
+
Already using ACC? Follow the [upgrade guide](UPGRADING.md) for the 0.4.x → 0.4.3
|
|
19
19
|
update or the data-format boundary when upgrading from 0.3.1.
|
|
20
20
|
|
|
21
21
|
```bash
|
|
@@ -39,13 +39,25 @@ printed by the installer. In Codex, use `/plugins` to check ACC is enabled, then
|
|
|
39
39
|
to review each ACC hook and enable/trust its current definition if needed. Restart the
|
|
40
40
|
session after that review; changed hook definitions may require trust again.
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
For Codex live delivery, follow the outgoing-permission and local-service instructions
|
|
43
|
+
from install/doctor, then start a new session. Default workspace permissions can be
|
|
44
|
+
configured automatically on Codex 0.153.4 or newer on macOS arm64. Custom settings are
|
|
45
|
+
preserved; see [outgoing permissions](CONFIGURATION.md#codex-outgoing-permissions).
|
|
46
|
+
With legacy sandbox settings, the named ACC state directory must also be in
|
|
47
|
+
`sandbox_workspace_write.writable_roots` in the config the installer identifies.
|
|
44
48
|
ACC keeps those user settings unchanged. Installed files alone do not establish that hooks
|
|
45
49
|
are active; `acc doctor` leaves current readiness unverified and directs you to Codex.
|
|
46
50
|
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
Read the delivery summary for each client. Live delivery needs an explicit opt-in and a
|
|
52
|
+
verified channel in the current session. Codex can save your choice even when its local
|
|
53
|
+
service is not running yet. Declining uses the reported fallback: `acc inbox`, or next-turn
|
|
54
|
+
hooks only where the exact client version and platform are certified.
|
|
55
|
+
|
|
56
|
+
If you opt into Claude Code's experimental idle delivery, check Claude's Channels startup
|
|
57
|
+
notice for ACC and accept its development-channel warning when shown. If it reports Channels
|
|
58
|
+
unavailable or blocked, a connected MCP server does not make inbound delivery work;
|
|
59
|
+
see [troubleshooting](TROUBLESHOOTING.md#i-enabled-live-delivery-but-got-fallback).
|
|
60
|
+
The feature is off by default, can spend
|
|
49
61
|
model tokens, and currently requires Apple Silicon macOS, zsh, and Claude Code 2.1.258 or
|
|
50
62
|
newer. You do not need it for durable messages or supported next-turn delivery.
|
|
51
63
|
|
package/docs/PROTOCOL.md
CHANGED
|
@@ -199,6 +199,10 @@ peer body into diagnostics.
|
|
|
199
199
|
Receipt `offered` is committed only after the transport accepts bytes. A failed attempt
|
|
200
200
|
leaves the receipt queued.
|
|
201
201
|
|
|
202
|
+
`transport_permission_denied` means the sender's OS or sandbox refused local transport
|
|
203
|
+
access (`EPERM` or `EACCES`). It is distinct from `recipient_unavailable` and remains a
|
|
204
|
+
failed offer with a queued receipt; raw OS error strings are not persisted.
|
|
205
|
+
|
|
202
206
|
## Inbox, reply, and acknowledgement
|
|
203
207
|
|
|
204
208
|
Without an id, public `inbox` lists bounded summary pages for unresolved messages owned
|
package/docs/RELEASING.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Releasing
|
|
2
2
|
|
|
3
3
|
Use this procedure to build one auditable npm artifact, verify that exact tarball, and keep
|
|
4
|
-
its evidence tied to the commit that supplied its bytes. The package is currently `0.4.
|
|
4
|
+
its evidence tied to the commit that supplied its bytes. The package is currently `0.4.3`;
|
|
5
5
|
the commands derive the version from `package.json` so the filename cannot drift.
|
|
6
6
|
|
|
7
7
|
```mermaid
|
package/docs/SECURITY_MODEL.md
CHANGED
|
@@ -79,6 +79,13 @@ consent before offers. A loaded daemon thread can receive messages after its TUI
|
|
|
79
79
|
exits. Delivery off and uninstall prevent new Codex submissions; a submission
|
|
80
80
|
already accepted by the vendor queue cannot be withdrawn.
|
|
81
81
|
|
|
82
|
+
On captured Codex/macOS configurations, live opt-in also grants outgoing access to ACC's
|
|
83
|
+
state and local Unix sockets through a deny-by-default network proxy. Custom permission
|
|
84
|
+
policies remain user-owned. Selection, proxy and grants are restored together only while
|
|
85
|
+
unchanged; edited or newly referenced settings remain intact. See
|
|
86
|
+
[Codex outgoing permissions](CONFIGURATION.md#codex-outgoing-permissions). Configuration
|
|
87
|
+
readiness does not prove that an active session's overrides permit a live offer.
|
|
88
|
+
|
|
82
89
|
## Claims
|
|
83
90
|
|
|
84
91
|
CLI claims default to advisory. Guarded enforcement must be requested explicitly and
|
package/docs/TROUBLESHOOTING.md
CHANGED
|
@@ -94,13 +94,65 @@ For Codex, use your ordinary launch command with 0.152.1 or newer on Apple Silic
|
|
|
94
94
|
macOS. Its LocalDaemon must already be running, and trusted hooks must establish
|
|
95
95
|
the receiver's exact thread and workspace. Embedded sessions, an absent socket,
|
|
96
96
|
ambiguous recipients or failed identity checks retain durable inbox access.
|
|
97
|
-
`acc doctor` reports
|
|
98
|
-
|
|
97
|
+
`acc doctor` reports readiness, consent and the current workspace's live channel separately.
|
|
98
|
+
`native_endpoint_unavailable` means the local service endpoint is missing or is not a safe socket;
|
|
99
|
+
`native_session_unavailable` means the service answered but has no loaded thread to probe.
|
|
100
|
+
An interactive install can save consent in either case. ACC preserves it through a temporary
|
|
101
|
+
outage and does not start the daemon for you.
|
|
102
|
+
|
|
103
|
+
On a supported Codex CLI, a missing daemon can be started with
|
|
104
|
+
`codex app-server daemon start`; open a new Codex session afterward. Doctor includes this
|
|
105
|
+
command when it detects the missing endpoint.
|
|
106
|
+
|
|
107
|
+
If a reply stays queued with `transport_permission_denied`, the sender's permissions
|
|
108
|
+
blocked local transport. This is distinct from an unavailable recipient. The message was
|
|
109
|
+
recorded successfully; the error does not mean it was read or acknowledged.
|
|
110
|
+
On Codex 0.153.4 or newer on macOS arm64, rerun `acc install --adapter codex` with existing
|
|
111
|
+
live consent (or add `--delivery actionable` to opt in), then start a new session.
|
|
112
|
+
Doctor's `outgoingDelivery` reports the installed permission configuration separately
|
|
113
|
+
from `nativeDelivery.runtime`: an active receiving channel does not establish outgoing
|
|
114
|
+
access. Custom policies and active-session overrides remain unverified; inspect the config
|
|
115
|
+
path doctor names and follow [outgoing permissions](CONFIGURATION.md#codex-outgoing-permissions).
|
|
116
|
+
|
|
117
|
+
Check `acc doctor --json` and `acc status --json` while both clients are open. If policy is
|
|
118
|
+
`off`, opt in with `acc install --adapter codex --delivery actionable` (or select another
|
|
119
|
+
adapter). This can spend model tokens. If policy is enabled but runtime is `waiting` and
|
|
120
|
+
`deliveryBindings` is empty, no live channel is bound in this workspace. Start a new client
|
|
121
|
+
session, check its integration prompts and re-run doctor. A healthy store, online peers,
|
|
122
|
+
or a connected MCP server does not by itself establish automatic delivery. `lifecycle:
|
|
123
|
+
manual` can also mean the current version has no certified session-end hook; it does not
|
|
124
|
+
prove that no hooks ran.
|
|
99
125
|
|
|
100
126
|
For Claude Code, open a fresh interactive zsh after installation so its launcher
|
|
101
|
-
is on PATH
|
|
102
|
-
|
|
103
|
-
|
|
127
|
+
is on PATH. Check Claude's **Channels startup notice for ACC**, and accept the
|
|
128
|
+
development-channel warning when it appears. A successful bootstrap cache means the
|
|
129
|
+
executable passed ACC's compatibility probe. `/mcp` showing `connected` and two tools
|
|
130
|
+
means the MCP server connected. Even `runtime: active` in ACC's doctor JSON describes
|
|
131
|
+
the local transport; none of these proves that Claude enabled inbound channel messages.
|
|
132
|
+
|
|
133
|
+
If Claude says `--dangerously-load-development-channels ignored` or `Channels are not
|
|
134
|
+
currently available`, it has not enabled that delivery path. On a fresh 2.1.266 test
|
|
135
|
+
profile, the first launch showed those messages and the next launch showed the development
|
|
136
|
+
warning; restarting once can recheck availability, but is not a guaranteed fix. If it
|
|
137
|
+
remains unavailable, follow Claude's notice. Organization policy can also block Channels;
|
|
138
|
+
an administrator must enable them where required. ACC does not override that policy.
|
|
139
|
+
See [Claude's Channels documentation](https://code.claude.com/docs/en/channels).
|
|
140
|
+
|
|
141
|
+
If `deliveryBindings` is empty, ACC has not bound a local transport either. Read the
|
|
142
|
+
per-session lines in `acc doctor`, or `nativeDelivery.sessions[].lastAttempt` in JSON:
|
|
143
|
+
|
|
144
|
+
- An absent launch policy means that hook did not receive delivery consent, even if an
|
|
145
|
+
earlier bootstrap probe succeeded. For Claude, open a new terminal and client through
|
|
146
|
+
the installed launcher.
|
|
147
|
+
- `client_process_unknown` means ACC could not identify the client process. A new client
|
|
148
|
+
session repeats that lookup.
|
|
149
|
+
- `handshake_failed` or `handshake_timeout` means the session could not bind the local
|
|
150
|
+
channel. Check the client's integration/channel setup; the next ordinary turn retries.
|
|
151
|
+
- No attempt observed can mean no native hook ran, an older runtime wrote the owner, or
|
|
152
|
+
diagnostic persistence failed. Check hook activation and the runtime versions in doctor.
|
|
153
|
+
|
|
154
|
+
The timestamp describes the last attempt for that exact generation. A past successful
|
|
155
|
+
handshake does not establish a currently reachable channel or client-side admission.
|
|
104
156
|
|
|
105
157
|
Closing a Codex terminal can leave its daemon thread loaded and eligible. Use
|
|
106
158
|
`acc install --adapter codex --delivery off` to stop new ACC native offers.
|
|
@@ -115,8 +167,9 @@ definitions need review, and a trusted hook can still be disabled.
|
|
|
115
167
|
|
|
116
168
|
`acc doctor` reports installed files separately from hook readiness, which it leaves
|
|
117
169
|
unverified. A saved trust record cannot prove current activation. If installation preserved
|
|
118
|
-
your own sandbox configuration, doctor also names the ACC state directory whose
|
|
119
|
-
you should check in `sandbox_workspace_write.writable_roots`.
|
|
170
|
+
your own legacy sandbox configuration, doctor also names the ACC state directory whose
|
|
171
|
+
access you should check in `sandbox_workspace_write.writable_roots`. Live delivery requires
|
|
172
|
+
local socket permissions as well; a writable state directory alone is insufficient.
|
|
120
173
|
|
|
121
174
|
## Gemini does not guard a write
|
|
122
175
|
|
package/docs/UPGRADING.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
# Upgrading to 0.4.
|
|
1
|
+
# Upgrading to 0.4.3
|
|
2
2
|
|
|
3
|
-
## From 0.4.0
|
|
3
|
+
## From 0.4.2, 0.4.1 or 0.4.0
|
|
4
4
|
|
|
5
|
-
This patch keeps the existing workspace data format. It fixes
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
This patch keeps the existing workspace data format. It fixes outgoing native delivery
|
|
6
|
+
from Codex's sandbox, separates permission failures from unavailable recipients, and
|
|
7
|
+
shows outgoing setup alongside receiving-channel state in doctor. It also includes the
|
|
8
|
+
previous 0.4.x delivery diagnostics, session recovery and client integration fixes.
|
|
8
9
|
|
|
9
|
-
Close
|
|
10
|
+
Close participating clients and persistent ACC MCP processes, then run:
|
|
10
11
|
|
|
11
12
|
```bash
|
|
12
13
|
acc update
|
|
@@ -14,17 +15,33 @@ acc version
|
|
|
14
15
|
acc doctor
|
|
15
16
|
```
|
|
16
17
|
|
|
17
|
-
After publication, `acc version` should report 0.4.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
in
|
|
18
|
+
After publication, `acc version` should report 0.4.3. If a pin keeps an older version,
|
|
19
|
+
select 0.4.3 or clear it first. A managed update refreshes installed integrations and
|
|
20
|
+
skills; use the npm instructions below for unmanaged or pre-0.4 installations. Start
|
|
21
|
+
clients again and complete any hook/trust review they request. With existing live consent,
|
|
22
|
+
Codex 0.153.4 or newer on macOS arm64 receives local socket permissions when its workspace
|
|
23
|
+
policy is default or contains only ACC's legacy state root. Custom policies are preserved
|
|
24
|
+
and reported as unverified. See [outgoing permissions](CONFIGURATION.md#codex-outgoing-permissions).
|
|
25
|
+
If doctor names a missing local service, run `codex app-server daemon start` before opening
|
|
26
|
+
the new session.
|
|
27
|
+
|
|
28
|
+
Run `acc doctor` in the project after the new clients have started (or submitted a normal
|
|
29
|
+
turn). Its per-session lines now explain missing launch consent, an unidentified client
|
|
30
|
+
process and a failed or timed-out handshake. `nativeDelivery.sessions[].lastAttempt` in
|
|
31
|
+
`acc doctor --json` provides the same closed metadata and timestamp. Existing owners may
|
|
32
|
+
have no attempt record until a new hook runs; missing metadata does not prove hooks are
|
|
33
|
+
disabled. A previous successful handshake and a connected MCP server do not prove that
|
|
34
|
+
Claude admitted inbound Channels messages. See [delivery troubleshooting](TROUBLESHOOTING.md#i-enabled-live-delivery-but-got-fallback).
|
|
35
|
+
|
|
36
|
+
Upgrading preserves delivery consent. If doctor reports native delivery off and you want
|
|
37
|
+
automatic peer requests, use `acc install --adapter codex --delivery actionable` (or the
|
|
38
|
+
relevant adapter); this can spend model tokens. Codex can save that consent before its
|
|
39
|
+
local service/session becomes available. ACC does not start the vendor daemon, and it
|
|
40
|
+
keeps durable inbox access when no verified live channel is bound.
|
|
41
|
+
|
|
42
|
+
In Grok, public status supplies the session's own CLI arguments through the next tool
|
|
43
|
+
hook. Grok still uses explicit inbox reads; this patch adds no external wake or guards.
|
|
44
|
+
Start clients in a project directory, rather than a home directory containing ACC state.
|
|
28
45
|
|
|
29
46
|
## From 0.3.1
|
|
30
47
|
|
|
@@ -47,7 +64,7 @@ restores access; deleting or editing the record is not a remedy.
|
|
|
47
64
|
2. Install the released package, then refresh the client integrations:
|
|
48
65
|
|
|
49
66
|
```bash
|
|
50
|
-
npm install --global agents-can-communicate@0.4.
|
|
67
|
+
npm install --global agents-can-communicate@0.4.3
|
|
51
68
|
acc version
|
|
52
69
|
acc install
|
|
53
70
|
```
|
|
@@ -97,7 +114,7 @@ acc update # download and apply, or report what is keeping it
|
|
|
97
114
|
acc update --check # check without installing or changing update settings
|
|
98
115
|
acc update --auto off # disable background updates
|
|
99
116
|
acc update --auto on # enable them again
|
|
100
|
-
acc update --pin 0.4.
|
|
117
|
+
acc update --pin 0.4.3 # stay on this exact stable version
|
|
101
118
|
acc update --pin none # follow stable releases again
|
|
102
119
|
```
|
|
103
120
|
|
|
@@ -11,9 +11,9 @@ import { bindNativeSession, offerMessage, planNativeActivation, probeNativeDeliv
|
|
|
11
11
|
export const CLAUDE_CODE_VERSION = "2.1.233";
|
|
12
12
|
export const CLAUDE_CHANNEL_MINIMUM = "2.1.258";
|
|
13
13
|
export const CLAUDE_DELIVERY_FALLBACK = Object.freeze({
|
|
14
|
-
diagnostic: "Claude Code native delivery
|
|
15
|
-
+ "
|
|
16
|
-
+ "
|
|
14
|
+
diagnostic: "Claude Code native delivery requires client-side Channels activation; "
|
|
15
|
+
+ "a successful bootstrap or connected ACC MCP server does not prove inbound delivery "
|
|
16
|
+
+ "is enabled. Messages remain durable for certified next-turn delivery or acc inbox",
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
2
2
|
import { chmodSync, existsSync, mkdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
3
|
import net from "node:net";
|
|
4
|
-
import os from "node:os";
|
|
5
4
|
import path from "node:path";
|
|
5
|
+
import { channelSocketDirectory } from "@agents-can-communicate/adapter-sdk";
|
|
6
6
|
|
|
7
7
|
// The production ACC Channel: a stdio MCP server Claude Code spawns, plus a
|
|
8
8
|
// session-scoped Unix endpoint the delivery router reaches. One envelope on the
|
|
@@ -39,8 +39,6 @@ const shortId = () => `endpoint_${randomBytes(16).toString("hex")}`;
|
|
|
39
39
|
// while the registration - discoverable by the hook-resolved pid - stays under
|
|
40
40
|
// the workspace. The registration records the socket's absolute path, so the
|
|
41
41
|
// two are decoupled.
|
|
42
|
-
const defaultSocketDir = () => path.join(os.tmpdir(),
|
|
43
|
-
`acc-ch-${typeof process.getuid === "function" ? process.getuid() : "u"}`);
|
|
44
42
|
|
|
45
43
|
/**
|
|
46
44
|
* Compose a Channel over an endpoint directory and injected ACC callbacks.
|
|
@@ -49,7 +47,7 @@ const defaultSocketDir = () => path.join(os.tmpdir(),
|
|
|
49
47
|
* ones backed by the real conversation service; a test supplies fakes. Neither
|
|
50
48
|
* the socket path nor the nonce leaves through a return value or a log line.
|
|
51
49
|
*/
|
|
52
|
-
export function createAccChannel({ endpointDir, socketDir =
|
|
50
|
+
export function createAccChannel({ endpointDir, socketDir = channelSocketDirectory(), clientPid,
|
|
53
51
|
protocolContract = PROTOCOL_CONTRACT, modes = CHANNEL_MODES, leaseMs = 60_000, routeReply,
|
|
54
52
|
routeAck, refreshBinding = null, observe = () => {},
|
|
55
53
|
clock = () => new Date().toISOString(), write, now = Date.now }) {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { cp, mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
|
+
// Kept together above 300 lines: source and cache publication, vendor registry
|
|
5
|
+
// merges and their exact uninstall share one ownership transaction and helpers.
|
|
6
|
+
|
|
4
7
|
import { AccError, EXIT } from "@agents-can-communicate/protocol";
|
|
5
8
|
import { fileURLToPath } from "node:url";
|
|
6
9
|
|
|
@@ -19,6 +22,9 @@ const manifest = fileURLToPath(new URL("../plugin/.claude-plugin/plugin.json",
|
|
|
19
22
|
const PLUGIN_NAME = "agents-can-communicate";
|
|
20
23
|
const MARKETPLACE = "acc-local";
|
|
21
24
|
const QUALIFIED = `${PLUGIN_NAME}@${MARKETPLACE}`;
|
|
25
|
+
const CHANNEL_ACTIVATION_CHECK = "Check Claude's Channels startup notice for ACC; "
|
|
26
|
+
+ "an MCP connection does not verify inbound delivery. If Channels are unavailable "
|
|
27
|
+
+ "or blocked, resolve that client warning before expecting live messages.";
|
|
22
28
|
|
|
23
29
|
/**
|
|
24
30
|
* How this client actually installs a plugin.
|
|
@@ -244,6 +250,7 @@ export async function installClaudePlugin({ configDir, runner, cli, preserveVers
|
|
|
244
250
|
changes: [source, cached, marketplaceFile(configDir),
|
|
245
251
|
knownMarketplacesPath(configDir), installedPluginsPath(configDir), file,
|
|
246
252
|
...(live ? [mcpPath(source), mcpPath(cached)] : [])],
|
|
253
|
+
needsAction: live ? [CHANNEL_ACTIVATION_CHECK] : [],
|
|
247
254
|
diagnostics: live
|
|
248
255
|
? ["native channel wired; Claude's experimental development-channel warning still applies"]
|
|
249
256
|
: [] };
|
|
@@ -290,7 +297,10 @@ export async function detectClaude({ configDir }) {
|
|
|
290
297
|
const registered = Object.hasOwn(
|
|
291
298
|
(await readJson(installedPluginsPath(configDir), { plugins: {} })).plugins ?? {},
|
|
292
299
|
QUALIFIED);
|
|
300
|
+
const channelConfigured = enabled && registered
|
|
301
|
+
&& (await readJson(mcpPath(sourceDir(configDir)), null))?.mcpServers?.["acc-channel"] != null;
|
|
293
302
|
return { ok: true, changes: [],
|
|
303
|
+
needsAction: channelConfigured ? [CHANNEL_ACTIVATION_CHECK] : [],
|
|
294
304
|
diagnostics: [enabled && registered
|
|
295
305
|
? "acc plugin registered and enabled"
|
|
296
306
|
: "acc plugin not registered"] };
|
|
@@ -206,7 +206,9 @@ function sendEnvelope({ record, message, binding, connect, timeoutMs, rejected }
|
|
|
206
206
|
const finish = value => { if (settled) return; settled = true; clearTimeout(timer);
|
|
207
207
|
socket.destroy(); resolve(value); };
|
|
208
208
|
const timer = setTimeout(() => finish(rejected("transport_error")), timeoutMs);
|
|
209
|
-
socket.once("error",
|
|
209
|
+
socket.once("error", error => finish(rejected(
|
|
210
|
+
["EPERM", "EACCES"].includes(error.code)
|
|
211
|
+
? "transport_permission_denied" : "recipient_unavailable")));
|
|
210
212
|
socket.once("connect", () => {
|
|
211
213
|
socket.write(`${JSON.stringify(envelope)}\n`);
|
|
212
214
|
let buffer = "";
|
|
@@ -65,7 +65,7 @@ export async function probeCodexQueue(peer, { threadId, minimum = MINIMUM_VERSIO
|
|
|
65
65
|
const loaded = await pageAll(peer, "thread/loaded/list", {});
|
|
66
66
|
threadId = loaded.find(id => typeof id === "string" && id !== "");
|
|
67
67
|
if (threadId === undefined) return { supported: false, serverVersion,
|
|
68
|
-
reasonCode: "
|
|
68
|
+
reasonCode: "native_session_unavailable" };
|
|
69
69
|
}
|
|
70
70
|
queueEntries(await peer.request("thread/queue/list", { threadId }));
|
|
71
71
|
} catch (error) {
|
|
@@ -3,10 +3,8 @@ import path from "node:path";
|
|
|
3
3
|
import { BEGIN, END, renderBlock } from "@agents-can-communicate/adapter-sdk";
|
|
4
4
|
import { AccError, EXIT } from "@agents-can-communicate/protocol";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
+ "repair ambiguous TOML or ACC markers before retrying", { reason });
|
|
9
|
-
};
|
|
6
|
+
import { statements, declaration, unsafe } from "./toml-scan.mjs";
|
|
7
|
+
|
|
10
8
|
const ROOT = "# ACC sandbox writable_roots created with: ";
|
|
11
9
|
export const sandboxOwnership = root => `${ROOT}${JSON.stringify(root)}`;
|
|
12
10
|
|
|
@@ -16,88 +14,6 @@ const OWNED = new Map([
|
|
|
16
14
|
[JSON.stringify(["sandbox_workspace_write"]), ["writable_roots"]],
|
|
17
15
|
]);
|
|
18
16
|
|
|
19
|
-
// A bounded lexical scan, not a TOML value parser. Newlines inside strings,
|
|
20
|
-
// arrays and inline tables cannot introduce a header or a managed marker.
|
|
21
|
-
function* statements(source) {
|
|
22
|
-
let start = 0, code = "", quote = null;
|
|
23
|
-
const stack = [];
|
|
24
|
-
for (let i = 0; i < source.length;) {
|
|
25
|
-
const char = source[i];
|
|
26
|
-
if (quote) {
|
|
27
|
-
if (quote[0] === '"' && char === "\\") {
|
|
28
|
-
code += source.slice(i, i + 2); i += 2; continue;
|
|
29
|
-
}
|
|
30
|
-
if (source.startsWith(quote, i)) {
|
|
31
|
-
let count = quote.length;
|
|
32
|
-
if (quote.length === 3) {
|
|
33
|
-
while (source[i + count] === quote[0]) count++;
|
|
34
|
-
if (count > 5) unsafe("unsupported string quote delimiter");
|
|
35
|
-
}
|
|
36
|
-
code += source.slice(i, i + count); i += count; quote = null; continue;
|
|
37
|
-
}
|
|
38
|
-
if (quote.length === 1 && /[\r\n]/.test(char)) unsafe("newline in single-line string");
|
|
39
|
-
code += char; i++; continue;
|
|
40
|
-
}
|
|
41
|
-
if (char === "#") {
|
|
42
|
-
while (i < source.length && source[i] !== "\n") i++;
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
if (char === '"' || char === "'") {
|
|
46
|
-
quote = source.startsWith(char.repeat(3), i) ? char.repeat(3) : char;
|
|
47
|
-
code += quote; i += quote.length; continue;
|
|
48
|
-
}
|
|
49
|
-
if (char === "[" || char === "{") stack.push(char);
|
|
50
|
-
if (char === "]" || char === "}") {
|
|
51
|
-
if (stack.pop() !== (char === "]" ? "[" : "{")) unsafe("mismatched collection delimiter");
|
|
52
|
-
}
|
|
53
|
-
code += char; i++;
|
|
54
|
-
if (char === "\n" && stack.length === 0) {
|
|
55
|
-
yield { raw: source.slice(start, i), code: code.trim() };
|
|
56
|
-
start = i; code = "";
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
if (quote || stack.length) unsafe(quote ? "unclosed string" : "unclosed collection");
|
|
60
|
-
if (start < source.length) yield { raw: source.slice(start), code: code.trim() };
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function decodeKey(key) {
|
|
64
|
-
if (key[0] === "'") return key.slice(1, -1);
|
|
65
|
-
if (key[0] !== '"') return key;
|
|
66
|
-
return key.slice(1, -1).replace(/\\(U[\da-fA-F]{8}|u[\da-fA-F]{4}|[btnfr"\\])|\\./g,
|
|
67
|
-
(match, escape) => {
|
|
68
|
-
if (!escape) unsafe("unsupported quoted-key escape");
|
|
69
|
-
if (/^[uU]/.test(escape)) {
|
|
70
|
-
const point = Number.parseInt(escape.slice(1), 16);
|
|
71
|
-
if (point > 0x10ffff || (point >= 0xd800 && point <= 0xdfff)) {
|
|
72
|
-
unsafe("invalid quoted-key Unicode escape");
|
|
73
|
-
}
|
|
74
|
-
return String.fromCodePoint(point);
|
|
75
|
-
}
|
|
76
|
-
return ({ b: "\b", t: "\t", n: "\n", f: "\f", r: "\r", '"': '"', "\\": "\\" })[escape];
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function keyPath(code) {
|
|
81
|
-
const keys = [];
|
|
82
|
-
let rest = code.trimStart();
|
|
83
|
-
for (;;) {
|
|
84
|
-
const match = /^(?:[A-Za-z0-9_-]+|'[^'\r\n]*'|"(?:[^"\\\r\n]|\\[^\r\n])*")/.exec(rest);
|
|
85
|
-
if (!match) unsafe("unrecognized TOML key");
|
|
86
|
-
keys.push(decodeKey(match[0]));
|
|
87
|
-
rest = rest.slice(match[0].length).trimStart();
|
|
88
|
-
if (!rest.startsWith(".")) return { keys, rest };
|
|
89
|
-
rest = rest.slice(1).trimStart();
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function declaration(code) {
|
|
94
|
-
const header = code.startsWith("[");
|
|
95
|
-
const array = header && code.startsWith("[[");
|
|
96
|
-
const { keys, rest } = keyPath(header ? code.slice(array ? 2 : 1) : code);
|
|
97
|
-
if (header ? rest !== (array ? "]]" : "]") : !rest.startsWith("=")) unsafe();
|
|
98
|
-
return { keys, header, array, value: header ? null : rest.slice(1).trim() };
|
|
99
|
-
}
|
|
100
|
-
|
|
101
17
|
// An unchanged, newly generated sandbox has value provenance. A legacy or
|
|
102
18
|
// edited sandbox belongs to the client as a whole and remains byte-preserved.
|
|
103
19
|
function ownsSandbox(body) {
|
|
@@ -214,8 +130,8 @@ export async function readConfig(file) {
|
|
|
214
130
|
});
|
|
215
131
|
}
|
|
216
132
|
|
|
217
|
-
export async function writeTomlBlock(file, body) {
|
|
218
|
-
const
|
|
133
|
+
export async function writeTomlBlock(file, body, preparedSource) {
|
|
134
|
+
const source = preparedSource ?? inspectConfig(await readConfig(file), file).source;
|
|
219
135
|
const separator = source === "" || source.endsWith("\n") ? "" : "\n";
|
|
220
136
|
await mkdir(path.dirname(file), { recursive: true });
|
|
221
137
|
await writeFile(file, `${source}${separator}${renderBlock(body)}\n`);
|