getprismo 0.1.34 → 0.1.35
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 +81 -2
- package/lib/prismo-dev/cli.js +6 -0
- package/lib/prismo-dev/help.js +10 -3
- package/lib/prismo-dev-scan.js +12 -0
- package/package.json +1 -1
package/lib/prismo-dev/agent.js
CHANGED
|
@@ -12,8 +12,11 @@ module.exports = function createAgent(deps) {
|
|
|
12
12
|
runGuard,
|
|
13
13
|
runShield,
|
|
14
14
|
runOptimize,
|
|
15
|
+
openUrl,
|
|
15
16
|
} = deps;
|
|
16
17
|
|
|
18
|
+
const DEFAULT_WORKSPACE_URL = "https://app.getprismo.dev/dashboard/dev";
|
|
19
|
+
|
|
17
20
|
const DEFAULT_API_URL = "https://api.getprismo.dev";
|
|
18
21
|
const TERMINAL_STATUSES = new Set(["completed", "failed", "cancelled"]);
|
|
19
22
|
const SAFE_SHIELD_COMMANDS = new Set(["npm", "pnpm", "yarn", "bun", "npx", "pytest", "python", "python3", "node"]);
|
|
@@ -128,6 +131,49 @@ module.exports = function createAgent(deps) {
|
|
|
128
131
|
return response.data;
|
|
129
132
|
}
|
|
130
133
|
|
|
134
|
+
function runAutoDetect(rootDir, options = {}) {
|
|
135
|
+
const mode = options.mode || "autopilot";
|
|
136
|
+
const startedAt = new Date().toISOString();
|
|
137
|
+
const result = runDoctor(rootDir, { limit: 3, applySuggestions: mode === "autopilot", json: true, dryRun: mode === "observe" });
|
|
138
|
+
const score = result.after?.score ?? result.scan?.score ?? null;
|
|
139
|
+
const issues = result.scan?.issues || [];
|
|
140
|
+
const generatedFiles = result.generatedFiles || result.optimize?.generatedFiles || [];
|
|
141
|
+
const findings = [];
|
|
142
|
+
|
|
143
|
+
if (score !== null && score < 80) {
|
|
144
|
+
findings.push({ type: "low-score", score, message: `Context health score is ${score}/100.` });
|
|
145
|
+
}
|
|
146
|
+
for (const issue of issues.slice(0, 5)) {
|
|
147
|
+
findings.push({ type: "issue", severity: issue.severity, message: issue.message || issue.recommendation || issue.label });
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
startedAt,
|
|
152
|
+
completedAt: new Date().toISOString(),
|
|
153
|
+
mode,
|
|
154
|
+
score,
|
|
155
|
+
findings,
|
|
156
|
+
generatedFiles,
|
|
157
|
+
applied: mode === "autopilot",
|
|
158
|
+
needsApproval: mode === "suggest" && findings.length > 0,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async function reportAutoDetect(config, detectResult, options = {}) {
|
|
163
|
+
const endpoint = options.detectEndpoint || `${apiBase(config)}/v1/dev/workspace/auto-detect`;
|
|
164
|
+
try {
|
|
165
|
+
await requestJson("POST", endpoint, config.token, detectResult, options.timeoutMs || 10000);
|
|
166
|
+
} catch (_) {}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function openWorkspace(config) {
|
|
170
|
+
const url = config?.workspaceUrl || DEFAULT_WORKSPACE_URL;
|
|
171
|
+
if (openUrl) {
|
|
172
|
+
openUrl(url);
|
|
173
|
+
}
|
|
174
|
+
return url;
|
|
175
|
+
}
|
|
176
|
+
|
|
131
177
|
async function executeAction(action, rootDir, options = {}) {
|
|
132
178
|
const root = repoRoot(path.resolve(rootDir || process.cwd()), action);
|
|
133
179
|
const parsed = parseCommand(action.command);
|
|
@@ -261,6 +307,12 @@ module.exports = function createAgent(deps) {
|
|
|
261
307
|
await sendHeartbeat(config, { mode, status: "online", lastPollAt: pollTime }, options);
|
|
262
308
|
} catch (_) {}
|
|
263
309
|
|
|
310
|
+
let autoDetectResult = null;
|
|
311
|
+
if (options.autoDetect) {
|
|
312
|
+
autoDetectResult = runAutoDetect(rootDir, { mode });
|
|
313
|
+
await reportAutoDetect(config, autoDetectResult, options);
|
|
314
|
+
}
|
|
315
|
+
|
|
264
316
|
const actions = await claimActions(config, options);
|
|
265
317
|
const results = [];
|
|
266
318
|
for (const action of actions) {
|
|
@@ -299,6 +351,7 @@ module.exports = function createAgent(deps) {
|
|
|
299
351
|
actionsCompleted: results.filter((item) => item.status === "completed").length,
|
|
300
352
|
actionsFailed: results.filter((item) => item.status === "failed").length,
|
|
301
353
|
actionsObserved: results.filter((item) => item.status === "observed" || item.status === "pending_approval").length,
|
|
354
|
+
autoDetect: autoDetectResult,
|
|
302
355
|
results,
|
|
303
356
|
privacy: {
|
|
304
357
|
rawPrompts: false,
|
|
@@ -332,6 +385,21 @@ module.exports = function createAgent(deps) {
|
|
|
332
385
|
if (result.actionsObserved > 0) {
|
|
333
386
|
lines.push(`Observed/Suggested: ${result.actionsObserved}`);
|
|
334
387
|
}
|
|
388
|
+
if (result.autoDetect) {
|
|
389
|
+
lines.push("");
|
|
390
|
+
lines.push("Auto-detect");
|
|
391
|
+
lines.push(` Score: ${result.autoDetect.score ?? "unknown"}/100`);
|
|
392
|
+
lines.push(` Findings: ${result.autoDetect.findings.length}`);
|
|
393
|
+
if (result.autoDetect.applied) lines.push(" Status: auto-fixed");
|
|
394
|
+
else if (result.autoDetect.needsApproval) lines.push(" Status: needs approval in workspace");
|
|
395
|
+
else lines.push(" Status: observed");
|
|
396
|
+
if (result.autoDetect.generatedFiles.length) {
|
|
397
|
+
lines.push(` Generated: ${result.autoDetect.generatedFiles.join(", ")}`);
|
|
398
|
+
}
|
|
399
|
+
result.autoDetect.findings.forEach((f) => {
|
|
400
|
+
lines.push(` - ${f.message}`);
|
|
401
|
+
});
|
|
402
|
+
}
|
|
335
403
|
if (result.results.length) {
|
|
336
404
|
lines.push("");
|
|
337
405
|
lines.push("Actions");
|
|
@@ -339,7 +407,7 @@ module.exports = function createAgent(deps) {
|
|
|
339
407
|
lines.push(`- ${item.status}: ${item.label}`);
|
|
340
408
|
if (item.statusMessage) lines.push(` ${item.statusMessage}`);
|
|
341
409
|
});
|
|
342
|
-
} else {
|
|
410
|
+
} else if (!result.autoDetect) {
|
|
343
411
|
lines.push("");
|
|
344
412
|
lines.push("No queued workspace actions.");
|
|
345
413
|
}
|
|
@@ -352,6 +420,12 @@ module.exports = function createAgent(deps) {
|
|
|
352
420
|
const intervalMs = Math.max(5, Number(options.interval || 15)) * 1000;
|
|
353
421
|
let running = true;
|
|
354
422
|
let sleepResolve = null;
|
|
423
|
+
let firstRun = true;
|
|
424
|
+
|
|
425
|
+
if (options.open) {
|
|
426
|
+
const config = loadConfig();
|
|
427
|
+
openWorkspace(config);
|
|
428
|
+
}
|
|
355
429
|
|
|
356
430
|
async function shutdown() {
|
|
357
431
|
if (!running) return;
|
|
@@ -371,7 +445,9 @@ module.exports = function createAgent(deps) {
|
|
|
371
445
|
process.on("SIGTERM", shutdown);
|
|
372
446
|
|
|
373
447
|
while (running) {
|
|
374
|
-
const
|
|
448
|
+
const runOptions = { ...options, autoDetect: firstRun && options.autoDetect !== false };
|
|
449
|
+
firstRun = false;
|
|
450
|
+
const result = await runAgentOnce(rootDir, runOptions);
|
|
375
451
|
if (!running) break;
|
|
376
452
|
if (options.json) console.log(JSON.stringify(result, null, 2));
|
|
377
453
|
else console.log(renderAgentTerminal(result));
|
|
@@ -388,10 +464,13 @@ module.exports = function createAgent(deps) {
|
|
|
388
464
|
return {
|
|
389
465
|
claimActions,
|
|
390
466
|
executeAction,
|
|
467
|
+
openWorkspace,
|
|
391
468
|
parseCommand,
|
|
392
469
|
renderAgentTerminal,
|
|
470
|
+
reportAutoDetect,
|
|
393
471
|
runAgent,
|
|
394
472
|
runAgentOnce,
|
|
473
|
+
runAutoDetect,
|
|
395
474
|
sendHeartbeat,
|
|
396
475
|
updateAction,
|
|
397
476
|
VALID_MODES,
|
package/lib/prismo-dev/cli.js
CHANGED
|
@@ -25,6 +25,7 @@ function createCli(deps) {
|
|
|
25
25
|
NPX_COMMAND,
|
|
26
26
|
DEFAULT_PRISMO_PROXY_URL,
|
|
27
27
|
AGENT_VALID_MODES,
|
|
28
|
+
openUrl,
|
|
28
29
|
printStep,
|
|
29
30
|
getPositionals,
|
|
30
31
|
parsePositiveInt,
|
|
@@ -321,6 +322,9 @@ function createCli(deps) {
|
|
|
321
322
|
device: deviceIndex >= 0 ? rest[deviceIndex + 1] : null,
|
|
322
323
|
limit: parsePositiveInt(limitIndex >= 0 ? rest[limitIndex + 1] : null, 20),
|
|
323
324
|
});
|
|
325
|
+
if (result.connected && (rest.includes("--open") || !rest.includes("--no-open"))) {
|
|
326
|
+
openUrl("https://app.getprismo.dev/dashboard/dev");
|
|
327
|
+
}
|
|
324
328
|
if (json) console.log(JSON.stringify(result, null, 2));
|
|
325
329
|
else console.log(renderConnectTerminal(result));
|
|
326
330
|
return;
|
|
@@ -372,6 +376,8 @@ function createCli(deps) {
|
|
|
372
376
|
json,
|
|
373
377
|
mode: modeValue,
|
|
374
378
|
watch: rest.includes("--watch") && !rest.includes("--once"),
|
|
379
|
+
open: rest.includes("--open"),
|
|
380
|
+
autoDetect: !rest.includes("--no-detect"),
|
|
375
381
|
interval: parsePositiveInt(intervalIndex >= 0 ? rest[intervalIndex + 1] : null, 15),
|
|
376
382
|
limit: parsePositiveInt(limitIndex >= 0 ? rest[limitIndex + 1] : null, 5),
|
|
377
383
|
tokenBudget: parseTokenBudget(budgetIndex >= 0 ? rest[budgetIndex + 1] : null) || 600000,
|
package/lib/prismo-dev/help.js
CHANGED
|
@@ -455,7 +455,7 @@ Output:
|
|
|
455
455
|
agent: `PrismoDev Agent
|
|
456
456
|
|
|
457
457
|
Usage:
|
|
458
|
-
prismo agent [--json] [--once] [--watch] [--interval N] [--limit N] [--mode MODE] [path]
|
|
458
|
+
prismo agent [--json] [--once] [--watch] [--open] [--no-detect] [--interval N] [--limit N] [--mode MODE] [path]
|
|
459
459
|
|
|
460
460
|
Modes:
|
|
461
461
|
observe Watch and report actions without executing. No changes made.
|
|
@@ -467,10 +467,17 @@ Examples:
|
|
|
467
467
|
prismo agent --watch --interval 15
|
|
468
468
|
prismo agent --watch --mode observe
|
|
469
469
|
prismo agent --watch --mode suggest
|
|
470
|
-
prismo agent --
|
|
470
|
+
prismo agent --watch --open
|
|
471
|
+
prismo agent --json --once --no-detect
|
|
472
|
+
|
|
473
|
+
Options:
|
|
474
|
+
--open Open the Prismo workspace in the browser on start.
|
|
475
|
+
--no-detect Skip the initial auto-detect scan on first poll.
|
|
471
476
|
|
|
472
477
|
Output:
|
|
473
|
-
|
|
478
|
+
On first poll, the agent proactively runs doctor to detect context issues.
|
|
479
|
+
In autopilot mode it auto-fixes safe issues. In suggest mode it reports them as pending_approval in the workspace.
|
|
480
|
+
Claims safe workspace actions queued from Prismo Cloud, runs them locally, and reports status back.
|
|
474
481
|
Sends heartbeat to Prismo Cloud on each poll so the dashboard shows agent online/offline status.
|
|
475
482
|
Handles SIGINT/SIGTERM gracefully and marks the agent offline before exiting.
|
|
476
483
|
Supported actions are doctor, sync, guard, context/optimize, and shield with a conservative command allowlist.
|
package/lib/prismo-dev-scan.js
CHANGED
|
@@ -3,8 +3,18 @@ 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
7
|
const { version: PACKAGE_VERSION } = require("../package.json");
|
|
7
8
|
|
|
9
|
+
function openUrl(url) {
|
|
10
|
+
try {
|
|
11
|
+
const cmd = process.platform === "darwin" ? "open"
|
|
12
|
+
: process.platform === "win32" ? "start"
|
|
13
|
+
: "xdg-open";
|
|
14
|
+
execSync(`${cmd} ${JSON.stringify(url)}`, { stdio: "ignore" });
|
|
15
|
+
} catch (_) {}
|
|
16
|
+
}
|
|
17
|
+
|
|
8
18
|
const {
|
|
9
19
|
HIGH_RISK_DIRS,
|
|
10
20
|
HIGH_RISK_FILE_NAMES,
|
|
@@ -320,6 +330,7 @@ const {
|
|
|
320
330
|
runGuard,
|
|
321
331
|
runShield,
|
|
322
332
|
runOptimize,
|
|
333
|
+
openUrl,
|
|
323
334
|
});
|
|
324
335
|
|
|
325
336
|
const {
|
|
@@ -383,6 +394,7 @@ const { runCli } = require("./prismo-dev/cli")({
|
|
|
383
394
|
NPX_COMMAND,
|
|
384
395
|
DEFAULT_PRISMO_PROXY_URL,
|
|
385
396
|
AGENT_VALID_MODES,
|
|
397
|
+
openUrl,
|
|
386
398
|
printStep,
|
|
387
399
|
getPositionals,
|
|
388
400
|
parsePositiveInt,
|
package/package.json
CHANGED