@illuminis/comprism 0.1.3 → 0.1.4

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 (131) hide show
  1. package/README.md +61 -2
  2. package/out/agent/command.d.ts +75 -4
  3. package/out/agent/command.js +220 -25
  4. package/out/agent/render.d.ts +17 -2
  5. package/out/agent/render.js +157 -14
  6. package/out/agent/session.d.ts +141 -2
  7. package/out/agent/session.js +735 -149
  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 +78 -11
  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 +188 -36
  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 +8 -1
  39. package/out/commands/repl.js +1207 -118
  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/worktrees.d.ts +5 -0
  55. package/out/commands/worktrees.js +186 -0
  56. package/out/executor/browser.d.ts +14 -0
  57. package/out/executor/browser.js +270 -0
  58. package/out/executor/diagnostics.d.ts +2 -0
  59. package/out/executor/diagnostics.js +181 -0
  60. package/out/executor/files.js +270 -40
  61. package/out/executor/git.js +42 -29
  62. package/out/executor/hooks.d.ts +42 -58
  63. package/out/executor/hooks.js +89 -182
  64. package/out/executor/index.d.ts +21 -5
  65. package/out/executor/index.js +160 -14
  66. package/out/executor/paths.d.ts +6 -1
  67. package/out/executor/paths.js +34 -6
  68. package/out/executor/sandbox.d.ts +40 -0
  69. package/out/executor/sandbox.js +299 -0
  70. package/out/executor/shell.d.ts +49 -4
  71. package/out/executor/shell.js +302 -56
  72. package/out/executor/toolservers.d.ts +20 -0
  73. package/out/executor/toolservers.js +189 -0
  74. package/out/executor/worktree.d.ts +9 -0
  75. package/out/executor/worktree.js +119 -0
  76. package/out/graph/read-python.js +2 -1
  77. package/out/lib/attach.d.ts +56 -12
  78. package/out/lib/attach.js +230 -63
  79. package/out/lib/clipboard.d.ts +23 -0
  80. package/out/lib/clipboard.js +182 -0
  81. package/out/lib/commandlist.d.ts +20 -0
  82. package/out/lib/commandlist.js +58 -0
  83. package/out/lib/decision.d.ts +22 -0
  84. package/out/lib/decision.js +50 -0
  85. package/out/lib/fingerprint.d.ts +25 -0
  86. package/out/lib/fingerprint.js +58 -0
  87. package/out/lib/gateway.d.ts +186 -2
  88. package/out/lib/gateway.js +59 -4
  89. package/out/lib/history.d.ts +24 -0
  90. package/out/lib/history.js +137 -0
  91. package/out/lib/ide.d.ts +19 -0
  92. package/out/lib/ide.js +131 -0
  93. package/out/lib/keyboard.d.ts +95 -0
  94. package/out/lib/keyboard.js +383 -0
  95. package/out/lib/machine.d.ts +21 -0
  96. package/out/lib/machine.js +91 -0
  97. package/out/lib/notify.d.ts +4 -0
  98. package/out/lib/notify.js +52 -0
  99. package/out/lib/output.d.ts +48 -0
  100. package/out/lib/output.js +108 -0
  101. package/out/lib/project-ops.d.ts +19 -0
  102. package/out/lib/project-ops.js +146 -0
  103. package/out/lib/project.d.ts +28 -0
  104. package/out/lib/project.js +114 -0
  105. package/out/lib/prompt.js +15 -2
  106. package/out/lib/queue.d.ts +13 -0
  107. package/out/lib/queue.js +116 -0
  108. package/out/lib/readiness.d.ts +19 -0
  109. package/out/lib/readiness.js +170 -1
  110. package/out/lib/self.d.ts +23 -0
  111. package/out/lib/self.js +124 -0
  112. package/out/lib/sessions.d.ts +19 -0
  113. package/out/lib/sessions.js +221 -0
  114. package/out/lib/stdin.d.ts +32 -0
  115. package/out/lib/stdin.js +117 -0
  116. package/out/lib/store.d.ts +40 -0
  117. package/out/lib/store.js +138 -0
  118. package/out/lib/sync.d.ts +18 -0
  119. package/out/lib/sync.js +81 -0
  120. package/out/lib/ui.d.ts +2 -4
  121. package/out/lib/ui.js +31 -25
  122. package/out/lib/voice.js +24 -0
  123. package/out/postinstall.js +42 -17
  124. package/out/providers/anthropic.d.ts +22 -0
  125. package/out/providers/anthropic.js +80 -0
  126. package/out/providers/index.d.ts +8 -0
  127. package/out/providers/index.js +83 -0
  128. package/out/providers/openai.d.ts +11 -0
  129. package/out/providers/openai.js +57 -0
  130. package/out/thin.js +594 -32
  131. package/package.json +9 -49
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ToolServers = void 0;
4
+ /**
5
+ * Tool servers on this machine (manual 9.10): started when a job needs one,
6
+ * spoken to over standard input and output, stopped when the job ends.
7
+ *
8
+ * A local helper and nothing more. Which servers exist, whether one may run
9
+ * in this project, whether a call is allowed and what a result means are all
10
+ * the service's. This starts the command the person approved, asks for the
11
+ * tool list, carries one call, and reports what came back or why nothing did.
12
+ *
13
+ * Only the two methods an agent needs: list the tools, call a tool.
14
+ */
15
+ const child_process_1 = require("child_process");
16
+ /** How long one request may take before it is reported as not answered. */
17
+ const timeoutMs = () => Number(process.env.COMPRISM_TOOL_SERVER_TIMEOUT_MS || 30_000);
18
+ /** What one result may carry back. The service cuts it again. */
19
+ const MAX_RESULT_CHARS = 20_000;
20
+ class Server {
21
+ name;
22
+ command;
23
+ proc;
24
+ buffer = "";
25
+ nextId = 1;
26
+ pending = new Map();
27
+ gone = null;
28
+ ready;
29
+ constructor(name, command, cwd) {
30
+ this.name = name;
31
+ this.command = command;
32
+ // The command exactly as the person approved it, through their shell, the
33
+ // way they would type it themselves.
34
+ // nosemgrep: javascript.lang.security.detect-child-process.detect-child-process -- the tool server command exactly as the person approved it
35
+ this.proc = (0, child_process_1.spawn)(this.command, { cwd, shell: true, stdio: ["pipe", "pipe", "pipe"],
36
+ windowsHide: true });
37
+ this.proc.stdout.setEncoding("utf8");
38
+ this.proc.stdout.on("data", (chunk) => this.read(chunk));
39
+ this.proc.stderr.on("data", () => { });
40
+ this.proc.stdin.on("error", () => { });
41
+ this.proc.on("error", (e) => this.fail(`could not be started: ${e.message}`));
42
+ this.proc.on("exit", (code) => this.fail(`stopped${code === null ? "" : ` (exit ${code})`}`));
43
+ this.ready = this.request("initialize", {
44
+ protocolVersion: "2025-06-18", capabilities: {},
45
+ clientInfo: { name: "comprism", version: "1" },
46
+ }).then(() => { this.notify("notifications/initialized"); });
47
+ this.ready.catch(() => { });
48
+ }
49
+ fail(why) {
50
+ if (this.gone)
51
+ return;
52
+ this.gone = `The tool server ${this.name} ${why}.`;
53
+ for (const [, p] of this.pending) {
54
+ clearTimeout(p.timer);
55
+ p.reject(new Error(this.gone));
56
+ }
57
+ this.pending.clear();
58
+ }
59
+ read(chunk) {
60
+ this.buffer += chunk;
61
+ let at;
62
+ while ((at = this.buffer.indexOf("\n")) >= 0) {
63
+ const line = this.buffer.slice(0, at).trim();
64
+ this.buffer = this.buffer.slice(at + 1);
65
+ if (!line)
66
+ continue;
67
+ let msg;
68
+ try {
69
+ msg = JSON.parse(line);
70
+ }
71
+ catch {
72
+ // A reply that is not a reply: every waiting request is told so.
73
+ for (const [id, p] of this.pending) {
74
+ clearTimeout(p.timer);
75
+ p.reject(new Error(`The tool server ${this.name} sent something that is not a reply.`));
76
+ this.pending.delete(id);
77
+ }
78
+ continue;
79
+ }
80
+ const id = typeof msg.id === "number" ? msg.id : Number(msg.id);
81
+ const waiting = this.pending.get(id);
82
+ if (!waiting)
83
+ continue;
84
+ clearTimeout(waiting.timer);
85
+ this.pending.delete(id);
86
+ if (msg.error) {
87
+ const e = msg.error;
88
+ waiting.reject(new Error(`The tool server ${this.name} refused: ${e.message ?? "an error"}.`));
89
+ }
90
+ else {
91
+ waiting.resolve((msg.result ?? {}));
92
+ }
93
+ }
94
+ }
95
+ notify(method) {
96
+ if (this.gone)
97
+ return;
98
+ this.proc.stdin.write(JSON.stringify({ jsonrpc: "2.0", method }) + "\n");
99
+ }
100
+ request(method, params) {
101
+ if (this.gone)
102
+ return Promise.reject(new Error(this.gone));
103
+ const id = this.nextId++;
104
+ return new Promise((resolve, reject) => {
105
+ const timer = setTimeout(() => {
106
+ this.pending.delete(id);
107
+ reject(new Error(`The tool server ${this.name} did not answer within ${Math.max(1, Math.round(timeoutMs() / 1000))} seconds.`));
108
+ }, timeoutMs());
109
+ this.pending.set(id, { resolve, reject, timer });
110
+ this.proc.stdin.write(JSON.stringify({ jsonrpc: "2.0", id, method, params }) + "\n");
111
+ });
112
+ }
113
+ stop() {
114
+ this.fail("was stopped");
115
+ try {
116
+ this.proc.stdin.end();
117
+ }
118
+ catch { /* already closed */ }
119
+ // On Windows the command runs under cmd.exe, and ending cmd.exe leaves
120
+ // the server itself running. The whole tree is ended instead, so nothing
121
+ // outlives the job (manual 9.10).
122
+ if (process.platform === "win32" && this.proc.pid && this.proc.exitCode === null) {
123
+ try {
124
+ (0, child_process_1.spawnSync)("taskkill", ["/pid", String(this.proc.pid), "/T", "/F"], { windowsHide: true, stdio: "ignore" });
125
+ return;
126
+ }
127
+ catch { /* fall through to the ordinary stop */ }
128
+ }
129
+ try {
130
+ this.proc.kill();
131
+ }
132
+ catch { /* already gone */ }
133
+ }
134
+ }
135
+ /** The tool servers one job started, by name. */
136
+ class ToolServers {
137
+ cwd;
138
+ running = new Map();
139
+ constructor(cwd) {
140
+ this.cwd = cwd;
141
+ }
142
+ async server(name, command) {
143
+ let s = this.running.get(name);
144
+ if (!s || s.command !== command) {
145
+ s?.stop();
146
+ s = new Server(name, command, this.cwd);
147
+ this.running.set(name, s);
148
+ }
149
+ await s.ready;
150
+ return s;
151
+ }
152
+ /** The server's tools, as it described them, as JSON text. */
153
+ async list(name, command) {
154
+ try {
155
+ const s = await this.server(name, command);
156
+ const r = await s.request("tools/list", {});
157
+ if (!Array.isArray(r.tools)) {
158
+ return { isError: true, content: `The tool server ${name} sent something that is not a tool list.` };
159
+ }
160
+ return { isError: false, content: JSON.stringify(r.tools) };
161
+ }
162
+ catch (e) {
163
+ this.running.get(name)?.stop();
164
+ this.running.delete(name);
165
+ return { isError: true, content: e.message };
166
+ }
167
+ }
168
+ /** One call, and the text the server returned. */
169
+ async call(name, command, tool, args) {
170
+ try {
171
+ const s = await this.server(name, command);
172
+ const r = await s.request("tools/call", { name: tool, arguments: args ?? {} });
173
+ const blocks = Array.isArray(r.content) ? r.content : [];
174
+ const text = blocks.filter((b) => b.type === "text").map((b) => String(b.text ?? "")).join("\n").trim();
175
+ return { isError: r.isError === true, content: (text || "(the tool returned nothing)").slice(0, MAX_RESULT_CHARS) };
176
+ }
177
+ catch (e) {
178
+ return { isError: true, content: e.message };
179
+ }
180
+ }
181
+ /** Every server this job started, stopped. Called when the job ends. */
182
+ stopAll() {
183
+ for (const [, s] of this.running)
184
+ s.stop();
185
+ this.running.clear();
186
+ }
187
+ get count() { return this.running.size; }
188
+ }
189
+ exports.ToolServers = ToolServers;
@@ -0,0 +1,9 @@
1
+ import { RunResult, ShellOptions } from "./shell";
2
+ /** Where a copy is, by its id, or undefined. */
3
+ export declare function worktreePath(id: string): string | undefined;
4
+ export declare function openWorktree(id: string, opts: ShellOptions): Promise<RunResult>;
5
+ /** What the helper changed in its copy, as one diff. */
6
+ export declare function diffWorktree(id: string, opts: ShellOptions): Promise<RunResult>;
7
+ export declare function closeWorktree(id: string, opts: ShellOptions): Promise<RunResult>;
8
+ /** Every copy this process made, removed; for the end of a session. */
9
+ export declare function closeAllWorktrees(root: string): Promise<void>;
@@ -0,0 +1,119 @@
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.worktreePath = worktreePath;
37
+ exports.openWorktree = openWorktree;
38
+ exports.diffWorktree = diffWorktree;
39
+ exports.closeWorktree = closeWorktree;
40
+ exports.closeAllWorktrees = closeAllWorktrees;
41
+ /**
42
+ * A helper's own copy of the project (manual 5.26).
43
+ *
44
+ * A git worktree in the temporary folder, started from the project as it is
45
+ * now: the last commit plus the person's uncommitted changes to tracked files,
46
+ * committed inside the copy as its starting point. The helper's edits land
47
+ * there and nowhere else; what comes back is a diff against that starting
48
+ * point, which the service applies to the real folder with the usual approval.
49
+ * Nothing here decides anything: it makes the copy, reads its diff, and
50
+ * removes it.
51
+ */
52
+ const fs = __importStar(require("fs"));
53
+ const os = __importStar(require("os"));
54
+ const path = __importStar(require("path"));
55
+ const shell_1 = require("./shell");
56
+ const copies = new Map();
57
+ const git = (args, opts) => (0, shell_1.runProgram)("git", args, opts);
58
+ const okExit = (r) => !r.isError && /^exit 0/.test(r.content);
59
+ const body = (r) => r.content.replace(/^exit -?\d+\n\n/, "");
60
+ /** Where a copy is, by its id, or undefined. */
61
+ function worktreePath(id) {
62
+ return copies.get(id);
63
+ }
64
+ async function openWorktree(id, opts) {
65
+ if (!/^[\w-]{1,40}$/.test(id))
66
+ return { isError: true, content: "Refused: not a usable copy name." };
67
+ if (copies.has(id))
68
+ return { content: copies.get(id), summary: `copy ${id}` };
69
+ const where = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), `comprism-helper-${id}-`));
70
+ fs.rmdirSync(where);
71
+ const made = await git(["worktree", "add", "--detach", "-q", where, "HEAD"], opts);
72
+ if (!okExit(made))
73
+ return { isError: true, content: `A separate copy could not be made: ${body(made)}` };
74
+ const inCopy = { ...opts, root: where, cwd: undefined };
75
+ // The person's uncommitted changes, so the helper starts from what they see.
76
+ const pending = await git(["diff", "--binary", "HEAD"], opts);
77
+ const patch = body(pending);
78
+ if (okExit(pending) && patch.trim() && patch.trim() !== "(no output)") {
79
+ const file = path.join(where, ".comprism-start.patch");
80
+ fs.writeFileSync(file, patch.endsWith("\n") ? patch : `${patch}\n`);
81
+ await git(["apply", "--whitespace=nowarn", file], inCopy);
82
+ fs.unlinkSync(file);
83
+ }
84
+ await git(["add", "-A"], inCopy);
85
+ await git(["-c", "user.name=comprism", "-c", "user.email=helper@illuminis.ai",
86
+ "commit", "-q", "--allow-empty", "--no-verify", "-m", "start"], inCopy);
87
+ copies.set(id, fs.realpathSync(where));
88
+ return { content: copies.get(id), summary: `copy ${id}` };
89
+ }
90
+ /** What the helper changed in its copy, as one diff. */
91
+ async function diffWorktree(id, opts) {
92
+ const where = copies.get(id);
93
+ if (!where)
94
+ return { isError: true, content: `There is no copy called ${id}.` };
95
+ const inCopy = { ...opts, root: where, cwd: undefined };
96
+ await git(["add", "-A"], inCopy);
97
+ const d = await git(["--no-pager", "diff", "--cached", "--binary", "--no-color", "HEAD"], inCopy);
98
+ if (!okExit(d))
99
+ return { isError: true, content: body(d) };
100
+ const text = body(d).trim() === "(no output)" ? "" : body(d);
101
+ return { content: text, summary: text ? "changes" : "no changes", facts: { changed: text ? 1 : 0 } };
102
+ }
103
+ async function closeWorktree(id, opts) {
104
+ const where = copies.get(id);
105
+ if (!where)
106
+ return { content: `${id} is already gone.` };
107
+ await git(["worktree", "remove", "--force", where], opts);
108
+ try {
109
+ fs.rmSync(where, { recursive: true, force: true });
110
+ }
111
+ catch { /* removed above */ }
112
+ copies.delete(id);
113
+ return { content: `Removed ${id}.` };
114
+ }
115
+ /** Every copy this process made, removed; for the end of a session. */
116
+ async function closeAllWorktrees(root) {
117
+ for (const id of [...copies.keys()])
118
+ await closeWorktree(id, { root });
119
+ }
@@ -51,9 +51,10 @@ const child_process_1 = require("child_process");
51
51
  const fs = __importStar(require("fs"));
52
52
  const os = __importStar(require("os"));
53
53
  const path = __importStar(require("path"));
54
+ const self_1 = require("../lib/self");
54
55
  /** The reader script, beside the built code in both a checkout and an install. */
55
56
  function scriptPath() {
56
- return path.resolve(__dirname, "..", "..", "scripts", "read_python.py");
57
+ return (0, self_1.shippedFile)("read_python.py", path.resolve(__dirname, "..", "..", "scripts", "read_python.py"));
57
58
  }
58
59
  let interpreter;
59
60
  /** Which Python this machine has, or null. Asked once per process. */
@@ -9,13 +9,27 @@ export interface Attached {
9
9
  /** The text was longer than one turn can carry and was cut. */
10
10
  truncated: boolean;
11
11
  isImage: boolean;
12
+ /** Bytes on disk, which the job record keeps (manual 3.11). */
13
+ sizeBytes: number;
14
+ /** What the service says about the file after its name, worded by the
15
+ * service so every client shows the same line (manual 3.1 and 3.6). */
16
+ summary: string;
17
+ }
18
+ /** Why one named file was left out, in the service's fixed list (manual 3.10). */
19
+ export interface Problem {
20
+ code: string;
21
+ message: string;
12
22
  }
13
23
  /** A path somebody named, before anything has been read. */
14
24
  export interface Mention {
15
25
  /** Exactly as it appeared, so it can be taken back out of the sentence. */
16
26
  raw: string;
17
- /** Resolved, unescaped and known to exist. */
27
+ /** Resolved and unescaped. */
18
28
  file: string;
29
+ /** As the person wrote it, unescaped, for the messages they read. */
30
+ shown: string;
31
+ /** Set when the file cannot be attached; nothing is sent for it. */
32
+ problem?: Problem;
19
33
  }
20
34
  /**
21
35
  * Take the shell's escaping back off a path.
@@ -23,17 +37,32 @@ export interface Mention {
23
37
  * A dragged file arrives as `/Users/me/My\ Report.pdf`, and a pasted one is
24
38
  * often in quotes. Both are the shell's way of saying "this is one thing", and
25
39
  * neither is part of the name.
40
+ *
41
+ * On Windows a backslash is the folder separator and never an escape: its
42
+ * terminals quote a dragged path instead. Stripping backslashes there turned
43
+ * `C:\Users\me\notes.txt` into `C:Usersmenotes.txt`, which was the Windows
44
+ * failure found in prompt 01.
45
+ */
46
+ export declare function unescapePath(token: string, platform?: string): string;
47
+ /**
48
+ * What stops a file being attached, checked on this machine before anything is
49
+ * sent (manual 3.10). Only the four facts the service cannot see: whether the
50
+ * file is there, is a folder, can be read, or is a link to nothing.
26
51
  */
27
- export declare function unescapePath(token: string): string;
52
+ export declare function localProblem(file: string, shown: string): Problem | undefined;
28
53
  /**
29
54
  * Every file the typed line points at, in the order they were named.
30
55
  *
31
- * A token that looks like a path but is not on the disk is left alone and stays
32
- * part of the question. Somebody writing about a path they plan to create is
33
- * doing something perfectly ordinary, and refusing their line over it would be
34
- * the tool arguing with them.
56
+ * Anything after an `@` is a request to attach, so a problem with it is
57
+ * reported. Any other path (absolute, `~/`, `./`, `../`, quoted) that is not a
58
+ * readable file is left alone and stays part of the question: somebody writing
59
+ * about a path they plan to create, or a folder they want looked at, is doing
60
+ * something perfectly ordinary.
35
61
  */
36
- export declare function mentions(line: string, cwd: string): Mention[];
62
+ export declare function mentions(line: string, root: string, here?: string, platform?: string): Mention[];
63
+ /** The line begins with an absolute path to something on the disk, as a
64
+ * dragged file does, rather than with a slashed command word. */
65
+ export declare function startsWithPath(line: string, platform?: string): boolean;
37
66
  /**
38
67
  * The question with the long paths taken out and the file names left in.
39
68
  *
@@ -43,20 +72,35 @@ export declare function mentions(line: string, cwd: string): Mention[];
43
72
  * nothing but a place for the model to try to open something it cannot reach.
44
73
  */
45
74
  export declare function withoutPaths(line: string, found: Mention[]): string;
75
+ /** The line with every mention taken out: empty when it named files and said
76
+ * nothing else, which is a drag and drop waiting for its question. */
77
+ export declare function withoutMentions(line: string, found: Mention[]): string;
46
78
  /**
47
79
  * Hand the files to the server and get back the ids the question will carry.
48
80
  *
49
81
  * One at a time and in order, because the caps are per file and a refusal names
50
- * which file it is refusing. A file that cannot be read does not stop the
51
- * others: the person gets their answer about the four that worked, and is told
52
- * plainly about the one that did not.
82
+ * which file it is refusing. The service is asked first, by name and size, so a
83
+ * program file or a file over the limit is refused before a byte of it moves.
84
+ * A file that cannot be read does not stop the others.
53
85
  */
54
86
  export declare function upload(baseUrl: string, credential: string, files: string[]): Promise<{
55
87
  attached: Attached[];
56
88
  refused: {
57
89
  file: string;
58
90
  why: string;
91
+ code?: string;
59
92
  }[];
60
93
  }>;
61
- /** What was attached, in one line each, for the person to see before it runs. */
62
- export declare function describe(a: Attached): string;
94
+ /** One `attached` line per file, names in a column, as manual 3.1 shows. */
95
+ export declare function describe(items: Attached[]): string[];
96
+ /** The waiting list, numbered for `detach N` (manual 3.6). */
97
+ export declare function listing(items: Attached[]): string[];
98
+ /**
99
+ * File names from the project for Tab after `@` (manual 3.1).
100
+ *
101
+ * A bounded walk, because a completion that takes a second is one nobody uses.
102
+ */
103
+ export declare function projectFiles(root: string, limit?: number): string[];
104
+ /** What Tab completes the line to, in readline's shape: the choices, and the
105
+ * part of the line they replace. */
106
+ export declare function completeAt(line: string, files: () => string[]): [string[], string];