@loompad/cli 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.
Files changed (177) hide show
  1. package/ARCHITECTURE.md +211 -0
  2. package/CHANGELOG.md +470 -0
  3. package/LICENSE +21 -0
  4. package/README.md +630 -0
  5. package/dist/adapters/base.d.ts +71 -0
  6. package/dist/adapters/base.js +187 -0
  7. package/dist/adapters/base.js.map +1 -0
  8. package/dist/adapters/bridges/antigravity.d.ts +53 -0
  9. package/dist/adapters/bridges/antigravity.js +106 -0
  10. package/dist/adapters/bridges/antigravity.js.map +1 -0
  11. package/dist/adapters/bridges/cdp.d.ts +82 -0
  12. package/dist/adapters/bridges/cdp.js +222 -0
  13. package/dist/adapters/bridges/cdp.js.map +1 -0
  14. package/dist/adapters/bridges/gui-chat.d.ts +113 -0
  15. package/dist/adapters/bridges/gui-chat.js +498 -0
  16. package/dist/adapters/bridges/gui-chat.js.map +1 -0
  17. package/dist/adapters/bridges/kiro.d.ts +19 -0
  18. package/dist/adapters/bridges/kiro.js +22 -0
  19. package/dist/adapters/bridges/kiro.js.map +1 -0
  20. package/dist/adapters/bridges/profiles.d.ts +82 -0
  21. package/dist/adapters/bridges/profiles.js +125 -0
  22. package/dist/adapters/bridges/profiles.js.map +1 -0
  23. package/dist/adapters/claude-code.d.ts +26 -0
  24. package/dist/adapters/claude-code.js +209 -0
  25. package/dist/adapters/claude-code.js.map +1 -0
  26. package/dist/adapters/codex.d.ts +51 -0
  27. package/dist/adapters/codex.js +291 -0
  28. package/dist/adapters/codex.js.map +1 -0
  29. package/dist/adapters/echo.d.ts +20 -0
  30. package/dist/adapters/echo.js +79 -0
  31. package/dist/adapters/echo.js.map +1 -0
  32. package/dist/adapters/grok.d.ts +61 -0
  33. package/dist/adapters/grok.js +217 -0
  34. package/dist/adapters/grok.js.map +1 -0
  35. package/dist/adapters/index.d.ts +9 -0
  36. package/dist/adapters/index.js +33 -0
  37. package/dist/adapters/index.js.map +1 -0
  38. package/dist/adapters/opencode.d.ts +64 -0
  39. package/dist/adapters/opencode.js +426 -0
  40. package/dist/adapters/opencode.js.map +1 -0
  41. package/dist/cli/common.d.ts +11 -0
  42. package/dist/cli/common.js +40 -0
  43. package/dist/cli/common.js.map +1 -0
  44. package/dist/cli/doctor.d.ts +12 -0
  45. package/dist/cli/doctor.js +181 -0
  46. package/dist/cli/doctor.js.map +1 -0
  47. package/dist/cli/index.d.ts +8 -0
  48. package/dist/cli/index.js +641 -0
  49. package/dist/cli/index.js.map +1 -0
  50. package/dist/cli/tui-model.d.ts +73 -0
  51. package/dist/cli/tui-model.js +312 -0
  52. package/dist/cli/tui-model.js.map +1 -0
  53. package/dist/cli/tui.d.ts +15 -0
  54. package/dist/cli/tui.js +451 -0
  55. package/dist/cli/tui.js.map +1 -0
  56. package/dist/cli/ui.d.ts +10 -0
  57. package/dist/cli/ui.js +135 -0
  58. package/dist/cli/ui.js.map +1 -0
  59. package/dist/core/ades.d.ts +79 -0
  60. package/dist/core/ades.js +130 -0
  61. package/dist/core/ades.js.map +1 -0
  62. package/dist/core/baton.d.ts +37 -0
  63. package/dist/core/baton.js +92 -0
  64. package/dist/core/baton.js.map +1 -0
  65. package/dist/core/brain-extract.d.ts +111 -0
  66. package/dist/core/brain-extract.js +248 -0
  67. package/dist/core/brain-extract.js.map +1 -0
  68. package/dist/core/brain-index.d.ts +128 -0
  69. package/dist/core/brain-index.js +338 -0
  70. package/dist/core/brain-index.js.map +1 -0
  71. package/dist/core/brain.d.ts +214 -0
  72. package/dist/core/brain.js +425 -0
  73. package/dist/core/brain.js.map +1 -0
  74. package/dist/core/claude-cli.d.ts +12 -0
  75. package/dist/core/claude-cli.js +47 -0
  76. package/dist/core/claude-cli.js.map +1 -0
  77. package/dist/core/distill.d.ts +19 -0
  78. package/dist/core/distill.js +88 -0
  79. package/dist/core/distill.js.map +1 -0
  80. package/dist/core/eventlog.d.ts +43 -0
  81. package/dist/core/eventlog.js +211 -0
  82. package/dist/core/eventlog.js.map +1 -0
  83. package/dist/core/git.d.ts +203 -0
  84. package/dist/core/git.js +460 -0
  85. package/dist/core/git.js.map +1 -0
  86. package/dist/core/logbook.d.ts +59 -0
  87. package/dist/core/logbook.js +118 -0
  88. package/dist/core/logbook.js.map +1 -0
  89. package/dist/core/memory.d.ts +34 -0
  90. package/dist/core/memory.js +124 -0
  91. package/dist/core/memory.js.map +1 -0
  92. package/dist/core/notify.d.ts +11 -0
  93. package/dist/core/notify.js +30 -0
  94. package/dist/core/notify.js.map +1 -0
  95. package/dist/core/projection.d.ts +20 -0
  96. package/dist/core/projection.js +96 -0
  97. package/dist/core/projection.js.map +1 -0
  98. package/dist/core/registry.d.ts +76 -0
  99. package/dist/core/registry.js +147 -0
  100. package/dist/core/registry.js.map +1 -0
  101. package/dist/core/router.d.ts +42 -0
  102. package/dist/core/router.js +99 -0
  103. package/dist/core/router.js.map +1 -0
  104. package/dist/core/routes.d.ts +93 -0
  105. package/dist/core/routes.js +399 -0
  106. package/dist/core/routes.js.map +1 -0
  107. package/dist/core/search.d.ts +63 -0
  108. package/dist/core/search.js +0 -0
  109. package/dist/core/search.js.map +1 -0
  110. package/dist/core/setup.d.ts +70 -0
  111. package/dist/core/setup.js +250 -0
  112. package/dist/core/setup.js.map +1 -0
  113. package/dist/core/suggestions.d.ts +15 -0
  114. package/dist/core/suggestions.js +38 -0
  115. package/dist/core/suggestions.js.map +1 -0
  116. package/dist/core/worktree.d.ts +32 -0
  117. package/dist/core/worktree.js +83 -0
  118. package/dist/core/worktree.js.map +1 -0
  119. package/dist/daemon/app-page.d.ts +32 -0
  120. package/dist/daemon/app-page.js +6363 -0
  121. package/dist/daemon/app-page.js.map +1 -0
  122. package/dist/daemon/auth.d.ts +51 -0
  123. package/dist/daemon/auth.js +135 -0
  124. package/dist/daemon/auth.js.map +1 -0
  125. package/dist/daemon/board.d.ts +117 -0
  126. package/dist/daemon/board.js +202 -0
  127. package/dist/daemon/board.js.map +1 -0
  128. package/dist/daemon/brand-icons.d.ts +29 -0
  129. package/dist/daemon/brand-icons.js +44 -0
  130. package/dist/daemon/brand-icons.js.map +1 -0
  131. package/dist/daemon/client.d.ts +127 -0
  132. package/dist/daemon/client.js +237 -0
  133. package/dist/daemon/client.js.map +1 -0
  134. package/dist/daemon/geist-font.d.ts +10 -0
  135. package/dist/daemon/geist-font.js +783 -0
  136. package/dist/daemon/geist-font.js.map +1 -0
  137. package/dist/daemon/guards.d.ts +18 -0
  138. package/dist/daemon/guards.js +40 -0
  139. package/dist/daemon/guards.js.map +1 -0
  140. package/dist/daemon/linear.d.ts +59 -0
  141. package/dist/daemon/linear.js +117 -0
  142. package/dist/daemon/linear.js.map +1 -0
  143. package/dist/daemon/push.d.ts +22 -0
  144. package/dist/daemon/push.js +58 -0
  145. package/dist/daemon/push.js.map +1 -0
  146. package/dist/daemon/runtime.d.ts +299 -0
  147. package/dist/daemon/runtime.js +1016 -0
  148. package/dist/daemon/runtime.js.map +1 -0
  149. package/dist/daemon/server.d.ts +125 -0
  150. package/dist/daemon/server.js +1728 -0
  151. package/dist/daemon/server.js.map +1 -0
  152. package/dist/daemon/tasks.d.ts +153 -0
  153. package/dist/daemon/tasks.js +264 -0
  154. package/dist/daemon/tasks.js.map +1 -0
  155. package/dist/daemon/terminals.d.ts +82 -0
  156. package/dist/daemon/terminals.js +372 -0
  157. package/dist/daemon/terminals.js.map +1 -0
  158. package/dist/index.d.ts +20 -0
  159. package/dist/index.js +20 -0
  160. package/dist/index.js.map +1 -0
  161. package/dist/sdk.d.ts +17 -0
  162. package/dist/sdk.js +17 -0
  163. package/dist/sdk.js.map +1 -0
  164. package/dist/types.d.ts +236 -0
  165. package/dist/types.js +18 -0
  166. package/dist/types.js.map +1 -0
  167. package/docs/SETUP.md +265 -0
  168. package/docs/adapters.md +132 -0
  169. package/docs/design-system.md +245 -0
  170. package/docs/img/board-linear.png +0 -0
  171. package/docs/img/board-projects.png +0 -0
  172. package/docs/img/brain.png +0 -0
  173. package/docs/img/settings.png +0 -0
  174. package/docs/img/workspace.png +0 -0
  175. package/docs/integration-notes.md +76 -0
  176. package/docs/proposals/brain.md +262 -0
  177. package/package.json +84 -0
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Terminal sessions for the workspace, in two flavours behind one interface.
3
+ *
4
+ * `pty` — a real pseudo-terminal via node-pty. The shell believes it's on a
5
+ * tty, so you get everything a terminal is supposed to do: its own prompt,
6
+ * echo, job control (^C/^Z), colour, `less`/`vim`/`htop`, and window size.
7
+ * node-pty is a native module, so it's an *optional* dependency.
8
+ *
9
+ * `pipe` — the fallback when node-pty isn't available (notably Linux without
10
+ * build tools, since node-pty ships prebuilds only for macOS/Windows). A
11
+ * long-lived shell on plain pipes: `cd` and variables persist and ^C works
12
+ * via the process group, but there's no echo or job control, so the client
13
+ * drives it a line at a time and draws its own prompt. See `docs/`.
14
+ *
15
+ * Both keep a scrollback buffer so a client that reloads can be replayed the
16
+ * session it left behind.
17
+ */
18
+ /** Sentinel the pipe shell prints after each command: `<MARK><rc>\t<cwd>\n`. */
19
+ export declare const TERM_MARK = "__LOOM_END__";
20
+ export type TermMode = "pty" | "pipe";
21
+ export interface TermEvents {
22
+ onData(projectId: string, termId: string, chunk: string): void;
23
+ /** pipe mode only: a command finished, with its exit code and new cwd. */
24
+ onCommandEnd(projectId: string, termId: string, exit: number, cwd: string): void;
25
+ onExit(projectId: string, termId: string): void;
26
+ onTitle(projectId: string, termId: string, title: string): void;
27
+ }
28
+ export interface TerminalSession {
29
+ readonly projectId: string;
30
+ readonly termId: string;
31
+ readonly mode: TermMode;
32
+ cwd: string;
33
+ /** Raw input. In pty mode these are keystrokes; in pipe mode, a command. */
34
+ write(data: string): void;
35
+ resize(cols: number, rows: number): void;
36
+ interrupt(): void;
37
+ kill(): void;
38
+ scrollback(): string;
39
+ }
40
+ export interface PtyProcess {
41
+ pid: number;
42
+ onData(cb: (d: string) => void): void;
43
+ onExit(cb: () => void): void;
44
+ write(d: string): void;
45
+ resize(cols: number, rows: number): void;
46
+ kill(signal?: string): void;
47
+ }
48
+ interface PtyModule {
49
+ spawn(file: string, args: string[], opts: {
50
+ name: string;
51
+ cols: number;
52
+ rows: number;
53
+ cwd: string;
54
+ env: NodeJS.ProcessEnv;
55
+ }): PtyProcess;
56
+ }
57
+ /** Load node-pty once, proving it can actually spawn before we rely on it. */
58
+ export declare function loadPty(): PtyModule | null;
59
+ export declare function ptyUnavailableReason(): string | null;
60
+ /**
61
+ * The session cap, distinct from every other reason a shell won't start. A
62
+ * spawn failure and "you have too many tabs open" are different facts and the
63
+ * caller answers them with different status codes.
64
+ */
65
+ export declare class TooManySessionsError extends Error {
66
+ constructor(max: number);
67
+ }
68
+ export declare class TerminalManager {
69
+ private events;
70
+ private maxSessions;
71
+ private sessions;
72
+ constructor(events: TermEvents, maxSessions?: number);
73
+ get mode(): TermMode;
74
+ private key;
75
+ get(projectId: string, termId: string): TerminalSession | undefined;
76
+ open(projectId: string, termId: string, dir: string, cols?: number, rows?: number): TerminalSession;
77
+ close(projectId: string, termId: string): void;
78
+ /** Drop a session from the registry once its process is gone. */
79
+ forget(projectId: string, termId: string): void;
80
+ closeAll(): void;
81
+ }
82
+ export {};
@@ -0,0 +1,372 @@
1
+ /**
2
+ * Terminal sessions for the workspace, in two flavours behind one interface.
3
+ *
4
+ * `pty` — a real pseudo-terminal via node-pty. The shell believes it's on a
5
+ * tty, so you get everything a terminal is supposed to do: its own prompt,
6
+ * echo, job control (^C/^Z), colour, `less`/`vim`/`htop`, and window size.
7
+ * node-pty is a native module, so it's an *optional* dependency.
8
+ *
9
+ * `pipe` — the fallback when node-pty isn't available (notably Linux without
10
+ * build tools, since node-pty ships prebuilds only for macOS/Windows). A
11
+ * long-lived shell on plain pipes: `cd` and variables persist and ^C works
12
+ * via the process group, but there's no echo or job control, so the client
13
+ * drives it a line at a time and draws its own prompt. See `docs/`.
14
+ *
15
+ * Both keep a scrollback buffer so a client that reloads can be replayed the
16
+ * session it left behind.
17
+ */
18
+ import { spawn } from "node:child_process";
19
+ import fs from "node:fs";
20
+ import { createRequire } from "node:module";
21
+ import path from "node:path";
22
+ const require_ = createRequire(import.meta.url);
23
+ /** Sentinel the pipe shell prints after each command: `<MARK><rc>\t<cwd>\n`. */
24
+ export const TERM_MARK = "__LOOM_END__";
25
+ const isWin = process.platform === "win32";
26
+ /** Keep the last of a session's output for replay after a client reload. */
27
+ const SCROLLBACK_MAX = 256 * 1024;
28
+ /** Per-command output budget in pipe mode (a pty is interactive, so unbounded). */
29
+ const PIPE_OUTPUT_MAX = 2_000_000;
30
+ let ptyModule;
31
+ let ptyLoadError = null;
32
+ /**
33
+ * node-pty's macOS/Linux prebuilds ship `spawn-helper` without the executable
34
+ * bit (npm doesn't preserve it through the prebuild archive), and node-pty
35
+ * then fails every spawn with a bare "posix_spawnp failed". Repair it rather
36
+ * than making every user chmod a file inside node_modules.
37
+ */
38
+ function fixSpawnHelper(moduleDir) {
39
+ if (isWin)
40
+ return;
41
+ const roots = [path.join(moduleDir, "prebuilds"), path.join(moduleDir, "build", "Release")];
42
+ for (const root of roots) {
43
+ let entries;
44
+ try {
45
+ entries = fs.readdirSync(root);
46
+ }
47
+ catch {
48
+ continue;
49
+ }
50
+ for (const entry of entries) {
51
+ const candidates = [path.join(root, entry, "spawn-helper"), path.join(root, entry)];
52
+ for (const file of candidates) {
53
+ try {
54
+ const st = fs.statSync(file);
55
+ if (!st.isFile() || path.basename(file) !== "spawn-helper")
56
+ continue;
57
+ if (st.mode & 0o111)
58
+ continue; // already executable
59
+ fs.chmodSync(file, st.mode | 0o755);
60
+ }
61
+ catch {
62
+ /* not present, or not ours to chmod — the probe below decides */
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+ /** Load node-pty once, proving it can actually spawn before we rely on it. */
69
+ export function loadPty() {
70
+ if (ptyModule !== undefined)
71
+ return ptyModule;
72
+ // An escape hatch: forces the pipe path on a machine that has node-pty, so
73
+ // the fallback stays exercisable (it is what Linux without a toolchain gets).
74
+ if (process.env.LOOM_NO_PTY === "1") {
75
+ ptyLoadError = "disabled by LOOM_NO_PTY=1";
76
+ ptyModule = null;
77
+ return null;
78
+ }
79
+ try {
80
+ const dir = path.dirname(require_.resolve("node-pty/package.json"));
81
+ fixSpawnHelper(dir);
82
+ const mod = require_("node-pty");
83
+ // A load isn't proof: the native binary can resolve and still fail to
84
+ // spawn (missing helper, hardened runtime, seccomp). Try it for real.
85
+ const probe = mod.spawn(isWin ? "cmd.exe" : "/bin/sh", [], {
86
+ name: "xterm-256color",
87
+ cols: 80,
88
+ rows: 24,
89
+ cwd: process.cwd(),
90
+ env: process.env,
91
+ });
92
+ probe.kill();
93
+ ptyModule = mod;
94
+ }
95
+ catch (err) {
96
+ ptyLoadError = err.message;
97
+ ptyModule = null;
98
+ }
99
+ return ptyModule;
100
+ }
101
+ export function ptyUnavailableReason() {
102
+ loadPty();
103
+ return ptyModule ? null : (ptyLoadError ?? "node-pty is not installed");
104
+ }
105
+ // ---------------------------------------------------------------------------
106
+ // sessions
107
+ // ---------------------------------------------------------------------------
108
+ function baseEnv() {
109
+ return {
110
+ ...process.env,
111
+ TERM: "xterm-256color",
112
+ COLORTERM: "truecolor",
113
+ // The pager would sit there waiting for a key we can't easily send in
114
+ // pipe mode; in pty mode `less` works, but git's default pager still
115
+ // fights the small pane, so keep output inline in both.
116
+ PAGER: "cat",
117
+ GIT_PAGER: "cat",
118
+ LOOM_TERMINAL: "1",
119
+ };
120
+ }
121
+ class PtySession {
122
+ projectId;
123
+ termId;
124
+ cwd;
125
+ mode = "pty";
126
+ buf = "";
127
+ proc;
128
+ constructor(projectId, termId, cwd, mod, events, cols, rows) {
129
+ this.projectId = projectId;
130
+ this.termId = termId;
131
+ this.cwd = cwd;
132
+ const shell = isWin ? "cmd.exe" : process.env.SHELL || "/bin/sh";
133
+ this.proc = mod.spawn(shell, [], {
134
+ name: "xterm-256color",
135
+ cols,
136
+ rows,
137
+ cwd,
138
+ env: baseEnv(),
139
+ });
140
+ this.proc.onData((d) => {
141
+ this.buf = (this.buf + d).slice(-SCROLLBACK_MAX);
142
+ // OSC 7 (cwd) and OSC 0/2 (title) are how a shell reports where it is;
143
+ // read them if present, but never strip them — the emulator wants them.
144
+ const cwdMatch = /\u001b\]7;file:\/\/[^/]*([^\u0007\u001b]*)(?:\u0007|\u001b\\)/.exec(d);
145
+ if (cwdMatch?.[1])
146
+ this.cwd = decodeURIComponent(cwdMatch[1]);
147
+ const titleMatch = /\u001b\][02];([^\u0007\u001b]*)(?:\u0007|\u001b\\)/.exec(d);
148
+ if (titleMatch?.[1])
149
+ events.onTitle(projectId, termId, titleMatch[1]);
150
+ events.onData(projectId, termId, d);
151
+ });
152
+ this.proc.onExit(() => events.onExit(projectId, termId));
153
+ }
154
+ write(data) {
155
+ this.proc.write(data);
156
+ }
157
+ resize(cols, rows) {
158
+ try {
159
+ this.proc.resize(Math.max(2, cols), Math.max(1, rows));
160
+ }
161
+ catch {
162
+ /* the pty went away mid-resize */
163
+ }
164
+ }
165
+ interrupt() {
166
+ // A real tty turns ^C into SIGINT for the foreground job itself.
167
+ this.write("\u0003");
168
+ }
169
+ kill() {
170
+ try {
171
+ this.proc.kill();
172
+ }
173
+ catch {
174
+ /* already gone */
175
+ }
176
+ }
177
+ scrollback() {
178
+ return this.buf;
179
+ }
180
+ }
181
+ class PipeSession {
182
+ projectId;
183
+ termId;
184
+ cwd;
185
+ events;
186
+ mode = "pipe";
187
+ child;
188
+ pending = "";
189
+ buf = "";
190
+ sent = 0;
191
+ constructor(projectId, termId, cwd, events) {
192
+ this.projectId = projectId;
193
+ this.termId = termId;
194
+ this.cwd = cwd;
195
+ this.events = events;
196
+ const shell = isWin ? "cmd.exe" : process.env.SHELL || "/bin/sh";
197
+ this.child = spawn(shell, isWin ? [] : ["-s"], {
198
+ cwd,
199
+ detached: !isWin, // own process group, so ^C reaches the foreground job
200
+ env: baseEnv(),
201
+ stdio: ["pipe", "pipe", "pipe"],
202
+ });
203
+ // A non-interactive shell dies on SIGINT by default, taking the session
204
+ // with it. A handled signal resets to default in children, so the shell
205
+ // survives while the foreground job still dies.
206
+ if (!isWin)
207
+ this.child.stdin?.write("trap ':' INT\n");
208
+ const onData = (b) => this.pump(b.toString("utf8"));
209
+ this.child.stdout?.on("data", onData);
210
+ this.child.stderr?.on("data", onData);
211
+ this.child.on("error", (err) => events.onData(projectId, termId, `loom: ${err.message}\n`));
212
+ this.child.on("close", () => events.onExit(projectId, termId));
213
+ }
214
+ write(data) {
215
+ this.sent = 0;
216
+ const probe = isWin
217
+ ? `\r\necho ${TERM_MARK}%ERRORLEVEL%\t%CD%\r\n`
218
+ : `\n__loom_rc=$?; printf '\\n${TERM_MARK}%s\\t%s\\n' "$__loom_rc" "$PWD"\n`;
219
+ this.child.stdin?.write(data + probe);
220
+ }
221
+ resize() {
222
+ /* no tty to resize */
223
+ }
224
+ interrupt() {
225
+ if (!this.child.pid)
226
+ return;
227
+ try {
228
+ process.kill(-this.child.pid, "SIGINT");
229
+ }
230
+ catch {
231
+ try {
232
+ this.child.kill("SIGINT");
233
+ }
234
+ catch {
235
+ /* gone */
236
+ }
237
+ }
238
+ }
239
+ kill() {
240
+ try {
241
+ if (this.child.pid && !isWin)
242
+ process.kill(-this.child.pid, "SIGKILL");
243
+ else
244
+ this.child.kill("SIGKILL");
245
+ }
246
+ catch {
247
+ /* gone */
248
+ }
249
+ }
250
+ scrollback() {
251
+ return this.buf;
252
+ }
253
+ /**
254
+ * Strip the end-of-command sentinel out of the stream and report it. It can
255
+ * straddle two reads, so hold back any trailing partial match.
256
+ */
257
+ pump(text) {
258
+ this.pending += text;
259
+ for (;;) {
260
+ const idx = this.pending.indexOf(TERM_MARK);
261
+ if (idx === -1)
262
+ break;
263
+ const nl = this.pending.indexOf("\n", idx);
264
+ if (nl === -1) {
265
+ this.emit(this.pending.slice(0, idx));
266
+ this.pending = this.pending.slice(idx);
267
+ return;
268
+ }
269
+ // the sentinel is printed with a leading newline so it lands on its own
270
+ // line; drop that one back off so output isn't padded by a blank line
271
+ let pre = this.pending.slice(0, idx);
272
+ if (pre.endsWith("\n"))
273
+ pre = pre.slice(0, -1);
274
+ this.emit(pre);
275
+ const line = this.pending.slice(idx + TERM_MARK.length, nl);
276
+ const tab = line.indexOf("\t");
277
+ const code = Number(tab === -1 ? line : line.slice(0, tab));
278
+ const cwd = tab === -1 ? "" : line.slice(tab + 1).trim();
279
+ if (cwd)
280
+ this.cwd = cwd;
281
+ this.pending = this.pending.slice(nl + 1);
282
+ this.events.onCommandEnd(this.projectId, this.termId, Number.isFinite(code) ? code : 0, this.cwd);
283
+ }
284
+ let hold = 0;
285
+ for (let i = Math.min(TERM_MARK.length - 1, this.pending.length); i > 0; i--) {
286
+ if (this.pending.endsWith(TERM_MARK.slice(0, i))) {
287
+ hold = i;
288
+ break;
289
+ }
290
+ }
291
+ const emit = this.pending.slice(0, this.pending.length - hold);
292
+ this.pending = this.pending.slice(this.pending.length - hold);
293
+ this.emit(emit);
294
+ }
295
+ emit(chunk) {
296
+ if (!chunk)
297
+ return;
298
+ if (this.sent >= PIPE_OUTPUT_MAX)
299
+ return;
300
+ let out = chunk;
301
+ if (this.sent + out.length > PIPE_OUTPUT_MAX) {
302
+ out = out.slice(0, PIPE_OUTPUT_MAX - this.sent) + "\n…output truncated…\n";
303
+ }
304
+ this.sent += out.length;
305
+ this.buf = (this.buf + out).slice(-SCROLLBACK_MAX);
306
+ this.events.onData(this.projectId, this.termId, out);
307
+ }
308
+ }
309
+ // ---------------------------------------------------------------------------
310
+ // manager
311
+ // ---------------------------------------------------------------------------
312
+ /**
313
+ * The session cap, distinct from every other reason a shell won't start. A
314
+ * spawn failure and "you have too many tabs open" are different facts and the
315
+ * caller answers them with different status codes.
316
+ */
317
+ export class TooManySessionsError extends Error {
318
+ constructor(max) {
319
+ super(`too many terminal sessions (max ${max})`);
320
+ this.name = "TooManySessionsError";
321
+ }
322
+ }
323
+ export class TerminalManager {
324
+ events;
325
+ maxSessions;
326
+ sessions = new Map();
327
+ constructor(events, maxSessions = 12) {
328
+ this.events = events;
329
+ this.maxSessions = maxSessions;
330
+ }
331
+ get mode() {
332
+ return loadPty() ? "pty" : "pipe";
333
+ }
334
+ key(projectId, termId) {
335
+ return `${projectId}:${termId}`;
336
+ }
337
+ get(projectId, termId) {
338
+ return this.sessions.get(this.key(projectId, termId));
339
+ }
340
+ open(projectId, termId, dir, cols = 80, rows = 24) {
341
+ const existing = this.get(projectId, termId);
342
+ if (existing)
343
+ return existing;
344
+ if (this.sessions.size >= this.maxSessions)
345
+ throw new TooManySessionsError(this.maxSessions);
346
+ const mod = loadPty();
347
+ const sess = mod
348
+ ? new PtySession(projectId, termId, dir, mod, this.events, cols, rows)
349
+ : new PipeSession(projectId, termId, dir, this.events);
350
+ this.sessions.set(this.key(projectId, termId), sess);
351
+ return sess;
352
+ }
353
+ close(projectId, termId) {
354
+ const key = this.key(projectId, termId);
355
+ const sess = this.sessions.get(key);
356
+ if (!sess)
357
+ return;
358
+ this.sessions.delete(key);
359
+ sess.kill();
360
+ }
361
+ /** Drop a session from the registry once its process is gone. */
362
+ forget(projectId, termId) {
363
+ this.sessions.delete(this.key(projectId, termId));
364
+ }
365
+ closeAll() {
366
+ for (const [key, sess] of this.sessions) {
367
+ this.sessions.delete(key);
368
+ sess.kill();
369
+ }
370
+ }
371
+ }
372
+ //# sourceMappingURL=terminals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminals.js","sourceRoot":"","sources":["../../src/daemon/terminals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Loom — library entry point.
3
+ * Everything a programmatic consumer (or the future iOS app's dev tooling)
4
+ * needs to talk to a loom daemon or embed the core.
5
+ */
6
+ export * from "./types.js";
7
+ export { EventLog } from "./core/eventlog.js";
8
+ export { BatonManager, NotHolderError } from "./core/baton.js";
9
+ export { buildBriefing, buildProjection } from "./core/projection.js";
10
+ export { buildUnifiedMemory, readNativeMemory, nativeMemoryFiles } from "./core/memory.js";
11
+ export { suggestHandoff } from "./core/suggestions.js";
12
+ export { RouteEngine, RouteActiveError, resolveSteps, stepName } from "./core/routes.js";
13
+ export { rulesRouter, llmRouter } from "./core/router.js";
14
+ export type { HopDecision, RouterContext } from "./core/router.js";
15
+ export { renderProjection } from "./core/distill.js";
16
+ export { claudeText } from "./core/claude-cli.js";
17
+ export { listProjects, findProject, registerProject, readProjectConfig, writeProjectConfig, loomHome, } from "./core/registry.js";
18
+ export { ProjectRuntime } from "./daemon/runtime.js";
19
+ export { LoomDaemon, DEFAULT_PORT, tailscaleIp } from "./daemon/server.js";
20
+ export { DaemonClient, ensureDaemon, daemonRunning, stopDaemon } from "./daemon/client.js";
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Loom — library entry point.
3
+ * Everything a programmatic consumer (or the future iOS app's dev tooling)
4
+ * needs to talk to a loom daemon or embed the core.
5
+ */
6
+ export * from "./types.js";
7
+ export { EventLog } from "./core/eventlog.js";
8
+ export { BatonManager, NotHolderError } from "./core/baton.js";
9
+ export { buildBriefing, buildProjection } from "./core/projection.js";
10
+ export { buildUnifiedMemory, readNativeMemory, nativeMemoryFiles } from "./core/memory.js";
11
+ export { suggestHandoff } from "./core/suggestions.js";
12
+ export { RouteEngine, RouteActiveError, resolveSteps, stepName } from "./core/routes.js";
13
+ export { rulesRouter, llmRouter } from "./core/router.js";
14
+ export { renderProjection } from "./core/distill.js";
15
+ export { claudeText } from "./core/claude-cli.js";
16
+ export { listProjects, findProject, registerProject, readProjectConfig, writeProjectConfig, loomHome, } from "./core/registry.js";
17
+ export { ProjectRuntime } from "./daemon/runtime.js";
18
+ export { LoomDaemon, DEFAULT_PORT, tailscaleIp } from "./daemon/server.js";
19
+ export { DaemonClient, ensureDaemon, daemonRunning, stopDaemon } from "./daemon/client.js";
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EACL,YAAY,EACZ,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,GACT,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/sdk.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Loom Adapter SDK — build an adapter (full-duplex) or a bridge (read-mostly)
3
+ * for a new agent and register it with `registerAgentKind`.
4
+ *
5
+ * Contract (see ARCHITECTURE.md):
6
+ * - Adapters MUST implement send / stream (onEvent) / injectMemory /
7
+ * interrupt / diff, and may hold the baton.
8
+ * - Bridges only observe and receive projections; they never hold the baton.
9
+ */
10
+ export type { Adapter, AdapterEvent, AgentCapabilities, AgentConfig, AgentRole, AgentTier, AnyAgent, Bridge, EventKind, SendInput, } from "./types.js";
11
+ export { isAdapter } from "./types.js";
12
+ export { AdapterBase, AgentBase, BridgeBase, cliAvailable, fetchJson, freePort, waitFor, } from "./adapters/base.js";
13
+ export { registerAgentKind, createAgent, knownAgentKinds } from "./adapters/index.js";
14
+ export { EchoAdapter } from "./adapters/echo.js";
15
+ export { ClaudeCodeAdapter } from "./adapters/claude-code.js";
16
+ export { OpenCodeAdapter } from "./adapters/opencode.js";
17
+ export { AntigravityBridge } from "./adapters/bridges/antigravity.js";
package/dist/sdk.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Loom Adapter SDK — build an adapter (full-duplex) or a bridge (read-mostly)
3
+ * for a new agent and register it with `registerAgentKind`.
4
+ *
5
+ * Contract (see ARCHITECTURE.md):
6
+ * - Adapters MUST implement send / stream (onEvent) / injectMemory /
7
+ * interrupt / diff, and may hold the baton.
8
+ * - Bridges only observe and receive projections; they never hold the baton.
9
+ */
10
+ export { isAdapter } from "./types.js";
11
+ export { AdapterBase, AgentBase, BridgeBase, cliAvailable, fetchJson, freePort, waitFor, } from "./adapters/base.js";
12
+ export { registerAgentKind, createAgent, knownAgentKinds } from "./adapters/index.js";
13
+ export { EchoAdapter } from "./adapters/echo.js";
14
+ export { ClaudeCodeAdapter } from "./adapters/claude-code.js";
15
+ export { OpenCodeAdapter } from "./adapters/opencode.js";
16
+ export { AntigravityBridge } from "./adapters/bridges/antigravity.js";
17
+ //# sourceMappingURL=sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.js","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EACL,WAAW,EACX,SAAS,EACT,UAAU,EACV,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,OAAO,GACR,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtF,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC"}