@illuminis/comprism 0.1.5 → 0.1.7
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/out/agent/command.js +4 -4
- package/out/agent/render.d.ts +24 -0
- package/out/agent/render.js +35 -3
- package/out/agent/session.d.ts +6 -1
- package/out/agent/session.js +17 -8
- package/out/commands/agents.js +3 -3
- package/out/commands/ask.js +8 -8
- package/out/commands/codemap.d.ts +1 -1
- package/out/commands/codemap.js +3 -3
- package/out/commands/commands-thin.js +4 -4
- package/out/commands/config.js +1 -1
- package/out/commands/cost.js +4 -4
- package/out/commands/decisionEngine.d.ts +1 -0
- package/out/commands/decisionEngine.js +66 -0
- package/out/commands/hooks.js +1 -1
- package/out/commands/install.d.ts +1 -1
- package/out/commands/install.js +3 -2
- package/out/commands/instructions.js +1 -1
- package/out/commands/integrations.js +4 -4
- package/out/commands/keys.js +6 -6
- package/out/commands/login.js +37 -21
- package/out/commands/permissions.js +2 -2
- package/out/commands/plugins.js +3 -3
- package/out/commands/privacy.js +2 -2
- package/out/commands/repl.js +107 -83
- package/out/commands/review.js +6 -6
- package/out/commands/settings.js +30 -123
- package/out/commands/skills.js +2 -2
- package/out/commands/unattended.js +6 -6
- package/out/commands/update.js +1 -1
- package/out/commands/welcome.js +20 -29
- package/out/commands/worktrees.d.ts +1 -1
- package/out/graph/sync.d.ts +1 -1
- package/out/graph/sync.js +6 -6
- package/out/lib/attach.js +4 -3
- package/out/lib/commandlist.d.ts +1 -1
- package/out/lib/commandlist.js +2 -2
- package/out/lib/config.d.ts +3 -2
- package/out/lib/config.js +7 -8
- package/out/lib/connection.js +1 -1
- package/out/lib/gateway.d.ts +5 -5
- package/out/lib/machine.js +1 -1
- package/out/lib/project-ops.d.ts +1 -1
- package/out/lib/project-ops.js +4 -4
- package/out/lib/queue.js +1 -1
- package/out/lib/readiness.d.ts +3 -30
- package/out/lib/readiness.js +13 -82
- package/out/lib/servicecommand.d.ts +14 -0
- package/out/lib/servicecommand.js +74 -0
- package/out/lib/sessions.js +3 -3
- package/out/lib/ui.d.ts +9 -6
- package/out/lib/ui.js +20 -26
- package/out/lib/voice.d.ts +2 -39
- package/out/lib/voice.js +7 -148
- package/out/lib/words.d.ts +20 -0
- package/out/lib/words.js +27 -0
- package/out/machine/codemap/build.d.ts +45 -0
- package/out/machine/codemap/build.js +91 -0
- package/out/machine/codemap/facts.d.ts +47 -0
- package/out/machine/codemap/facts.js +12 -0
- package/out/machine/codemap/files.d.ts +45 -0
- package/out/machine/codemap/files.js +207 -0
- package/out/machine/codemap/read-locales.d.ts +29 -0
- package/out/machine/codemap/read-locales.js +246 -0
- package/out/machine/codemap/read-python.d.ts +11 -0
- package/out/machine/codemap/read-python.js +116 -0
- package/out/machine/codemap/read-typescript.d.ts +16 -0
- package/out/machine/codemap/read-typescript.js +292 -0
- package/out/machine/executor/browser.d.ts +14 -0
- package/out/machine/executor/browser.js +270 -0
- package/out/machine/executor/diagnostics.d.ts +2 -0
- package/out/machine/executor/diagnostics.js +181 -0
- package/out/machine/executor/documents.d.ts +40 -0
- package/out/machine/executor/documents.js +170 -0
- package/out/machine/executor/files.d.ts +2 -0
- package/out/machine/executor/files.js +590 -0
- package/out/machine/executor/git.d.ts +48 -0
- package/out/machine/executor/git.js +145 -0
- package/out/machine/executor/hooks.d.ts +51 -0
- package/out/machine/executor/hooks.js +154 -0
- package/out/machine/executor/index.d.ts +45 -0
- package/out/machine/executor/index.js +367 -0
- package/out/machine/executor/notebook.d.ts +2 -0
- package/out/machine/executor/notebook.js +147 -0
- package/out/machine/executor/paths.d.ts +20 -0
- package/out/machine/executor/paths.js +154 -0
- package/out/machine/executor/sandbox.d.ts +40 -0
- package/out/machine/executor/sandbox.js +299 -0
- package/out/machine/executor/shell.d.ts +86 -0
- package/out/machine/executor/shell.js +582 -0
- package/out/machine/executor/toolservers.d.ts +20 -0
- package/out/machine/executor/toolservers.js +189 -0
- package/out/machine/executor/worktree.d.ts +9 -0
- package/out/machine/executor/worktree.js +119 -0
- package/out/machine/folder/project.d.ts +28 -0
- package/out/machine/folder/project.js +114 -0
- package/out/machine/runtime/home.d.ts +2 -0
- package/out/machine/runtime/home.js +48 -0
- package/out/machine/runtime/needs.d.ts +30 -0
- package/out/machine/runtime/needs.js +89 -0
- package/out/machine/runtime/self.d.ts +23 -0
- package/out/machine/runtime/self.js +124 -0
- package/out/machine/voice/record.d.ts +38 -0
- package/out/machine/voice/record.js +208 -0
- package/out/providers/index.js +2 -1
- package/out/thin.js +18 -10
- package/package.json +4 -4
|
@@ -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 home_1 = require("./home");
|
|
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, home_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, home_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,38 @@
|
|
|
1
|
+
/** One recording tool, as this file needs to drive it. */
|
|
2
|
+
export interface Recorder {
|
|
3
|
+
/** What to tell somebody who wants to know what is listening. */
|
|
4
|
+
name: string;
|
|
5
|
+
command: string;
|
|
6
|
+
args: (out: string) => string[];
|
|
7
|
+
}
|
|
8
|
+
/** The first recording tool this machine has, or null. */
|
|
9
|
+
export declare function recorder(): Recorder | null;
|
|
10
|
+
/**
|
|
11
|
+
* What to tell somebody who has no recording tool, or null when they do.
|
|
12
|
+
*
|
|
13
|
+
* One sentence and one command. Not a list of three options with trade-offs:
|
|
14
|
+
* somebody who just wanted to say a sentence out loud is not shopping for audio
|
|
15
|
+
* software.
|
|
16
|
+
*/
|
|
17
|
+
export declare function missing(): string | null;
|
|
18
|
+
/** A recording in progress. */
|
|
19
|
+
export interface Recording {
|
|
20
|
+
/** Where the audio is being written. */
|
|
21
|
+
file: string;
|
|
22
|
+
/** What is doing the listening, for the line on screen. */
|
|
23
|
+
by: string;
|
|
24
|
+
/** Stop, wait for the file to be finished properly, and hand it back. */
|
|
25
|
+
stop: () => Promise<{
|
|
26
|
+
file: string;
|
|
27
|
+
bytes: number;
|
|
28
|
+
}>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Start listening.
|
|
32
|
+
*
|
|
33
|
+
* Throws when there is nothing to listen with, which the caller should have
|
|
34
|
+
* headed off with `missing` so the person gets a sentence rather than an error.
|
|
35
|
+
*/
|
|
36
|
+
export declare function start(): Recording;
|
|
37
|
+
/** Delete the recording and the folder holding it. Always, and immediately. */
|
|
38
|
+
export declare function discard(file: string): void;
|
|
@@ -0,0 +1,208 @@
|
|
|
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.recorder = recorder;
|
|
37
|
+
exports.missing = missing;
|
|
38
|
+
exports.start = start;
|
|
39
|
+
exports.discard = discard;
|
|
40
|
+
/**
|
|
41
|
+
* Recording what a person says, on their own computer, for every client that
|
|
42
|
+
* offers a microphone: the command line and the editor extension.
|
|
43
|
+
*
|
|
44
|
+
* Physical work on the person's machine, so it lives here once rather than in
|
|
45
|
+
* each client (rule 17). Nothing here transcribes: the recording goes to our
|
|
46
|
+
* server, which asks a vendor, and the words come back. See the terminal's
|
|
47
|
+
* `lib/voice.ts` and the service's `transcription.py`.
|
|
48
|
+
*
|
|
49
|
+
* ── Recording without adding a dependency ─────────────────────────────────
|
|
50
|
+
*
|
|
51
|
+
* This drives a recording tool the machine already has rather than a compiled
|
|
52
|
+
* microphone library on every customer's laptop. macOS ships no command line
|
|
53
|
+
* recorder, so on a Mac with neither ffmpeg nor sox this does not work, and
|
|
54
|
+
* `missing` says so in one sentence naming the one command that fixes it.
|
|
55
|
+
*
|
|
56
|
+
* ── Stopping ──────────────────────────────────────────────────────────────
|
|
57
|
+
*
|
|
58
|
+
* Every one of these tools writes a WAV header that is only correct once the
|
|
59
|
+
* recording ends properly, so stopping means an interrupt and then WAITING for
|
|
60
|
+
* the tool to finish writing. Killing it outright leaves a file whose header
|
|
61
|
+
* claims a length it does not have, which every transcriber reads as silence.
|
|
62
|
+
*/
|
|
63
|
+
const node_child_process_1 = require("node:child_process");
|
|
64
|
+
const fs = __importStar(require("node:fs"));
|
|
65
|
+
const os = __importStar(require("node:os"));
|
|
66
|
+
const path = __importStar(require("node:path"));
|
|
67
|
+
/** Is this on the PATH at all. */
|
|
68
|
+
function present(command) {
|
|
69
|
+
try {
|
|
70
|
+
return (0, node_child_process_1.spawnSync)('which', [command], { stdio: 'ignore' }).status === 0;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Sixteen kilohertz, one channel, everywhere.
|
|
78
|
+
*
|
|
79
|
+
* What every speech model wants and nothing more. Recording in studio quality
|
|
80
|
+
* would make a file several times the size, take longer to upload, and be
|
|
81
|
+
* downsampled by the vendor on arrival anyway.
|
|
82
|
+
*/
|
|
83
|
+
const RATE = '16000';
|
|
84
|
+
const RECORDERS = [
|
|
85
|
+
// sox first. It is the one built for this, it needs no device name, and it
|
|
86
|
+
// stops cleanly.
|
|
87
|
+
{ name: 'sox', command: 'rec', args: (out) => ['-q', '-c', '1', '-r', RATE, out] },
|
|
88
|
+
{
|
|
89
|
+
name: 'ffmpeg',
|
|
90
|
+
command: 'ffmpeg',
|
|
91
|
+
args: (out) => [
|
|
92
|
+
'-loglevel', 'quiet', '-nostdin',
|
|
93
|
+
...(process.platform === 'darwin'
|
|
94
|
+
? ['-f', 'avfoundation', '-i', ':default']
|
|
95
|
+
: ['-f', 'alsa', '-i', 'default']),
|
|
96
|
+
// Written as it is heard, not held until the end, so the meter and the
|
|
97
|
+
// words so far have something to read while the person is speaking.
|
|
98
|
+
'-ac', '1', '-ar', RATE, '-flush_packets', '1', '-y', out,
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
// Linux's own, present on most desktop installs.
|
|
102
|
+
{ name: 'arecord', command: 'arecord', args: (out) => ['-q', '-f', 'S16_LE', '-c', '1', '-r', RATE, out] },
|
|
103
|
+
];
|
|
104
|
+
/** The first recording tool this machine has, or null. */
|
|
105
|
+
function recorder() {
|
|
106
|
+
return RECORDERS.find((r) => present(r.command)) ?? null;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* What to tell somebody who has no recording tool, or null when they do.
|
|
110
|
+
*
|
|
111
|
+
* One sentence and one command. Not a list of three options with trade-offs:
|
|
112
|
+
* somebody who just wanted to say a sentence out loud is not shopping for audio
|
|
113
|
+
* software.
|
|
114
|
+
*/
|
|
115
|
+
function missing() {
|
|
116
|
+
if (recorder())
|
|
117
|
+
return null;
|
|
118
|
+
return process.platform === 'darwin'
|
|
119
|
+
? 'Speaking needs a recording tool, and macOS does not come with one. '
|
|
120
|
+
+ 'Install it once with: brew install sox'
|
|
121
|
+
: 'Speaking needs a recording tool. Install it once with: '
|
|
122
|
+
+ 'sudo apt install sox (or your system\'s package manager)';
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Start listening.
|
|
126
|
+
*
|
|
127
|
+
* Throws when there is nothing to listen with, which the caller should have
|
|
128
|
+
* headed off with `missing` so the person gets a sentence rather than an error.
|
|
129
|
+
*/
|
|
130
|
+
function start() {
|
|
131
|
+
const tool = recorder();
|
|
132
|
+
if (!tool)
|
|
133
|
+
throw new Error(missing() ?? 'No recording tool.');
|
|
134
|
+
const file = path.join(fs.mkdtempSync(path.join(os.tmpdir(), 'comprism-voice-')), 'said.wav');
|
|
135
|
+
const child = (0, node_child_process_1.spawn)(tool.command, tool.args(file), {
|
|
136
|
+
stdio: ['ignore', 'ignore', 'ignore'],
|
|
137
|
+
});
|
|
138
|
+
let stopped = null;
|
|
139
|
+
// The recorder never outlives the session. Closing the window or ending the
|
|
140
|
+
// process while it listens would otherwise leave a microphone recording to a
|
|
141
|
+
// file nobody knows about, the worst thing this tool could do.
|
|
142
|
+
const abandon = () => {
|
|
143
|
+
try {
|
|
144
|
+
child.kill('SIGKILL');
|
|
145
|
+
}
|
|
146
|
+
catch { /* already gone */ }
|
|
147
|
+
discard(file);
|
|
148
|
+
};
|
|
149
|
+
const onSignal = (signal) => {
|
|
150
|
+
abandon();
|
|
151
|
+
release();
|
|
152
|
+
process.kill(process.pid, signal);
|
|
153
|
+
};
|
|
154
|
+
const release = () => {
|
|
155
|
+
process.off('exit', abandon);
|
|
156
|
+
process.off('SIGHUP', onSignal);
|
|
157
|
+
process.off('SIGTERM', onSignal);
|
|
158
|
+
};
|
|
159
|
+
process.once('exit', abandon);
|
|
160
|
+
process.once('SIGHUP', onSignal);
|
|
161
|
+
process.once('SIGTERM', onSignal);
|
|
162
|
+
child.once('close', release);
|
|
163
|
+
const stop = () => {
|
|
164
|
+
if (stopped)
|
|
165
|
+
return stopped;
|
|
166
|
+
stopped = new Promise((resolve) => {
|
|
167
|
+
const done = () => {
|
|
168
|
+
let bytes = 0;
|
|
169
|
+
try {
|
|
170
|
+
bytes = fs.statSync(file).size;
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
bytes = 0;
|
|
174
|
+
}
|
|
175
|
+
resolve({ file, bytes });
|
|
176
|
+
};
|
|
177
|
+
// Interrupt, not kill. Every one of these tools finishes writing the WAV
|
|
178
|
+
// header on an interrupt and none of them does on a kill, and a header
|
|
179
|
+
// that was never finished reads as silence to whoever transcribes it.
|
|
180
|
+
child.once('close', done);
|
|
181
|
+
try {
|
|
182
|
+
child.kill('SIGINT');
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
done();
|
|
186
|
+
}
|
|
187
|
+
// A tool that has not closed in two seconds is not going to. Taking the
|
|
188
|
+
// file as it stands beats leaving somebody at a prompt that has stopped
|
|
189
|
+
// answering them.
|
|
190
|
+
setTimeout(() => {
|
|
191
|
+
try {
|
|
192
|
+
child.kill('SIGKILL');
|
|
193
|
+
}
|
|
194
|
+
catch { /* already gone */ }
|
|
195
|
+
done();
|
|
196
|
+
}, 2000).unref();
|
|
197
|
+
});
|
|
198
|
+
return stopped;
|
|
199
|
+
};
|
|
200
|
+
return { file, by: tool.name, stop };
|
|
201
|
+
}
|
|
202
|
+
/** Delete the recording and the folder holding it. Always, and immediately. */
|
|
203
|
+
function discard(file) {
|
|
204
|
+
try {
|
|
205
|
+
fs.rmSync(path.dirname(file), { recursive: true, force: true });
|
|
206
|
+
}
|
|
207
|
+
catch { /* a temp file we could not remove is not worth a word to anybody */ }
|
|
208
|
+
}
|
package/out/providers/index.js
CHANGED
|
@@ -19,6 +19,7 @@ exports.callModel = callModel;
|
|
|
19
19
|
const catalog_1 = require("../internal/catalog");
|
|
20
20
|
const anthropic_1 = require("./anthropic");
|
|
21
21
|
const openai_1 = require("./openai");
|
|
22
|
+
const words_1 = require("../lib/words");
|
|
22
23
|
var anthropic_2 = require("./anthropic");
|
|
23
24
|
Object.defineProperty(exports, "ProviderHttpError", { enumerable: true, get: function () { return anthropic_2.ProviderHttpError; } });
|
|
24
25
|
const DEFAULT_MAX_TOKENS = 4096;
|
|
@@ -62,7 +63,7 @@ async function callModel(call, keys) {
|
|
|
62
63
|
continue;
|
|
63
64
|
}
|
|
64
65
|
const latency = err instanceof anthropic_1.ProviderHttpError ? err.latencyMs : 0;
|
|
65
|
-
return errorResult(err instanceof Error ? err.message :
|
|
66
|
+
return errorResult(err instanceof Error ? err.message : (0, words_1.word)('providerCallFailed'), latency);
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
return errorResult('provider call failed', 0);
|
package/out/thin.js
CHANGED
|
@@ -56,7 +56,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
56
56
|
*/
|
|
57
57
|
const ui = __importStar(require("./lib/ui"));
|
|
58
58
|
const version_1 = require("./lib/version");
|
|
59
|
-
const self_1 = require("./
|
|
59
|
+
const self_1 = require("./machine/runtime/self");
|
|
60
|
+
const words_1 = require("./lib/words");
|
|
60
61
|
const out = (s = '') => process.stdout.write(s + '\n');
|
|
61
62
|
/** A refusal a script reads: always on standard error (Appendix B). */
|
|
62
63
|
const err = (s = '') => process.stderr.write(s + '\n');
|
|
@@ -115,24 +116,25 @@ function usage() {
|
|
|
115
116
|
out();
|
|
116
117
|
out(ui.table(['COMMAND', 'WHAT IT DOES'], [
|
|
117
118
|
['comprism ask "<your question>"', 'one prompt, one answer, and what it cost'],
|
|
118
|
-
['comprism work', 'have it do the work: reads your
|
|
119
|
+
['comprism work', 'have it do the work: reads your workspace, edits, runs your tests'],
|
|
119
120
|
['comprism login', 'sign in with your email and password'],
|
|
120
121
|
['comprism', 'start a session and just type your questions'],
|
|
121
|
-
['comprism --continue', 'carry on the most recent session in this
|
|
122
|
+
['comprism --continue', 'carry on the most recent session in this workspace'],
|
|
122
123
|
['comprism --resume [number]', 'carry on a session; with no number, choose from a list'],
|
|
123
124
|
['comprism sessions', 'your recent sessions, newest first; --search to find one'],
|
|
124
125
|
['comprism keys', 'add a provider key, or point at a file of them'],
|
|
125
126
|
['comprism model', 'the model your savings are measured against'],
|
|
126
127
|
['comprism providers', 'every AI vendor and model, and what you can reach'],
|
|
127
|
-
['comprism
|
|
128
|
+
['comprism workspace', 'the folder to work in, default is where you are'],
|
|
128
129
|
['comprism config', 'settings in force and where each came from'],
|
|
129
130
|
['comprism instructions', 'the instructions the next job receives'],
|
|
130
|
-
['comprism memory', 'this
|
|
131
|
+
['comprism memory', 'this workspace\'s notes'],
|
|
131
132
|
['comprism skills', 'the skills here and where each came from; /name runs one'],
|
|
132
133
|
['comprism integrations', 'outside tools the agent can call, and their sign in'],
|
|
133
134
|
['comprism plugins', 'packs of skills, helpers, hooks and connections'],
|
|
134
135
|
['comprism worktrees', 'separate copies of the repository'],
|
|
135
136
|
['comprism privacy', 'what your company keeps about your work'],
|
|
137
|
+
['comprism decision-engine', 'whether your work uses a decision engine; add none or jev to change it'],
|
|
136
138
|
['comprism permissions', 'the rules in force here; permissions why <action> "<target>"'],
|
|
137
139
|
['comprism status', 'is this machine signed in, and to what'],
|
|
138
140
|
['comprism check', 'what this machine still needs, and how to add it'],
|
|
@@ -307,6 +309,12 @@ async function main() {
|
|
|
307
309
|
process.exitCode = await cmdPrivacy();
|
|
308
310
|
return;
|
|
309
311
|
}
|
|
312
|
+
// Whether your work uses a decision engine (web manual 11.4).
|
|
313
|
+
case 'decision-engine': {
|
|
314
|
+
const { cmdDecisionEngine } = await Promise.resolve().then(() => __importStar(require('./commands/decisionEngine')));
|
|
315
|
+
process.exitCode = await cmdDecisionEngine(args);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
310
318
|
// Separate copies of the repository (manual 2.11).
|
|
311
319
|
case 'worktrees': {
|
|
312
320
|
const { cmdWorktrees } = await Promise.resolve().then(() => __importStar(require('./commands/worktrees')));
|
|
@@ -378,7 +386,7 @@ async function main() {
|
|
|
378
386
|
const reply = await askGateway({ intent: 'usage', prompt: '', tzMinutes: -new Date().getTimezoneOffset() });
|
|
379
387
|
const found = reply.usage;
|
|
380
388
|
if (!reply.ok || reply.served === false || !found?.lines) {
|
|
381
|
-
err(ui.fail(reply.message || 'Usage could not be read from your
|
|
389
|
+
err(ui.fail(reply.message || 'Usage could not be read from your organization.'));
|
|
382
390
|
process.exitCode = exitFor(reply.httpStatus === 401 ? 'signed_out'
|
|
383
391
|
: reply.ok || reply.httpStatus ? 'incomplete' : 'unreachable');
|
|
384
392
|
return;
|
|
@@ -400,7 +408,7 @@ async function main() {
|
|
|
400
408
|
const reply = await askGateway({ intent: 'schema', prompt: '' });
|
|
401
409
|
const doc = reply.schema_doc;
|
|
402
410
|
if (!reply.ok || reply.served === false || !doc?.output) {
|
|
403
|
-
err(ui.fail(reply.message || 'The schema could not be read from your
|
|
411
|
+
err(ui.fail(reply.message || 'The schema could not be read from your organization.'));
|
|
404
412
|
const { exitFor } = await Promise.resolve().then(() => __importStar(require('./lib/output')));
|
|
405
413
|
process.exitCode = exitFor(reply.httpStatus === 401 ? 'signed_out'
|
|
406
414
|
: reply.ok || reply.httpStatus ? 'incomplete' : 'unreachable');
|
|
@@ -512,7 +520,7 @@ async function main() {
|
|
|
512
520
|
const slashWord = /^\/([a-z][a-z0-9-]*)(?:\s|$)/i.exec(request.trim());
|
|
513
521
|
if (slashWord && !(await Promise.resolve().then(() => __importStar(require('./lib/attach')))).startsWithPath(request.trim())) {
|
|
514
522
|
const { fetchCommandList } = await Promise.resolve().then(() => __importStar(require('./lib/commandlist')));
|
|
515
|
-
const { resolveProject } = await Promise.resolve().then(() => __importStar(require('./
|
|
523
|
+
const { resolveProject } = await Promise.resolve().then(() => __importStar(require('./machine/folder/project')));
|
|
516
524
|
const where = flag(args, '--cwd') ?? (await Promise.resolve().then(() => __importStar(require('./commands/settings')))).currentWorkspace().path;
|
|
517
525
|
const list = await fetchCommandList(resolveProject(where).root, []);
|
|
518
526
|
const name = slashWord[1].toLowerCase();
|
|
@@ -562,7 +570,7 @@ async function main() {
|
|
|
562
570
|
?? (await Promise.resolve().then(() => __importStar(require('./commands/settings')))).currentWorkspace().path;
|
|
563
571
|
const worktree = flag(args, '--worktree');
|
|
564
572
|
if (worktree) {
|
|
565
|
-
const { checkFolder, resolveProject } = await Promise.resolve().then(() => __importStar(require('./
|
|
573
|
+
const { checkFolder, resolveProject } = await Promise.resolve().then(() => __importStar(require('./machine/folder/project')));
|
|
566
574
|
const start = checkFolder(workFolder);
|
|
567
575
|
if (!start.ok) {
|
|
568
576
|
out(ui.fail(start.why));
|
|
@@ -842,6 +850,6 @@ async function main() {
|
|
|
842
850
|
}
|
|
843
851
|
}
|
|
844
852
|
main().catch((err) => {
|
|
845
|
-
process.stderr.write(ui.fail(err instanceof Error ? err.message :
|
|
853
|
+
process.stderr.write(ui.fail(err instanceof Error ? err.message : (0, words_1.word)('somethingWrong')) + '\n');
|
|
846
854
|
process.exitCode = 1;
|
|
847
855
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@illuminis/comprism",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "CompletionPrism Companion. Records what finishing a piece of work actually costs - every attempt, and the human time spent noticing and repairing the ones that failed.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"private": false,
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"node": ">=22"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
|
-
"build": "tsc -p ./ && node scripts/build-native.mjs",
|
|
27
|
-
"dev": "tsc -w -p ./",
|
|
26
|
+
"build": "node scripts/sync-machine-services.mjs && tsc -p ./ && node scripts/build-native.mjs",
|
|
27
|
+
"dev": "node scripts/sync-machine-services.mjs && tsc -w -p ./",
|
|
28
28
|
"test": "npm run build && node --test out/**/*.test.js",
|
|
29
29
|
"gate": "npm run build && npm test && npm run shipcheck",
|
|
30
30
|
"prepublishOnly": "npm run build",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"repository": {
|
|
45
45
|
"type": "git",
|
|
46
46
|
"url": "git+https://github.com/Illuminis-ai/completionprism.git",
|
|
47
|
-
"directory": "app/
|
|
47
|
+
"directory": "app/frontend/terminal"
|
|
48
48
|
},
|
|
49
49
|
"keywords": [
|
|
50
50
|
"ai",
|