@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.
Files changed (142) hide show
  1. package/README.md +61 -2
  2. package/out/agent/command.d.ts +75 -4
  3. package/out/agent/command.js +221 -26
  4. package/out/agent/render.d.ts +56 -8
  5. package/out/agent/render.js +441 -39
  6. package/out/agent/session.d.ts +156 -2
  7. package/out/agent/session.js +795 -154
  8. package/out/commands/agents.d.ts +2 -0
  9. package/out/commands/agents.js +79 -0
  10. package/out/commands/ask.d.ts +1 -1
  11. package/out/commands/ask.js +88 -12
  12. package/out/commands/commands-thin.js +79 -17
  13. package/out/commands/config.d.ts +1 -0
  14. package/out/commands/config.js +138 -0
  15. package/out/commands/cost.d.ts +1 -0
  16. package/out/commands/cost.js +167 -0
  17. package/out/commands/hooks.d.ts +1 -0
  18. package/out/commands/hooks.js +83 -0
  19. package/out/commands/install.d.ts +44 -1
  20. package/out/commands/install.js +198 -4
  21. package/out/commands/instructions.d.ts +1 -0
  22. package/out/commands/instructions.js +113 -0
  23. package/out/commands/integrations.d.ts +3 -0
  24. package/out/commands/integrations.js +215 -0
  25. package/out/commands/jobs.d.ts +5 -0
  26. package/out/commands/jobs.js +157 -0
  27. package/out/commands/login.js +249 -43
  28. package/out/commands/memory.d.ts +3 -0
  29. package/out/commands/memory.js +113 -0
  30. package/out/commands/permissions.d.ts +1 -0
  31. package/out/commands/permissions.js +94 -0
  32. package/out/commands/plugins.d.ts +4 -0
  33. package/out/commands/plugins.js +192 -0
  34. package/out/commands/privacy.d.ts +1 -0
  35. package/out/commands/privacy.js +57 -0
  36. package/out/commands/providerKey.d.ts +32 -0
  37. package/out/commands/providerKey.js +108 -0
  38. package/out/commands/repl.d.ts +12 -1
  39. package/out/commands/repl.js +1649 -122
  40. package/out/commands/report.d.ts +39 -0
  41. package/out/commands/report.js +115 -0
  42. package/out/commands/review.d.ts +5 -0
  43. package/out/commands/review.js +223 -0
  44. package/out/commands/sessions.d.ts +23 -0
  45. package/out/commands/sessions.js +115 -0
  46. package/out/commands/settings.d.ts +3 -1
  47. package/out/commands/settings.js +18 -16
  48. package/out/commands/skills.d.ts +21 -0
  49. package/out/commands/skills.js +207 -0
  50. package/out/commands/unattended.d.ts +7 -0
  51. package/out/commands/unattended.js +351 -0
  52. package/out/commands/update.d.ts +1 -0
  53. package/out/commands/update.js +123 -0
  54. package/out/commands/welcome.d.ts +25 -1
  55. package/out/commands/welcome.js +71 -35
  56. package/out/commands/worktrees.d.ts +5 -0
  57. package/out/commands/worktrees.js +186 -0
  58. package/out/executor/browser.d.ts +14 -0
  59. package/out/executor/browser.js +270 -0
  60. package/out/executor/diagnostics.d.ts +2 -0
  61. package/out/executor/diagnostics.js +181 -0
  62. package/out/executor/files.js +270 -40
  63. package/out/executor/git.js +42 -29
  64. package/out/executor/hooks.d.ts +42 -58
  65. package/out/executor/hooks.js +89 -182
  66. package/out/executor/index.d.ts +21 -5
  67. package/out/executor/index.js +160 -14
  68. package/out/executor/paths.d.ts +6 -1
  69. package/out/executor/paths.js +34 -6
  70. package/out/executor/sandbox.d.ts +40 -0
  71. package/out/executor/sandbox.js +299 -0
  72. package/out/executor/shell.d.ts +49 -4
  73. package/out/executor/shell.js +302 -56
  74. package/out/executor/toolservers.d.ts +20 -0
  75. package/out/executor/toolservers.js +189 -0
  76. package/out/executor/worktree.d.ts +9 -0
  77. package/out/executor/worktree.js +119 -0
  78. package/out/graph/read-python.js +2 -1
  79. package/out/lib/attach.d.ts +56 -12
  80. package/out/lib/attach.js +230 -63
  81. package/out/lib/clipboard.d.ts +23 -0
  82. package/out/lib/clipboard.js +182 -0
  83. package/out/lib/commandlist.d.ts +20 -0
  84. package/out/lib/commandlist.js +58 -0
  85. package/out/lib/decision.d.ts +22 -0
  86. package/out/lib/decision.js +50 -0
  87. package/out/lib/fingerprint.d.ts +25 -0
  88. package/out/lib/fingerprint.js +58 -0
  89. package/out/lib/gateway.d.ts +190 -2
  90. package/out/lib/gateway.js +59 -4
  91. package/out/lib/history.d.ts +24 -0
  92. package/out/lib/history.js +137 -0
  93. package/out/lib/ide.d.ts +19 -0
  94. package/out/lib/ide.js +131 -0
  95. package/out/lib/keyboard.d.ts +98 -0
  96. package/out/lib/keyboard.js +390 -0
  97. package/out/lib/lastlogin.d.ts +14 -0
  98. package/out/lib/lastlogin.js +105 -0
  99. package/out/lib/machine.d.ts +21 -0
  100. package/out/lib/machine.js +91 -0
  101. package/out/lib/notify.d.ts +4 -0
  102. package/out/lib/notify.js +52 -0
  103. package/out/lib/output.d.ts +48 -0
  104. package/out/lib/output.js +108 -0
  105. package/out/lib/picker.d.ts +1 -0
  106. package/out/lib/picker.js +158 -0
  107. package/out/lib/project-ops.d.ts +19 -0
  108. package/out/lib/project-ops.js +146 -0
  109. package/out/lib/project.d.ts +28 -0
  110. package/out/lib/project.js +114 -0
  111. package/out/lib/prompt.d.ts +3 -0
  112. package/out/lib/prompt.js +36 -2
  113. package/out/lib/queue.d.ts +13 -0
  114. package/out/lib/queue.js +116 -0
  115. package/out/lib/readiness.d.ts +19 -0
  116. package/out/lib/readiness.js +170 -1
  117. package/out/lib/self.d.ts +23 -0
  118. package/out/lib/self.js +124 -0
  119. package/out/lib/sessions.d.ts +19 -0
  120. package/out/lib/sessions.js +221 -0
  121. package/out/lib/startcache.d.ts +13 -0
  122. package/out/lib/startcache.js +78 -0
  123. package/out/lib/stdin.d.ts +32 -0
  124. package/out/lib/stdin.js +117 -0
  125. package/out/lib/store.d.ts +40 -0
  126. package/out/lib/store.js +138 -0
  127. package/out/lib/sync.d.ts +18 -0
  128. package/out/lib/sync.js +81 -0
  129. package/out/lib/ui.d.ts +10 -4
  130. package/out/lib/ui.js +65 -25
  131. package/out/lib/voice.d.ts +36 -0
  132. package/out/lib/voice.js +160 -1
  133. package/out/native/dictate +0 -0
  134. package/out/postinstall.js +42 -17
  135. package/out/providers/anthropic.d.ts +22 -0
  136. package/out/providers/anthropic.js +80 -0
  137. package/out/providers/index.d.ts +8 -0
  138. package/out/providers/index.js +83 -0
  139. package/out/providers/openai.d.ts +11 -0
  140. package/out/providers/openai.js +57 -0
  141. package/out/thin.js +595 -33
  142. 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
- open().question(prompt, (answer) => resolve(answer.trim()));
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.trim());
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
+ };
@@ -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
+ }
@@ -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[]>;
@@ -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
- (0, node_child_process_1.execFileSync)('/usr/bin/env', ['which', program], { stdio: 'ignore' });
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;
@@ -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>;