getprismo 0.1.35 → 0.1.37
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/lib/prismo-dev/agent.js +1 -1
- package/lib/prismo-dev/cli.js +59 -3
- package/lib/prismo-dev/cloud-sync.js +5 -0
- package/lib/prismo-dev/connector.js +299 -0
- package/lib/prismo-dev/help.js +35 -1
- package/lib/prismo-dev-scan.js +27 -1
- package/package.json +1 -1
package/lib/prismo-dev/agent.js
CHANGED
|
@@ -15,7 +15,7 @@ module.exports = function createAgent(deps) {
|
|
|
15
15
|
openUrl,
|
|
16
16
|
} = deps;
|
|
17
17
|
|
|
18
|
-
const DEFAULT_WORKSPACE_URL = "https://
|
|
18
|
+
const DEFAULT_WORKSPACE_URL = "https://getprismo.dev/dashboard/dev";
|
|
19
19
|
|
|
20
20
|
const DEFAULT_API_URL = "https://api.getprismo.dev";
|
|
21
21
|
const TERMINAL_STATUSES = new Set(["completed", "failed", "cancelled"]);
|
package/lib/prismo-dev/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ const { printHelp, printCommandHelp } = require("./help");
|
|
|
3
3
|
|
|
4
4
|
const VALID_COMMANDS = new Set([
|
|
5
5
|
"dev", "init", "doctor", "firewall", "benchmark", "shield", "mcp",
|
|
6
|
-
"connect", "sync", "status", "disconnect", "agent", "setup", "scan",
|
|
6
|
+
"connect", "sync", "status", "disconnect", "agent", "connector", "setup", "scan",
|
|
7
7
|
"optimize", "context", "cc", "cursor", "receipt", "instructions",
|
|
8
8
|
"timeline", "replay", "boundaries", "usage", "guard", "watch", "demo",
|
|
9
9
|
]);
|
|
@@ -70,6 +70,12 @@ function createCli(deps) {
|
|
|
70
70
|
runGuard,
|
|
71
71
|
renderAgentTerminal,
|
|
72
72
|
runAgent,
|
|
73
|
+
renderConnectorTerminal,
|
|
74
|
+
runConnectorInstall,
|
|
75
|
+
runConnectorStart,
|
|
76
|
+
runConnectorStatus,
|
|
77
|
+
runConnectorStop,
|
|
78
|
+
runConnectorUninstall,
|
|
73
79
|
renderInstructionsAblationTerminal,
|
|
74
80
|
renderInstructionsApplyTerminal,
|
|
75
81
|
renderInstructionsAuditTerminal,
|
|
@@ -131,7 +137,7 @@ function createCli(deps) {
|
|
|
131
137
|
return;
|
|
132
138
|
}
|
|
133
139
|
if (!VALID_COMMANDS.has(command)) {
|
|
134
|
-
throw new Error(`Unknown command: ${command}. Try: prismo connect, prismo agent, prismo guard, prismo sync, prismo doctor, prismo watch, prismo receipt, prismo benchmark, prismo shield, prismo mcp, prismo firewall, prismo init, prismo scan, prismo optimize, prismo context, prismo cc, prismo cursor, or prismo usage`);
|
|
140
|
+
throw new Error(`Unknown command: ${command}. Try: prismo connect, prismo connector, prismo agent, prismo guard, prismo sync, prismo doctor, prismo watch, prismo receipt, prismo benchmark, prismo shield, prismo mcp, prismo firewall, prismo init, prismo scan, prismo optimize, prismo context, prismo cc, prismo cursor, or prismo usage`);
|
|
135
141
|
}
|
|
136
142
|
|
|
137
143
|
if (command === "demo") {
|
|
@@ -314,6 +320,14 @@ function createCli(deps) {
|
|
|
314
320
|
const userIndex = rest.indexOf("--user");
|
|
315
321
|
const deviceIndex = rest.indexOf("--device");
|
|
316
322
|
const limitIndex = rest.indexOf("--limit");
|
|
323
|
+
const intervalIndex = rest.indexOf("--interval");
|
|
324
|
+
const modeIndex = rest.indexOf("--mode");
|
|
325
|
+
const modeValue = modeIndex >= 0 ? rest[modeIndex + 1] : "autopilot";
|
|
326
|
+
if (!AGENT_VALID_MODES.has(modeValue)) {
|
|
327
|
+
throw new Error(`Invalid connector mode: ${modeValue}. Valid modes: observe, suggest, autopilot`);
|
|
328
|
+
}
|
|
329
|
+
const positional = getPositionals(rest, new Set(["--token", "--api-url", "--org", "--user", "--device", "--limit", "--interval", "--mode"]));
|
|
330
|
+
const target = positional[0] || process.cwd();
|
|
317
331
|
const result = runConnect({
|
|
318
332
|
token: tokenIndex >= 0 ? rest[tokenIndex + 1] : null,
|
|
319
333
|
apiUrl: apiUrlIndex >= 0 ? rest[apiUrlIndex + 1] : null,
|
|
@@ -322,14 +336,56 @@ function createCli(deps) {
|
|
|
322
336
|
device: deviceIndex >= 0 ? rest[deviceIndex + 1] : null,
|
|
323
337
|
limit: parsePositiveInt(limitIndex >= 0 ? rest[limitIndex + 1] : null, 20),
|
|
324
338
|
});
|
|
339
|
+
if (result.connected && !rest.includes("--no-agent") && runConnectorInstall) {
|
|
340
|
+
result.connector = runConnectorInstall(target, {
|
|
341
|
+
interval: parsePositiveInt(intervalIndex >= 0 ? rest[intervalIndex + 1] : null, 15),
|
|
342
|
+
mode: modeValue,
|
|
343
|
+
dryRun: rest.includes("--dry-run"),
|
|
344
|
+
});
|
|
345
|
+
result.next = result.connector?.started
|
|
346
|
+
? [`${NPX_COMMAND} status`, "Refresh Prismo Workspace"]
|
|
347
|
+
: [`${NPX_COMMAND} connector install`, `${NPX_COMMAND} status`];
|
|
348
|
+
}
|
|
325
349
|
if (result.connected && (rest.includes("--open") || !rest.includes("--no-open"))) {
|
|
326
|
-
openUrl("https://
|
|
350
|
+
openUrl("https://getprismo.dev/dashboard/dev");
|
|
327
351
|
}
|
|
328
352
|
if (json) console.log(JSON.stringify(result, null, 2));
|
|
329
353
|
else console.log(renderConnectTerminal(result));
|
|
330
354
|
return;
|
|
331
355
|
}
|
|
332
356
|
|
|
357
|
+
if (command === "connector") {
|
|
358
|
+
const json = rest.includes("--json");
|
|
359
|
+
const intervalIndex = rest.indexOf("--interval");
|
|
360
|
+
const modeIndex = rest.indexOf("--mode");
|
|
361
|
+
const modeValue = modeIndex >= 0 ? rest[modeIndex + 1] : "autopilot";
|
|
362
|
+
if (!AGENT_VALID_MODES.has(modeValue)) {
|
|
363
|
+
throw new Error(`Invalid connector mode: ${modeValue}. Valid modes: observe, suggest, autopilot`);
|
|
364
|
+
}
|
|
365
|
+
const positional = getPositionals(rest, new Set(["--interval", "--mode"]));
|
|
366
|
+
const action = ["install", "start", "stop", "status", "uninstall"].includes(positional[0]) ? positional[0] : "status";
|
|
367
|
+
const target = ["install"].includes(action) ? positional[1] || process.cwd() : positional[0] || process.cwd();
|
|
368
|
+
let result;
|
|
369
|
+
if (action === "install") {
|
|
370
|
+
result = runConnectorInstall(target, {
|
|
371
|
+
interval: parsePositiveInt(intervalIndex >= 0 ? rest[intervalIndex + 1] : null, 15),
|
|
372
|
+
mode: modeValue,
|
|
373
|
+
dryRun: rest.includes("--dry-run"),
|
|
374
|
+
});
|
|
375
|
+
} else if (action === "start") {
|
|
376
|
+
result = runConnectorStart({ dryRun: rest.includes("--dry-run") });
|
|
377
|
+
} else if (action === "stop") {
|
|
378
|
+
result = runConnectorStop({ dryRun: rest.includes("--dry-run") });
|
|
379
|
+
} else if (action === "uninstall") {
|
|
380
|
+
result = runConnectorUninstall({ dryRun: rest.includes("--dry-run") });
|
|
381
|
+
} else {
|
|
382
|
+
result = runConnectorStatus();
|
|
383
|
+
}
|
|
384
|
+
if (json) console.log(JSON.stringify(result, null, 2));
|
|
385
|
+
else console.log(renderConnectorTerminal(result));
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
|
|
333
389
|
if (command === "sync") {
|
|
334
390
|
const json = rest.includes("--json");
|
|
335
391
|
const limitIndex = rest.indexOf("--limit");
|
|
@@ -411,6 +411,11 @@ module.exports = function createCloudSync(deps) {
|
|
|
411
411
|
lines.push(`Config: ${result.configPath}`);
|
|
412
412
|
lines.push(`API: ${result.apiUrl}`);
|
|
413
413
|
lines.push(`Device: ${result.device.name}`);
|
|
414
|
+
if (result.connector) {
|
|
415
|
+
lines.push(`Connector: ${result.connector.started ? "started" : result.connector.installed ? "installed" : "not started"}`);
|
|
416
|
+
if (result.connector.reason) lines.push(`Connector note: ${result.connector.reason}`);
|
|
417
|
+
if (result.connector.error) lines.push(`Connector error: ${result.connector.error}`);
|
|
418
|
+
}
|
|
414
419
|
lines.push("");
|
|
415
420
|
lines.push("Next");
|
|
416
421
|
result.next.forEach((item, index) => lines.push(`${index + 1}. ${item}`));
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
module.exports = function createConnector(deps) {
|
|
2
|
+
const {
|
|
3
|
+
fs,
|
|
4
|
+
os,
|
|
5
|
+
path,
|
|
6
|
+
spawnSync,
|
|
7
|
+
NPX_COMMAND,
|
|
8
|
+
} = deps;
|
|
9
|
+
|
|
10
|
+
const LABEL = "dev.getprismo.connector";
|
|
11
|
+
const BACKGROUND_COMMAND = String(NPX_COMMAND || "").includes(" -y ")
|
|
12
|
+
? NPX_COMMAND
|
|
13
|
+
: "npx -y getprismo@latest";
|
|
14
|
+
|
|
15
|
+
function prismoHome() {
|
|
16
|
+
return process.env.PRISMO_HOME || path.join(os.homedir(), ".prismo");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function connectorDir() {
|
|
20
|
+
return path.join(prismoHome(), "connector");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function statePath() {
|
|
24
|
+
return path.join(connectorDir(), "state.json");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function scriptPath() {
|
|
28
|
+
return path.join(connectorDir(), "run.sh");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function logPath() {
|
|
32
|
+
return path.join(connectorDir(), "connector.log");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function errorLogPath() {
|
|
36
|
+
return path.join(connectorDir(), "connector.err.log");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function plistPath() {
|
|
40
|
+
return path.join(os.homedir(), "Library", "LaunchAgents", `${LABEL}.plist`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function readJson(filePath) {
|
|
44
|
+
try {
|
|
45
|
+
if (!fs.existsSync(filePath)) return null;
|
|
46
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
47
|
+
} catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function writeJson(filePath, payload) {
|
|
53
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
54
|
+
fs.writeFileSync(filePath, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function shellEscape(value) {
|
|
58
|
+
return `'${String(value).replace(/'/g, "'\\''")}'`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function xmlEscape(value) {
|
|
62
|
+
return String(value)
|
|
63
|
+
.replace(/&/g, "&")
|
|
64
|
+
.replace(/</g, "<")
|
|
65
|
+
.replace(/>/g, ">")
|
|
66
|
+
.replace(/"/g, """);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function launchctl(args, options = {}) {
|
|
70
|
+
if (options.dryRun) return { status: 0, stdout: "", stderr: "" };
|
|
71
|
+
const result = spawnSync("launchctl", args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
72
|
+
return {
|
|
73
|
+
status: result.status,
|
|
74
|
+
stdout: String(result.stdout || ""),
|
|
75
|
+
stderr: String(result.stderr || ""),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function writeRunner(rootDir, options = {}) {
|
|
80
|
+
const root = path.resolve(rootDir || process.cwd());
|
|
81
|
+
const interval = Math.max(5, Number(options.interval || 15));
|
|
82
|
+
const mode = options.mode || "autopilot";
|
|
83
|
+
fs.mkdirSync(connectorDir(), { recursive: true });
|
|
84
|
+
const command = `${BACKGROUND_COMMAND} agent --watch --interval ${interval} --mode ${shellEscape(mode)} ${shellEscape(root)}`;
|
|
85
|
+
const contents = [
|
|
86
|
+
"#!/bin/sh",
|
|
87
|
+
"set -eu",
|
|
88
|
+
`cd ${shellEscape(root)}`,
|
|
89
|
+
`exec ${command}`,
|
|
90
|
+
"",
|
|
91
|
+
].join("\n");
|
|
92
|
+
fs.writeFileSync(scriptPath(), contents, { encoding: "utf8", mode: 0o700 });
|
|
93
|
+
writeJson(statePath(), {
|
|
94
|
+
schemaVersion: 1,
|
|
95
|
+
installedAt: new Date().toISOString(),
|
|
96
|
+
root,
|
|
97
|
+
interval,
|
|
98
|
+
mode,
|
|
99
|
+
command,
|
|
100
|
+
platform: process.platform,
|
|
101
|
+
runner: scriptPath(),
|
|
102
|
+
logPath: logPath(),
|
|
103
|
+
errorLogPath: errorLogPath(),
|
|
104
|
+
});
|
|
105
|
+
return { root, interval, mode, command };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function writePlist() {
|
|
109
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
110
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
111
|
+
<plist version="1.0">
|
|
112
|
+
<dict>
|
|
113
|
+
<key>Label</key>
|
|
114
|
+
<string>${LABEL}</string>
|
|
115
|
+
<key>ProgramArguments</key>
|
|
116
|
+
<array>
|
|
117
|
+
<string>/bin/sh</string>
|
|
118
|
+
<string>${xmlEscape(scriptPath())}</string>
|
|
119
|
+
</array>
|
|
120
|
+
<key>RunAtLoad</key>
|
|
121
|
+
<true/>
|
|
122
|
+
<key>KeepAlive</key>
|
|
123
|
+
<true/>
|
|
124
|
+
<key>StandardOutPath</key>
|
|
125
|
+
<string>${xmlEscape(logPath())}</string>
|
|
126
|
+
<key>StandardErrorPath</key>
|
|
127
|
+
<string>${xmlEscape(errorLogPath())}</string>
|
|
128
|
+
</dict>
|
|
129
|
+
</plist>
|
|
130
|
+
`;
|
|
131
|
+
fs.mkdirSync(path.dirname(plistPath()), { recursive: true });
|
|
132
|
+
fs.writeFileSync(plistPath(), plist, "utf8");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function isMacLaunchdAvailable() {
|
|
136
|
+
return process.platform === "darwin";
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function runConnectorInstall(rootDir = process.cwd(), options = {}) {
|
|
140
|
+
const runner = writeRunner(rootDir, options);
|
|
141
|
+
if (!isMacLaunchdAvailable()) {
|
|
142
|
+
return {
|
|
143
|
+
schemaVersion: 1,
|
|
144
|
+
command: "connector",
|
|
145
|
+
action: "install",
|
|
146
|
+
installed: false,
|
|
147
|
+
started: false,
|
|
148
|
+
platform: process.platform,
|
|
149
|
+
statePath: statePath(),
|
|
150
|
+
runner: scriptPath(),
|
|
151
|
+
reason: "background-service-not-supported",
|
|
152
|
+
next: [`${NPX_COMMAND} agent --watch`],
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
writePlist();
|
|
157
|
+
launchctl(["bootout", `gui/${process.getuid()}`, plistPath()], options);
|
|
158
|
+
const bootstrap = launchctl(["bootstrap", `gui/${process.getuid()}`, plistPath()], options);
|
|
159
|
+
const kickstart = launchctl(["kickstart", "-k", `gui/${process.getuid()}/${LABEL}`], options);
|
|
160
|
+
const started = bootstrap.status === 0 || kickstart.status === 0 || options.dryRun;
|
|
161
|
+
return {
|
|
162
|
+
schemaVersion: 1,
|
|
163
|
+
command: "connector",
|
|
164
|
+
action: "install",
|
|
165
|
+
installed: true,
|
|
166
|
+
started,
|
|
167
|
+
label: LABEL,
|
|
168
|
+
root: runner.root,
|
|
169
|
+
mode: runner.mode,
|
|
170
|
+
interval: runner.interval,
|
|
171
|
+
plistPath: plistPath(),
|
|
172
|
+
statePath: statePath(),
|
|
173
|
+
runner: scriptPath(),
|
|
174
|
+
logPath: logPath(),
|
|
175
|
+
errorLogPath: errorLogPath(),
|
|
176
|
+
error: started ? null : (bootstrap.stderr || kickstart.stderr || "launchctl failed").trim(),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function runConnectorStart(options = {}) {
|
|
181
|
+
if (!isMacLaunchdAvailable()) {
|
|
182
|
+
return { schemaVersion: 1, command: "connector", action: "start", started: false, reason: "background-service-not-supported" };
|
|
183
|
+
}
|
|
184
|
+
if (!fs.existsSync(plistPath())) {
|
|
185
|
+
return { schemaVersion: 1, command: "connector", action: "start", started: false, reason: "not-installed", next: [`${NPX_COMMAND} connector install`] };
|
|
186
|
+
}
|
|
187
|
+
const result = launchctl(["kickstart", "-k", `gui/${process.getuid()}/${LABEL}`], options);
|
|
188
|
+
return {
|
|
189
|
+
schemaVersion: 1,
|
|
190
|
+
command: "connector",
|
|
191
|
+
action: "start",
|
|
192
|
+
started: result.status === 0 || options.dryRun,
|
|
193
|
+
label: LABEL,
|
|
194
|
+
error: result.status === 0 || options.dryRun ? null : result.stderr.trim(),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function runConnectorStop(options = {}) {
|
|
199
|
+
if (!isMacLaunchdAvailable()) {
|
|
200
|
+
return { schemaVersion: 1, command: "connector", action: "stop", stopped: false, reason: "background-service-not-supported" };
|
|
201
|
+
}
|
|
202
|
+
const result = launchctl(["bootout", `gui/${process.getuid()}`, plistPath()], options);
|
|
203
|
+
return {
|
|
204
|
+
schemaVersion: 1,
|
|
205
|
+
command: "connector",
|
|
206
|
+
action: "stop",
|
|
207
|
+
stopped: result.status === 0 || options.dryRun,
|
|
208
|
+
label: LABEL,
|
|
209
|
+
error: result.status === 0 || options.dryRun ? null : result.stderr.trim(),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function runConnectorUninstall(options = {}) {
|
|
214
|
+
const stop = runConnectorStop(options);
|
|
215
|
+
if (!options.dryRun) {
|
|
216
|
+
if (fs.existsSync(plistPath())) fs.rmSync(plistPath(), { force: true });
|
|
217
|
+
if (fs.existsSync(scriptPath())) fs.rmSync(scriptPath(), { force: true });
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
schemaVersion: 1,
|
|
221
|
+
command: "connector",
|
|
222
|
+
action: "uninstall",
|
|
223
|
+
uninstalled: true,
|
|
224
|
+
stopped: stop.stopped,
|
|
225
|
+
removed: [plistPath(), scriptPath()],
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function runConnectorStatus() {
|
|
230
|
+
const state = readJson(statePath());
|
|
231
|
+
const installed = fs.existsSync(plistPath()) || fs.existsSync(scriptPath());
|
|
232
|
+
let online = false;
|
|
233
|
+
let raw = "";
|
|
234
|
+
if (isMacLaunchdAvailable() && fs.existsSync(plistPath())) {
|
|
235
|
+
const result = launchctl(["print", `gui/${process.getuid()}/${LABEL}`]);
|
|
236
|
+
raw = `${result.stdout}${result.stderr}`;
|
|
237
|
+
online = result.status === 0 && /state = running|pid = \d+/i.test(raw);
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
schemaVersion: 1,
|
|
241
|
+
command: "connector",
|
|
242
|
+
action: "status",
|
|
243
|
+
installed,
|
|
244
|
+
online,
|
|
245
|
+
label: LABEL,
|
|
246
|
+
platform: process.platform,
|
|
247
|
+
state,
|
|
248
|
+
plistPath: plistPath(),
|
|
249
|
+
runner: scriptPath(),
|
|
250
|
+
logPath: logPath(),
|
|
251
|
+
errorLogPath: errorLogPath(),
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function renderConnectorTerminal(result) {
|
|
256
|
+
const lines = [];
|
|
257
|
+
lines.push("");
|
|
258
|
+
lines.push("PrismoDev Connector");
|
|
259
|
+
lines.push("");
|
|
260
|
+
if (result.action === "status") {
|
|
261
|
+
lines.push(`Installed: ${result.installed ? "yes" : "no"}`);
|
|
262
|
+
lines.push(`Status: ${result.online ? "online" : "idle"}`);
|
|
263
|
+
if (result.state?.root) lines.push(`Repo: ${result.state.root}`);
|
|
264
|
+
lines.push(`Logs: ${result.logPath}`);
|
|
265
|
+
} else if (result.action === "install") {
|
|
266
|
+
lines.push(`Status: ${result.started ? "started" : result.installed ? "installed" : "not installed"}`);
|
|
267
|
+
if (result.root) lines.push(`Repo: ${result.root}`);
|
|
268
|
+
if (result.reason) lines.push(`Note: ${result.reason}`);
|
|
269
|
+
if (result.error) lines.push(`Error: ${result.error}`);
|
|
270
|
+
} else if (result.action === "start") {
|
|
271
|
+
lines.push(`Status: ${result.started ? "started" : "not started"}`);
|
|
272
|
+
if (result.reason) lines.push(`Note: ${result.reason}`);
|
|
273
|
+
if (result.error) lines.push(`Error: ${result.error}`);
|
|
274
|
+
} else if (result.action === "stop") {
|
|
275
|
+
lines.push(`Status: ${result.stopped ? "stopped" : "not stopped"}`);
|
|
276
|
+
if (result.reason) lines.push(`Note: ${result.reason}`);
|
|
277
|
+
if (result.error) lines.push(`Error: ${result.error}`);
|
|
278
|
+
} else if (result.action === "uninstall") {
|
|
279
|
+
lines.push("Status: uninstalled");
|
|
280
|
+
}
|
|
281
|
+
if (result.next?.length) {
|
|
282
|
+
lines.push("");
|
|
283
|
+
lines.push("Next");
|
|
284
|
+
result.next.forEach((item, index) => lines.push(`${index + 1}. ${item}`));
|
|
285
|
+
}
|
|
286
|
+
return lines.join("\n");
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return {
|
|
290
|
+
LABEL,
|
|
291
|
+
renderConnectorTerminal,
|
|
292
|
+
runConnectorInstall,
|
|
293
|
+
runConnectorStart,
|
|
294
|
+
runConnectorStatus,
|
|
295
|
+
runConnectorStop,
|
|
296
|
+
runConnectorUninstall,
|
|
297
|
+
writeRunner,
|
|
298
|
+
};
|
|
299
|
+
};
|
package/lib/prismo-dev/help.js
CHANGED
|
@@ -13,6 +13,7 @@ Usage:
|
|
|
13
13
|
prismo mcp [path]
|
|
14
14
|
prismo mcp doctor [--json] [path]
|
|
15
15
|
prismo connect [--json] [--token TOKEN] [--api-url URL] [--org ORG] [--user USER] [--device NAME]
|
|
16
|
+
prismo connector [status|install|start|stop|uninstall] [--json] [--interval N] [--mode observe|suggest|autopilot] [path]
|
|
16
17
|
prismo sync [--json] [--dry-run] [--watch] [--interval N] [--limit N] [--tool all|codex|claude|cursor] [path]
|
|
17
18
|
prismo status [--json]
|
|
18
19
|
prismo disconnect [--json]
|
|
@@ -44,6 +45,7 @@ Commands:
|
|
|
44
45
|
shield Run a noisy command, store full output locally, and return a compact summary.
|
|
45
46
|
mcp Start a local MCP server exposing Prismo tools over stdio.
|
|
46
47
|
connect Store a PrismoDev cloud connection for seamless dashboard sync.
|
|
48
|
+
connector Install or manage the background Prismo Workspace connector.
|
|
47
49
|
sync Send safe aggregate local agent telemetry to Prismo; use --watch for background-style sync.
|
|
48
50
|
status Show local PrismoDev connection and last sync state.
|
|
49
51
|
disconnect Remove the local PrismoDev cloud connection.
|
|
@@ -98,6 +100,7 @@ Options:
|
|
|
98
100
|
--org ORG Organization identifier for connect mode.
|
|
99
101
|
--user USER User email or identifier for connect mode.
|
|
100
102
|
--device NAME Local device name for connect mode.
|
|
103
|
+
--no-agent Connect without installing the background workspace connector.
|
|
101
104
|
--tool TOOL Tool filter for sync mode: all, codex, claude, or cursor.
|
|
102
105
|
--watch Keep sync running and send updates on an interval.
|
|
103
106
|
--once Run watch mode once, useful for tests and scripts.
|
|
@@ -406,6 +409,7 @@ Output:
|
|
|
406
409
|
|
|
407
410
|
Usage:
|
|
408
411
|
prismo connect [--json] [--token TOKEN] [--api-url URL] [--org ORG] [--user USER] [--device NAME]
|
|
412
|
+
prismo connector [status|install|start|stop|uninstall] [--json] [--interval N] [--mode observe|suggest|autopilot] [path]
|
|
409
413
|
prismo sync [--json] [--dry-run] [--watch] [--interval N] [--limit N] [--tool all|codex|claude|cursor] [path]
|
|
410
414
|
prismo status [--json]
|
|
411
415
|
prismo disconnect [--json]
|
|
@@ -413,6 +417,9 @@ Usage:
|
|
|
413
417
|
Examples:
|
|
414
418
|
prismo connect --token <token>
|
|
415
419
|
prismo connect --token <token> --api-url https://api.getprismo.dev
|
|
420
|
+
prismo connect --token <token> --no-agent
|
|
421
|
+
prismo connector status
|
|
422
|
+
prismo connector install
|
|
416
423
|
prismo sync --dry-run
|
|
417
424
|
prismo sync
|
|
418
425
|
prismo sync --watch --interval 60
|
|
@@ -420,10 +427,37 @@ Examples:
|
|
|
420
427
|
prismo disconnect
|
|
421
428
|
|
|
422
429
|
Output:
|
|
423
|
-
connect stores a local PrismoDev device connection in ~/.prismo/config.json.
|
|
430
|
+
connect stores a local PrismoDev device connection in ~/.prismo/config.json and starts the background workspace connector by default.
|
|
431
|
+
connector keeps Prismo Workspace online so repairs queued in the dashboard run locally without copy/paste commands.
|
|
424
432
|
sync reads local Codex, Claude Code, and Cursor session logs, builds aggregate agent-efficiency telemetry, and sends it to Prismo.
|
|
425
433
|
sync --watch keeps running so a local service manager can keep the Waste Scanner dashboard fresh.
|
|
426
434
|
Sync does not upload prompts, source code, file contents, stdout, stderr, or full command logs.`,
|
|
435
|
+
connector: `PrismoDev Connector
|
|
436
|
+
|
|
437
|
+
Usage:
|
|
438
|
+
prismo connector status [--json]
|
|
439
|
+
prismo connector install [--json] [--interval N] [--mode observe|suggest|autopilot] [path]
|
|
440
|
+
prismo connector start [--json]
|
|
441
|
+
prismo connector stop [--json]
|
|
442
|
+
prismo connector uninstall [--json]
|
|
443
|
+
|
|
444
|
+
Modes:
|
|
445
|
+
observe Keep the workspace connected but do not execute queued repairs.
|
|
446
|
+
suggest Stage repairs as pending approval.
|
|
447
|
+
autopilot Execute safe queued repairs automatically. (default)
|
|
448
|
+
|
|
449
|
+
Examples:
|
|
450
|
+
prismo connector status
|
|
451
|
+
prismo connector install
|
|
452
|
+
prismo connector install --mode suggest --interval 30
|
|
453
|
+
prismo connector stop
|
|
454
|
+
prismo connector uninstall
|
|
455
|
+
|
|
456
|
+
Output:
|
|
457
|
+
Installs and manages the local Prismo Workspace connector.
|
|
458
|
+
On macOS this creates a LaunchAgent so Prismo stays online after the terminal closes.
|
|
459
|
+
The connector claims safe repairs queued from Prismo Cloud, runs them locally, and reports status back.
|
|
460
|
+
It does not upload prompts, source code, file contents, stdout, stderr, or full command logs.`,
|
|
427
461
|
sync: `PrismoDev Sync
|
|
428
462
|
|
|
429
463
|
Usage:
|
package/lib/prismo-dev-scan.js
CHANGED
|
@@ -3,7 +3,7 @@ const http = require("http");
|
|
|
3
3
|
const https = require("https");
|
|
4
4
|
const os = require("os");
|
|
5
5
|
const path = require("path");
|
|
6
|
-
const { execSync } = require("child_process");
|
|
6
|
+
const { execSync, spawnSync } = require("child_process");
|
|
7
7
|
const { version: PACKAGE_VERSION } = require("../package.json");
|
|
8
8
|
|
|
9
9
|
function openUrl(url) {
|
|
@@ -333,6 +333,21 @@ const {
|
|
|
333
333
|
openUrl,
|
|
334
334
|
});
|
|
335
335
|
|
|
336
|
+
const {
|
|
337
|
+
renderConnectorTerminal,
|
|
338
|
+
runConnectorInstall,
|
|
339
|
+
runConnectorStart,
|
|
340
|
+
runConnectorStatus,
|
|
341
|
+
runConnectorStop,
|
|
342
|
+
runConnectorUninstall,
|
|
343
|
+
} = require("./prismo-dev/connector")({
|
|
344
|
+
fs,
|
|
345
|
+
os,
|
|
346
|
+
path,
|
|
347
|
+
spawnSync,
|
|
348
|
+
NPX_COMMAND,
|
|
349
|
+
});
|
|
350
|
+
|
|
336
351
|
const {
|
|
337
352
|
buildInstructionsAblationPlan,
|
|
338
353
|
buildInstructionsApply,
|
|
@@ -439,6 +454,12 @@ const { runCli } = require("./prismo-dev/cli")({
|
|
|
439
454
|
runGuard,
|
|
440
455
|
renderAgentTerminal,
|
|
441
456
|
runAgent,
|
|
457
|
+
renderConnectorTerminal,
|
|
458
|
+
runConnectorInstall,
|
|
459
|
+
runConnectorStart,
|
|
460
|
+
runConnectorStatus,
|
|
461
|
+
runConnectorStop,
|
|
462
|
+
runConnectorUninstall,
|
|
442
463
|
renderInstructionsAblationTerminal,
|
|
443
464
|
renderInstructionsApplyTerminal,
|
|
444
465
|
renderInstructionsAuditTerminal,
|
|
@@ -531,6 +552,11 @@ module.exports = {
|
|
|
531
552
|
runConnect,
|
|
532
553
|
runDisconnect,
|
|
533
554
|
runGuard,
|
|
555
|
+
runConnectorInstall,
|
|
556
|
+
runConnectorStart,
|
|
557
|
+
runConnectorStatus,
|
|
558
|
+
runConnectorStop,
|
|
559
|
+
runConnectorUninstall,
|
|
534
560
|
runStatus,
|
|
535
561
|
runSync,
|
|
536
562
|
getUsageSummary,
|
package/package.json
CHANGED