@illuminis/comprism 0.1.3 → 0.1.5
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 +61 -2
- package/out/agent/command.d.ts +75 -4
- package/out/agent/command.js +221 -26
- package/out/agent/render.d.ts +56 -8
- package/out/agent/render.js +441 -39
- package/out/agent/session.d.ts +156 -2
- package/out/agent/session.js +795 -154
- package/out/commands/agents.d.ts +2 -0
- package/out/commands/agents.js +79 -0
- package/out/commands/ask.d.ts +1 -1
- package/out/commands/ask.js +88 -12
- package/out/commands/commands-thin.js +79 -17
- package/out/commands/config.d.ts +1 -0
- package/out/commands/config.js +138 -0
- package/out/commands/cost.d.ts +1 -0
- package/out/commands/cost.js +167 -0
- package/out/commands/hooks.d.ts +1 -0
- package/out/commands/hooks.js +83 -0
- package/out/commands/install.d.ts +44 -1
- package/out/commands/install.js +198 -4
- package/out/commands/instructions.d.ts +1 -0
- package/out/commands/instructions.js +113 -0
- package/out/commands/integrations.d.ts +3 -0
- package/out/commands/integrations.js +215 -0
- package/out/commands/jobs.d.ts +5 -0
- package/out/commands/jobs.js +157 -0
- package/out/commands/login.js +249 -43
- package/out/commands/memory.d.ts +3 -0
- package/out/commands/memory.js +113 -0
- package/out/commands/permissions.d.ts +1 -0
- package/out/commands/permissions.js +94 -0
- package/out/commands/plugins.d.ts +4 -0
- package/out/commands/plugins.js +192 -0
- package/out/commands/privacy.d.ts +1 -0
- package/out/commands/privacy.js +57 -0
- package/out/commands/providerKey.d.ts +32 -0
- package/out/commands/providerKey.js +108 -0
- package/out/commands/repl.d.ts +12 -1
- package/out/commands/repl.js +1649 -122
- package/out/commands/report.d.ts +39 -0
- package/out/commands/report.js +115 -0
- package/out/commands/review.d.ts +5 -0
- package/out/commands/review.js +223 -0
- package/out/commands/sessions.d.ts +23 -0
- package/out/commands/sessions.js +115 -0
- package/out/commands/settings.d.ts +3 -1
- package/out/commands/settings.js +18 -16
- package/out/commands/skills.d.ts +21 -0
- package/out/commands/skills.js +207 -0
- package/out/commands/unattended.d.ts +7 -0
- package/out/commands/unattended.js +351 -0
- package/out/commands/update.d.ts +1 -0
- package/out/commands/update.js +123 -0
- package/out/commands/welcome.d.ts +25 -1
- package/out/commands/welcome.js +71 -35
- package/out/commands/worktrees.d.ts +5 -0
- package/out/commands/worktrees.js +186 -0
- package/out/executor/browser.d.ts +14 -0
- package/out/executor/browser.js +270 -0
- package/out/executor/diagnostics.d.ts +2 -0
- package/out/executor/diagnostics.js +181 -0
- package/out/executor/files.js +270 -40
- package/out/executor/git.js +42 -29
- package/out/executor/hooks.d.ts +42 -58
- package/out/executor/hooks.js +89 -182
- package/out/executor/index.d.ts +21 -5
- package/out/executor/index.js +160 -14
- package/out/executor/paths.d.ts +6 -1
- package/out/executor/paths.js +34 -6
- package/out/executor/sandbox.d.ts +40 -0
- package/out/executor/sandbox.js +299 -0
- package/out/executor/shell.d.ts +49 -4
- package/out/executor/shell.js +302 -56
- package/out/executor/toolservers.d.ts +20 -0
- package/out/executor/toolservers.js +189 -0
- package/out/executor/worktree.d.ts +9 -0
- package/out/executor/worktree.js +119 -0
- package/out/graph/read-python.js +2 -1
- package/out/lib/attach.d.ts +56 -12
- package/out/lib/attach.js +230 -63
- package/out/lib/clipboard.d.ts +23 -0
- package/out/lib/clipboard.js +182 -0
- package/out/lib/commandlist.d.ts +20 -0
- package/out/lib/commandlist.js +58 -0
- package/out/lib/decision.d.ts +22 -0
- package/out/lib/decision.js +50 -0
- package/out/lib/fingerprint.d.ts +25 -0
- package/out/lib/fingerprint.js +58 -0
- package/out/lib/gateway.d.ts +190 -2
- package/out/lib/gateway.js +59 -4
- package/out/lib/history.d.ts +24 -0
- package/out/lib/history.js +137 -0
- package/out/lib/ide.d.ts +19 -0
- package/out/lib/ide.js +131 -0
- package/out/lib/keyboard.d.ts +98 -0
- package/out/lib/keyboard.js +390 -0
- package/out/lib/lastlogin.d.ts +14 -0
- package/out/lib/lastlogin.js +105 -0
- package/out/lib/machine.d.ts +21 -0
- package/out/lib/machine.js +91 -0
- package/out/lib/notify.d.ts +4 -0
- package/out/lib/notify.js +52 -0
- package/out/lib/output.d.ts +48 -0
- package/out/lib/output.js +108 -0
- package/out/lib/picker.d.ts +1 -0
- package/out/lib/picker.js +158 -0
- package/out/lib/project-ops.d.ts +19 -0
- package/out/lib/project-ops.js +146 -0
- package/out/lib/project.d.ts +28 -0
- package/out/lib/project.js +114 -0
- package/out/lib/prompt.d.ts +3 -0
- package/out/lib/prompt.js +36 -2
- package/out/lib/queue.d.ts +13 -0
- package/out/lib/queue.js +116 -0
- package/out/lib/readiness.d.ts +19 -0
- package/out/lib/readiness.js +170 -1
- package/out/lib/self.d.ts +23 -0
- package/out/lib/self.js +124 -0
- package/out/lib/sessions.d.ts +19 -0
- package/out/lib/sessions.js +221 -0
- package/out/lib/startcache.d.ts +13 -0
- package/out/lib/startcache.js +78 -0
- package/out/lib/stdin.d.ts +32 -0
- package/out/lib/stdin.js +117 -0
- package/out/lib/store.d.ts +40 -0
- package/out/lib/store.js +138 -0
- package/out/lib/sync.d.ts +18 -0
- package/out/lib/sync.js +81 -0
- package/out/lib/ui.d.ts +10 -4
- package/out/lib/ui.js +65 -25
- package/out/lib/voice.d.ts +36 -0
- package/out/lib/voice.js +160 -1
- package/out/native/dictate +0 -0
- package/out/postinstall.js +42 -17
- package/out/providers/anthropic.d.ts +22 -0
- package/out/providers/anthropic.js +80 -0
- package/out/providers/index.d.ts +8 -0
- package/out/providers/index.js +83 -0
- package/out/providers/openai.d.ts +11 -0
- package/out/providers/openai.js +57 -0
- package/out/thin.js +595 -33
- package/package.json +11 -50
package/out/lib/prompt.js
CHANGED
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.closePrompt = closePrompt;
|
|
7
7
|
exports.ask = ask;
|
|
8
|
+
exports.askOrCancel = askOrCancel;
|
|
8
9
|
exports.askHidden = askHidden;
|
|
9
10
|
exports.freeText = freeText;
|
|
10
11
|
exports.subject = subject;
|
|
@@ -24,6 +25,11 @@ function open() {
|
|
|
24
25
|
output: process.stdout,
|
|
25
26
|
terminal: process.stdin.isTTY === true,
|
|
26
27
|
});
|
|
28
|
+
// Ctrl+C closes it. The next question then opens a new one instead of
|
|
29
|
+
// asking a closed reader, which threw and ended the whole program.
|
|
30
|
+
const mine = reader;
|
|
31
|
+
mine.once('close', () => { if (reader === mine)
|
|
32
|
+
reader = null; });
|
|
27
33
|
}
|
|
28
34
|
return reader;
|
|
29
35
|
}
|
|
@@ -35,7 +41,33 @@ function closePrompt() {
|
|
|
35
41
|
/** Ask a question and wait for the answer. */
|
|
36
42
|
function ask(prompt) {
|
|
37
43
|
return new Promise((resolve) => {
|
|
38
|
-
|
|
44
|
+
const r = open();
|
|
45
|
+
// Standard input closed before a line arrived: nothing was said. Without
|
|
46
|
+
// this the process simply ran out of work and exited 0, so a script that
|
|
47
|
+
// piped in nothing was told it had succeeded (manual Appendix B).
|
|
48
|
+
// Input that had already ended before this reader opened never says so
|
|
49
|
+
// again, so the last chance is the moment nothing else is left to wait on.
|
|
50
|
+
const closed = () => resolve('');
|
|
51
|
+
r.once('close', closed);
|
|
52
|
+
process.once('beforeExit', closed);
|
|
53
|
+
r.question(prompt, (answer) => {
|
|
54
|
+
r.off('close', closed);
|
|
55
|
+
process.off('beforeExit', closed);
|
|
56
|
+
resolve(answer.trim());
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/** Ask, telling a cancel (Ctrl+C, input closed) apart from an empty answer:
|
|
61
|
+
* null is "never mind", "" is Enter. */
|
|
62
|
+
function askOrCancel(prompt) {
|
|
63
|
+
return new Promise((resolve) => {
|
|
64
|
+
const r = open();
|
|
65
|
+
const closed = () => resolve(null);
|
|
66
|
+
r.once('close', closed);
|
|
67
|
+
r.question(prompt, (answer) => {
|
|
68
|
+
r.off('close', closed);
|
|
69
|
+
resolve(answer.trim());
|
|
70
|
+
});
|
|
39
71
|
});
|
|
40
72
|
}
|
|
41
73
|
/**
|
|
@@ -73,12 +105,14 @@ function askHidden(prompt) {
|
|
|
73
105
|
process.stdout.write(`\r${prompt}${"\u2022".repeat(inner.line.length)}`);
|
|
74
106
|
};
|
|
75
107
|
return new Promise((resolve) => {
|
|
108
|
+
// Ctrl+C at the password is "never mind", answered as nothing, never a crash.
|
|
109
|
+
reader.once('close', () => { inner._writeToOutput = asItWas; resolve(''); });
|
|
76
110
|
reader.question(prompt, (answer) => {
|
|
77
111
|
// Put readline back the way it was, whatever happened, or every later
|
|
78
112
|
// question on this reader would come out as dots.
|
|
79
113
|
inner._writeToOutput = asItWas;
|
|
80
114
|
process.stdout.write("\n");
|
|
81
|
-
resolve(answer
|
|
115
|
+
resolve(answer);
|
|
82
116
|
});
|
|
83
117
|
});
|
|
84
118
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type GatewayReply } from "./gateway";
|
|
2
|
+
export declare function queue(op: string, payload?: Record<string, unknown>): Promise<GatewayReply>;
|
|
3
|
+
/** The limits and mode typed on the line, for the service to hold (10.17). */
|
|
4
|
+
export declare function limitsFrom(args: string[]): Record<string, unknown>;
|
|
5
|
+
export declare const workerLog: () => string;
|
|
6
|
+
/** Whether this machine's runner is going, and its process number. */
|
|
7
|
+
export declare function workerRunning(): number | null;
|
|
8
|
+
export declare function notePid(): void;
|
|
9
|
+
/** Start the runner in the background when it is not running. */
|
|
10
|
+
export declare function ensureWorker(): {
|
|
11
|
+
pid: number;
|
|
12
|
+
started: boolean;
|
|
13
|
+
};
|
package/out/lib/queue.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.workerLog = void 0;
|
|
37
|
+
exports.queue = queue;
|
|
38
|
+
exports.limitsFrom = limitsFrom;
|
|
39
|
+
exports.workerRunning = workerRunning;
|
|
40
|
+
exports.notePid = notePid;
|
|
41
|
+
exports.ensureWorker = ensureWorker;
|
|
42
|
+
/**
|
|
43
|
+
* Jobs nobody is sitting at, from this side (manual 10.17 to 10.19).
|
|
44
|
+
*
|
|
45
|
+
* The service holds the schedules, the triggers and the queue, and decides what
|
|
46
|
+
* is due and what may run where. This file asks it, and keeps one runner going
|
|
47
|
+
* on this machine to take what the service offers.
|
|
48
|
+
*/
|
|
49
|
+
const fs = __importStar(require("fs"));
|
|
50
|
+
const path = __importStar(require("path"));
|
|
51
|
+
const child_process_1 = require("child_process");
|
|
52
|
+
const gateway_1 = require("./gateway");
|
|
53
|
+
const config_1 = require("./config");
|
|
54
|
+
const self_1 = require("./self");
|
|
55
|
+
async function queue(op, payload = {}) {
|
|
56
|
+
return (0, gateway_1.ask)({
|
|
57
|
+
intent: "queue", prompt: "", op,
|
|
58
|
+
payload: { tz_minutes: -new Date().getTimezoneOffset(), ...payload },
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/** The limits and mode typed on the line, for the service to hold (10.17). */
|
|
62
|
+
function limitsFrom(args) {
|
|
63
|
+
const value = (name) => {
|
|
64
|
+
const at = args.indexOf(name);
|
|
65
|
+
return at === -1 ? undefined : args[at + 1];
|
|
66
|
+
};
|
|
67
|
+
const out = {};
|
|
68
|
+
if (value("--mode"))
|
|
69
|
+
out.mode = value("--mode");
|
|
70
|
+
if (value("--max-spend"))
|
|
71
|
+
out.max_spend = Number(value("--max-spend"));
|
|
72
|
+
if (value("--max-steps"))
|
|
73
|
+
out.max_steps = Number(value("--max-steps"));
|
|
74
|
+
if (value("--max-minutes"))
|
|
75
|
+
out.max_minutes = Number(value("--max-minutes"));
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
const pidFile = () => path.join((0, config_1.homeDir)(), "worker.pid");
|
|
79
|
+
const workerLog = () => path.join((0, config_1.homeDir)(), "worker.log");
|
|
80
|
+
exports.workerLog = workerLog;
|
|
81
|
+
function alive(pid) {
|
|
82
|
+
try {
|
|
83
|
+
process.kill(pid, 0);
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** Whether this machine's runner is going, and its process number. */
|
|
91
|
+
function workerRunning() {
|
|
92
|
+
try {
|
|
93
|
+
const pid = Number(fs.readFileSync(pidFile(), "utf8").trim());
|
|
94
|
+
return pid && alive(pid) ? pid : null;
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function notePid() {
|
|
101
|
+
fs.mkdirSync((0, config_1.homeDir)(), { recursive: true });
|
|
102
|
+
fs.writeFileSync(pidFile(), String(process.pid));
|
|
103
|
+
}
|
|
104
|
+
/** Start the runner in the background when it is not running. */
|
|
105
|
+
function ensureWorker() {
|
|
106
|
+
const running = workerRunning();
|
|
107
|
+
if (running)
|
|
108
|
+
return { pid: running, started: false };
|
|
109
|
+
fs.mkdirSync((0, config_1.homeDir)(), { recursive: true });
|
|
110
|
+
const log = fs.openSync((0, exports.workerLog)(), "a");
|
|
111
|
+
const child = (0, child_process_1.spawn)(...(0, self_1.selfLaunch)(["worker"]), {
|
|
112
|
+
detached: true, stdio: ["ignore", log, log], env: { ...process.env, NO_COLOR: "1" },
|
|
113
|
+
});
|
|
114
|
+
child.unref();
|
|
115
|
+
return { pid: child.pid ?? 0, started: true };
|
|
116
|
+
}
|
package/out/lib/readiness.d.ts
CHANGED
|
@@ -28,3 +28,22 @@ export interface Readiness {
|
|
|
28
28
|
}
|
|
29
29
|
/** What this machine can and cannot do, and how to close the gap. */
|
|
30
30
|
export declare function check(): Readiness;
|
|
31
|
+
/** One checked item: its line, whether it is required, and the fix. */
|
|
32
|
+
export interface Finding {
|
|
33
|
+
ok: boolean;
|
|
34
|
+
required: boolean;
|
|
35
|
+
line: string;
|
|
36
|
+
fix?: string;
|
|
37
|
+
}
|
|
38
|
+
/** The system this is, in the words its owner would use. */
|
|
39
|
+
export declare function systemName(): string;
|
|
40
|
+
/**
|
|
41
|
+
* Everything `comprism check` reports (manual 1.6).
|
|
42
|
+
*
|
|
43
|
+
* Required: Node 22 or newer (built in for the install script and Python
|
|
44
|
+
* installs), a sign in, and a service that answers. Anything
|
|
45
|
+
* else is optional and never makes the check fail. Whether the service still
|
|
46
|
+
* accepts this machine is asked of the service itself, on the same session
|
|
47
|
+
* operation `status` uses, so the two can never disagree.
|
|
48
|
+
*/
|
|
49
|
+
export declare function diagnose(): Promise<Finding[]>;
|
package/out/lib/readiness.js
CHANGED
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
@@ -7,6 +40,8 @@ exports.REQUIREMENTS = void 0;
|
|
|
7
40
|
exports.present = present;
|
|
8
41
|
exports.howToInstall = howToInstall;
|
|
9
42
|
exports.check = check;
|
|
43
|
+
exports.systemName = systemName;
|
|
44
|
+
exports.diagnose = diagnose;
|
|
10
45
|
/**
|
|
11
46
|
* What this machine needs before the work can be done on it, and what to type
|
|
12
47
|
* when something is missing.
|
|
@@ -38,6 +73,10 @@ exports.check = check;
|
|
|
38
73
|
*/
|
|
39
74
|
const node_child_process_1 = require("node:child_process");
|
|
40
75
|
const node_os_1 = __importDefault(require("node:os"));
|
|
76
|
+
const install_1 = require("../commands/install");
|
|
77
|
+
const connection_1 = require("./connection");
|
|
78
|
+
const gateway_1 = require("./gateway");
|
|
79
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
41
80
|
exports.REQUIREMENTS = [
|
|
42
81
|
{
|
|
43
82
|
purpose: 'working with a repository',
|
|
@@ -57,7 +96,11 @@ exports.REQUIREMENTS = [
|
|
|
57
96
|
/** Is this program on the machine, by name, without running anything of theirs. */
|
|
58
97
|
function present(program) {
|
|
59
98
|
try {
|
|
60
|
-
|
|
99
|
+
// Windows has no /usr/bin/env, so every program read as missing there.
|
|
100
|
+
if (node_os_1.default.platform() === 'win32')
|
|
101
|
+
(0, node_child_process_1.execFileSync)('where', [program], { stdio: 'ignore' });
|
|
102
|
+
else
|
|
103
|
+
(0, node_child_process_1.execFileSync)('/usr/bin/env', ['which', program], { stdio: 'ignore' });
|
|
61
104
|
return true;
|
|
62
105
|
}
|
|
63
106
|
catch {
|
|
@@ -105,3 +148,129 @@ function check() {
|
|
|
105
148
|
}
|
|
106
149
|
return { ready: missing.length === 0, lines, fix: howToInstall(missing) };
|
|
107
150
|
}
|
|
151
|
+
/** The system this is, in the words its owner would use. */
|
|
152
|
+
function systemName() {
|
|
153
|
+
try {
|
|
154
|
+
if (node_os_1.default.platform() === 'darwin') {
|
|
155
|
+
const v = (0, node_child_process_1.execFileSync)('sw_vers', ['-productVersion'], { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
|
|
156
|
+
return `macOS ${v} ${node_os_1.default.arch()}`;
|
|
157
|
+
}
|
|
158
|
+
if (node_os_1.default.platform() === 'linux') {
|
|
159
|
+
const release = node_fs_1.default.readFileSync('/etc/os-release', 'utf8').match(/^PRETTY_NAME="?([^"\n]+)"?/m);
|
|
160
|
+
return `${release ? release[1] : 'Linux'} ${node_os_1.default.arch()}`;
|
|
161
|
+
}
|
|
162
|
+
if (node_os_1.default.platform() === 'win32')
|
|
163
|
+
return `${node_os_1.default.version()} ${node_os_1.default.arch()}`;
|
|
164
|
+
}
|
|
165
|
+
catch { /* fall through to the plain name */ }
|
|
166
|
+
return `${node_os_1.default.type()} ${node_os_1.default.release()} ${node_os_1.default.arch()}`;
|
|
167
|
+
}
|
|
168
|
+
function version(program, args) {
|
|
169
|
+
try {
|
|
170
|
+
const text = (0, node_child_process_1.execFileSync)(program, args, { stdio: ['ignore', 'pipe', 'ignore'] }).toString();
|
|
171
|
+
return text.match(/\d+\.\d+(\.\d+)?/)?.[0] ?? '';
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Everything `comprism check` reports (manual 1.6).
|
|
179
|
+
*
|
|
180
|
+
* Required: Node 22 or newer (built in for the install script and Python
|
|
181
|
+
* installs), a sign in, and a service that answers. Anything
|
|
182
|
+
* else is optional and never makes the check fail. Whether the service still
|
|
183
|
+
* accepts this machine is asked of the service itself, on the same session
|
|
184
|
+
* operation `status` uses, so the two can never disagree.
|
|
185
|
+
*/
|
|
186
|
+
async function diagnose() {
|
|
187
|
+
const found = [];
|
|
188
|
+
found.push({ ok: true, required: false, line: systemName() });
|
|
189
|
+
// Which proxy and certificate file are in use (manual 1.11).
|
|
190
|
+
const proxy = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy;
|
|
191
|
+
if (proxy) {
|
|
192
|
+
const bypass = process.env.NO_PROXY || process.env.no_proxy;
|
|
193
|
+
found.push({ ok: true, required: false, line: `proxy ${proxy.replace(/\/\/[^@/]*@/, '//***@')}`
|
|
194
|
+
+ (bypass ? `, not used for ${bypass}` : '') });
|
|
195
|
+
}
|
|
196
|
+
const caFile = process.env.NODE_EXTRA_CA_CERTS;
|
|
197
|
+
if (caFile) {
|
|
198
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
199
|
+
found.push(fs.existsSync(caFile)
|
|
200
|
+
? { ok: true, required: false, line: `extra certificate authorities from ${caFile}` }
|
|
201
|
+
: { ok: false, required: true, line: `NODE_EXTRA_CA_CERTS names ${caFile}, which does not exist`,
|
|
202
|
+
fix: 'point NODE_EXTRA_CA_CERTS at your company certificate authority file' });
|
|
203
|
+
}
|
|
204
|
+
const node = process.versions.node;
|
|
205
|
+
const major = Number(node.split('.')[0]);
|
|
206
|
+
// The install script and Python installs carry their own Node (manual 1.1),
|
|
207
|
+
// so the line says so rather than asking for a Node nobody installed.
|
|
208
|
+
const { installMethod, isStandalone } = await Promise.resolve().then(() => __importStar(require('./self')));
|
|
209
|
+
if (isStandalone()) {
|
|
210
|
+
const how = installMethod() === 'script' ? 'the install script' : 'Python (pip)';
|
|
211
|
+
found.push({ ok: true, required: true, line: `installed with ${how}; Node ${node} is built in, nothing else needed` });
|
|
212
|
+
}
|
|
213
|
+
else
|
|
214
|
+
found.push(major >= 22
|
|
215
|
+
? { ok: true, required: true, line: `Node ${node} (22 or newer needed)` }
|
|
216
|
+
: { ok: false, required: true, line: `Node ${node} is too old: 22 or newer needed`,
|
|
217
|
+
fix: 'install Node 22 or newer from https://nodejs.org' });
|
|
218
|
+
const connection = (0, connection_1.readConnection)();
|
|
219
|
+
if (!connection?.url || !connection.workspaceKey) {
|
|
220
|
+
found.push({ ok: false, required: true, line: 'not signed in', fix: 'comprism login' });
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
const started = Date.now();
|
|
224
|
+
const reply = await (0, gateway_1.ask)({ intent: 'session', prompt: '' });
|
|
225
|
+
const ms = Date.now() - started;
|
|
226
|
+
if (!reply.ok && !reply.httpStatus && /certificate problem/.test(reply.message || '')) {
|
|
227
|
+
found.push({ ok: false, required: true, line: `service at ${connection.url}: ${reply.message}`,
|
|
228
|
+
fix: 'set NODE_EXTRA_CA_CERTS to your company certificate authority file' });
|
|
229
|
+
}
|
|
230
|
+
else if (!reply.ok && !reply.httpStatus) {
|
|
231
|
+
found.push({ ok: false, required: true, line: `service at ${connection.url} did not answer`,
|
|
232
|
+
fix: 'check your network, then comprism status' });
|
|
233
|
+
}
|
|
234
|
+
else if (reply.httpStatus === 401 || (reply.ok && reply.session && !reply.session.signed_in)) {
|
|
235
|
+
found.push({ ok: false, required: true, line: "signed out: this machine's key was revoked or has expired",
|
|
236
|
+
fix: 'comprism login' });
|
|
237
|
+
found.push({ ok: true, required: true, line: `service reachable in ${ms} ms` });
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
found.push({ ok: true, required: true,
|
|
241
|
+
line: `signed in to ${reply.session?.company || connection.url}` });
|
|
242
|
+
found.push({ ok: true, required: true, line: `service reachable in ${ms} ms` });
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const { powershellProfiles } = await Promise.resolve().then(() => __importStar(require('../commands/install')));
|
|
246
|
+
const profile = [...powershellProfiles(), ...(0, install_1.shellProfiles)()].find(install_1.profileHasSetup);
|
|
247
|
+
const home = node_os_1.default.homedir();
|
|
248
|
+
if (profile) {
|
|
249
|
+
found.push({ ok: true, required: false,
|
|
250
|
+
line: `shell profile line present in ${profile.startsWith(home) ? `~${profile.slice(home.length)}` : profile}` });
|
|
251
|
+
}
|
|
252
|
+
else if (node_os_1.default.platform() === 'win32') {
|
|
253
|
+
found.push({ ok: false, required: false,
|
|
254
|
+
line: 'no PowerShell profile line, so other AI tools here are not measured', fix: 'comprism install' });
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
found.push({ ok: false, required: false, line: 'no shell profile line, so other AI tools here are not measured',
|
|
258
|
+
fix: 'comprism install' });
|
|
259
|
+
}
|
|
260
|
+
const git = version('git', ['--version']);
|
|
261
|
+
found.push(git !== null
|
|
262
|
+
? { ok: true, required: false, line: `git ${git}` }
|
|
263
|
+
: { ok: false, required: false, line: 'git not found: reading, branching and committing a project will not work',
|
|
264
|
+
fix: howToInstall(['git']) });
|
|
265
|
+
const rg = version('rg', ['--version']);
|
|
266
|
+
found.push(rg !== null
|
|
267
|
+
? { ok: true, required: false, line: `ripgrep ${rg}` }
|
|
268
|
+
: { ok: false, required: false, line: 'ripgrep not found: searches will be slower',
|
|
269
|
+
fix: howToInstall(['ripgrep']) });
|
|
270
|
+
const pdf = exports.REQUIREMENTS[1];
|
|
271
|
+
found.push(pdf.anyOf.some(present)
|
|
272
|
+
? { ok: true, required: false, line: 'a PDF reader' }
|
|
273
|
+
: { ok: false, required: false, line: `no PDF reader: ${pdf.without} will not work`,
|
|
274
|
+
fix: howToInstall(['pdftotext']) });
|
|
275
|
+
return found;
|
|
276
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** True when running as the ready to run program rather than under Node. */
|
|
2
|
+
export declare function isStandalone(): boolean;
|
|
3
|
+
/** Where the install script keeps the program: `~/.comprism/bin`. */
|
|
4
|
+
export declare function standaloneBinDir(): string;
|
|
5
|
+
export type InstallMethod = "script" | "npm" | "python";
|
|
6
|
+
/**
|
|
7
|
+
* Which of the three install options put this copy here.
|
|
8
|
+
*
|
|
9
|
+
* The program is only ever distributed two ways, so where it sits decides it:
|
|
10
|
+
* in `~/.comprism/bin` it came from the install script, anywhere else pip put
|
|
11
|
+
* it. Under Node it came from npm.
|
|
12
|
+
*/
|
|
13
|
+
export declare function installMethod(): InstallMethod;
|
|
14
|
+
/** The command and arguments that start another copy of this tool. */
|
|
15
|
+
export declare function selfLaunch(args: string[], nodeFlags?: string[]): [string, string[]];
|
|
16
|
+
/**
|
|
17
|
+
* A file shipped beside the code, as a path on disk.
|
|
18
|
+
*
|
|
19
|
+
* Under npm it sits in the package. Inside the program it is carried as an
|
|
20
|
+
* asset and written once to `~/.comprism/assets`, because the programs it is
|
|
21
|
+
* handed to (Python, for the reader script) need a real file.
|
|
22
|
+
*/
|
|
23
|
+
export declare function shippedFile(name: string, packagePath: string): string;
|
package/out/lib/self.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.isStandalone = isStandalone;
|
|
37
|
+
exports.standaloneBinDir = standaloneBinDir;
|
|
38
|
+
exports.installMethod = installMethod;
|
|
39
|
+
exports.selfLaunch = selfLaunch;
|
|
40
|
+
exports.shippedFile = shippedFile;
|
|
41
|
+
/**
|
|
42
|
+
* How this copy of the tool was installed, and how it starts another copy of
|
|
43
|
+
* itself (manual 1.1).
|
|
44
|
+
*
|
|
45
|
+
* The same code ships two ways. Through npm it is a script that Node runs, so
|
|
46
|
+
* `process.argv[1]` is the script and a second copy is `node <script> <args>`.
|
|
47
|
+
* Through the install script and the Python package it is one ready to run
|
|
48
|
+
* program with Node built in, where `process.argv[1]` is the program again and
|
|
49
|
+
* a second copy is just `<program> <args>`. Passing the program's own path as
|
|
50
|
+
* the first argument there would read as a command called "/Users/me/...", so
|
|
51
|
+
* every place that starts a copy of the tool asks here instead of guessing.
|
|
52
|
+
*/
|
|
53
|
+
const fs = __importStar(require("fs"));
|
|
54
|
+
const path = __importStar(require("path"));
|
|
55
|
+
const config_1 = require("./config");
|
|
56
|
+
let sea;
|
|
57
|
+
/** True when running as the ready to run program rather than under Node. */
|
|
58
|
+
function isStandalone() {
|
|
59
|
+
if (sea === undefined) {
|
|
60
|
+
try {
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
62
|
+
sea = Boolean(require("node:sea").isSea());
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
sea = false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return sea;
|
|
69
|
+
}
|
|
70
|
+
/** Where the install script keeps the program: `~/.comprism/bin`. */
|
|
71
|
+
function standaloneBinDir() {
|
|
72
|
+
return path.join((0, config_1.homeDir)(), "bin");
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Which of the three install options put this copy here.
|
|
76
|
+
*
|
|
77
|
+
* The program is only ever distributed two ways, so where it sits decides it:
|
|
78
|
+
* in `~/.comprism/bin` it came from the install script, anywhere else pip put
|
|
79
|
+
* it. Under Node it came from npm.
|
|
80
|
+
*/
|
|
81
|
+
function installMethod() {
|
|
82
|
+
if (!isStandalone())
|
|
83
|
+
return "npm";
|
|
84
|
+
try {
|
|
85
|
+
const here = fs.realpathSync(process.execPath);
|
|
86
|
+
const bin = fs.realpathSync(standaloneBinDir());
|
|
87
|
+
if (path.dirname(here) === bin)
|
|
88
|
+
return "script";
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// No `~/.comprism/bin`: not an install script install.
|
|
92
|
+
}
|
|
93
|
+
return "python";
|
|
94
|
+
}
|
|
95
|
+
/** The command and arguments that start another copy of this tool. */
|
|
96
|
+
function selfLaunch(args, nodeFlags = []) {
|
|
97
|
+
if (isStandalone())
|
|
98
|
+
return [process.execPath, args];
|
|
99
|
+
return [process.execPath, [...nodeFlags, process.argv[1] ?? "", ...args]];
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* A file shipped beside the code, as a path on disk.
|
|
103
|
+
*
|
|
104
|
+
* Under npm it sits in the package. Inside the program it is carried as an
|
|
105
|
+
* asset and written once to `~/.comprism/assets`, because the programs it is
|
|
106
|
+
* handed to (Python, for the reader script) need a real file.
|
|
107
|
+
*/
|
|
108
|
+
function shippedFile(name, packagePath) {
|
|
109
|
+
if (!isStandalone())
|
|
110
|
+
return packagePath;
|
|
111
|
+
const target = path.join((0, config_1.homeDir)(), "assets", name);
|
|
112
|
+
try {
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
114
|
+
const text = require("node:sea").getAsset(name, "utf8");
|
|
115
|
+
if (!fs.existsSync(target) || fs.readFileSync(target, "utf8") !== text) {
|
|
116
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
117
|
+
fs.writeFileSync(target, text);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// An asset that cannot be written leaves the caller's own fallback in charge.
|
|
122
|
+
}
|
|
123
|
+
return target;
|
|
124
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { GatewayReply } from './gateway';
|
|
2
|
+
/** Ask the service one sessions question, with where this machine is. */
|
|
3
|
+
export declare function sessions(op: 'list' | 'resume' | 'latest' | 'opened' | 'rename' | 'branch' | 'export' | 'by_pr' | 'remote_on' | 'remote_poll' | 'remote_off' | 'lease' | 'read' | 'steering' | 'steer', extra?: Record<string, unknown>, folder?: string): Promise<GatewayReply>;
|
|
4
|
+
/** Why a sessions question got no answer, in the service's words when it has them. */
|
|
5
|
+
export declare function failure(reply: GatewayReply): string;
|
|
6
|
+
/** The exit number for a sessions question that got no answer (Appendix B). */
|
|
7
|
+
export declare function exitFor(reply: GatewayReply): number;
|
|
8
|
+
/**
|
|
9
|
+
* Choose one line with the arrow keys; Enter picks, Esc or Ctrl+C leaves.
|
|
10
|
+
* Resolves with the index chosen, or null. Without a terminal it asks for a
|
|
11
|
+
* number instead, so a script is never left waiting on keys it cannot send.
|
|
12
|
+
*/
|
|
13
|
+
export declare function pick(lines: string[]): Promise<number | null>;
|
|
14
|
+
/**
|
|
15
|
+
* `comprism sessions` and its words (manual 8.5 to 8.7, 8.10). Every answer,
|
|
16
|
+
* every line and every refusal is the service's; the export is written to
|
|
17
|
+
* standard output exactly as it came, so `> session.md` holds the file.
|
|
18
|
+
*/
|
|
19
|
+
export declare function cmdSessions(args: string[]): Promise<number>;
|