@heyditto/cli 2.10.0 → 2.12.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 (53) hide show
  1. package/README.md +74 -0
  2. package/dist/agents/launch.d.ts +11 -0
  3. package/dist/agents/launch.js +207 -9
  4. package/dist/agents/launch.js.map +1 -1
  5. package/dist/api.d.ts +129 -0
  6. package/dist/api.js +82 -0
  7. package/dist/api.js.map +1 -1
  8. package/dist/cli.js +14 -0
  9. package/dist/cli.js.map +1 -1
  10. package/dist/commands.js +5 -1
  11. package/dist/commands.js.map +1 -1
  12. package/dist/org-commands.d.ts +52 -0
  13. package/dist/org-commands.js +511 -0
  14. package/dist/org-commands.js.map +1 -0
  15. package/dist/remote/attachments.d.ts +22 -0
  16. package/dist/remote/attachments.js +0 -0
  17. package/dist/remote/attachments.js.map +1 -0
  18. package/dist/remote/catalog.d.ts +18 -0
  19. package/dist/remote/catalog.js +309 -0
  20. package/dist/remote/catalog.js.map +1 -0
  21. package/dist/remote/controller.d.ts +76 -0
  22. package/dist/remote/controller.js +352 -0
  23. package/dist/remote/controller.js.map +1 -0
  24. package/dist/remote/fork-command.d.ts +8 -0
  25. package/dist/remote/fork-command.js +50 -0
  26. package/dist/remote/fork-command.js.map +1 -0
  27. package/dist/remote/fork.d.ts +22 -0
  28. package/dist/remote/fork.js +113 -0
  29. package/dist/remote/fork.js.map +1 -0
  30. package/dist/remote/headless.d.ts +30 -0
  31. package/dist/remote/headless.js +75 -0
  32. package/dist/remote/headless.js.map +1 -0
  33. package/dist/remote/hook.d.ts +2 -0
  34. package/dist/remote/hook.js +69 -0
  35. package/dist/remote/hook.js.map +1 -0
  36. package/dist/remote/hooks.d.ts +30 -0
  37. package/dist/remote/hooks.js +95 -0
  38. package/dist/remote/hooks.js.map +1 -0
  39. package/dist/remote/host.d.ts +63 -0
  40. package/dist/remote/host.js +240 -0
  41. package/dist/remote/host.js.map +1 -0
  42. package/dist/remote/protocol.d.ts +163 -0
  43. package/dist/remote/protocol.js +11 -0
  44. package/dist/remote/protocol.js.map +1 -0
  45. package/dist/remote/pty.d.ts +56 -0
  46. package/dist/remote/pty.js +100 -0
  47. package/dist/remote/pty.js.map +1 -0
  48. package/dist/store.d.ts +11 -0
  49. package/dist/store.js.map +1 -1
  50. package/dist/teleport/commands.d.ts +6 -0
  51. package/dist/teleport/commands.js +11 -0
  52. package/dist/teleport/commands.js.map +1 -1
  53. package/package.json +9 -2
@@ -0,0 +1,309 @@
1
+ import { watch } from "node:fs";
2
+ import { readFile, readdir, stat } from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ /**
6
+ * The command catalog a session announces (`session.commands`): what the app
7
+ * may put behind "/" in its composer. Builtins are listed per harness version
8
+ * we ship against; custom commands, skills and plugin skills are read from the
9
+ * same directories the harness reads, so the catalog is what the user would
10
+ * see locally. Everything is best effort: an unreadable directory contributes
11
+ * nothing rather than failing the session.
12
+ */
13
+ function claudeHome() {
14
+ return process.env.CLAUDE_CONFIG_DIR?.trim() || path.join(os.homedir(), ".claude");
15
+ }
16
+ function codexHome() {
17
+ return process.env.CODEX_HOME?.trim() || path.join(os.homedir(), ".codex");
18
+ }
19
+ /**
20
+ * Claude Code 2.1.x builtins. `headless` is true only for the ones that are
21
+ * prompt expansions (they work under `claude -p`); the rest drive the TUI.
22
+ */
23
+ const CLAUDE_BUILTINS = [
24
+ ["help", "show help and available commands", false],
25
+ ["clear", "clear conversation history", false],
26
+ ["compact", "compact the conversation, optionally with focus instructions", false, "[instructions]"],
27
+ ["context", "show current context usage", false],
28
+ ["cost", "show token usage and cost for this session", false],
29
+ ["model", "set the model for the session", false, "[model]"],
30
+ ["review", "review a pull request", true, "[pr]"],
31
+ ["init", "create a CLAUDE.md for this repository", true],
32
+ ["memory", "edit memory files", false],
33
+ ["config", "open the settings", false],
34
+ ["status", "show session status", false],
35
+ ["doctor", "check the health of the installation", false],
36
+ ["permissions", "view or update permissions", false],
37
+ ["mcp", "manage MCP servers", false],
38
+ ["agents", "manage agent configurations", false],
39
+ ["hooks", "manage hook configurations", false],
40
+ ["resume", "resume a previous conversation", false],
41
+ ["rewind", "rewind the conversation or code", false],
42
+ ["export", "export the conversation", false, "[file]"],
43
+ ["add-dir", "add a working directory", false, "<path>"],
44
+ ["plan", "enter plan mode", false],
45
+ ["fast", "toggle fast mode", false],
46
+ ["pr-comments", "fetch comments from a GitHub pull request", true, "[pr]"],
47
+ ["release-notes", "show release notes", false],
48
+ ["bug", "report a bug", false],
49
+ ["vim", "toggle vim editing mode", false],
50
+ ["exit", "exit the session", false],
51
+ ];
52
+ /** Codex 0.153.x builtins; none of them exist under `codex exec`. */
53
+ const CODEX_BUILTINS = [
54
+ ["model", "choose the model and reasoning effort"],
55
+ ["new", "start a new chat"],
56
+ ["compact", "summarize the conversation to free context"],
57
+ ["diff", "show git diff (including untracked files)"],
58
+ ["status", "show session configuration and token usage"],
59
+ ["approvals", "choose what Codex can do without approval"],
60
+ ["permissions", "choose what Codex can do without approval"],
61
+ ["init", "create an AGENTS.md for this repository"],
62
+ ["mention", "mention a file", "<path>"],
63
+ ["review", "review the working tree changes"],
64
+ ["mcp", "list configured MCP tools"],
65
+ ["skills", "list the available skills"],
66
+ ["plan", "plan mode"],
67
+ ["undo", "undo the last file changes"],
68
+ ["resume", "resume a saved chat"],
69
+ ["personality", "choose the assistant's personality"],
70
+ ["feedback", "send feedback"],
71
+ ["logout", "log out of Codex"],
72
+ ["quit", "exit Codex"],
73
+ ];
74
+ /** `key: value` lines between the leading `---` fences; enough for command and skill files. */
75
+ export function parseFrontmatter(text) {
76
+ const fields = {};
77
+ if (!text.startsWith("---"))
78
+ return { fields, body: text };
79
+ const end = text.indexOf("\n---", 3);
80
+ if (end === -1)
81
+ return { fields, body: text };
82
+ for (const line of text.slice(3, end).split("\n")) {
83
+ const m = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
84
+ if (m)
85
+ fields[m[1].toLowerCase()] = m[2].trim().replace(/^["']|["']$/g, "");
86
+ }
87
+ return { fields, body: text.slice(end + 4).replace(/^\r?\n/, "") };
88
+ }
89
+ function firstLine(body) {
90
+ const line = body
91
+ .split("\n")
92
+ .map((l) => l.trim())
93
+ .find((l) => l && !l.startsWith("#") && !l.startsWith("<!--"));
94
+ return (line ?? "").slice(0, 200);
95
+ }
96
+ async function isDir(p) {
97
+ try {
98
+ return (await stat(p)).isDirectory();
99
+ }
100
+ catch {
101
+ return false;
102
+ }
103
+ }
104
+ async function readText(p) {
105
+ try {
106
+ return await readFile(p, "utf8");
107
+ }
108
+ catch {
109
+ return undefined;
110
+ }
111
+ }
112
+ /** Markdown command files under `dir` (recursive), as `<name>` entries. */
113
+ async function commandFiles(dir, source, prefix = "") {
114
+ if (!(await isDir(dir)))
115
+ return [];
116
+ const out = [];
117
+ let entries;
118
+ try {
119
+ entries = (await readdir(dir)).sort();
120
+ }
121
+ catch {
122
+ return [];
123
+ }
124
+ for (const entry of entries) {
125
+ const full = path.join(dir, entry);
126
+ if (await isDir(full)) {
127
+ out.push(...(await commandFiles(full, source, prefix)));
128
+ continue;
129
+ }
130
+ if (!entry.endsWith(".md"))
131
+ continue;
132
+ const text = await readText(full);
133
+ if (text === undefined)
134
+ continue;
135
+ const { fields, body } = parseFrontmatter(text);
136
+ out.push({
137
+ name: `${prefix}${path.basename(entry, ".md")}`,
138
+ description: fields.description || firstLine(body),
139
+ source,
140
+ ...(fields["argument-hint"] ? { argsHint: fields["argument-hint"] } : {}),
141
+ headless: true,
142
+ });
143
+ }
144
+ return out;
145
+ }
146
+ /** Skills (one SKILL.md per folder under `dir`) that the user may invoke by name. */
147
+ async function skillDirs(dir, source, prefix = "") {
148
+ if (!(await isDir(dir)))
149
+ return [];
150
+ const out = [];
151
+ let entries;
152
+ try {
153
+ entries = (await readdir(dir)).sort();
154
+ }
155
+ catch {
156
+ return [];
157
+ }
158
+ for (const entry of entries) {
159
+ const text = await readText(path.join(dir, entry, "SKILL.md"));
160
+ if (text === undefined)
161
+ continue;
162
+ const { fields, body } = parseFrontmatter(text);
163
+ if ((fields["user-invocable"] ?? fields["user-invokable"] ?? "true").toLowerCase() === "false")
164
+ continue;
165
+ out.push({
166
+ name: `${prefix}${fields.name || entry}`,
167
+ description: fields.description || firstLine(body),
168
+ source,
169
+ ...(fields["argument-hint"] ? { argsHint: fields["argument-hint"] } : {}),
170
+ headless: true,
171
+ });
172
+ }
173
+ return out;
174
+ }
175
+ /** Plugins from `~/.claude/plugins/installed_plugins.json` that apply to `cwd`. */
176
+ async function installedPlugins(cwd) {
177
+ const text = await readText(path.join(claudeHome(), "plugins", "installed_plugins.json"));
178
+ if (!text)
179
+ return [];
180
+ let parsed;
181
+ try {
182
+ parsed = JSON.parse(text);
183
+ }
184
+ catch {
185
+ return [];
186
+ }
187
+ const out = [];
188
+ for (const [key, installs] of Object.entries(parsed.plugins ?? {})) {
189
+ const name = key.split("@")[0];
190
+ for (const install of installs ?? []) {
191
+ if (!install.installPath)
192
+ continue;
193
+ if (install.scope === "project" && install.projectPath && !cwd.startsWith(install.projectPath))
194
+ continue;
195
+ out.push({ name, installPath: install.installPath, scope: install.scope, projectPath: install.projectPath });
196
+ }
197
+ }
198
+ return out;
199
+ }
200
+ /** Directories whose contents feed the catalog; watched for changes. */
201
+ export function catalogDirs(harness, cwd) {
202
+ if (harness === "claude") {
203
+ return [
204
+ path.join(cwd, ".claude", "commands"),
205
+ path.join(cwd, ".claude", "skills"),
206
+ path.join(claudeHome(), "commands"),
207
+ path.join(claudeHome(), "skills"),
208
+ path.join(claudeHome(), "plugins"),
209
+ ];
210
+ }
211
+ return [
212
+ path.join(codexHome(), "prompts"),
213
+ path.join(codexHome(), "skills"),
214
+ path.join(cwd, ".agents", "skills"),
215
+ path.join(cwd, ".codex", "skills"),
216
+ path.join(os.homedir(), ".agents", "skills"),
217
+ ];
218
+ }
219
+ export async function discoverCommands(harness, cwd) {
220
+ const seen = new Set();
221
+ const out = [];
222
+ const add = (entries) => {
223
+ for (const e of entries) {
224
+ if (seen.has(e.name))
225
+ continue;
226
+ seen.add(e.name);
227
+ out.push(e);
228
+ }
229
+ };
230
+ if (harness === "claude") {
231
+ add(await commandFiles(path.join(cwd, ".claude", "commands"), "custom"));
232
+ add(await commandFiles(path.join(claudeHome(), "commands"), "custom"));
233
+ add(await skillDirs(path.join(cwd, ".claude", "skills"), "skill"));
234
+ add(await skillDirs(path.join(claudeHome(), "skills"), "skill"));
235
+ for (const plugin of await installedPlugins(cwd)) {
236
+ add(await skillDirs(path.join(plugin.installPath, "skills"), "plugin", `${plugin.name}:`));
237
+ add(await commandFiles(path.join(plugin.installPath, "commands"), "plugin", `${plugin.name}:`));
238
+ }
239
+ add(CLAUDE_BUILTINS.map(([name, description, headless, argsHint]) => ({
240
+ name,
241
+ description,
242
+ source: "builtin",
243
+ ...(argsHint ? { argsHint } : {}),
244
+ headless,
245
+ })));
246
+ return out;
247
+ }
248
+ // Codex: custom prompts are typed as /prompts:<name>; skills are mentioned as $<name>.
249
+ add(await commandFiles(path.join(codexHome(), "prompts"), "custom", "prompts:"));
250
+ add(await skillDirs(path.join(cwd, ".agents", "skills"), "skill", "$"));
251
+ add(await skillDirs(path.join(cwd, ".codex", "skills"), "skill", "$"));
252
+ add(await skillDirs(path.join(codexHome(), "skills"), "skill", "$"));
253
+ add(await skillDirs(path.join(os.homedir(), ".agents", "skills"), "skill", "$"));
254
+ add(CODEX_BUILTINS.map(([name, description, argsHint]) => ({
255
+ name,
256
+ description,
257
+ source: "builtin",
258
+ ...(argsHint ? { argsHint } : {}),
259
+ headless: false,
260
+ })));
261
+ return out;
262
+ }
263
+ /** The text typed into the harness for a catalog command. */
264
+ export function commandInvocation(harness, entry, name, args) {
265
+ const trimmed = args?.trim();
266
+ const suffix = trimmed ? ` ${trimmed}` : "";
267
+ if (harness === "codex" && (entry?.source === "skill" || name.startsWith("$"))) {
268
+ return `${name.startsWith("$") ? name : `$${name}`}${suffix}`;
269
+ }
270
+ return `/${name.replace(/^\//, "")}${suffix}`;
271
+ }
272
+ /**
273
+ * Re-runs discovery when any catalog directory changes (debounced). Node's
274
+ * recursive watch is unsupported on some platforms; those fall back to a
275
+ * shallow watch, which still catches new command files and skill folders.
276
+ */
277
+ export function watchCatalog(harness, cwd, onChange, debounceMs = 500) {
278
+ const watchers = [];
279
+ let timer;
280
+ const trigger = () => {
281
+ if (timer)
282
+ clearTimeout(timer);
283
+ timer = setTimeout(onChange, debounceMs);
284
+ timer.unref?.();
285
+ };
286
+ for (const dir of catalogDirs(harness, cwd)) {
287
+ try {
288
+ let w;
289
+ try {
290
+ w = watch(dir, { recursive: true, persistent: false }, trigger);
291
+ }
292
+ catch {
293
+ w = watch(dir, { persistent: false }, trigger);
294
+ }
295
+ w.on("error", () => undefined);
296
+ watchers.push(w);
297
+ }
298
+ catch {
299
+ /* directory missing or not watchable: nothing to watch */
300
+ }
301
+ }
302
+ return () => {
303
+ if (timer)
304
+ clearTimeout(timer);
305
+ for (const w of watchers)
306
+ w.close();
307
+ };
308
+ }
309
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/remote/catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import type { Harness } from "../agents/types.js";
2
+ import type { HeadlessTurn } from "./headless.js";
3
+ import { HostClient, type HostClientOptions } from "./host.js";
4
+ import type { HookServer } from "./hooks.js";
5
+ import type { PtySession } from "./pty.js";
6
+ import type { CommandEntry, HarnessName, SessionMode } from "./protocol.js";
7
+ /**
8
+ * Glue between the host socket and the harness this process runs: turns
9
+ * arrive from the app, get typed into the harness (TUI) or run as one
10
+ * headless invocation, and the turn's lifecycle is reported back. One turn at
11
+ * a time; later turns queue. Answers to a pending harness prompt bypass the
12
+ * queue, since the running turn is what is waiting for them.
13
+ */
14
+ export interface RemoteSessionContext {
15
+ harness: Harness;
16
+ sessionId: string;
17
+ cwd: string;
18
+ mode: SessionMode;
19
+ baseUrl: string;
20
+ apiKey: string;
21
+ log: (line: string) => void;
22
+ /** Pushes a teleport checkpoint for the session; resolves with the generation. */
23
+ checkpoint?: (cwd: string) => Promise<number>;
24
+ /** Milliseconds of screen silence after which a TUI turn counts as finished when no hook fired. */
25
+ quietFallbackMs?: number;
26
+ hostOptions?: Partial<HostClientOptions>;
27
+ }
28
+ export declare function harnessName(harness: Harness): HarnessName;
29
+ export declare class RemoteSession {
30
+ readonly host: HostClient;
31
+ private readonly ctx;
32
+ private readonly hooks?;
33
+ private pty?;
34
+ private runHeadless?;
35
+ private readonly queue;
36
+ private current?;
37
+ private draining;
38
+ private stopped;
39
+ private catalog;
40
+ private stopWatching?;
41
+ private pending?;
42
+ constructor(ctx: RemoteSessionContext, hooks?: HookServer);
43
+ attachTui(pty: PtySession): void;
44
+ attachHeadless(run: (prompt: string) => HeadlessTurn): void;
45
+ /** The catalog last announced (tests and diagnostics). */
46
+ get commands(): CommandEntry[];
47
+ /** Connects (best effort), announces the session and its command catalog. Returns whether the backend answered in time. */
48
+ start(): Promise<boolean>;
49
+ stop(): void;
50
+ refreshCatalog(): Promise<void>;
51
+ private finish;
52
+ private onTurn;
53
+ private onInterrupt;
54
+ private onCheckpoint;
55
+ private onHook;
56
+ private turnEnded;
57
+ private requestQuestion;
58
+ private requestPrompt;
59
+ private clearPending;
60
+ /** `prompt.answer` frame: inject the keystrokes for the pending prompt. */
61
+ private answerPrompt;
62
+ /** `turn.deliver {kind: "answer"}`: same as a `prompt.answer`, reported as an instant turn. */
63
+ private deliverAnswer;
64
+ private drain;
65
+ private lookupCommand;
66
+ /** The text that goes into the harness for a turn, or a reason it cannot run here. */
67
+ private resolveText;
68
+ private runTurn;
69
+ /**
70
+ * Safety net when a harness never reports its turn end (older builds, hooks
71
+ * disabled, builtin commands): once the screen has been quiet for the limit
72
+ * after the prompt went in, the turn counts as finished. Hooks are the
73
+ * primary signal; a pending prompt never times out this way.
74
+ */
75
+ private quietFallback;
76
+ }