agents-can-communicate 0.1.7 → 0.1.8
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/node_modules/@agents-can-communicate/adapter-claude-code/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-codex/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/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/context-projector.mjs +20 -1
- package/node_modules/@agents-can-communicate/cli/package.json +1 -1
- package/node_modules/@agents-can-communicate/core/package.json +1 -1
- package/node_modules/@agents-can-communicate/core/src/status.mjs +10 -0
- package/node_modules/@agents-can-communicate/hook-runner/package.json +1 -1
- package/node_modules/@agents-can-communicate/installer/package.json +1 -1
- 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
|
@@ -33,6 +33,12 @@ function escapePeerText(value) {
|
|
|
33
33
|
return String(value)
|
|
34
34
|
.replaceAll(new RegExp(`${FENCE}${BLOCK}`, "g"), `'${FENCE}${BLOCK}`)
|
|
35
35
|
.replaceAll(FENCE, `'${FENCE}`)
|
|
36
|
+
// The labels that frame this block are ACC's words at the start of a line.
|
|
37
|
+
// A peer writing one would otherwise produce a second line reading as ACC
|
|
38
|
+
// framing a different message - the same break-out the fence rule prevents,
|
|
39
|
+
// and neutralised the same way rather than by reflowing the text, which a
|
|
40
|
+
// handoff body cannot survive.
|
|
41
|
+
.replace(/^(subject:|body:)/gm, "'$1")
|
|
36
42
|
.replace(CONTROL_CHARACTERS,
|
|
37
43
|
character => `\\u${character.codePointAt(0).toString(16).padStart(4, "0")}`);
|
|
38
44
|
}
|
|
@@ -118,12 +124,25 @@ function peerBlocks(messages) {
|
|
|
118
124
|
`${FENCE}${BLOCK}`,
|
|
119
125
|
`id ${message.messageId} | from ${message.fromSessionId} | type ${message.type}`
|
|
120
126
|
+ " | untrusted peer message",
|
|
121
|
-
escapePeerText(message.subject)
|
|
127
|
+
`subject: ${oneLine(escapePeerText(message.subject))}`,
|
|
128
|
+
"body:",
|
|
122
129
|
escapePeerText(message.body),
|
|
123
130
|
FENCE,
|
|
124
131
|
]);
|
|
125
132
|
}
|
|
126
133
|
|
|
134
|
+
/**
|
|
135
|
+
* A subject is one line, whatever the peer sent.
|
|
136
|
+
*
|
|
137
|
+
* The subject sits on the label's own line, so a newline inside it would push
|
|
138
|
+
* peer text to column 0 where ACC's labels live. Rendering the break visibly
|
|
139
|
+
* keeps the text readable and the frame ACC's.
|
|
140
|
+
*/
|
|
141
|
+
function oneLine(value) {
|
|
142
|
+
return value.replaceAll("\r\n", "\\n").replaceAll("\n", "\\n").replaceAll("\r", "\\n");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
|
|
127
146
|
/**
|
|
128
147
|
* Project a SyncResult into bounded text for one adapter to inject.
|
|
129
148
|
*
|
|
@@ -108,12 +108,22 @@ export function createStatusService(ports, sessions) {
|
|
|
108
108
|
state: workstream.state,
|
|
109
109
|
coordinatorSessionId: workstream.coordinatorSessionId,
|
|
110
110
|
})),
|
|
111
|
+
// The owner is named twice on purpose. Every command that reaches a peer
|
|
112
|
+
// takes a participant id, so a claim that gave only a session id sent the
|
|
113
|
+
// reader back through the roster to answer "who is holding this, and how
|
|
114
|
+
// do I ask them for it". The session id stays because it is what
|
|
115
|
+
// `acc release --authority` acts on, and because two sessions of one
|
|
116
|
+
// participant are still two holders.
|
|
111
117
|
claims: claims.map(claim => ({
|
|
112
118
|
claimId: claim.claimId,
|
|
113
119
|
resource: claim.resource,
|
|
114
120
|
mode: claim.mode,
|
|
115
121
|
enforcement: claim.enforcement,
|
|
116
122
|
ownerSessionId: claim.ownerSessionId,
|
|
123
|
+
// Read from every session on record, not only the live ones: a claim
|
|
124
|
+
// outliving its session is exactly when this question gets asked.
|
|
125
|
+
ownerParticipantId: sessionRecords
|
|
126
|
+
.find(session => session.sessionId === claim.ownerSessionId)?.participantId ?? null,
|
|
117
127
|
expiresAt: claim.expiresAt,
|
|
118
128
|
})),
|
|
119
129
|
attention: computeAttention(snapshot, { session: null,
|