@cluesmith/codev 3.3.0 → 3.3.2
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/dashboard-dist/assets/{index-JCbkpAcV.js → index-D3XaKpZW.js} +45 -43
- package/dashboard-dist/assets/index-D3XaKpZW.js.map +1 -0
- package/dashboard-dist/index.html +1 -1
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +99 -36
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/reset/constants.d.ts +119 -1
- package/dist/agent-farm/commands/reset/constants.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/constants.js +119 -1
- package/dist/agent-farm/commands/reset/constants.js.map +1 -1
- package/dist/agent-farm/commands/reset/context.d.ts +20 -2
- package/dist/agent-farm/commands/reset/context.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/context.js +44 -3
- package/dist/agent-farm/commands/reset/context.js.map +1 -1
- package/dist/agent-farm/commands/reset/index.d.ts +7 -7
- package/dist/agent-farm/commands/reset/index.js +8 -8
- package/dist/agent-farm/commands/reset/index.js.map +1 -1
- package/dist/agent-farm/commands/reset/receipt.d.ts +1 -1
- package/dist/agent-farm/commands/reset/receipt.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/receipt.js +19 -8
- package/dist/agent-farm/commands/reset/receipt.js.map +1 -1
- package/dist/agent-farm/commands/reset/reorient.d.ts +1 -1
- package/dist/agent-farm/commands/reset/reorient.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/reorient.js +12 -5
- package/dist/agent-farm/commands/reset/reorient.js.map +1 -1
- package/dist/agent-farm/commands/reset/self.d.ts +335 -0
- package/dist/agent-farm/commands/reset/self.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/self.js +636 -0
- package/dist/agent-farm/commands/reset/self.js.map +1 -0
- package/dist/agent-farm/commands/reset.d.ts +18 -3
- package/dist/agent-farm/commands/reset.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset.js +55 -33
- package/dist/agent-farm/commands/reset.js.map +1 -1
- package/dist/agent-farm/commands/self-refresh.d.ts +60 -0
- package/dist/agent-farm/commands/self-refresh.d.ts.map +1 -0
- package/dist/agent-farm/commands/self-refresh.js +506 -0
- package/dist/agent-farm/commands/self-refresh.js.map +1 -0
- package/dist/agent-farm/commands/send.d.ts.map +1 -1
- package/dist/agent-farm/commands/send.js +27 -2
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
- package/dist/agent-farm/commands/spawn.d.ts +7 -0
- package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn.js +13 -1
- package/dist/agent-farm/commands/spawn.js.map +1 -1
- package/dist/agent-farm/commands/tower.d.ts.map +1 -1
- package/dist/agent-farm/commands/tower.js +13 -0
- package/dist/agent-farm/commands/tower.js.map +1 -1
- package/dist/agent-farm/lib/reconnect-backoff.d.ts +10 -0
- package/dist/agent-farm/lib/reconnect-backoff.d.ts.map +1 -1
- package/dist/agent-farm/lib/reconnect-backoff.js +10 -0
- package/dist/agent-farm/lib/reconnect-backoff.js.map +1 -1
- package/dist/agent-farm/lib/tower-client.d.ts +12 -0
- package/dist/agent-farm/lib/tower-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tower-client.js +12 -0
- package/dist/agent-farm/lib/tower-client.js.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.js +7 -3
- package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
- package/dist/agent-farm/servers/canvas-relay.d.ts +60 -0
- package/dist/agent-farm/servers/canvas-relay.d.ts.map +1 -0
- package/dist/agent-farm/servers/canvas-relay.js +376 -0
- package/dist/agent-farm/servers/canvas-relay.js.map +1 -0
- package/dist/agent-farm/servers/gate-profiles.d.ts +1 -1
- package/dist/agent-farm/servers/gate-profiles.js +1 -1
- package/dist/agent-farm/servers/mailbox-delivery.d.ts +141 -13
- package/dist/agent-farm/servers/mailbox-delivery.d.ts.map +1 -1
- package/dist/agent-farm/servers/mailbox-delivery.js +172 -16
- package/dist/agent-farm/servers/mailbox-delivery.js.map +1 -1
- package/dist/agent-farm/servers/mailbox-wiring.d.ts +24 -2
- package/dist/agent-farm/servers/mailbox-wiring.d.ts.map +1 -1
- package/dist/agent-farm/servers/mailbox-wiring.js +92 -32
- package/dist/agent-farm/servers/mailbox-wiring.js.map +1 -1
- package/dist/agent-farm/servers/message-write.d.ts +58 -18
- package/dist/agent-farm/servers/message-write.d.ts.map +1 -1
- package/dist/agent-farm/servers/message-write.js +73 -28
- package/dist/agent-farm/servers/message-write.js.map +1 -1
- package/dist/agent-farm/servers/overview.d.ts +19 -0
- package/dist/agent-farm/servers/overview.d.ts.map +1 -1
- package/dist/agent-farm/servers/overview.js +78 -1
- package/dist/agent-farm/servers/overview.js.map +1 -1
- package/dist/agent-farm/servers/render-gate.d.ts +13 -0
- package/dist/agent-farm/servers/render-gate.d.ts.map +1 -1
- package/dist/agent-farm/servers/render-gate.js +21 -0
- package/dist/agent-farm/servers/render-gate.js.map +1 -1
- package/dist/agent-farm/servers/session-submit.d.ts +221 -28
- package/dist/agent-farm/servers/session-submit.d.ts.map +1 -1
- package/dist/agent-farm/servers/session-submit.js +334 -43
- package/dist/agent-farm/servers/session-submit.js.map +1 -1
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-routes.js +269 -64
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +25 -3
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts +6 -0
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.js +30 -5
- package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
- package/dist/agent-farm/servers/tower-tunnel.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-tunnel.js +14 -0
- package/dist/agent-farm/servers/tower-tunnel.js.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.d.ts +6 -1
- package/dist/agent-farm/servers/tower-websocket.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.js +90 -37
- package/dist/agent-farm/servers/tower-websocket.js.map +1 -1
- package/dist/agent-farm/types.d.ts +37 -2
- package/dist/agent-farm/types.d.ts.map +1 -1
- package/dist/agent-farm/utils/harness.d.ts +3 -3
- package/dist/agent-farm/utils/harness.js +1 -1
- package/dist/agent-farm/utils/message-format.d.ts +67 -3
- package/dist/agent-farm/utils/message-format.d.ts.map +1 -1
- package/dist/agent-farm/utils/message-format.js +127 -14
- package/dist/agent-farm/utils/message-format.js.map +1 -1
- package/dist/agent-farm/utils/server-utils.d.ts +86 -4
- package/dist/agent-farm/utils/server-utils.d.ts.map +1 -1
- package/dist/agent-farm/utils/server-utils.js +303 -5
- package/dist/agent-farm/utils/server-utils.js.map +1 -1
- package/dist/commands/porch/context-refresh.d.ts +181 -0
- package/dist/commands/porch/context-refresh.d.ts.map +1 -0
- package/dist/commands/porch/context-refresh.js +270 -0
- package/dist/commands/porch/context-refresh.js.map +1 -0
- package/dist/commands/porch/index.d.ts +6 -0
- package/dist/commands/porch/index.d.ts.map +1 -1
- package/dist/commands/porch/index.js +46 -0
- package/dist/commands/porch/index.js.map +1 -1
- package/dist/commands/porch/next.d.ts +0 -9
- package/dist/commands/porch/next.d.ts.map +1 -1
- package/dist/commands/porch/next.js +133 -4
- package/dist/commands/porch/next.js.map +1 -1
- package/dist/commands/porch/protocol.d.ts.map +1 -1
- package/dist/commands/porch/protocol.js +102 -0
- package/dist/commands/porch/protocol.js.map +1 -1
- package/dist/commands/porch/types.d.ts +61 -0
- package/dist/commands/porch/types.d.ts.map +1 -1
- package/dist/lib/forge-contracts.d.ts +9 -0
- package/dist/lib/forge-contracts.d.ts.map +1 -1
- package/dist/lib/forge-contracts.js.map +1 -1
- package/dist/lib/github.d.ts +15 -1
- package/dist/lib/github.d.ts.map +1 -1
- package/dist/lib/github.js +17 -0
- package/dist/lib/github.js.map +1 -1
- package/dist/lib/self-refresh-invocation.d.ts +60 -0
- package/dist/lib/self-refresh-invocation.d.ts.map +1 -0
- package/dist/lib/self-refresh-invocation.js +64 -0
- package/dist/lib/self-refresh-invocation.js.map +1 -0
- package/dist/lib/test-env.d.ts +50 -0
- package/dist/lib/test-env.d.ts.map +1 -1
- package/dist/lib/test-env.js +76 -0
- package/dist/lib/test-env.js.map +1 -1
- package/dist/terminal/attach-replay.d.ts +39 -0
- package/dist/terminal/attach-replay.d.ts.map +1 -0
- package/dist/terminal/attach-replay.js +76 -0
- package/dist/terminal/attach-replay.js.map +1 -0
- package/dist/terminal/pty-manager.d.ts.map +1 -1
- package/dist/terminal/pty-manager.js +35 -17
- package/dist/terminal/pty-manager.js.map +1 -1
- package/dist/terminal/pty-session.d.ts +81 -12
- package/dist/terminal/pty-session.d.ts.map +1 -1
- package/dist/terminal/pty-session.js +113 -25
- package/dist/terminal/pty-session.js.map +1 -1
- package/dist/terminal/session-screen.d.ts +25 -0
- package/dist/terminal/session-screen.d.ts.map +1 -1
- package/dist/terminal/session-screen.js +53 -8
- package/dist/terminal/session-screen.js.map +1 -1
- package/package.json +10 -7
- package/scripts/forge/gitea/pr-view.sh +4 -1
- package/scripts/forge/github/pr-view.sh +1 -1
- package/scripts/forge/gitlab/pr-view.sh +4 -1
- package/skeleton/.claude/skills/afx/SKILL.md +54 -0
- package/skeleton/.claude/skills/arch-save/SKILL.md +8 -2
- package/skeleton/.claude/skills/builder-refresh/SKILL.md +138 -0
- package/skeleton/.codex/skills/afx/SKILL.md +54 -0
- package/skeleton/.codex/skills/arch-save/SKILL.md +8 -2
- package/skeleton/.codex/skills/builder-refresh/SKILL.md +138 -0
- package/skeleton/protocol-schema.json +17 -0
- package/skeleton/protocols/air/protocol.json +1 -1
- package/skeleton/protocols/aspir/protocol.json +5 -1
- package/skeleton/protocols/bugfix/protocol.json +1 -1
- package/skeleton/protocols/experiment/protocol.json +1 -1
- package/skeleton/protocols/maintain/protocol.json +1 -1
- package/skeleton/protocols/pir/builder-prompt.md +3 -2
- package/skeleton/protocols/pir/prompts/implement.md +1 -1
- package/skeleton/protocols/pir/prompts/plan.md +1 -1
- package/skeleton/protocols/pir/prompts/review.md +1 -1
- package/skeleton/protocols/pir/protocol.json +1 -1
- package/skeleton/protocols/pir/protocol.md +4 -4
- package/skeleton/protocols/protocol-schema.json +17 -0
- package/skeleton/protocols/research/protocol.json +1 -1
- package/skeleton/protocols/spike/protocol.json +1 -1
- package/skeleton/protocols/spir/protocol.json +5 -1
- package/skeleton/resources/commands/agent-farm.md +14 -11
- package/skeleton/roles/builder.md +3 -4
- package/templates/3d-viewer.html +32 -4
- package/templates/open.html +58 -12
- package/templates/tower.html +26 -7
- package/templates/vendor/three-3MFLoader.js +1478 -0
- package/templates/vendor/three-STLLoader.js +410 -0
- package/templates/vendor/three-TrackballControls.js +828 -0
- package/templates/vendor/three-fflate.module.js +2474 -0
- package/templates/vendor/three.module.js +53044 -0
- package/dashboard-dist/assets/index-JCbkpAcV.js.map +0 -1
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
* WebSocket upgrade routing (direct + workspace-scoped).
|
|
7
7
|
*/
|
|
8
8
|
import { WebSocket } from 'ws';
|
|
9
|
-
import { WS_CLOSE_SESSION_UNKNOWN } from '../lib/reconnect-backoff.js';
|
|
9
|
+
import { WS_CLOSE_SESSION_UNKNOWN, WS_CLOSE_UNAUTHORIZED } from '../lib/reconnect-backoff.js';
|
|
10
|
+
import { isWebSocketAllowed } from '../utils/server-utils.js';
|
|
10
11
|
import { encodeData, encodeControl, decodeFrame } from '../../terminal/ws-protocol.js';
|
|
11
|
-
import {
|
|
12
|
+
import { attachWithReplay } from '../../terminal/attach-replay.js';
|
|
13
|
+
import { getTerminalManager, isStartupReconcileSettled, whenStartupReconcileSettled, logTerminal } from './tower-terminals.js';
|
|
12
14
|
import { normalizeWorkspacePath } from './tower-utils.js';
|
|
13
15
|
import { decodeWorkspacePath } from '../lib/tower-client.js';
|
|
14
16
|
import { addSubscriber, removeSubscriber } from './tower-messages.js';
|
|
@@ -26,8 +28,13 @@ const WS_HIGH_WATER_MARK = 1 * 1024 * 1024; // 1 MB
|
|
|
26
28
|
* Uses hybrid binary protocol (Spec 0085):
|
|
27
29
|
* - 0x00 prefix: Control frame (JSON)
|
|
28
30
|
* - 0x01 prefix: Data frame (raw PTY bytes)
|
|
31
|
+
*
|
|
32
|
+
* Async since PIR #1354: the replay payload is the session mirror's serialized
|
|
33
|
+
* O(screen) snapshot, whose parser flush awaits. Input/close handlers are
|
|
34
|
+
* registered BEFORE that await so the client can type during the flush and a
|
|
35
|
+
* close can never race the registration.
|
|
29
36
|
*/
|
|
30
|
-
export function handleTerminalWebSocket(ws, session, req) {
|
|
37
|
+
export async function handleTerminalWebSocket(ws, session, req) {
|
|
31
38
|
// Support resume via header (server-to-server) or query param (browser WebSocket)
|
|
32
39
|
const reqUrl = new URL(req.url || '/', `http://localhost`);
|
|
33
40
|
const resumeSeq = req.headers['x-session-resume'] || reqUrl.searchParams.get('resume');
|
|
@@ -41,36 +48,8 @@ export function handleTerminalWebSocket(ws, session, req) {
|
|
|
41
48
|
}
|
|
42
49
|
},
|
|
43
50
|
};
|
|
44
|
-
//
|
|
45
|
-
let
|
|
46
|
-
if (resumeSeq && typeof resumeSeq === 'string') {
|
|
47
|
-
replayLines = session.attachResume(client, parseInt(resumeSeq, 10));
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
replayLines = session.attach(client);
|
|
51
|
-
}
|
|
52
|
-
// Send replay data as binary data frame, bracketed by pause/resume control
|
|
53
|
-
// frames (#1047). The bracket tells the client "this is the one-shot buffer
|
|
54
|
-
// snapshot" so it paces the write and excludes it from its live-backpressure
|
|
55
|
-
// budget. Without it, a client counts a large replay as live overload and
|
|
56
|
-
// (historically) looped forever reconnecting for the same oversized replay.
|
|
57
|
-
if (replayLines.length > 0) {
|
|
58
|
-
const replayData = replayLines.join('\n');
|
|
59
|
-
if (ws.readyState === WebSocket.OPEN) {
|
|
60
|
-
ws.send(encodeControl({ type: 'pause', payload: {} }));
|
|
61
|
-
ws.send(encodeData(replayData));
|
|
62
|
-
ws.send(encodeControl({ type: 'resume', payload: {} }));
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
// Send current sequence number so client can resume from this point (Bugfix #442)
|
|
66
|
-
const sendSeq = () => {
|
|
67
|
-
if (ws.readyState === WebSocket.OPEN) {
|
|
68
|
-
ws.send(encodeControl({ type: 'seq', payload: { seq: session.ringBuffer.currentSeq } }));
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
sendSeq();
|
|
72
|
-
// Periodic seq heartbeat so client always has a recent sequence number
|
|
73
|
-
const seqInterval = setInterval(sendSeq, 10_000);
|
|
51
|
+
// Created only after the replay lands; the close handler must tolerate null.
|
|
52
|
+
let seqInterval = null;
|
|
74
53
|
// Handle incoming messages from client (binary protocol)
|
|
75
54
|
ws.on('message', (rawData) => {
|
|
76
55
|
try {
|
|
@@ -109,13 +88,54 @@ export function handleTerminalWebSocket(ws, session, req) {
|
|
|
109
88
|
}
|
|
110
89
|
});
|
|
111
90
|
ws.on('close', () => {
|
|
112
|
-
|
|
91
|
+
if (seqInterval)
|
|
92
|
+
clearInterval(seqInterval);
|
|
113
93
|
session.detach(client);
|
|
114
94
|
});
|
|
115
95
|
ws.on('error', () => {
|
|
116
|
-
|
|
96
|
+
if (seqInterval)
|
|
97
|
+
clearInterval(seqInterval);
|
|
117
98
|
session.detach(client);
|
|
118
99
|
});
|
|
100
|
+
// Attach and compute the replay payload: the O(screen) snapshot, or raw ring
|
|
101
|
+
// lines on the normal-buffer delta-resume path and on snapshot fallback
|
|
102
|
+
// (PIR #1354; routing and fallback logging live in attachWithReplay).
|
|
103
|
+
let sinceSeq = null;
|
|
104
|
+
if (resumeSeq && typeof resumeSeq === 'string') {
|
|
105
|
+
sinceSeq = parseInt(resumeSeq, 10);
|
|
106
|
+
}
|
|
107
|
+
const replay = await attachWithReplay(session, client, sinceSeq, logTerminal);
|
|
108
|
+
if (ws.readyState !== WebSocket.OPEN) {
|
|
109
|
+
// Closed while the snapshot flushed — undo the attach registration.
|
|
110
|
+
session.detach(client);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// Send replay as a binary data frame, bracketed by pause/resume control
|
|
114
|
+
// frames (#1047). The bracket tells the client "this is the one-shot buffer
|
|
115
|
+
// snapshot" so it paces the write and excludes it from its live-backpressure
|
|
116
|
+
// budget. Without it, a client counts a large replay as live overload and
|
|
117
|
+
// (historically) looped forever reconnecting for the same oversized replay.
|
|
118
|
+
let replayData = '';
|
|
119
|
+
if (replay.kind === 'snapshot') {
|
|
120
|
+
replayData = replay.data;
|
|
121
|
+
}
|
|
122
|
+
else if (replay.lines.length > 0) {
|
|
123
|
+
replayData = replay.lines.join('\n');
|
|
124
|
+
}
|
|
125
|
+
if (replayData.length > 0) {
|
|
126
|
+
ws.send(encodeControl({ type: 'pause', payload: {} }));
|
|
127
|
+
ws.send(encodeData(replayData));
|
|
128
|
+
ws.send(encodeControl({ type: 'resume', payload: {} }));
|
|
129
|
+
}
|
|
130
|
+
// Send current sequence number so client can resume from this point (Bugfix #442)
|
|
131
|
+
const sendSeq = () => {
|
|
132
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
133
|
+
ws.send(encodeControl({ type: 'seq', payload: { seq: session.ringBuffer.currentSeq } }));
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
sendSeq();
|
|
137
|
+
// Periodic seq heartbeat so client always has a recent sequence number
|
|
138
|
+
seqInterval = setInterval(sendSeq, 10_000);
|
|
119
139
|
}
|
|
120
140
|
// ============================================================================
|
|
121
141
|
// WebSocket upgrade routing
|
|
@@ -148,6 +168,25 @@ function rejectUnknownSession(req, socket, head, wss) {
|
|
|
148
168
|
socket.write('HTTP/1.1 404 Not Found\r\n\r\n');
|
|
149
169
|
socket.destroy();
|
|
150
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Reject an upgrade that failed request authentication (advisory
|
|
173
|
+
* GHSA-xvjp-7748-v88v). Mirrors {@link rejectUnknownSession}'s two client
|
|
174
|
+
* shapes: a browser (has `Origin`, can't read a failed upgrade's HTTP status)
|
|
175
|
+
* gets an accepted-then-closed handshake with {@link WS_CLOSE_UNAUTHORIZED};
|
|
176
|
+
* a Node `ws` client gets the HTTP-stage `401`. This runs BEFORE any session
|
|
177
|
+
* lookup and is independent of `Origin`, so a missing `Origin` cannot degrade
|
|
178
|
+
* into an auth bypass.
|
|
179
|
+
*/
|
|
180
|
+
function rejectUnauthorized(req, socket, head, wss) {
|
|
181
|
+
if (req.headers.origin) {
|
|
182
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
183
|
+
ws.close(WS_CLOSE_UNAUTHORIZED, 'unauthorized');
|
|
184
|
+
});
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
|
|
188
|
+
socket.destroy();
|
|
189
|
+
}
|
|
151
190
|
/**
|
|
152
191
|
* Set up the WebSocket upgrade handler on the HTTP server.
|
|
153
192
|
* Parses upgrade requests and routes them to the appropriate terminal session:
|
|
@@ -157,6 +196,14 @@ function rejectUnknownSession(req, socket, head, wss) {
|
|
|
157
196
|
export function setupUpgradeHandler(server, wss, port) {
|
|
158
197
|
server.on('upgrade', async (req, socket, head) => {
|
|
159
198
|
const reqUrl = new URL(req.url || '/', `http://localhost:${port}`);
|
|
199
|
+
// Request authentication (advisory GHSA-xvjp-7748-v88v): validate the key at
|
|
200
|
+
// the handshake, before any session lookup or PTY attach, for every WS route.
|
|
201
|
+
// Independent of the Origin header so a missing Origin cannot bypass auth.
|
|
202
|
+
if (!isWebSocketAllowed(req)) {
|
|
203
|
+
logTerminal('WARN', `WS upgrade 401 ${reqUrl.pathname} — disallowed Host or missing/invalid key`);
|
|
204
|
+
rejectUnauthorized(req, socket, head, wss);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
160
207
|
// Phase 2: Handle /ws/terminal/:id routes directly
|
|
161
208
|
const terminalMatch = reqUrl.pathname.match(/^\/ws\/terminal\/([^/]+)$/);
|
|
162
209
|
if (terminalMatch) {
|
|
@@ -174,7 +221,10 @@ export function setupUpgradeHandler(server, wss, port) {
|
|
|
174
221
|
return;
|
|
175
222
|
}
|
|
176
223
|
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
177
|
-
handleTerminalWebSocket(ws, session, req)
|
|
224
|
+
handleTerminalWebSocket(ws, session, req).catch((err) => {
|
|
225
|
+
logTerminal('ERROR', `terminal WS handler failed for ${terminalId}: ${String(err)}`);
|
|
226
|
+
ws.close();
|
|
227
|
+
});
|
|
178
228
|
});
|
|
179
229
|
return;
|
|
180
230
|
}
|
|
@@ -239,7 +289,10 @@ export function setupUpgradeHandler(server, wss, port) {
|
|
|
239
289
|
return;
|
|
240
290
|
}
|
|
241
291
|
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
242
|
-
handleTerminalWebSocket(ws, session, req)
|
|
292
|
+
handleTerminalWebSocket(ws, session, req).catch((err) => {
|
|
293
|
+
logTerminal('ERROR', `terminal WS handler failed for ${terminalId}: ${String(err)}`);
|
|
294
|
+
ws.close();
|
|
295
|
+
});
|
|
243
296
|
});
|
|
244
297
|
return;
|
|
245
298
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tower-websocket.js","sourceRoot":"","sources":["../../../src/agent-farm/servers/tower-websocket.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAmB,SAAS,EAAE,MAAM,IAAI,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"tower-websocket.js","sourceRoot":"","sources":["../../../src/agent-farm/servers/tower-websocket.ts"],"names":[],"mappings":"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"}
|
|
@@ -127,7 +127,12 @@ export interface SendOptions {
|
|
|
127
127
|
/**
|
|
128
128
|
* Spec 1307: hold in Tower and deliver after this many seconds. Resolution
|
|
129
129
|
* and authorization still happen at request time; only delivery is deferred.
|
|
130
|
-
*
|
|
130
|
+
*
|
|
131
|
+
* Persisted, and deliberately so: the body is written to the durable mailbox
|
|
132
|
+
* with a `not_before` timestamp, so Tower holds no timer and a restart inside
|
|
133
|
+
* the window does not drop the send (see `servers/delayed-send.ts`). Only the
|
|
134
|
+
* Ctrl+C nudge of a delayed `--interrupt` is lost to a restart, because that
|
|
135
|
+
* one genuinely is an in-memory timer.
|
|
131
136
|
*
|
|
132
137
|
* Named `delay` here to match the user-facing `--delay` flag; it becomes
|
|
133
138
|
* `deliverAfter` at the client and wire layers, where the question is *when
|
|
@@ -147,7 +152,7 @@ export interface InterruptOptions {
|
|
|
147
152
|
noEnter?: boolean;
|
|
148
153
|
}
|
|
149
154
|
/**
|
|
150
|
-
* Options for `afx
|
|
155
|
+
* Options for `afx refresh` — save-state → /clear → re-orient (Spec 1273).
|
|
151
156
|
*
|
|
152
157
|
* The timing knobs exist because the safe failure of every gate is "abort
|
|
153
158
|
* without clearing". A builder that legitimately needs longer than a default
|
|
@@ -164,6 +169,36 @@ export interface ResetOptions {
|
|
|
164
169
|
minBytes?: number;
|
|
165
170
|
quietWindow?: number;
|
|
166
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Options for `afx self-refresh` (Spec 1470).
|
|
174
|
+
*
|
|
175
|
+
* NOTE what is absent: there is no `builder` field. This command refreshes the
|
|
176
|
+
* builder that RUNS it, and identity is derived from the worktree rather than
|
|
177
|
+
* supplied — so "cannot target another session" is structural rather than a
|
|
178
|
+
* validation rule a later edit could drop.
|
|
179
|
+
*/
|
|
180
|
+
export interface SelfRefreshOptions {
|
|
181
|
+
/** Mode flag, not a target: mint a challenge and print the save request. */
|
|
182
|
+
begin?: boolean;
|
|
183
|
+
/** Boundary id from porch (e.g. `enter:review`), bound into the challenge. */
|
|
184
|
+
boundary?: string;
|
|
185
|
+
/** Inline addendum appended to the re-orientation. */
|
|
186
|
+
note?: string;
|
|
187
|
+
/** Report what would happen; send nothing, clear nothing, consume nothing. */
|
|
188
|
+
dryRun?: boolean;
|
|
189
|
+
/** Proceed despite uncommitted tracked changes. Off by default. */
|
|
190
|
+
allowDirty?: boolean;
|
|
191
|
+
/** Override when the builder prompt file is gone. */
|
|
192
|
+
mode?: 'strict' | 'soft';
|
|
193
|
+
/** Minimum state-file size to count as substantive. */
|
|
194
|
+
minBytes?: string | number;
|
|
195
|
+
/** Seconds Tower holds the re-entry before delivering it. */
|
|
196
|
+
delay?: string | number;
|
|
197
|
+
/** ms the state file must be unchanged across two observations. */
|
|
198
|
+
stabilityWindow?: string | number;
|
|
199
|
+
/** ms after which an unused challenge is refused. */
|
|
200
|
+
challengeMaxAge?: string | number;
|
|
201
|
+
}
|
|
167
202
|
/**
|
|
168
203
|
* User-facing config.json structure
|
|
169
204
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agent-farm/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agent-farm/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,11 +36,11 @@ export interface HarnessProvider {
|
|
|
36
36
|
};
|
|
37
37
|
/**
|
|
38
38
|
* Whether this harness can clear its conversation context in-session, without
|
|
39
|
-
* restarting the process (Spec 1273 — `afx
|
|
39
|
+
* restarting the process (Spec 1273 — `afx refresh`).
|
|
40
40
|
*
|
|
41
41
|
* Optional, and absence means "no": a harness that has not declared support
|
|
42
42
|
* must not be reset, and defaulting to unsupported is the safe direction. Only
|
|
43
|
-
* Claude declares it today (`/clear`), which is why `afx
|
|
43
|
+
* Claude declares it today (`/clear`), which is why `afx refresh` refuses other
|
|
44
44
|
* harnesses loudly rather than improvising a substitute mechanism.
|
|
45
45
|
*/
|
|
46
46
|
supportsContextReset?: boolean;
|
|
@@ -136,7 +136,7 @@ export declare const CLAUDE_HARNESS: HarnessProvider;
|
|
|
136
136
|
export declare const CODEX_HARNESS: HarnessProvider;
|
|
137
137
|
export declare const OPENCODE_HARNESS: HarnessProvider;
|
|
138
138
|
/**
|
|
139
|
-
* Exported for Spec 1273: `afx
|
|
139
|
+
* Exported for Spec 1273: `afx refresh` identifies a running builder's harness from
|
|
140
140
|
* its launch script and must check `supportsContextReset` before typing into the
|
|
141
141
|
* terminal. It needs the name→provider map, not just the workspace default.
|
|
142
142
|
*/
|
|
@@ -85,7 +85,7 @@ export const OPENCODE_HARNESS = {
|
|
|
85
85
|
}]),
|
|
86
86
|
};
|
|
87
87
|
/**
|
|
88
|
-
* Exported for Spec 1273: `afx
|
|
88
|
+
* Exported for Spec 1273: `afx refresh` identifies a running builder's harness from
|
|
89
89
|
* its launch script and must check `supportsContextReset` before typing into the
|
|
90
90
|
* terminal. It needs the name→provider map, not just the workspace default.
|
|
91
91
|
*/
|
|
@@ -3,15 +3,79 @@
|
|
|
3
3
|
* Spec 0110: Messaging Infrastructure — Phase 2
|
|
4
4
|
*
|
|
5
5
|
* Shared between CLI (commands/send.ts) and Tower server (tower-routes.ts).
|
|
6
|
+
*
|
|
7
|
+
* #1574: every wrapper is **self-attesting** — the header names the RECIPIENT
|
|
8
|
+
* (`→ <toAgent>`) as well as the sender, so an agent reading a frame on its own
|
|
9
|
+
* pane can verify the message was addressed to it. Before this, a misdelivery was
|
|
10
|
+
* invisible to its victim (the one party positioned to detect it), and an agent
|
|
11
|
+
* could confidently assert that builder-addressed traffic had landed on its
|
|
12
|
+
* terminal with nothing on screen able to refute it. `toAgent` is REQUIRED, not
|
|
13
|
+
* optional: a frame that silently omits the recipient is exactly the defect.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Hard ceiling on a single message BODY, in bytes (Issue #1573).
|
|
17
|
+
*
|
|
18
|
+
* Nothing between the CLI flag and the PTY bytes bounded message size before this: only
|
|
19
|
+
* the generic 1 MiB HTTP body cap and the `--file` attachment cap. A body far past what a
|
|
20
|
+
* composer can absorb is exactly the shape that arrived truncated in #1564 (a ~1,900-char
|
|
21
|
+
* send landing as its final ~30 chars) — and it did so while the sender read
|
|
22
|
+
* `[ok] Message delivered`. So the limit is enforced LOUDLY at both boundaries (the CLI,
|
|
23
|
+
* so the failure is local and immediate, and `POST /api/send`, because the route is
|
|
24
|
+
* public) and the message is NEVER silently truncated.
|
|
25
|
+
*
|
|
26
|
+
* The value matches the pre-existing `--file` attachment bound rather than inventing a
|
|
27
|
+
* second number: `--file` content is appended to the body, so one shared ceiling is the
|
|
28
|
+
* only way the two cannot disagree.
|
|
29
|
+
*/
|
|
30
|
+
export declare const MAX_MESSAGE_BYTES: number;
|
|
31
|
+
/** The over-limit error text, shared by the CLI precheck and the route (one wording). */
|
|
32
|
+
export declare function messageTooLargeError(bytes: number): string;
|
|
33
|
+
/**
|
|
34
|
+
* The over-limit error for `message`, or null when it is within the ceiling (Issue #1573).
|
|
35
|
+
*
|
|
36
|
+
* The one place the byte count and the ceiling meet, so every local boundary that sends a body
|
|
37
|
+
* — `afx send`, `afx refresh`'s prompt + `--file` addendum — fails the same way with the same
|
|
38
|
+
* wording, instead of some of them discovering the limit as a 400 from the route.
|
|
6
39
|
*/
|
|
40
|
+
export declare function messageLimitError(message: string): string | null;
|
|
7
41
|
/**
|
|
8
|
-
*
|
|
42
|
+
* The reply channel, stated at the point of need (#1574, closing the real #1530
|
|
43
|
+
* defect). A builder instructed to "reply" has no reply affordance in its own
|
|
44
|
+
* terminal — assistant text it types goes nowhere, silently. Porch phase prompts
|
|
45
|
+
* teach `afx send architect`, but a task-lane builder never gets them, and any
|
|
46
|
+
* builder loses them to a `/clear`. Carried on the frame, it survives both.
|
|
47
|
+
*/
|
|
48
|
+
export declare const REPLY_HINT = "(reply: afx send architect \"\u2026\")";
|
|
49
|
+
/**
|
|
50
|
+
* Format an architect-instruction frame.
|
|
51
|
+
*
|
|
52
|
+
* Carries NO reply hint: this variant also frames the unknown-sender → architect
|
|
53
|
+
* fallback, and telling an architect to reply via `afx send architect` would point
|
|
54
|
+
* it at itself. Builder-bound sends use {@link formatArchitectToBuilderMessage}.
|
|
55
|
+
*
|
|
9
56
|
* Wraps in a structured header/footer unless raw mode is requested.
|
|
10
57
|
*/
|
|
11
|
-
export declare function formatArchitectMessage(message: string, fileContent?: string, raw?: boolean): string;
|
|
58
|
+
export declare function formatArchitectMessage(toAgent: string, message: string, fileContent?: string, raw?: boolean): string;
|
|
59
|
+
/**
|
|
60
|
+
* Format a message from the architect to a BUILDER — the architect-instruction
|
|
61
|
+
* frame with the reply hint on its closing delimiter line (#1574). The hint is
|
|
62
|
+
* keyed to the recipient being a builder, not to who sent it: a builder is the
|
|
63
|
+
* party with no reply affordance of its own, and it is the party that loses its
|
|
64
|
+
* porch prompts to a `/clear`. `--raw` sends are unchanged — no wrapper, so no
|
|
65
|
+
* hint. Line count is unchanged from the plain frame; see {@link FOOTER}.
|
|
66
|
+
*/
|
|
67
|
+
export declare function formatArchitectToBuilderMessage(toAgent: string, message: string, fileContent?: string, raw?: boolean): string;
|
|
68
|
+
/**
|
|
69
|
+
* Format a message the VS Code extension relays on a human's behalf (#1494) to
|
|
70
|
+
* the architect, e.g. the Approve-gate button. The distinct `[USER via VS Code]`
|
|
71
|
+
* header lets the architect tell a button relay apart from a peer-architect
|
|
72
|
+
* instruction or the user typing directly in the pane. Wraps in a structured
|
|
73
|
+
* header/footer unless raw mode is requested.
|
|
74
|
+
*/
|
|
75
|
+
export declare function formatUserViaVsCodeMessage(toAgent: string, message: string, fileContent?: string, raw?: boolean): string;
|
|
12
76
|
/**
|
|
13
77
|
* Format a message from a builder to the architect.
|
|
14
78
|
* Wraps in a structured header/footer unless raw mode is requested.
|
|
15
79
|
*/
|
|
16
|
-
export declare function formatBuilderMessage(builderId: string, message: string, fileContent?: string, raw?: boolean): string;
|
|
80
|
+
export declare function formatBuilderMessage(builderId: string, toAgent: string, message: string, fileContent?: string, raw?: boolean): string;
|
|
17
81
|
//# sourceMappingURL=message-format.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-format.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/utils/message-format.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"message-format.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/utils/message-format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAE3C,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGhE;AAuBD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,2CAAoC,CAAC;AAkB5D;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,OAAe,GAAG,MAAM,CAW3H;AAED;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,OAAe,GAAG,MAAM,CAIpI;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,OAAe,GAAG,MAAM,CAW/H;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,OAAe,GAAG,MAAM,CAW5I"}
|
|
@@ -3,39 +3,152 @@
|
|
|
3
3
|
* Spec 0110: Messaging Infrastructure — Phase 2
|
|
4
4
|
*
|
|
5
5
|
* Shared between CLI (commands/send.ts) and Tower server (tower-routes.ts).
|
|
6
|
+
*
|
|
7
|
+
* #1574: every wrapper is **self-attesting** — the header names the RECIPIENT
|
|
8
|
+
* (`→ <toAgent>`) as well as the sender, so an agent reading a frame on its own
|
|
9
|
+
* pane can verify the message was addressed to it. Before this, a misdelivery was
|
|
10
|
+
* invisible to its victim (the one party positioned to detect it), and an agent
|
|
11
|
+
* could confidently assert that builder-addressed traffic had landed on its
|
|
12
|
+
* terminal with nothing on screen able to refute it. `toAgent` is REQUIRED, not
|
|
13
|
+
* optional: a frame that silently omits the recipient is exactly the defect.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Hard ceiling on a single message BODY, in bytes (Issue #1573).
|
|
17
|
+
*
|
|
18
|
+
* Nothing between the CLI flag and the PTY bytes bounded message size before this: only
|
|
19
|
+
* the generic 1 MiB HTTP body cap and the `--file` attachment cap. A body far past what a
|
|
20
|
+
* composer can absorb is exactly the shape that arrived truncated in #1564 (a ~1,900-char
|
|
21
|
+
* send landing as its final ~30 chars) — and it did so while the sender read
|
|
22
|
+
* `[ok] Message delivered`. So the limit is enforced LOUDLY at both boundaries (the CLI,
|
|
23
|
+
* so the failure is local and immediate, and `POST /api/send`, because the route is
|
|
24
|
+
* public) and the message is NEVER silently truncated.
|
|
25
|
+
*
|
|
26
|
+
* The value matches the pre-existing `--file` attachment bound rather than inventing a
|
|
27
|
+
* second number: `--file` content is appended to the body, so one shared ceiling is the
|
|
28
|
+
* only way the two cannot disagree.
|
|
29
|
+
*/
|
|
30
|
+
export const MAX_MESSAGE_BYTES = 48 * 1024;
|
|
31
|
+
/** The over-limit error text, shared by the CLI precheck and the route (one wording). */
|
|
32
|
+
export function messageTooLargeError(bytes) {
|
|
33
|
+
return (`Message body is ${bytes} bytes, over the ${MAX_MESSAGE_BYTES}-byte (48KB) limit. ` +
|
|
34
|
+
`A body this large cannot be typed into an agent's composer reliably — it is refused ` +
|
|
35
|
+
`rather than silently truncated. Split it into smaller sends, or write it to a file ` +
|
|
36
|
+
`and send the path for the agent to read.`);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The over-limit error for `message`, or null when it is within the ceiling (Issue #1573).
|
|
40
|
+
*
|
|
41
|
+
* The one place the byte count and the ceiling meet, so every local boundary that sends a body
|
|
42
|
+
* — `afx send`, `afx refresh`'s prompt + `--file` addendum — fails the same way with the same
|
|
43
|
+
* wording, instead of some of them discovering the limit as a 400 from the route.
|
|
44
|
+
*/
|
|
45
|
+
export function messageLimitError(message) {
|
|
46
|
+
const bytes = Buffer.byteLength(message, 'utf8');
|
|
47
|
+
return bytes > MAX_MESSAGE_BYTES ? messageTooLargeError(bytes) : null;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Recipient segment of a header. Kept in one place so all variants agree.
|
|
51
|
+
*
|
|
52
|
+
* Empty is REFUSED, not rendered. The type system requires `toAgent`, but a
|
|
53
|
+
* required-and-empty string yields `[BUILDER x MESSAGE → | ts]` — a frame that
|
|
54
|
+
* looks self-attesting and attests to nothing, which is the very defect class
|
|
55
|
+
* #1574 exists to close. Same doctrine `reorient.ts` states for its frame:
|
|
56
|
+
* presence of a label is not presence of a value. Throwing surfaces as a 500 to
|
|
57
|
+
* the sender via `handleRequest`'s catch, BEFORE the row is enqueued — a loud
|
|
58
|
+
* failure, never a bogus frame persisted or delivered.
|
|
59
|
+
*/
|
|
60
|
+
function recipient(toAgent) {
|
|
61
|
+
if (!toAgent) {
|
|
62
|
+
throw new Error('Cannot format a delivered message frame without a recipient. ' +
|
|
63
|
+
'A frame that names no recipient cannot be verified by the agent reading it (#1574).');
|
|
64
|
+
}
|
|
65
|
+
return ` → ${toAgent}`;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The reply channel, stated at the point of need (#1574, closing the real #1530
|
|
69
|
+
* defect). A builder instructed to "reply" has no reply affordance in its own
|
|
70
|
+
* terminal — assistant text it types goes nowhere, silently. Porch phase prompts
|
|
71
|
+
* teach `afx send architect`, but a task-lane builder never gets them, and any
|
|
72
|
+
* builder loses them to a `/clear`. Carried on the frame, it survives both.
|
|
6
73
|
*/
|
|
74
|
+
export const REPLY_HINT = '(reply: afx send architect "…")';
|
|
7
75
|
/**
|
|
8
|
-
*
|
|
76
|
+
* The closing delimiter. The builder-bound variant carries {@link REPLY_HINT} on
|
|
77
|
+
* this SAME line rather than on a trailing one, and that is load-bearing: a fourth
|
|
78
|
+
* line would push the frame past `PACED_WRITE_LINE_THRESHOLD` in `message-write.ts`,
|
|
79
|
+
* moving every short architect→builder message off the single-write path onto the
|
|
80
|
+
* paced line-by-line one. A formatter change must not widen the delivery-write
|
|
81
|
+
* exposure window (#1521/#1573 family) as a side effect, so the frame stays 3 lines
|
|
82
|
+
* and the write path stays byte-identical.
|
|
83
|
+
*/
|
|
84
|
+
const FOOTER = '###############################';
|
|
85
|
+
function withBody(message, fileContent) {
|
|
86
|
+
if (!fileContent)
|
|
87
|
+
return message;
|
|
88
|
+
return message + '\n\nAttached content:\n```\n' + fileContent + '\n```';
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Format an architect-instruction frame.
|
|
92
|
+
*
|
|
93
|
+
* Carries NO reply hint: this variant also frames the unknown-sender → architect
|
|
94
|
+
* fallback, and telling an architect to reply via `afx send architect` would point
|
|
95
|
+
* it at itself. Builder-bound sends use {@link formatArchitectToBuilderMessage}.
|
|
96
|
+
*
|
|
9
97
|
* Wraps in a structured header/footer unless raw mode is requested.
|
|
10
98
|
*/
|
|
11
|
-
export function formatArchitectMessage(message, fileContent, raw = false) {
|
|
12
|
-
|
|
13
|
-
if (
|
|
14
|
-
|
|
99
|
+
export function formatArchitectMessage(toAgent, message, fileContent, raw = false) {
|
|
100
|
+
const content = withBody(message, fileContent);
|
|
101
|
+
if (raw) {
|
|
102
|
+
return content;
|
|
15
103
|
}
|
|
104
|
+
const timestamp = new Date().toISOString();
|
|
105
|
+
return `### [ARCHITECT INSTRUCTION${recipient(toAgent)} | ${timestamp}] ###
|
|
106
|
+
${content}
|
|
107
|
+
${FOOTER}`;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Format a message from the architect to a BUILDER — the architect-instruction
|
|
111
|
+
* frame with the reply hint on its closing delimiter line (#1574). The hint is
|
|
112
|
+
* keyed to the recipient being a builder, not to who sent it: a builder is the
|
|
113
|
+
* party with no reply affordance of its own, and it is the party that loses its
|
|
114
|
+
* porch prompts to a `/clear`. `--raw` sends are unchanged — no wrapper, so no
|
|
115
|
+
* hint. Line count is unchanged from the plain frame; see {@link FOOTER}.
|
|
116
|
+
*/
|
|
117
|
+
export function formatArchitectToBuilderMessage(toAgent, message, fileContent, raw = false) {
|
|
118
|
+
const frame = formatArchitectMessage(toAgent, message, fileContent, raw);
|
|
119
|
+
if (raw)
|
|
120
|
+
return frame;
|
|
121
|
+
return frame.slice(0, -FOOTER.length) + `${FOOTER} ${REPLY_HINT}`;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Format a message the VS Code extension relays on a human's behalf (#1494) to
|
|
125
|
+
* the architect, e.g. the Approve-gate button. The distinct `[USER via VS Code]`
|
|
126
|
+
* header lets the architect tell a button relay apart from a peer-architect
|
|
127
|
+
* instruction or the user typing directly in the pane. Wraps in a structured
|
|
128
|
+
* header/footer unless raw mode is requested.
|
|
129
|
+
*/
|
|
130
|
+
export function formatUserViaVsCodeMessage(toAgent, message, fileContent, raw = false) {
|
|
131
|
+
const content = withBody(message, fileContent);
|
|
16
132
|
if (raw) {
|
|
17
133
|
return content;
|
|
18
134
|
}
|
|
19
135
|
const timestamp = new Date().toISOString();
|
|
20
|
-
return `### [
|
|
136
|
+
return `### [USER via VS Code${recipient(toAgent)} | ${timestamp}] ###
|
|
21
137
|
${content}
|
|
22
|
-
|
|
138
|
+
${FOOTER}`;
|
|
23
139
|
}
|
|
24
140
|
/**
|
|
25
141
|
* Format a message from a builder to the architect.
|
|
26
142
|
* Wraps in a structured header/footer unless raw mode is requested.
|
|
27
143
|
*/
|
|
28
|
-
export function formatBuilderMessage(builderId, message, fileContent, raw = false) {
|
|
29
|
-
|
|
30
|
-
if (fileContent) {
|
|
31
|
-
content += '\n\nAttached content:\n```\n' + fileContent + '\n```';
|
|
32
|
-
}
|
|
144
|
+
export function formatBuilderMessage(builderId, toAgent, message, fileContent, raw = false) {
|
|
145
|
+
const content = withBody(message, fileContent);
|
|
33
146
|
if (raw) {
|
|
34
147
|
return content;
|
|
35
148
|
}
|
|
36
149
|
const timestamp = new Date().toISOString();
|
|
37
|
-
return `### [BUILDER ${builderId} MESSAGE | ${timestamp}] ###
|
|
150
|
+
return `### [BUILDER ${builderId} MESSAGE${recipient(toAgent)} | ${timestamp}] ###
|
|
38
151
|
${content}
|
|
39
|
-
|
|
152
|
+
${FOOTER}`;
|
|
40
153
|
}
|
|
41
154
|
//# sourceMappingURL=message-format.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-format.js","sourceRoot":"","sources":["../../../src/agent-farm/utils/message-format.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"message-format.js","sourceRoot":"","sources":["../../../src/agent-farm/utils/message-format.ts"],"names":[],"mappings":"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"}
|