@illuminis/comprism 0.1.0
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/LICENSE +15 -0
- package/README.md +281 -0
- package/out/agent/command.d.ts +86 -0
- package/out/agent/command.js +259 -0
- package/out/agent/render.d.ts +97 -0
- package/out/agent/render.js +255 -0
- package/out/agent/session.d.ts +175 -0
- package/out/agent/session.js +573 -0
- package/out/commands/ask.d.ts +1 -0
- package/out/commands/ask.js +146 -0
- package/out/commands/codemap.d.ts +2 -0
- package/out/commands/codemap.js +151 -0
- package/out/commands/commands-thin.d.ts +39 -0
- package/out/commands/commands-thin.js +182 -0
- package/out/commands/install.d.ts +163 -0
- package/out/commands/install.js +543 -0
- package/out/commands/keys.d.ts +55 -0
- package/out/commands/keys.js +344 -0
- package/out/commands/login.d.ts +9 -0
- package/out/commands/login.js +384 -0
- package/out/commands/repl.d.ts +1 -0
- package/out/commands/repl.js +752 -0
- package/out/commands/settings.d.ts +21 -0
- package/out/commands/settings.js +244 -0
- package/out/commands/welcome.d.ts +1 -0
- package/out/commands/welcome.js +196 -0
- package/out/executor/documents.d.ts +40 -0
- package/out/executor/documents.js +170 -0
- package/out/executor/files.d.ts +2 -0
- package/out/executor/files.js +360 -0
- package/out/executor/git.d.ts +48 -0
- package/out/executor/git.js +132 -0
- package/out/executor/hooks.d.ts +67 -0
- package/out/executor/hooks.js +247 -0
- package/out/executor/index.d.ts +29 -0
- package/out/executor/index.js +221 -0
- package/out/executor/notebook.d.ts +2 -0
- package/out/executor/notebook.js +147 -0
- package/out/executor/paths.d.ts +15 -0
- package/out/executor/paths.js +126 -0
- package/out/executor/shell.d.ts +41 -0
- package/out/executor/shell.js +336 -0
- package/out/graph/build.d.ts +45 -0
- package/out/graph/build.js +91 -0
- package/out/graph/facts.d.ts +47 -0
- package/out/graph/facts.js +12 -0
- package/out/graph/files.d.ts +45 -0
- package/out/graph/files.js +207 -0
- package/out/graph/read-locales.d.ts +29 -0
- package/out/graph/read-locales.js +246 -0
- package/out/graph/read-python.d.ts +11 -0
- package/out/graph/read-python.js +115 -0
- package/out/graph/read-typescript.d.ts +16 -0
- package/out/graph/read-typescript.js +292 -0
- package/out/graph/sync.d.ts +66 -0
- package/out/graph/sync.js +242 -0
- package/out/lib/attach.d.ts +62 -0
- package/out/lib/attach.js +228 -0
- package/out/lib/config.d.ts +93 -0
- package/out/lib/config.js +198 -0
- package/out/lib/connection.d.ts +73 -0
- package/out/lib/connection.js +188 -0
- package/out/lib/gateway.d.ts +239 -0
- package/out/lib/gateway.js +171 -0
- package/out/lib/prompt.d.ts +34 -0
- package/out/lib/prompt.js +108 -0
- package/out/lib/types.d.ts +417 -0
- package/out/lib/types.js +21 -0
- package/out/lib/ui.d.ts +114 -0
- package/out/lib/ui.js +265 -0
- package/out/lib/version.d.ts +24 -0
- package/out/lib/version.js +27 -0
- package/out/lib/voice.d.ts +50 -0
- package/out/lib/voice.js +218 -0
- package/out/postinstall.d.ts +2 -0
- package/out/postinstall.js +92 -0
- package/out/thin.d.ts +2 -0
- package/out/thin.js +259 -0
- package/package.json +101 -0
- package/scripts/read_python.py +270 -0
|
@@ -0,0 +1,146 @@
|
|
|
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.cmdAsk = cmdAsk;
|
|
37
|
+
/**
|
|
38
|
+
* `comprism ask` — one prompt, one answer, one receipt.
|
|
39
|
+
*
|
|
40
|
+
* The shortest complete demonstration of the product: a person types a
|
|
41
|
+
* question, gets an answer on whichever model finishes it for least, and sees
|
|
42
|
+
* what that cost against what their own model would have cost.
|
|
43
|
+
*
|
|
44
|
+
* NOTHING HERE DECIDES ANYTHING. The prompt goes to our server, the server
|
|
45
|
+
* chooses the model, runs it, prices both paths and returns the receipt already
|
|
46
|
+
* worded. This file formats what came back and prints a link. That is the whole
|
|
47
|
+
* division: a client draws, a server decides.
|
|
48
|
+
*/
|
|
49
|
+
const gateway_1 = require("../lib/gateway");
|
|
50
|
+
const connection_1 = require("../lib/connection");
|
|
51
|
+
const config_1 = require("../lib/config");
|
|
52
|
+
const ui = __importStar(require("../lib/ui"));
|
|
53
|
+
const prompt_1 = require("../lib/prompt");
|
|
54
|
+
const out = (s = '') => process.stdout.write(s + '\n');
|
|
55
|
+
async function cmdAsk(args) {
|
|
56
|
+
// What they are being compared against, said BEFORE they type. A saving means
|
|
57
|
+
// nothing without knowing what it is a saving against, and asking a person to
|
|
58
|
+
// remember what they set last week is asking them to take the figure on
|
|
59
|
+
// trust. Shown every time, so the number that comes back is never a surprise.
|
|
60
|
+
const flagged = args.indexOf('--model');
|
|
61
|
+
const comparedTo = (flagged >= 0 ? args[flagged + 1] : undefined)
|
|
62
|
+
|| (0, config_1.loadConfig)().defaultModel
|
|
63
|
+
|| 'claude-sonnet-5';
|
|
64
|
+
out(ui.c.dim(` comparing against ${ui.c.bold(comparedTo)}`)
|
|
65
|
+
+ ui.c.dim(' change it with `comprism model`'));
|
|
66
|
+
out();
|
|
67
|
+
// Either way round: on the line for somebody who knows what they want, or
|
|
68
|
+
// asked for when they simply typed the command.
|
|
69
|
+
const prompt = await (0, prompt_1.subject)(args, ' prompt: ', ['--model']);
|
|
70
|
+
if (!prompt) {
|
|
71
|
+
out(ui.fail('Nothing was asked.'));
|
|
72
|
+
out();
|
|
73
|
+
(0, prompt_1.closePrompt)();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const conn = (0, connection_1.readConnection)();
|
|
77
|
+
(0, prompt_1.closePrompt)();
|
|
78
|
+
if (!conn?.url || !conn.workspaceKey) {
|
|
79
|
+
out(ui.fail('This machine is not signed in.'));
|
|
80
|
+
out(` ${ui.c.dim('$')} comprism login`);
|
|
81
|
+
out();
|
|
82
|
+
process.exitCode = 1;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
// NO KEY IS READ FROM THIS MACHINE.
|
|
86
|
+
//
|
|
87
|
+
// This used to scan the shell and the settings file for a vendor key and
|
|
88
|
+
// forward it with the question. It looks harmless and it is not: a person
|
|
89
|
+
// whose account holds a key, and who also happens to have one exported in
|
|
90
|
+
// their shell, would have the work billed to the second account without ever
|
|
91
|
+
// being told. Two answers to "whose money is this", and the product's whole
|
|
92
|
+
// claim is a figure on an invoice the customer can check.
|
|
93
|
+
//
|
|
94
|
+
// The account's keys are the only keys. They are stored on the workspace,
|
|
95
|
+
// visible to that person's colleagues, to the portal and to the editor, and
|
|
96
|
+
// revocable in one place. Owner's rule, 17 September 2026.
|
|
97
|
+
// The same value shown above. Resolved once, so the line a person read and
|
|
98
|
+
// the figure they are given can never be about different models.
|
|
99
|
+
const callingModel = comparedTo;
|
|
100
|
+
const live = new ui.LiveIndicator();
|
|
101
|
+
live.start('choosing the model that finishes this for least');
|
|
102
|
+
const reply = await (0, gateway_1.ask)({
|
|
103
|
+
intent: 'answer',
|
|
104
|
+
prompt,
|
|
105
|
+
callingModel,
|
|
106
|
+
});
|
|
107
|
+
live.stop();
|
|
108
|
+
if (!reply.answer) {
|
|
109
|
+
out(ui.fail(reply.decision.rationale || 'no answer came back'));
|
|
110
|
+
out();
|
|
111
|
+
process.exitCode = 1;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
out();
|
|
115
|
+
out(reply.answer.trim());
|
|
116
|
+
out();
|
|
117
|
+
if (reply.receipt) {
|
|
118
|
+
out(ui.c.dim(' ' + reply.receipt.split('\n').join('\n ')));
|
|
119
|
+
out();
|
|
120
|
+
}
|
|
121
|
+
const money = (n) => n === null || n === undefined ? null : `$${n.toFixed(4)}`;
|
|
122
|
+
const ran = reply.ran_on || 'your own model';
|
|
123
|
+
const ours = money(reply.cost_usd);
|
|
124
|
+
const theirs = money(reply.would_have_cost_usd);
|
|
125
|
+
const saved = reply.saved_usd;
|
|
126
|
+
if (ours && theirs) {
|
|
127
|
+
const verb = saved !== null && saved !== undefined && saved < 0 ? 'more' : 'less';
|
|
128
|
+
const amount = money(Math.abs(saved ?? 0));
|
|
129
|
+
out(` ran on ${ui.c.bold(ran)} ${ours} to finish`);
|
|
130
|
+
out(` ${ui.c.dim(`on ${callingModel} it would have been ${theirs}, so ${amount} ${verb}`)}`);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
out(` ran on ${ui.c.bold(ran)}`);
|
|
134
|
+
}
|
|
135
|
+
// Said plainly rather than hidden: a figure that rests on a coarse lookup is
|
|
136
|
+
// still worth showing, and it is never shown as if it were measured.
|
|
137
|
+
if (reply.estimated) {
|
|
138
|
+
out(` ${ui.c.amber('these figures are estimated')}${ui.c.dim(', because this work has no close match in the corpus yet')}`);
|
|
139
|
+
}
|
|
140
|
+
if (reply.details_url) {
|
|
141
|
+
out();
|
|
142
|
+
out(` ${ui.c.dim('the full breakdown, every figure traceable:')}`);
|
|
143
|
+
out(` ${ui.c.bold(reply.details_url)}`);
|
|
144
|
+
}
|
|
145
|
+
out();
|
|
146
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const MAP_HELP = "\n comprism map what the map of this project holds\n comprism map refresh read every file again, now\n comprism map forget remove this project's map from the service\n comprism map off ask your administrator to switch it off\n\n The map is a record of what your project is made of: its functions, screens,\n endpoints and tables, and what connects to what. It is read on this machine\n and only its structure is sent. Your source code never leaves here.\n\n It is kept current by itself. Every job checks the files first and reads back\n whatever moved, so you should not normally need any of this.\n";
|
|
2
|
+
export declare function cmdMap(args: string[]): Promise<number>;
|
|
@@ -0,0 +1,151 @@
|
|
|
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.MAP_HELP = void 0;
|
|
37
|
+
exports.cmdMap = cmdMap;
|
|
38
|
+
/**
|
|
39
|
+
* `comprism map` — look at the map of this project, refresh it, or switch it
|
|
40
|
+
* off for one job.
|
|
41
|
+
*
|
|
42
|
+
* The map is normally kept current on its own: every job checks the files
|
|
43
|
+
* before it starts and reads back whatever moved. This command exists for the
|
|
44
|
+
* two moments that happen anyway. Somebody has just had an answer they did not
|
|
45
|
+
* believe and wants it rebuilt from scratch. And somebody wants to see what the
|
|
46
|
+
* product actually holds about their codebase, which is a fair question to ask
|
|
47
|
+
* of any tool that holds anything.
|
|
48
|
+
*
|
|
49
|
+
* Nothing here decides anything. It reads files, sends structure, and prints
|
|
50
|
+
* what the service says back.
|
|
51
|
+
*/
|
|
52
|
+
const ui = __importStar(require("../lib/ui"));
|
|
53
|
+
const gateway_1 = require("../lib/gateway");
|
|
54
|
+
const sync_1 = require("../graph/sync");
|
|
55
|
+
const settings_1 = require("./settings");
|
|
56
|
+
const out = (s = "") => process.stdout.write(`${s}\n`);
|
|
57
|
+
exports.MAP_HELP = `
|
|
58
|
+
comprism map what the map of this project holds
|
|
59
|
+
comprism map refresh read every file again, now
|
|
60
|
+
comprism map forget remove this project's map from the service
|
|
61
|
+
comprism map off ask your administrator to switch it off
|
|
62
|
+
|
|
63
|
+
The map is a record of what your project is made of: its functions, screens,
|
|
64
|
+
endpoints and tables, and what connects to what. It is read on this machine
|
|
65
|
+
and only its structure is sent. Your source code never leaves here.
|
|
66
|
+
|
|
67
|
+
It is kept current by itself. Every job checks the files first and reads back
|
|
68
|
+
whatever moved, so you should not normally need any of this.
|
|
69
|
+
`;
|
|
70
|
+
/** The project name the service holds the map under: the folder's own name,
|
|
71
|
+
* which is what every other part of the tool sends as the workspace. */
|
|
72
|
+
function projectName(root) {
|
|
73
|
+
return root.split("/").filter(Boolean).pop() || root;
|
|
74
|
+
}
|
|
75
|
+
async function cmdMap(args) {
|
|
76
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
77
|
+
out(exports.MAP_HELP);
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
const root = (0, settings_1.currentWorkspace)().path;
|
|
81
|
+
const workspace = projectName(root);
|
|
82
|
+
const action = (args[0] || "status").toLowerCase();
|
|
83
|
+
if (action === "forget") {
|
|
84
|
+
const gone = await (0, gateway_1.ask)({
|
|
85
|
+
intent: "graph", prompt: "", graphOp: "forget", workspace,
|
|
86
|
+
});
|
|
87
|
+
if (!gone.ok) {
|
|
88
|
+
out(ui.fail("The service could not be reached, so nothing was removed."));
|
|
89
|
+
return 1;
|
|
90
|
+
}
|
|
91
|
+
out(ui.ok(`The map of ${workspace} has been removed. The next job will read it again.`));
|
|
92
|
+
return 0;
|
|
93
|
+
}
|
|
94
|
+
if (action === "off") {
|
|
95
|
+
// Said rather than done. The switch is company-wide and belongs to an
|
|
96
|
+
// administrator, and a machine credential is not the thing that should be
|
|
97
|
+
// able to change a control every colleague is subject to. One job can still
|
|
98
|
+
// go without a map with `comprism work --no-map`.
|
|
99
|
+
out();
|
|
100
|
+
out(" The code map is switched on and off for the whole company, under");
|
|
101
|
+
out(" Administration in the web portal. An administrator can do it there.");
|
|
102
|
+
out();
|
|
103
|
+
out(" To run one job without it: comprism work --no-map \"...\"");
|
|
104
|
+
out();
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
if (action === "refresh" || action === "rebuild") {
|
|
108
|
+
out();
|
|
109
|
+
out(` Reading ${workspace}...`);
|
|
110
|
+
const done = await (0, sync_1.refresh)(root, workspace, { force: true });
|
|
111
|
+
out();
|
|
112
|
+
out(done.current ? ui.ok(done.message) : ui.fail(done.message));
|
|
113
|
+
if (done.unread)
|
|
114
|
+
out(` ${ui.c.dim((0, sync_1.readerReport)())}`);
|
|
115
|
+
out();
|
|
116
|
+
return done.current ? 0 : 1;
|
|
117
|
+
}
|
|
118
|
+
const now = await (0, sync_1.status)(root, workspace);
|
|
119
|
+
out();
|
|
120
|
+
if (!now.reachable) {
|
|
121
|
+
out(ui.fail("The service could not be reached."));
|
|
122
|
+
out();
|
|
123
|
+
return 1;
|
|
124
|
+
}
|
|
125
|
+
if (!now.enabled) {
|
|
126
|
+
out(" Your company has the code map switched off. Nothing about your code");
|
|
127
|
+
out(" is read, sent or stored, and jobs read files the ordinary way.");
|
|
128
|
+
out();
|
|
129
|
+
return 0;
|
|
130
|
+
}
|
|
131
|
+
if (!now.hasMap) {
|
|
132
|
+
out(` There is no map of ${workspace} yet. It will be read the first time`);
|
|
133
|
+
out(" you run a job here, or now with: comprism map refresh");
|
|
134
|
+
out();
|
|
135
|
+
return 0;
|
|
136
|
+
}
|
|
137
|
+
const held = now.held ?? {};
|
|
138
|
+
const counts = (held.counts ?? {});
|
|
139
|
+
out(` ${ui.c.bold(workspace)}`);
|
|
140
|
+
out(` ${held.files ?? 0} files, read from commit ${String(held.commit ?? "").slice(0, 8) || "none"}`);
|
|
141
|
+
out(` ${counts.objects ?? 0} things and ${counts.links ?? 0} links between them`);
|
|
142
|
+
out(` ${counts.endpoints ?? 0} endpoints, ${counts.data_models ?? 0} data models, `
|
|
143
|
+
+ `${counts.tables ?? 0} tables, ${counts.screens ?? 0} screens`);
|
|
144
|
+
out(` ${now.fresh ? "Matches the files on disk." : "The code has moved since it was read. The next job will bring it up to date."}`);
|
|
145
|
+
if (held.coverage)
|
|
146
|
+
out(` ${ui.c.dim(String(held.coverage))}`);
|
|
147
|
+
out();
|
|
148
|
+
out(` ${ui.c.dim(now.autoRefresh ? "Kept current automatically." : "Only refreshed when you ask.")}`);
|
|
149
|
+
out();
|
|
150
|
+
return 0;
|
|
151
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sign this machine out.
|
|
3
|
+
*
|
|
4
|
+
* ── Forgetting is not signing out ─────────────────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* This used to delete the local copy of the credential and say "disconnected".
|
|
7
|
+
* The credential stayed live: still listed in the portal, still accepted on
|
|
8
|
+
* every call, so anybody holding a copy of that file was still signed in and
|
|
9
|
+
* the person who signed out had no way to know it.
|
|
10
|
+
*
|
|
11
|
+
* So the server is told FIRST, on the one service every client shares, and it
|
|
12
|
+
* revokes the credential where it was minted. The local copy is then removed
|
|
13
|
+
* whatever the server said, because a person who asked to sign out must not be
|
|
14
|
+
* left holding a credential on a laptop they have finished with: if the server
|
|
15
|
+
* could not be reached, the key on this machine is gone and the words say
|
|
16
|
+
* plainly that it may still be live until it is revoked in the portal.
|
|
17
|
+
*
|
|
18
|
+
* `logout`, `signout` and `disconnect` are the same act under the three words
|
|
19
|
+
* people actually type. `logout` printed "there is no command called logout",
|
|
20
|
+
* which is the product telling somebody their own vocabulary is wrong.
|
|
21
|
+
*/
|
|
22
|
+
export declare function cmdDisconnect(): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Where this machine is pointed, and whether the workspace still accepts it.
|
|
25
|
+
*
|
|
26
|
+
* ── Why this asks the server rather than reading the file ─────────────────
|
|
27
|
+
*
|
|
28
|
+
* It used to report "signed in" from the presence of a local file, which is a
|
|
29
|
+
* statement about a laptop and not about an account. A credential revoked in
|
|
30
|
+
* the portal an hour ago still reads as signed in; so does a machine pointed at
|
|
31
|
+
* an address that has not answered for a week. That is precisely how a
|
|
32
|
+
* developer spent an evening on 17 September 2026 believing he was signed in to
|
|
33
|
+
* a workspace while every call was going to a dead port on his own laptop.
|
|
34
|
+
*
|
|
35
|
+
* Status is the command a person runs when something is wrong, so it is the one
|
|
36
|
+
* command that must never report a local guess as a fact. It asks the one
|
|
37
|
+
* service and prints what came back, or says it heard nothing.
|
|
38
|
+
*/
|
|
39
|
+
export declare function cmdStatus(): Promise<void>;
|
|
@@ -0,0 +1,182 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.cmdDisconnect = cmdDisconnect;
|
|
40
|
+
exports.cmdStatus = cmdStatus;
|
|
41
|
+
const node_readline_1 = __importDefault(require("node:readline"));
|
|
42
|
+
const connection_1 = require("../lib/connection");
|
|
43
|
+
const gateway_1 = require("../lib/gateway");
|
|
44
|
+
const ui = __importStar(require("../lib/ui"));
|
|
45
|
+
const out = (s = '') => process.stdout.write(s + '\n');
|
|
46
|
+
function argValue(args, flag) {
|
|
47
|
+
const i = args.indexOf(flag);
|
|
48
|
+
return i >= 0 ? args[i + 1] : undefined;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Read a password without echoing it.
|
|
52
|
+
*
|
|
53
|
+
* It never reaches a file, a log or the shell history: the only copy is the
|
|
54
|
+
* string handed straight to the sign-in call.
|
|
55
|
+
*/
|
|
56
|
+
function askHidden(prompt) {
|
|
57
|
+
return new Promise((resolve) => {
|
|
58
|
+
const rl = node_readline_1.default.createInterface({
|
|
59
|
+
input: process.stdin, output: process.stdout, terminal: true,
|
|
60
|
+
});
|
|
61
|
+
const silent = rl;
|
|
62
|
+
silent._writeToOutput = () => { };
|
|
63
|
+
process.stdout.write(prompt);
|
|
64
|
+
rl.question('', (answer) => {
|
|
65
|
+
rl.close();
|
|
66
|
+
process.stdout.write('\n');
|
|
67
|
+
resolve(answer);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
// `cmdConnect` lived here and is gone.
|
|
72
|
+
//
|
|
73
|
+
// It was a second sign in: it called the authentication routes and the key
|
|
74
|
+
// route directly, in its own order, and nothing reached it. The published
|
|
75
|
+
// command `connect` has routed to `cmdLogin` for some time, so this was an
|
|
76
|
+
// unreachable copy of the one act the product most needs to have exactly one
|
|
77
|
+
// of. Two sign ins are two places for a rule about who may sign in to be
|
|
78
|
+
// enforced differently, and the dead one is always the one nobody updates.
|
|
79
|
+
/**
|
|
80
|
+
* Sign this machine out.
|
|
81
|
+
*
|
|
82
|
+
* ── Forgetting is not signing out ─────────────────────────────────────────
|
|
83
|
+
*
|
|
84
|
+
* This used to delete the local copy of the credential and say "disconnected".
|
|
85
|
+
* The credential stayed live: still listed in the portal, still accepted on
|
|
86
|
+
* every call, so anybody holding a copy of that file was still signed in and
|
|
87
|
+
* the person who signed out had no way to know it.
|
|
88
|
+
*
|
|
89
|
+
* So the server is told FIRST, on the one service every client shares, and it
|
|
90
|
+
* revokes the credential where it was minted. The local copy is then removed
|
|
91
|
+
* whatever the server said, because a person who asked to sign out must not be
|
|
92
|
+
* left holding a credential on a laptop they have finished with: if the server
|
|
93
|
+
* could not be reached, the key on this machine is gone and the words say
|
|
94
|
+
* plainly that it may still be live until it is revoked in the portal.
|
|
95
|
+
*
|
|
96
|
+
* `logout`, `signout` and `disconnect` are the same act under the three words
|
|
97
|
+
* people actually type. `logout` printed "there is no command called logout",
|
|
98
|
+
* which is the product telling somebody their own vocabulary is wrong.
|
|
99
|
+
*/
|
|
100
|
+
async function cmdDisconnect() {
|
|
101
|
+
out(ui.banner('Sign out'));
|
|
102
|
+
out();
|
|
103
|
+
const conn = (0, connection_1.readConnection)();
|
|
104
|
+
if (!conn?.url || !conn.workspaceKey) {
|
|
105
|
+
(0, connection_1.clearConnection)();
|
|
106
|
+
out(ui.info('This machine was not signed in.'));
|
|
107
|
+
out();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const reply = await (0, gateway_1.ask)({ intent: 'sign_out', prompt: '' });
|
|
111
|
+
const removed = (0, connection_1.clearConnection)();
|
|
112
|
+
if (reply.signed_out) {
|
|
113
|
+
out(ui.ok(reply.message || 'Signed out. This machine\'s key is revoked.'));
|
|
114
|
+
out(` ${ui.c.dim('sign back in with')} ${ui.c.bold('comprism login')}`);
|
|
115
|
+
}
|
|
116
|
+
else if (removed) {
|
|
117
|
+
// Said plainly rather than dressed up. A person who is told "signed out"
|
|
118
|
+
// when the key is still live has been given the one piece of information
|
|
119
|
+
// they would have acted on.
|
|
120
|
+
out(ui.warn('Removed from this machine, but the key could not be revoked.'));
|
|
121
|
+
out(` ${ui.c.dim(reply.message
|
|
122
|
+
|| 'the service could not be reached, so revoke this machine in the portal')}`);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
out(ui.info('This machine was not signed in.'));
|
|
126
|
+
}
|
|
127
|
+
out();
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Where this machine is pointed, and whether the workspace still accepts it.
|
|
131
|
+
*
|
|
132
|
+
* ── Why this asks the server rather than reading the file ─────────────────
|
|
133
|
+
*
|
|
134
|
+
* It used to report "signed in" from the presence of a local file, which is a
|
|
135
|
+
* statement about a laptop and not about an account. A credential revoked in
|
|
136
|
+
* the portal an hour ago still reads as signed in; so does a machine pointed at
|
|
137
|
+
* an address that has not answered for a week. That is precisely how a
|
|
138
|
+
* developer spent an evening on 17 September 2026 believing he was signed in to
|
|
139
|
+
* a workspace while every call was going to a dead port on his own laptop.
|
|
140
|
+
*
|
|
141
|
+
* Status is the command a person runs when something is wrong, so it is the one
|
|
142
|
+
* command that must never report a local guess as a fact. It asks the one
|
|
143
|
+
* service and prints what came back, or says it heard nothing.
|
|
144
|
+
*/
|
|
145
|
+
async function cmdStatus() {
|
|
146
|
+
const c = (0, connection_1.readConnection)();
|
|
147
|
+
out(ui.banner('Status'));
|
|
148
|
+
out();
|
|
149
|
+
if (!c?.url) {
|
|
150
|
+
out(ui.warn('Not signed in.'));
|
|
151
|
+
out(` ${ui.c.dim('$')} comprism login`);
|
|
152
|
+
out();
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const reply = await (0, gateway_1.ask)({ intent: 'session', prompt: '' });
|
|
156
|
+
const me = reply.ok && reply.served !== false ? reply.session : null;
|
|
157
|
+
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')}`);
|
|
161
|
+
out();
|
|
162
|
+
process.exitCode = 1;
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
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.
|
|
168
|
+
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();
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
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`)}`);
|
|
179
|
+
out();
|
|
180
|
+
out(ui.c.dim(' Every figure you see is computed on our servers, never here.'));
|
|
181
|
+
out();
|
|
182
|
+
}
|