@securecoms/agent-bridge 0.30.1 → 0.30.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 +77 -6
- package/dist/bin.d.ts +20 -1
- package/dist/bin.js +413 -63
- package/dist/bridge-agent.d.ts +60 -0
- package/dist/config.d.ts +13 -0
- package/dist/consumer-grants.d.ts +15 -0
- package/dist/grants/binding.d.ts +30 -2
- package/dist/grants/manifest.d.ts +11 -1
- package/dist/grants/search-providers.d.ts +9 -0
- package/dist/http-server.d.ts +2 -0
- package/dist/index.js +266 -32
- package/dist/preflight-upgrade.d.cts +1 -2
- package/dist/preflight.cjs +52 -49
- package/dist/preflight.d.cts +14 -0
- package/dist/service/credential-arg.d.ts +23 -0
- package/dist/service/install.d.ts +7 -0
- package/dist/service/resolve-node.d.ts +1 -0
- package/dist/service/runtime-config-dir.d.ts +4 -0
- package/dist/version.d.ts +1 -1
- package/dist/ws-server.d.ts +1 -1
- package/package.json +2 -2
package/dist/preflight.cjs
CHANGED
|
@@ -33,6 +33,7 @@ var init_resolve_node = __esm({
|
|
|
33
33
|
// src/preflight-upgrade.cts
|
|
34
34
|
var preflight_upgrade_exports = {};
|
|
35
35
|
__export(preflight_upgrade_exports, {
|
|
36
|
+
DIST_BASE: () => DIST_BASE,
|
|
36
37
|
guidedUpgrade: () => guidedUpgrade,
|
|
37
38
|
parseShasums: () => parseShasums,
|
|
38
39
|
promptYesNo: () => promptYesNo,
|
|
@@ -41,11 +42,10 @@ __export(preflight_upgrade_exports, {
|
|
|
41
42
|
sha256Hex: () => sha256Hex
|
|
42
43
|
});
|
|
43
44
|
function parseShasums(text, arch) {
|
|
44
|
-
const want = "-darwin-" + arch + ".pkg";
|
|
45
45
|
const lines = String(text).split("\n");
|
|
46
46
|
for (let i = 0; i < lines.length; i++) {
|
|
47
47
|
const m = lines[i].trim().match(/^([0-9a-f]{6,64})\s+(\S+)$/);
|
|
48
|
-
if (m &&
|
|
48
|
+
if (m && PKG_NAME.test(m[2])) {
|
|
49
49
|
return { filename: m[2], sha256: m[1] };
|
|
50
50
|
}
|
|
51
51
|
}
|
|
@@ -62,48 +62,47 @@ async function promptYesNo(question, deps) {
|
|
|
62
62
|
}
|
|
63
63
|
async function guidedUpgrade(deps) {
|
|
64
64
|
if (deps.platform !== "darwin") return false;
|
|
65
|
+
let consented = false;
|
|
66
|
+
const failed = () => {
|
|
67
|
+
if (consented) deps.stderr("[bridge] Couldn't install Node 24 from nodejs.org.\n");
|
|
68
|
+
return false;
|
|
69
|
+
};
|
|
65
70
|
try {
|
|
66
71
|
const existing = deps.existingCompatibleNode();
|
|
67
72
|
if (existing) {
|
|
68
73
|
deps.stderr(
|
|
69
|
-
"[bridge]
|
|
74
|
+
"[bridge] Using Node " + REQUIRED_NODE_MAJOR + " or newer found at " + existing + ". (The node command on this computer is an older version.)\n"
|
|
70
75
|
);
|
|
71
76
|
return deps.reexec(existing);
|
|
72
77
|
}
|
|
73
|
-
const viaBrew = deps.hasBrew();
|
|
74
|
-
const source = viaBrew ? "Homebrew (brew install node \u2014 user-space, no sudo)" : "the official installer from " + DIST_BASE + " (needs your admin password)";
|
|
75
78
|
const ok = await promptYesNo(
|
|
76
|
-
"[bridge] Node 24
|
|
79
|
+
"[bridge] SecureComs needs Node 24. Install it now from nodejs.org? This needs your computer's administrator password. [y/N] ",
|
|
77
80
|
deps
|
|
78
81
|
);
|
|
79
82
|
if (!ok) return false;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
deps.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (deps.fileSha256(dest) !== entry.sha256) {
|
|
92
|
-
deps.stderr("[bridge] checksum mismatch \u2014 aborting install (file discarded)\n");
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
deps.stderr("[bridge] running: sudo installer -pkg " + entry.filename + " -target /\n");
|
|
96
|
-
if (deps.runSudoInstaller(dest) !== 0) return false;
|
|
97
|
-
} finally {
|
|
98
|
-
deps.cleanup(dest);
|
|
83
|
+
consented = true;
|
|
84
|
+
const shasums = await deps.fetchText(DIST_BASE + "/SHASUMS256.txt");
|
|
85
|
+
const entry = parseShasums(shasums, deps.arch);
|
|
86
|
+
if (!entry) return failed();
|
|
87
|
+
const dest = deps.tmpdir() + "/" + entry.filename;
|
|
88
|
+
deps.stderr("[bridge] downloading " + DIST_BASE + "/" + entry.filename + "\n");
|
|
89
|
+
try {
|
|
90
|
+
await deps.fetchBinary(DIST_BASE + "/" + entry.filename, dest);
|
|
91
|
+
if (deps.fileSha256(dest) !== entry.sha256) {
|
|
92
|
+
deps.stderr("[bridge] checksum mismatch \u2014 aborting install (file discarded)\n");
|
|
93
|
+
return failed();
|
|
99
94
|
}
|
|
95
|
+
deps.stderr("[bridge] running: sudo installer -pkg " + entry.filename + " -target /\n");
|
|
96
|
+
if (deps.runSudoInstaller(dest) !== 0) return failed();
|
|
97
|
+
} finally {
|
|
98
|
+
deps.cleanup(dest);
|
|
100
99
|
}
|
|
101
100
|
const fresh = deps.resolveNewNode();
|
|
102
|
-
if (!fresh) return
|
|
101
|
+
if (!fresh) return failed();
|
|
103
102
|
deps.stderr("[bridge] Node 24 installed \u2014 continuing under " + fresh + "\n");
|
|
104
103
|
return deps.reexec(fresh);
|
|
105
104
|
} catch {
|
|
106
|
-
return
|
|
105
|
+
return failed();
|
|
107
106
|
}
|
|
108
107
|
}
|
|
109
108
|
function resolveNewNodeFrom(probe, candidates) {
|
|
@@ -152,11 +151,6 @@ function realUpgradeDeps(originalArgv) {
|
|
|
152
151
|
resolve(a);
|
|
153
152
|
});
|
|
154
153
|
}),
|
|
155
|
-
hasBrew: () => spawnSync("brew", ["--version"], { stdio: "ignore" }).status === 0,
|
|
156
|
-
runBrew: () => {
|
|
157
|
-
var _a;
|
|
158
|
-
return (_a = spawnSync("brew", ["install", "node"], { stdio: "inherit" }).status) != null ? _a : 1;
|
|
159
|
-
},
|
|
160
154
|
fetchText: async (url) => {
|
|
161
155
|
const res = await fetch(url, 3);
|
|
162
156
|
let out = "";
|
|
@@ -197,12 +191,13 @@ function realUpgradeDeps(originalArgv) {
|
|
|
197
191
|
}
|
|
198
192
|
};
|
|
199
193
|
}
|
|
200
|
-
var DIST_BASE, NODE_CANDIDATES;
|
|
194
|
+
var DIST_BASE, PKG_NAME, NODE_CANDIDATES;
|
|
201
195
|
var init_preflight_upgrade = __esm({
|
|
202
196
|
"src/preflight-upgrade.cts"() {
|
|
203
197
|
"use strict";
|
|
204
198
|
init_resolve_node();
|
|
205
199
|
DIST_BASE = "https://nodejs.org/dist/latest-v24.x";
|
|
200
|
+
PKG_NAME = /^node-v24\.\d+\.\d+\.pkg$/;
|
|
206
201
|
NODE_CANDIDATES = [
|
|
207
202
|
"/usr/local/bin/node",
|
|
208
203
|
// nodejs.org pkg (stable across upgrades)
|
|
@@ -216,6 +211,7 @@ var init_preflight_upgrade = __esm({
|
|
|
216
211
|
// src/preflight.cts
|
|
217
212
|
var preflight_exports = {};
|
|
218
213
|
__export(preflight_exports, {
|
|
214
|
+
NODE_FLOOR: () => NODE_FLOOR,
|
|
219
215
|
effectiveVersion: () => effectiveVersion,
|
|
220
216
|
instructionsBlock: () => instructionsBlock,
|
|
221
217
|
meetsFloor: () => meetsFloor,
|
|
@@ -224,7 +220,6 @@ __export(preflight_exports, {
|
|
|
224
220
|
});
|
|
225
221
|
module.exports = __toCommonJS(preflight_exports);
|
|
226
222
|
var NODE_FLOOR = 24;
|
|
227
|
-
var FLOOR_REASON = "requires >= 24 (node:sqlite stable API)";
|
|
228
223
|
function parseNodeMajor(version) {
|
|
229
224
|
const n = Number(String(version).split(".")[0]);
|
|
230
225
|
return Number.isFinite(n) && n > 0 ? n : 0;
|
|
@@ -239,23 +234,30 @@ function effectiveVersion(real, faked) {
|
|
|
239
234
|
return real;
|
|
240
235
|
}
|
|
241
236
|
function instructionsBlock(platform, current) {
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
"How to get Node 24 LTS:",
|
|
246
|
-
" 1. Official installer (recommended): https://nodejs.org \u2014 download the",
|
|
247
|
-
" Node 24 LTS installer for your platform and run it."
|
|
248
|
-
];
|
|
237
|
+
const n = String(NODE_FLOOR);
|
|
238
|
+
const head = "[bridge] This computer has Node " + current + ". SecureComs needs Node " + n + " or newer.";
|
|
239
|
+
let lines;
|
|
249
240
|
if (platform === "darwin") {
|
|
250
|
-
lines
|
|
241
|
+
lines = [
|
|
242
|
+
head,
|
|
243
|
+
"",
|
|
244
|
+
"To get Node " + n + ":",
|
|
245
|
+
" 1. Download the Node " + n + " LTS installer for macOS from https://nodejs.org and run it.",
|
|
246
|
+
" 2. Run the SecureComs install command again."
|
|
247
|
+
];
|
|
248
|
+
} else if (platform === "win32") {
|
|
249
|
+
lines = [
|
|
250
|
+
head,
|
|
251
|
+
"",
|
|
252
|
+
"Install Node " + n + " from https://nodejs.org, then run the SecureComs install command again."
|
|
253
|
+
];
|
|
254
|
+
} else {
|
|
255
|
+
lines = [
|
|
256
|
+
head,
|
|
257
|
+
"",
|
|
258
|
+
"Install Node " + n + " so that it is at /usr/local/bin/node or /usr/bin/node, then run the SecureComs install command again. See https://nodejs.org for options."
|
|
259
|
+
];
|
|
251
260
|
}
|
|
252
|
-
lines.push(" " + (platform === "darwin" ? "3" : "2") + ". nvm: nvm install 24 && nvm use 24");
|
|
253
|
-
lines.push(
|
|
254
|
-
"",
|
|
255
|
-
"Then re-run the install command. (Always re-run the install command after",
|
|
256
|
-
"upgrading Node \u2014 the background service pins the Node path it was",
|
|
257
|
-
"installed with.)"
|
|
258
|
-
);
|
|
259
261
|
return lines.join("\n") + "\n";
|
|
260
262
|
}
|
|
261
263
|
async function runPreflight(deps) {
|
|
@@ -292,6 +294,7 @@ if (require.main === module) {
|
|
|
292
294
|
}
|
|
293
295
|
// Annotate the CommonJS export names for ESM import in node:
|
|
294
296
|
0 && (module.exports = {
|
|
297
|
+
NODE_FLOOR,
|
|
295
298
|
effectiveVersion,
|
|
296
299
|
instructionsBlock,
|
|
297
300
|
meetsFloor,
|
package/dist/preflight.d.cts
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CommonJS preflight shim — the package's bin entry. CJS on purpose: any
|
|
4
|
+
* Node back to v10 can parse it, so a machine with stale Node always gets
|
|
5
|
+
* the friendly diagnosis instead of an ESM/builtin crash (static imports in
|
|
6
|
+
* the ESM bundle hoist — node:sqlite would detonate before any guard ran).
|
|
7
|
+
* Built with esbuild format=cjs target=node10 to dist/preflight.cjs.
|
|
8
|
+
*
|
|
9
|
+
* AUDIT C1: this file must contain ZERO dynamic `import()` — esbuild's
|
|
10
|
+
* node10 downlevel would turn it into require() (cannot load ESM), and
|
|
11
|
+
* keeping the syntax breaks node10 parse. The real import lives in
|
|
12
|
+
* preflight-modern.cts, which is only require()d AFTER the gate passes.
|
|
13
|
+
* An artifact test greps the emitted file to pin this.
|
|
14
|
+
*/
|
|
15
|
+
export declare const NODE_FLOOR = 24;
|
|
2
16
|
export declare function parseNodeMajor(version: string): number;
|
|
3
17
|
export declare function meetsFloor(version: string): boolean;
|
|
4
18
|
export declare function effectiveVersion(real: string, faked: string | undefined): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How `--credential` is read for `install` and run mode (spec 2026-10-15
|
|
3
|
+
* §5.3, OQ-18 (b)). A flag that is present with an empty value means "no key
|
|
4
|
+
* file": it never falls back to SECURECOMS_CREDENTIAL, so a copied command
|
|
5
|
+
* whose Downloads lookup found nothing cannot silently pick up a different
|
|
6
|
+
* agent's key file from the environment. The variable is used only when the
|
|
7
|
+
* flag is absent. Every other flag keeps argOrEnv's behaviour.
|
|
8
|
+
*/
|
|
9
|
+
export type CredentialArg = {
|
|
10
|
+
kind: "path";
|
|
11
|
+
path: string;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "empty_flag";
|
|
14
|
+
} | {
|
|
15
|
+
kind: "absent";
|
|
16
|
+
};
|
|
17
|
+
export declare function readCredentialArg(argv: string[], env: NodeJS.ProcessEnv): CredentialArg;
|
|
18
|
+
/**
|
|
19
|
+
* The one line printed when no key file was given: E8 for run mode
|
|
20
|
+
* (approved), E9 for install (DRAFT: the approved E9 names the agent, which
|
|
21
|
+
* the bridge cannot know when no key file was found).
|
|
22
|
+
*/
|
|
23
|
+
export declare function noCredentialLine(verb: "run" | "install"): string;
|
|
@@ -13,7 +13,14 @@ export interface ServiceDeps {
|
|
|
13
13
|
mkdirp: (path: string) => void;
|
|
14
14
|
fileExists: (path: string) => boolean;
|
|
15
15
|
user: string;
|
|
16
|
+
/** kill(pid, 0): true while the process runs (EPERM counts as running). */
|
|
17
|
+
pidAlive: (pid: number) => boolean;
|
|
18
|
+
/** Blocking sleep: installService is synchronous end to end. */
|
|
19
|
+
sleepMs: (ms: number) => void;
|
|
20
|
+
now: () => number;
|
|
16
21
|
}
|
|
22
|
+
/** How long install waits for the previous bridge to exit after bootout. */
|
|
23
|
+
export declare const PREVIOUS_EXIT_WAIT_MS = 10000;
|
|
17
24
|
export interface InstallResult {
|
|
18
25
|
label: string;
|
|
19
26
|
filePath: string;
|
|
@@ -7,6 +7,7 @@ export interface ResolveNodeDeps {
|
|
|
7
7
|
arch: () => string;
|
|
8
8
|
archOf: (p: string) => string | null;
|
|
9
9
|
}
|
|
10
|
+
export declare const STABLE_LOCATIONS: readonly string[];
|
|
10
11
|
export declare function resolveStableNodePath(runningExecPath: string, deps: ResolveNodeDeps): {
|
|
11
12
|
path: string;
|
|
12
13
|
stable: boolean;
|
|
@@ -49,6 +49,10 @@ export interface LocalReport {
|
|
|
49
49
|
persona: Record<string, string>;
|
|
50
50
|
has_search_key: boolean;
|
|
51
51
|
has_llm_key: boolean;
|
|
52
|
+
/** L-2 (spec §7.9): a readable key for an extract-capable provider. Only a real true counts; absent is false. */
|
|
53
|
+
has_extract_provider: boolean;
|
|
54
|
+
/** D39: the owner-DM daily search cap the runtime enforces; an integer in [0, 2000], otherwise undefined. */
|
|
55
|
+
owner_dm_search_cap_effective?: number;
|
|
52
56
|
legacy_memory: LegacyMemoryReport[];
|
|
53
57
|
/** §B.4 counts; undefined when the runtime reported none or the block was malformed. */
|
|
54
58
|
secret_paths?: SecretPathsReport;
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const BRIDGE_VERSION = "0.30.
|
|
1
|
+
export declare const BRIDGE_VERSION = "0.30.3";
|
package/dist/ws-server.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ export declare const MEMORY_UNIFIED_FEATURE = "memory_unified";
|
|
|
51
51
|
* fake against this list at run time (7b gate fix: a member added here without
|
|
52
52
|
* a fake made three tests throw "is not a function").
|
|
53
53
|
*/
|
|
54
|
-
export declare const WS_AGENT_MEMBERS: readonly ["ackRuntimeMessages", "action", "admitRuntimeDelivery", "applyMemoryNote", "clearHarnessReport", "clearManifestConsumer", "clearPerToolConsumer", "harnessGrantsWithheld", "isRuntimeMessageRetired", "noteConsumerCapability", "noteManifestConsumer", "noteRoomCapReached", "noteNotesConsumer", "notePerToolConsumer", "noteRecallConsumer", "noteUnifiedConsumer", "noteSessionClose", "noteSessionEvicted", "noteSessionOpen", "notesAppliedGeneration", "notesForDelivery", "recallForDelivery", "unifiedFeatureOn", "unifiedForDelivery", "recordHarnessReport", "recordRuntimeReply", "reportStatusGated", "requeueFailedRuntimeDeliveries", "requeueFront", "runtimeReplyReceipt", "send", "sendA2A", "subscribe", "takeDeliverable", "wakeListeners"];
|
|
54
|
+
export declare const WS_AGENT_MEMBERS: readonly ["ackRuntimeMessages", "action", "admitRuntimeDelivery", "applyMemoryNote", "clearHarnessReport", "clearManifestConsumer", "clearPerToolConsumer", "clearSearchProvidersSocket", "harnessGrantsWithheld", "signedSearchProvider", "isRuntimeMessageRetired", "noteConsumerCapability", "noteManifestConsumer", "noteRoomCapReached", "noteSearchProvidersSocket", "noteNotesConsumer", "notePerToolConsumer", "noteRecallConsumer", "noteUnifiedConsumer", "noteSessionClose", "noteSessionEvicted", "noteSessionOpen", "notesAppliedGeneration", "notesForDelivery", "recallForDelivery", "unifiedFeatureOn", "unifiedForDelivery", "recordHarnessReport", "recordRuntimeReply", "reportStatusGated", "requeueFailedRuntimeDeliveries", "requeueFront", "runtimeReplyReceipt", "send", "sendA2A", "subscribe", "takeDeliverable", "wakeListeners"];
|
|
55
55
|
export type WsAgent = Pick<BridgeAgent, (typeof WS_AGENT_MEMBERS)[number]>;
|
|
56
56
|
export declare function attachAgentWebSocket(server: HttpServer, agent: WsAgent, opts: AgentWebSocketOptions): {
|
|
57
57
|
close(): void;
|