@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
@@ -0,0 +1,2 @@
1
+ export declare function helperLines(folder: string): Promise<string[]>;
2
+ export declare function cmdAgents(args: string[]): Promise<number>;
@@ -0,0 +1,79 @@
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.helperLines = helperLines;
37
+ exports.cmdAgents = cmdAgents;
38
+ /**
39
+ * `comprism agents` (manual 5.24): the helpers available in this project and
40
+ * where each came from. The service decides what counts as a helper, which one
41
+ * wins a clash and what each line says; this reads the files it names, inside
42
+ * the project and through the executor's own checks, and prints its lines.
43
+ */
44
+ const files_1 = require("../executor/files");
45
+ const project_1 = require("../lib/project");
46
+ const gateway_1 = require("../lib/gateway");
47
+ const ui = __importStar(require("../lib/ui"));
48
+ const ROUNDS = 6;
49
+ async function helperLines(folder) {
50
+ const root = (0, project_1.resolveProject)(folder).root;
51
+ const files = {};
52
+ const listings = {};
53
+ for (let round = 0; round < ROUNDS; round += 1) {
54
+ const reply = await (0, gateway_1.ask)({ intent: "agents", prompt: "", agentsPayload: { round, files, listings, project: root } });
55
+ const body = reply.agents;
56
+ if (!reply.ok || reply.served === false || !body) {
57
+ return [ui.fail(reply.message || "The helper list could not be read from your workspace.")];
58
+ }
59
+ if (!body.wants)
60
+ return body.lines;
61
+ for (const p of body.wants.read ?? []) {
62
+ const r = (0, files_1.performFileAction)(root, "read_file", { path: p });
63
+ files[p] = r.isError ? null : r.content.slice(0, 8000);
64
+ }
65
+ for (const f of body.wants.list ?? []) {
66
+ const r = (0, files_1.performFileAction)(root, "list_dir", { path: f });
67
+ listings[f] = r.isError ? null : (r.content === "(empty)" ? [] : r.content.split("\n").filter(Boolean));
68
+ }
69
+ }
70
+ return [ui.fail("The helper list could not be completed.")];
71
+ }
72
+ async function cmdAgents(args) {
73
+ const at = args.indexOf("--cwd");
74
+ const folder = at >= 0 && args[at + 1] ? String(args[at + 1]) : process.cwd();
75
+ const lines = await helperLines(folder);
76
+ for (const line of lines)
77
+ process.stdout.write(` ${line}\n`);
78
+ return lines.length === 1 && /could not/.test(lines[0] ?? "") ? 1 : 0;
79
+ }
@@ -1 +1 @@
1
- export declare function cmdAsk(args: string[]): Promise<void>;
1
+ export declare function cmdAsk(args: string[]): Promise<number>;
@@ -50,9 +50,38 @@ const gateway_1 = require("../lib/gateway");
50
50
  const connection_1 = require("../lib/connection");
51
51
  const config_1 = require("../lib/config");
52
52
  const ui = __importStar(require("../lib/ui"));
53
+ const render_1 = require("../agent/render");
53
54
  const prompt_1 = require("../lib/prompt");
54
- const out = (s = '') => process.stdout.write(s + '\n');
55
+ const output_1 = require("../lib/output");
56
+ const stdout = (s = '') => process.stdout.write(s + '\n');
57
+ const stderr = (s = '') => process.stderr.write(s + '\n');
55
58
  async function cmdAsk(args) {
59
+ // A typing mistake is refused before anything is sent (manual 10.6, exit 2).
60
+ const output = (0, output_1.outputChoice)(args);
61
+ const typo = (why) => {
62
+ stderr(ui.fail(why) + ui.c.dim(' Nothing ran and nothing was charged.'));
63
+ return 2;
64
+ };
65
+ if ('bad' in output)
66
+ return typo(output.bad);
67
+ if (output.format === 'stream')
68
+ return typo('--output stream is for comprism work; ask gives one answer, so use --output json.');
69
+ const stray = (0, output_1.unknownFlag)(args, ['--model', '--output'], ['--quiet']);
70
+ if (stray)
71
+ return typo(`${stray} is not an option of comprism ask.`);
72
+ const json = output.format === 'json';
73
+ // With standard output going to a script, only the answer goes there and
74
+ // everything else goes to standard error (manual 10.2). `--quiet` drops the
75
+ // rest altogether.
76
+ const toErr = (0, output_1.progressToErr)(output);
77
+ const out = output.quiet ? (_s = '') => undefined : toErr ? stderr : stdout;
78
+ const ended = (reason, why, table) => {
79
+ if (json)
80
+ (0, output_1.printJson)((0, output_1.localResult)(reason, why));
81
+ else if (output.quiet || toErr)
82
+ stderr(` ${why}`);
83
+ return (0, output_1.exitFor)(reason, table);
84
+ };
56
85
  // What they are being compared against, said BEFORE they type. A saving means
57
86
  // nothing without knowing what it is a saving against, and asking a person to
58
87
  // remember what they set last week is asking them to take the figure on
@@ -66,12 +95,20 @@ async function cmdAsk(args) {
66
95
  out();
67
96
  // Either way round: on the line for somebody who knows what they want, or
68
97
  // asked for when they simply typed the command.
69
- const prompt = await (0, prompt_1.subject)(args, ' prompt: ', ['--model']);
98
+ // Text piped in is read to its end first and attached as `standard input`:
99
+ // material to read, never the question (manual 3.9).
100
+ const { readPiped, attachPiped } = await Promise.resolve().then(() => __importStar(require('../lib/stdin')));
101
+ const piped = await readPiped();
102
+ const prompt = await (0, prompt_1.subject)(args, ' prompt: ', ['--model', '--output']);
103
+ if (!prompt && piped?.trim()) {
104
+ (0, prompt_1.closePrompt)();
105
+ return typo('Piped text needs a question with it, for example: '
106
+ + 'python3 -m pytest -q 2>&1 | comprism ask "why is this failing"');
107
+ }
70
108
  if (!prompt) {
71
- out(ui.fail('Nothing was asked.'));
72
- out();
73
109
  (0, prompt_1.closePrompt)();
74
- return;
110
+ // Standard input closed with nothing on it is a missing question.
111
+ return typo('Nothing was asked.');
75
112
  }
76
113
  const conn = (0, connection_1.readConnection)();
77
114
  (0, prompt_1.closePrompt)();
@@ -79,8 +116,7 @@ async function cmdAsk(args) {
79
116
  out(ui.fail('This machine is not signed in.'));
80
117
  out(` ${ui.c.dim('$')} comprism login`);
81
118
  out();
82
- process.exitCode = 1;
83
- return;
119
+ return ended('signed_out', 'This machine is not signed in. Run comprism login.');
84
120
  }
85
121
  // NO KEY IS READ FROM THIS MACHINE.
86
122
  //
@@ -97,24 +133,63 @@ async function cmdAsk(args) {
97
133
  // The same value shown above. Resolved once, so the line a person read and
98
134
  // the figure they are given can never be about different models.
99
135
  const callingModel = comparedTo;
136
+ let attachments = [];
137
+ if (piped?.trim()) {
138
+ const attach = await Promise.resolve().then(() => __importStar(require('../lib/attach')));
139
+ const { attached, refused } = await attachPiped(piped, conn.url, conn.workspaceKey);
140
+ for (const line of attach.describe(attached))
141
+ out(ui.c.dim(` ${line}`));
142
+ for (const r of refused)
143
+ stderr(ui.c.amber(` ${r.why}`));
144
+ if (refused.length > 0)
145
+ return ended('incomplete', 'The piped text could not be attached, so nothing was sent.');
146
+ attachments = attached.map((a) => a.id);
147
+ }
100
148
  const live = new ui.LiveIndicator();
101
- live.start('choosing the model that finishes this for least');
149
+ if (!toErr)
150
+ live.start('choosing the model that finishes this for least');
102
151
  const reply = await (0, gateway_1.ask)({
103
152
  intent: 'answer',
104
153
  prompt,
105
154
  callingModel,
155
+ attachments,
106
156
  });
107
157
  live.stop();
158
+ if (!reply.ok) {
159
+ // Never answered: no connection is 6, a refused sign in is 3 (Appendix B).
160
+ const why = reply.message || 'the service could not be reached';
161
+ out(ui.fail(why));
162
+ out();
163
+ return ended(reply.httpStatus === 401 ? 'signed_out' : reply.httpStatus ? 'incomplete' : 'unreachable', why, reply.exit_status);
164
+ }
165
+ if (json && reply.result) {
166
+ // The object the service built, printed as it came (manual 10.3).
167
+ (0, output_1.printJson)(reply.result);
168
+ return (0, output_1.exitFor)(String(reply.result.status ?? 'incomplete'), reply.exit_status);
169
+ }
108
170
  if (!reply.answer) {
109
171
  out(ui.fail(reply.decision.rationale || 'no answer came back'));
110
172
  out();
111
- process.exitCode = 1;
112
- return;
173
+ return ended('incomplete', reply.decision.rationale || 'no answer came back', reply.exit_status);
174
+ }
175
+ if (json) {
176
+ // An older service sent no result object: the answer in the same shape.
177
+ (0, output_1.printJson)({ ...(0, output_1.localResult)('done', ''), error: null, exit: 0, result: reply.answer });
178
+ return 0;
113
179
  }
114
180
  out();
115
- out(reply.answer.trim());
181
+ // The answer itself always reaches standard output (manual 10.2). On a
182
+ // screen it is laid out for reading (manual 6.17); piped, it stays exactly
183
+ // as the model wrote it, for the program reading it.
184
+ const answer = reply.answer.trim();
185
+ stdout(process.stdout.isTTY ? (0, render_1.plain)(answer) : answer);
116
186
  out();
117
- if (reply.receipt) {
187
+ if (reply.card) {
188
+ // The server's card, drawn as the approved look draws it.
189
+ out((0, render_1.receipt)(reply.receipt ?? '', [], undefined, reply.card).trimEnd());
190
+ out();
191
+ }
192
+ else if (reply.receipt) {
118
193
  out(ui.c.dim(' ' + reply.receipt.split('\n').join('\n ')));
119
194
  out();
120
195
  }
@@ -143,4 +218,5 @@ async function cmdAsk(args) {
143
218
  out(` ${ui.c.bold(reply.details_url)}`);
144
219
  }
145
220
  out();
221
+ return 0;
146
222
  }
@@ -38,10 +38,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.cmdDisconnect = cmdDisconnect;
40
40
  exports.cmdStatus = cmdStatus;
41
+ /**
42
+ * The commands the PUBLISHED tool has, written so none of them can reach the
43
+ * decision, the price list or the study.
44
+ *
45
+ * The full internal tool has richer versions of some of these in `cli.ts`. They
46
+ * are deliberately not shared: sharing them is how a module that must never
47
+ * ship ends up imported by one that does, which is the exact accident this
48
+ * whole split exists to make impossible.
49
+ */
50
+ const node_child_process_1 = require("node:child_process");
51
+ const node_os_1 = __importDefault(require("node:os"));
41
52
  const node_readline_1 = __importDefault(require("node:readline"));
42
53
  const connection_1 = require("../lib/connection");
43
54
  const gateway_1 = require("../lib/gateway");
44
55
  const ui = __importStar(require("../lib/ui"));
56
+ const settings_1 = require("./settings");
45
57
  const out = (s = '') => process.stdout.write(s + '\n');
46
58
  function argValue(args, flag) {
47
59
  const i = args.indexOf(flag);
@@ -109,6 +121,8 @@ async function cmdDisconnect() {
109
121
  }
110
122
  const reply = await (0, gateway_1.ask)({ intent: 'sign_out', prompt: '' });
111
123
  const removed = (0, connection_1.clearConnection)();
124
+ // A new terminal must stop presenting the key that was just given up.
125
+ (await Promise.resolve().then(() => __importStar(require('./install')))).refreshEnvScript();
112
126
  if (reply.signed_out) {
113
127
  out(ui.ok(reply.message || 'Signed out. This machine\'s key is revoked.'));
114
128
  out(` ${ui.c.dim('sign back in with')} ${ui.c.bold('comprism login')}`);
@@ -119,7 +133,7 @@ async function cmdDisconnect() {
119
133
  // they would have acted on.
120
134
  out(ui.warn('Removed from this machine, but the key could not be revoked.'));
121
135
  out(` ${ui.c.dim(reply.message
122
- || 'the service could not be reached, so revoke this machine in the portal')}`);
136
+ || 'The service could not be reached. Revoke this machine from Administration in the web portal.')}`);
123
137
  }
124
138
  else {
125
139
  out(ui.info('This machine was not signed in.'));
@@ -146,7 +160,10 @@ async function cmdStatus() {
146
160
  const c = (0, connection_1.readConnection)();
147
161
  out(ui.banner('Status'));
148
162
  out();
149
- if (!c?.url) {
163
+ // Exit numbers are Appendix B of the manual: 3 not signed in, revoked or
164
+ // expired; 6 service unreachable; 1 anything else that stopped the answer.
165
+ if (!c?.url || !c.workspaceKey) {
166
+ process.exitCode = 3;
150
167
  out(ui.warn('Not signed in.'));
151
168
  out(` ${ui.c.dim('$')} comprism login`);
152
169
  out();
@@ -155,28 +172,73 @@ async function cmdStatus() {
155
172
  const reply = await (0, gateway_1.ask)({ intent: 'session', prompt: '' });
156
173
  const me = reply.ok && reply.served !== false ? reply.session : null;
157
174
  if (!reply.ok) {
158
- out(ui.fail(`This machine is pointed at ${ui.c.bold(c.url)}, which did not answer.`));
159
- out(` ${ui.c.dim(reply.message || 'no answer from the workspace')}`);
160
- out(` ${ui.c.dim('sign in again with')} ${ui.c.bold('comprism login')}`);
175
+ if (reply.httpStatus === 401) {
176
+ out(ui.fail("Signed out: this machine's key was revoked or has expired."));
177
+ out(` ${ui.c.dim('sign in again with')} ${ui.c.bold('comprism login')}`);
178
+ process.exitCode = 3;
179
+ }
180
+ else if (reply.httpStatus) {
181
+ out(ui.fail('The workspace could not confirm this account.'));
182
+ out(` ${ui.c.dim(reply.message || 'the service refused the request')}`);
183
+ process.exitCode = 1;
184
+ }
185
+ else {
186
+ // Only what this machine knows, and said to be only that (manual 1.4).
187
+ out(ui.fail(`This machine is pointed at ${ui.c.bold(c.url)}, which did not answer.`));
188
+ out(` ${ui.c.dim(reply.message || 'no answer from the workspace')}`);
189
+ out(` ${ui.c.dim('on this machine only:')} ${machineLine(c)}`);
190
+ process.exitCode = 6;
191
+ }
161
192
  out();
162
- process.exitCode = 1;
163
193
  return;
164
194
  }
165
- if (!me) {
166
- // It answered, but this build does not carry the question. Say that, rather
167
- // than pretending to know or pretending not to have heard.
195
+ if (reply.served === false) {
168
196
  out(ui.warn(`${ui.c.bold(c.url)} answered, but is running a build that cannot report a session.`));
169
- out(` ${ui.c.dim(reply.message || 'the workspace is behind this copy of the tool')}`);
170
- out();
197
+ out(ui.c.dim(reply.message || 'Ask your workspace administrator to update the service.'));
198
+ process.exitCode = 1;
171
199
  return;
172
200
  }
173
- out(ui.ok(`Signed in to ${ui.c.bold(me.workspace_url || c.url)}`));
174
- out(` ${ui.c.dim('as')} ${me.user_email}${ui.c.dim(' at ')}${me.company}`);
175
- out(` ${ui.c.dim(me.machine ? `this machine is enrolled as "${me.machine}"` : 'this machine is enrolled')}`);
176
- out(` ${ui.c.dim(me.vendors_known === false
177
- ? 'your vendor keys could not be checked, so that is unknown rather than none'
178
- : `${me.vendors_with_key} vendor key${me.vendors_with_key === 1 ? '' : 's'} stored on your account`)}`);
201
+ if (reply.granted === false || !me?.signed_in) {
202
+ out(ui.fail(reply.message || 'The workspace did not confirm a signed in account.'));
203
+ out(' Run comprism login to sign in.');
204
+ process.exitCode = 3;
205
+ return;
206
+ }
207
+ const providers = me.vendors_known === false
208
+ ? 'could not be checked, so unknown rather than none'
209
+ : me.vendor_names?.length
210
+ ? `${me.vendor_names.join(', ')} (keys on your account)`
211
+ : me.vendors_with_key ? `${me.vendors_with_key} (keys on your account)` : 'none yet: comprism keys';
212
+ const project = currentProject();
213
+ out(` ${ui.c.bold(me.user_email)} at ${ui.c.bold(me.company)}`);
214
+ out(` ${ui.c.dim('workspace ')} ${me.workspace_url || c.url}`);
215
+ out(` ${ui.c.dim('machine ')} ${machineLine(c, me.machine)}`);
216
+ out(` ${ui.c.dim('providers ')} ${providers}`);
217
+ if (me.comparing)
218
+ out(` ${ui.c.dim('baseline ')} ${me.comparing}`);
219
+ out(` ${ui.c.dim('project ')} ${project}`);
179
220
  out();
180
221
  out(ui.c.dim(' Every figure you see is computed on our servers, never here.'));
181
222
  out();
182
223
  }
224
+ /** Enrollment date and the last four characters of the key: enough to match
225
+ * the machine against Administration, never enough to use it. */
226
+ function machineLine(c, label) {
227
+ const when = c.connectedAt ? new Date(c.connectedAt) : null;
228
+ const date = when && !Number.isNaN(when.getTime())
229
+ ? when.toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' }) : '';
230
+ const key = c.workspaceKey ? `key ending ${c.workspaceKey.slice(-4)}` : 'no key';
231
+ return [label ? `"${label}"` : '', date ? `enrolled ${date}` : 'enrolled', key].filter(Boolean).join(', ');
232
+ }
233
+ /** The project folder, with its Git branch when it is a repository. */
234
+ function currentProject() {
235
+ const folder = (0, settings_1.currentWorkspace)().path;
236
+ const shown = folder.startsWith(node_os_1.default.homedir()) ? `~${folder.slice(node_os_1.default.homedir().length)}` : folder;
237
+ try {
238
+ const branch = (0, node_child_process_1.execFileSync)('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: folder, stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
239
+ return branch ? `${shown} (${branch})` : shown;
240
+ }
241
+ catch {
242
+ return shown;
243
+ }
244
+ }
@@ -0,0 +1 @@
1
+ export declare function cmdConfig(args: string[]): Promise<number>;
@@ -0,0 +1,138 @@
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.cmdConfig = cmdConfig;
37
+ /**
38
+ * `comprism config`: the settings for this machine (manual 2.10, 6.5, 6.10 to
39
+ * 6.12).
40
+ *
41
+ * The machine's own settings live here: theme, keys, notify, plain, history
42
+ * and editor. Settings that change what the agent does, such as the permission
43
+ * mode, are resolved by the service from the company, the command, the local
44
+ * and project settings files and the person's account (manual 2.10); this
45
+ * command sends the files and prints the service's answer.
46
+ */
47
+ const ui = __importStar(require("../lib/ui"));
48
+ const machine_1 = require("../lib/machine");
49
+ const project_ops_1 = require("../lib/project-ops");
50
+ /** The settings files the service reads, as the manual names them. */
51
+ const SETTINGS_FILES = ['.completionprism/settings.local.json', '.completionprism/settings.json'];
52
+ /** `--config <file>` and `--no-personal`: show what a job run with them uses
53
+ * (manual 10.8). Set by `cmdConfig`, sent as read. */
54
+ let automation = {};
55
+ async function service(op, payload) {
56
+ const facts = await (0, project_ops_1.currentProject)();
57
+ const reply = await (0, project_ops_1.call)('config', op, {
58
+ ...payload, ...automation, files: (0, project_ops_1.readSome)(facts.root, SETTINGS_FILES),
59
+ }, facts);
60
+ if (!reply)
61
+ return 1;
62
+ const write = reply.data?.write;
63
+ if (write)
64
+ (0, project_ops_1.writeSetting)(facts.root, write.file, write.key, write.value);
65
+ return 0;
66
+ }
67
+ const out = (s = '') => process.stdout.write(s + '\n');
68
+ function notHere(key) {
69
+ out(ui.fail(`\`${key}\` is not a setting for this machine, so nothing was changed.`));
70
+ out(ui.c.dim(` This machine keeps: ${Object.keys(machine_1.MACHINE_KEYS).join(', ')}. Project and personal settings are kept by the service (manual 2.10).`));
71
+ out();
72
+ return 1;
73
+ }
74
+ async function cmdConfig(args) {
75
+ const configAt = args.indexOf('--config');
76
+ if (configAt !== -1) {
77
+ const { readJsonFile } = await Promise.resolve().then(() => __importStar(require('../lib/output')));
78
+ const got = readJsonFile(String(args[configAt + 1] ?? ''), '--config');
79
+ if ('bad' in got) {
80
+ process.stderr.write(ui.fail(got.bad) + '\n');
81
+ return 2;
82
+ }
83
+ automation.settings_config = got.value;
84
+ args = args.filter((_, i) => i !== configAt && i !== configAt + 1);
85
+ }
86
+ if (args.includes('--no-personal')) {
87
+ automation.no_personal = true;
88
+ args = args.filter((a) => a !== '--no-personal');
89
+ }
90
+ const scopeAt = args.indexOf('--scope');
91
+ const scope = scopeAt === -1 ? undefined : args[scopeAt + 1];
92
+ const rest = scopeAt === -1 ? args : args.filter((_, i) => i !== scopeAt && i !== scopeAt + 1);
93
+ const [verb, key, ...value] = rest;
94
+ if (!verb) {
95
+ out();
96
+ const code = await service('list', {});
97
+ const now = (0, machine_1.machineSettings)();
98
+ for (const [k, spec] of Object.entries(machine_1.MACHINE_KEYS)) {
99
+ const shown = now[k] || '(not set)';
100
+ out(` ${k.padEnd(9)} ${ui.c.bold(shown.padEnd(10))} ${ui.c.dim((0, machine_1.isSet)(k) ? 'this machine' : 'default')} ${ui.c.dim(spec.what)}`);
101
+ }
102
+ out();
103
+ return code;
104
+ }
105
+ if (!key) {
106
+ out(ui.fail(`Say which setting: comprism config ${verb} <name>`));
107
+ return 1;
108
+ }
109
+ if (!machine_1.MACHINE_KEYS[key]) {
110
+ if (!['get', 'set', 'unset'].includes(verb)) {
111
+ out(ui.fail(`\`config ${verb}\` is not a command. Use get, set or unset.`));
112
+ return 2;
113
+ }
114
+ return service(verb, { key, value: value.join(' ').trim(), scope: scope ?? 'local' });
115
+ }
116
+ if (scope && scope !== 'machine' && scope !== 'local')
117
+ return notHere(`--scope ${scope}`);
118
+ if (verb === 'get') {
119
+ out((0, machine_1.machineSettings)()[key] ?? '');
120
+ return 0;
121
+ }
122
+ if (verb === 'set') {
123
+ const why = (0, machine_1.setMachine)(key, value.join(' ').trim());
124
+ if (why) {
125
+ out(ui.fail(why));
126
+ return 1;
127
+ }
128
+ out(ui.ok(`${key} is ${(0, machine_1.machineSettings)()[key]} on this machine.`));
129
+ return 0;
130
+ }
131
+ if (verb === 'unset') {
132
+ (0, machine_1.unsetMachine)(key);
133
+ out(ui.ok(`${key} is back to its default, ${machine_1.MACHINE_KEYS[key]?.fallback || 'not set'}.`));
134
+ return 0;
135
+ }
136
+ out(ui.fail(`\`config ${verb}\` is not a command. Use get, set or unset.`));
137
+ return 1;
138
+ }
@@ -0,0 +1 @@
1
+ export declare function cmdCost(args: string[]): Promise<number>;