@floh-solutions/pharos-cli 0.29.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/dist/capabilities.d.ts +7 -0
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +25 -0
- package/dist/capabilities.js.map +1 -1
- package/dist/cli.d.ts +18 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +193 -86
- package/dist/cli.js.map +1 -1
- package/dist/commands/delegate.d.ts +248 -0
- package/dist/commands/delegate.d.ts.map +1 -0
- package/dist/commands/delegate.js +582 -0
- package/dist/commands/delegate.js.map +1 -0
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +179 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +7 -3
- package/dist/commands/setup.js.map +1 -1
- package/dist/delegate/hosts.d.ts +83 -0
- package/dist/delegate/hosts.d.ts.map +1 -0
- package/dist/delegate/hosts.js +154 -0
- package/dist/delegate/hosts.js.map +1 -0
- package/dist/delegate/quote.d.ts +78 -0
- package/dist/delegate/quote.d.ts.map +1 -0
- package/dist/delegate/quote.js +134 -0
- package/dist/delegate/quote.js.map +1 -0
- package/dist/delegate/sessions.d.ts +121 -0
- package/dist/delegate/sessions.d.ts.map +1 -0
- package/dist/delegate/sessions.js +229 -0
- package/dist/delegate/sessions.js.map +1 -0
- package/dist/delegate/vsix.d.ts +122 -0
- package/dist/delegate/vsix.d.ts.map +1 -0
- package/dist/delegate/vsix.js +329 -0
- package/dist/delegate/vsix.js.map +1 -0
- package/package.json +5 -4
- package/skill/SKILL.md +47 -0
- package/vscode/README.md +30 -0
- package/vscode/pharos-bridge.json +10 -0
- package/vscode/pharos-bridge.vsix +0 -0
- package/dist/commands/pr.d.ts +0 -56
- package/dist/commands/pr.d.ts.map +0 -1
- package/dist/commands/pr.js +0 -202
- package/dist/commands/pr.js.map +0 -1
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { stat } from "node:fs/promises";
|
|
3
|
+
import { basename, isAbsolute, join } from "node:path";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
import { findApp, HOSTS, HOST_IDS, AGENT_IDS, MODES, isAgentId, isHostId, isMode, } from "../delegate/hosts.js";
|
|
6
|
+
import { asTypedInput, LAUNCH_SCRIPT, launchCommand, SEND_TO_TAB_SCRIPT } from "../delegate/quote.js";
|
|
7
|
+
import { findSessions, rankSessions, systemProbes, } from "../delegate/sessions.js";
|
|
8
|
+
import { BRIDGE_EXTENSION_ID, CLAUDE_EXTENSION_ID, extensionsDirectory, installedExtensions, } from "../delegate/vsix.js";
|
|
9
|
+
import { CliError, EXIT_FAILED, EXIT_USAGE, emit, emitText, usageError } from "../output.js";
|
|
10
|
+
import { resolveOnPath } from "./doctor.js";
|
|
11
|
+
const run = promisify(execFile);
|
|
12
|
+
/**
|
|
13
|
+
* The closed set. The app renders these as facts; do not rename one without a
|
|
14
|
+
* note on the board and a matching change on the app side.
|
|
15
|
+
*/
|
|
16
|
+
export const REASONS = [
|
|
17
|
+
"host-not-installed",
|
|
18
|
+
"agent-not-installed",
|
|
19
|
+
"bridge-not-installed",
|
|
20
|
+
"automation-denied",
|
|
21
|
+
"folder-missing",
|
|
22
|
+
"unsupported",
|
|
23
|
+
/** `--session <id>` named a session that is no longer a target on this folder. */
|
|
24
|
+
"session-gone",
|
|
25
|
+
];
|
|
26
|
+
export const SYSTEM_DEPS = {
|
|
27
|
+
findApp,
|
|
28
|
+
resolveOnPath,
|
|
29
|
+
probes: systemProbes,
|
|
30
|
+
installedExtensions,
|
|
31
|
+
osascript: async (source, args) => {
|
|
32
|
+
// `--` ends option parsing, so a prompt that begins with a dash is an
|
|
33
|
+
// argument and not a flag. Every variable value travels as argv; nothing
|
|
34
|
+
// is spliced into the script (see `delegate/quote.ts`).
|
|
35
|
+
const { stdout } = await run("/usr/bin/osascript", ["-e", source, "--", ...args], {
|
|
36
|
+
timeout: 30_000,
|
|
37
|
+
maxBuffer: 1024 * 1024,
|
|
38
|
+
// Scrubbed: if this Apple Event auto-launches Terminal, the app must not
|
|
39
|
+
// inherit a nested-session identity. See {@link childEnv}.
|
|
40
|
+
env: childEnv(process.env),
|
|
41
|
+
});
|
|
42
|
+
return stdout;
|
|
43
|
+
},
|
|
44
|
+
open: async (uri) => {
|
|
45
|
+
// **`open` hands the caller's environment to the app it launches** (measured
|
|
46
|
+
// by the bridge track, #1375): a VS Code launched with `CLAUDE_CODE_*` set
|
|
47
|
+
// gives every integrated terminal a nested-session identity for the app's
|
|
48
|
+
// whole lifetime, so a `claude` started in one registers as a child and
|
|
49
|
+
// never appears in `claude agents --json`. Scrubbed here at the source.
|
|
50
|
+
await run("/usr/bin/open", [uri], { timeout: 30_000, env: childEnv(process.env) });
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* The environment to hand a launched app or shell, with this session's
|
|
55
|
+
* Claude Code identity removed.
|
|
56
|
+
*
|
|
57
|
+
* A `pharos delegate` run BY a coding agent inherits that agent's
|
|
58
|
+
* `CLAUDECODE`, `CLAUDE_PID` and `CLAUDE_CODE_*` variables. Passed on to `open`
|
|
59
|
+
* or an auto-launched Terminal, they stamp the launched agent as a *child* of
|
|
60
|
+
* the launcher's session — invisible to `claude agents --json`, with its
|
|
61
|
+
* transcript off — which is exactly the session both this verb and the bridge
|
|
62
|
+
* rely on `agents --json` to find. `CLAUDE_CODE_SSE_PORT` is kept: it points a
|
|
63
|
+
* child at a shared MCP server rather than at the parent's identity, and
|
|
64
|
+
* dropping it would break that connection without helping here.
|
|
65
|
+
*/
|
|
66
|
+
export function childEnv(env) {
|
|
67
|
+
const clean = {};
|
|
68
|
+
for (const [key, value] of Object.entries(env)) {
|
|
69
|
+
if (key === "CLAUDECODE" || key === "CLAUDE_PID")
|
|
70
|
+
continue;
|
|
71
|
+
if (key.startsWith("CLAUDE_CODE_") && key !== "CLAUDE_CODE_SSE_PORT")
|
|
72
|
+
continue;
|
|
73
|
+
clean[key] = value;
|
|
74
|
+
}
|
|
75
|
+
return clean;
|
|
76
|
+
}
|
|
77
|
+
/** The reserved id. `--list` never prints it, so it can never shadow a real session. */
|
|
78
|
+
export const NEW_SESSION = "new";
|
|
79
|
+
/**
|
|
80
|
+
* `--session <id>` → a pick, or a usage error.
|
|
81
|
+
*
|
|
82
|
+
* A malformed id is a **usage error rather than a refusal**: `session-gone` is
|
|
83
|
+
* a fact about the machine ("that session is not there any more"), and the app
|
|
84
|
+
* renders it as one. An id the verb could never have printed is the caller
|
|
85
|
+
* getting the call wrong, and saying `session-gone` about it would teach the
|
|
86
|
+
* person their session had died when it never existed.
|
|
87
|
+
*/
|
|
88
|
+
export function sessionPick(value, host) {
|
|
89
|
+
if (value === undefined)
|
|
90
|
+
return undefined;
|
|
91
|
+
const given = value.trim();
|
|
92
|
+
if (given === "") {
|
|
93
|
+
throw usageError(`--session needs an id from \`pharos delegate --list\`, or ${NEW_SESSION} for a fresh session.`);
|
|
94
|
+
}
|
|
95
|
+
if (given === NEW_SESSION)
|
|
96
|
+
return { kind: "new" };
|
|
97
|
+
if (!/^[0-9]+$/.test(given) || !Number.isSafeInteger(Number(given)) || Number(given) <= 0) {
|
|
98
|
+
throw usageError(`--session takes the \`id\` \`pharos delegate --list\` printed, which in ${HOSTS[host].name} is a process `
|
|
99
|
+
+ `id, or the reserved ${NEW_SESSION} — not ${JSON.stringify(given)}. (Navarch's ids are worker UUIDs, and `
|
|
100
|
+
+ "that route is not available yet.)", { session: given, host });
|
|
101
|
+
}
|
|
102
|
+
return { kind: "pid", pid: Number(given) };
|
|
103
|
+
}
|
|
104
|
+
export async function runDelegate(io, env, options, deps = SYSTEM_DEPS) {
|
|
105
|
+
const host = oneOf(options.host, "--host", HOST_IDS, isHostId);
|
|
106
|
+
const agent = oneOf(options.agent, "--agent", AGENT_IDS, isAgentId);
|
|
107
|
+
const mode = options.mode === undefined ? "terminal" : oneOf(options.mode, "--mode", MODES, isMode);
|
|
108
|
+
if (mode === "extension" && HOSTS[host].vscode === undefined) {
|
|
109
|
+
throw usageError(`--mode extension applies to the VS Code hosts only; ${HOSTS[host].name} has no extension to `
|
|
110
|
+
+ "open the prompt in. Leave --mode off, or pass --host vscode / vscode-insiders.", { host, mode });
|
|
111
|
+
}
|
|
112
|
+
if (options.list && options.session !== undefined) {
|
|
113
|
+
throw usageError("--list and --session are different questions: --list reports what is running and sends nothing, "
|
|
114
|
+
+ "--session sends to one of the ids it printed. Pass one.");
|
|
115
|
+
}
|
|
116
|
+
const pick = sessionPick(options.session, host);
|
|
117
|
+
// **`--list` needs no prompt**, and demanding one would make the app build a
|
|
118
|
+
// message it is only going to throw away to refresh a menu.
|
|
119
|
+
const text = (options.text ?? "").replace(/\r\n/g, "\n").trim();
|
|
120
|
+
if (text === "" && !options.list) {
|
|
121
|
+
throw usageError("Nothing to send. Pass the prompt with --text, --file or --stdin.");
|
|
122
|
+
}
|
|
123
|
+
const folder = (options.folder ?? "").trim();
|
|
124
|
+
if (folder === "")
|
|
125
|
+
throw usageError("--folder is required: the absolute path of the project folder.");
|
|
126
|
+
if (!isAbsolute(folder)) {
|
|
127
|
+
throw usageError(`--folder must be absolute, got ${JSON.stringify(folder)}.`, { folder });
|
|
128
|
+
}
|
|
129
|
+
const base = { host, agent, mode, folder };
|
|
130
|
+
const refuse = (reason, detail) => emitRefusal(io, options.pretty, { ok: false, reason, detail, ...base });
|
|
131
|
+
const succeed = (outcome) => emitOutcome(io, options.pretty, {
|
|
132
|
+
ok: true,
|
|
133
|
+
...base,
|
|
134
|
+
...outcome,
|
|
135
|
+
...(options.dryRun ? { dryRun: true } : {}),
|
|
136
|
+
});
|
|
137
|
+
// Cheapest fact first: nothing else is worth asking about a folder that is
|
|
138
|
+
// not there, and it is the one refusal that is entirely the caller's to fix.
|
|
139
|
+
const info = await stat(folder).catch(() => null);
|
|
140
|
+
if (info === null || !info.isDirectory()) {
|
|
141
|
+
return refuse("folder-missing", `${folder} is not a directory on this machine. The linked folder for this project has moved `
|
|
142
|
+
+ "or was never here — pick it again in Settings ▸ Agents.");
|
|
143
|
+
}
|
|
144
|
+
const app = await deps.findApp(host, env);
|
|
145
|
+
if (app === null) {
|
|
146
|
+
return refuse("host-not-installed", `${HOSTS[host].name} is not installed — looked up by bundle id ${HOSTS[host].bundleId} through `
|
|
147
|
+
+ "Spotlight and at the usual paths under /Applications and ~/Applications."
|
|
148
|
+
+ (HOSTS[host].cask === undefined ? "" : ` \`brew install --cask ${HOSTS[host].cask}\` installs it.`));
|
|
149
|
+
}
|
|
150
|
+
// Navarch is refused before the agent is even resolved: it cannot take a
|
|
151
|
+
// delegation at all yet, so an `agent-not-installed` about it would name the
|
|
152
|
+
// wrong problem.
|
|
153
|
+
//
|
|
154
|
+
// **`--list` is refused here too, rather than answering with rows.** The
|
|
155
|
+
// contract gives a Navarch row the worker's UUID as its `id` and the worker's
|
|
156
|
+
// name as its `name`, and both come from `fleet_status` over the Argus socket
|
|
157
|
+
// — which is #1393's half of this. Listing the pids instead would hand the
|
|
158
|
+
// app ids that `--session` can never accept, so the whole route is one honest
|
|
159
|
+
// refusal until #1393 lifts it in one place.
|
|
160
|
+
if (host === "navarch") {
|
|
161
|
+
return refuse("unsupported", "Navarch cannot take a delegation yet, and cannot list its sessions either. The Argus side of "
|
|
162
|
+
+ "it exists — #1378 added a `delegate` op that finds-or-creates a worker on a folder without "
|
|
163
|
+
+ "a board todo, which every other operator action there still needs — but this verb does not "
|
|
164
|
+
+ "speak that socket yet. #1393 on the ask-agent board is the todo that teaches it, and it is "
|
|
165
|
+
+ "also what supplies the worker ids `--session` would take; until it lands, choose Terminal "
|
|
166
|
+
+ "or VS Code.");
|
|
167
|
+
}
|
|
168
|
+
// **May be null, and that is not always a refusal.** The Terminal route runs
|
|
169
|
+
// the agent by this path, so it must exist there; the VS Code extension route
|
|
170
|
+
// runs the agent's OWN bundled binary through the extension, so an agent off
|
|
171
|
+
// PATH is fine there. Each route decides — see {@link delegateToVsCode}.
|
|
172
|
+
const agentPath = await deps.resolveOnPath(agent, env);
|
|
173
|
+
if (options.list) {
|
|
174
|
+
return listSessions(io, host, agent, mode, folder, agentPath, env, deps, options.pretty, refuse);
|
|
175
|
+
}
|
|
176
|
+
if (host === "vscode" || host === "vscode-insiders") {
|
|
177
|
+
return delegateToVsCode(host, agent, mode, folder, text, agentPath, env, deps, options.dryRun, pick, refuse, succeed);
|
|
178
|
+
}
|
|
179
|
+
if (agentPath === null)
|
|
180
|
+
return refuse("agent-not-installed", agentNotInstalled(agent, env));
|
|
181
|
+
return delegateToTerminal(agent, folder, text, agentPath, env, deps, options.dryRun, pick, refuse, succeed);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* `--list` — the inventory, and nothing else.
|
|
185
|
+
*
|
|
186
|
+
* **The bridge is deliberately NOT required here.** Listing is
|
|
187
|
+
* `claude agents --json` plus `ps`; it reads the same on a VS Code with no
|
|
188
|
+
* extensions at all. Refusing `bridge-not-installed` for a question the bridge
|
|
189
|
+
* plays no part in would hide the answer behind an unrelated fix, so only the
|
|
190
|
+
* three facts that make the question unanswerable refuse: the host, the agent
|
|
191
|
+
* and the folder.
|
|
192
|
+
*
|
|
193
|
+
* The agent still has to be findable, because that is what runs the inventory —
|
|
194
|
+
* and for Codex, where detection is `ps` and needs no binary, it is refused all
|
|
195
|
+
* the same: a list is offered so it can be picked from, and `delegate` with
|
|
196
|
+
* these flags would refuse on the next call anyway.
|
|
197
|
+
*/
|
|
198
|
+
async function listSessions(io, host, agent, mode, folder, agentPath, env, deps, pretty, refuse) {
|
|
199
|
+
// The Claude Code extension bundles its own `claude`, and it can list the
|
|
200
|
+
// machine's sessions as well as the one on PATH — so a VS Code host with the
|
|
201
|
+
// extension installed still answers when PATH has none.
|
|
202
|
+
let probePath = agent === "claude" ? agentPath : null;
|
|
203
|
+
if (agent === "claude" && probePath === null && HOSTS[host].vscode !== undefined) {
|
|
204
|
+
const extensions = await deps.installedExtensions(host, env);
|
|
205
|
+
probePath = bundledClaude(extensions?.find((extension) => extension.id === CLAUDE_EXTENSION_ID));
|
|
206
|
+
}
|
|
207
|
+
if (agent === "claude" ? probePath === null : agentPath === null) {
|
|
208
|
+
return refuse("agent-not-installed", agentNotInstalled(agent, env));
|
|
209
|
+
}
|
|
210
|
+
const { sessions, incomplete, detail: probeDetail } = await findSessions(agent, folder, deps.probes(env, probePath));
|
|
211
|
+
const ranked = rankSessions(sessions, host);
|
|
212
|
+
const rows = ranked.map((session, index) => toRow(session, index === 0));
|
|
213
|
+
const agentName = nameOf(agent);
|
|
214
|
+
const where = `${HOSTS[host].name} on ${folder}`;
|
|
215
|
+
const core = rows.length === 0
|
|
216
|
+
? `No ${agentName} session is running in ${where}.`
|
|
217
|
+
: `${rows.length} ${agentName} session${rows.length === 1 ? "" : "s"} in ${where}. A plain delegate `
|
|
218
|
+
+ `would use ${rows[0].name} (${rows[0].status}).`;
|
|
219
|
+
const detail = incomplete
|
|
220
|
+
? `${core} Detection was incomplete (${probeDetail ?? "a probe failed"}), so this list may be short.`
|
|
221
|
+
: core;
|
|
222
|
+
const listing = { ok: true, host, agent, mode, folder, sessions: rows, incomplete, detail };
|
|
223
|
+
if (!pretty)
|
|
224
|
+
return emit(io, listing);
|
|
225
|
+
return emitText(io, [
|
|
226
|
+
detail,
|
|
227
|
+
...rows.map((row) => `${row.recommended ? "*" : " "} ${row.id} ${row.name} — ${row.status}, ${row.detail}`),
|
|
228
|
+
].join("\n"));
|
|
229
|
+
}
|
|
230
|
+
/** The `claude` the Claude Code extension carries, at the path measured on 2.1.228. */
|
|
231
|
+
function bundledClaude(claudeExt) {
|
|
232
|
+
return claudeExt === undefined ? null : join(claudeExt.path, "resources", "native-binary", "claude");
|
|
233
|
+
}
|
|
234
|
+
/** One listed row. `recommended` is passed in, because the ranking decides it, not this. */
|
|
235
|
+
function toRow(session, recommended) {
|
|
236
|
+
// `rankSessions` filtered on the host, so it is never null here.
|
|
237
|
+
const host = session.host;
|
|
238
|
+
return {
|
|
239
|
+
id: String(session.pid),
|
|
240
|
+
name: displayName(session),
|
|
241
|
+
agent: session.agent,
|
|
242
|
+
host,
|
|
243
|
+
status: session.status ?? "unknown",
|
|
244
|
+
detail: host === "terminal"
|
|
245
|
+
? session.tty === null ? "Terminal" : `Terminal tab ${basename(session.tty)}`
|
|
246
|
+
: HOSTS[host].name,
|
|
247
|
+
recommended,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* What to call a session in a menu.
|
|
252
|
+
*
|
|
253
|
+
* Claude names its own (`team-sync-6c`) and that is what the person sees in the
|
|
254
|
+
* session itself, so it wins. Codex names nothing, so the pid is the identity —
|
|
255
|
+
* and a Claude session too old or too new to carry a name falls back to the
|
|
256
|
+
* same shape rather than to an empty row.
|
|
257
|
+
*/
|
|
258
|
+
function displayName(session) {
|
|
259
|
+
if (session.agent === "codex")
|
|
260
|
+
return `Codex · pid ${session.pid}`;
|
|
261
|
+
return session.name ?? `Claude · pid ${session.pid}`;
|
|
262
|
+
}
|
|
263
|
+
function nameOf(agent) {
|
|
264
|
+
return agent === "claude" ? "Claude" : "Codex";
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* The `session-gone` detail: what was asked for, what is actually there, and
|
|
268
|
+
* why nothing was started instead.
|
|
269
|
+
*/
|
|
270
|
+
function sessionGone(pid, agent, host, ranked, incomplete, probeDetail) {
|
|
271
|
+
const agentName = nameOf(agent);
|
|
272
|
+
const now = ranked.length === 0
|
|
273
|
+
? `No ${agentName} session is in ${HOSTS[host].name} on this folder now`
|
|
274
|
+
: `What is there now: ${ranked.map((session) => `${displayName(session)} (pid ${session.pid})`).join(", ")}`;
|
|
275
|
+
return (`Session ${pid} is no longer a ${agentName} session in ${HOSTS[host].name} on this folder — it exited, `
|
|
276
|
+
+ `moved, or the list it came from is stale. ${now}. Nothing was sent and nothing was launched: a chosen `
|
|
277
|
+
+ "session is a choice, so this refuses rather than quietly starting a second one. Re-read the inventory "
|
|
278
|
+
+ "with `pharos delegate --list`, or pass `--session new` to start a fresh session on purpose."
|
|
279
|
+
+ (incomplete
|
|
280
|
+
? ` Detection was also incomplete (${probeDetail ?? "a probe failed"}), so the session may be running and unseeable.`
|
|
281
|
+
: ""));
|
|
282
|
+
}
|
|
283
|
+
/** The `agent-not-installed` detail — one place, because two routes reach it. */
|
|
284
|
+
function agentNotInstalled(agent, env) {
|
|
285
|
+
const entries = (env["PATH"] ?? "").split(":").filter((entry) => entry !== "").length;
|
|
286
|
+
return (`\`${agent}\` is not on the PATH this ran with (${entries} entries). A coding agent is your `
|
|
287
|
+
+ "login and is never installed by pharos — "
|
|
288
|
+
+ (agent === "claude" ? "`npm i -g @anthropic-ai/claude-code`" : "`npm i -g @openai/codex`")
|
|
289
|
+
+ " puts it there. If it IS installed, `pharos doctor` prints the PATH that was searched.");
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* The URI the bridge handles.
|
|
293
|
+
*
|
|
294
|
+
* **Every value is percent-encoded TWICE.** VS Code decodes the query once
|
|
295
|
+
* before any extension sees it (`Uri.parse` percent-decodes the query
|
|
296
|
+
* component — measured by the bridge track with `vscode-uri`, the class the
|
|
297
|
+
* workbench uses), so a single encoding breaks on any prompt holding `&`,
|
|
298
|
+
* `=`, `+` or `%`: `text=a%26b` would arrive as `text=a&b` and split. The
|
|
299
|
+
* bridge refuses a query with unknown keys, so that failure would be loud
|
|
300
|
+
* rather than a silently truncated prompt — but loud is still failed.
|
|
301
|
+
*
|
|
302
|
+
* `session` is added only when one was asked for, and it is `agent`/`mode`
|
|
303
|
+
* shaped rather than `text` shaped: digits or the literal `new`, so there is
|
|
304
|
+
* nothing in it for either decode to change. Its absence is what says "the
|
|
305
|
+
* ordinary rule", which is why it is omitted rather than sent empty.
|
|
306
|
+
*/
|
|
307
|
+
export function delegateUri(scheme, job) {
|
|
308
|
+
const twice = (value) => encodeURIComponent(encodeURIComponent(value));
|
|
309
|
+
const session = job.session === undefined ? "" : `&session=${job.session.kind === "new" ? NEW_SESSION : job.session.pid}`;
|
|
310
|
+
return `${scheme}://${BRIDGE_EXTENSION_ID}/delegate?folder=${twice(job.folder)}&agent=${job.agent}`
|
|
311
|
+
+ `&mode=${job.mode}&text=${twice(job.text)}${session}`;
|
|
312
|
+
}
|
|
313
|
+
async function delegateToVsCode(host, agent, mode, folder, text, agentPath, env, deps, dryRun, pick, refuse, succeed) {
|
|
314
|
+
const spec = HOSTS[host];
|
|
315
|
+
const name = spec.name;
|
|
316
|
+
if (mode === "extension" && agent === "codex") {
|
|
317
|
+
return refuse("unsupported", "The Codex extension takes no prompt from outside — measured on 26.5803: its URI handler "
|
|
318
|
+
+ "routes only to its own views and `chatgpt.newChat` takes no arguments. Use --mode terminal "
|
|
319
|
+
+ "for Codex; the bridge runs it in an integrated terminal instead.");
|
|
320
|
+
}
|
|
321
|
+
const extensions = await deps.installedExtensions(host, env);
|
|
322
|
+
const bridge = extensions?.find((extension) => extension.id === BRIDGE_EXTENSION_ID);
|
|
323
|
+
if (bridge === undefined) {
|
|
324
|
+
const directory = extensionsDirectory(host, env) ?? "the extensions directory";
|
|
325
|
+
return refuse("bridge-not-installed", `The Pharos bridge (${BRIDGE_EXTENSION_ID}) is not installed in ${name} — looked in ${directory}`
|
|
326
|
+
+ (extensions === null ? ", which does not exist: that VS Code has never run" : "")
|
|
327
|
+
+ ". `pharos setup --install vscode-bridge` installs the one this pharos ships.");
|
|
328
|
+
}
|
|
329
|
+
const claudeExt = extensions?.find((extension) => extension.id === CLAUDE_EXTENSION_ID);
|
|
330
|
+
const usesExtensionBinary = mode === "extension" && agent === "claude" && claudeExt !== undefined;
|
|
331
|
+
// **The extension route needs no agent on PATH.** The Claude Code extension
|
|
332
|
+
// bundles its own binary at `resources/native-binary/claude` and the bridge
|
|
333
|
+
// runs it through `claude-vscode.terminal.open`, so an agent off PATH is only
|
|
334
|
+
// a refusal when there is no extension to fall back on. This is the ask's
|
|
335
|
+
// "if their VS Code has claude extensions installed … use the extension".
|
|
336
|
+
if (agentPath === null && !usesExtensionBinary) {
|
|
337
|
+
return refuse("agent-not-installed", agentNotInstalled(agent, env));
|
|
338
|
+
}
|
|
339
|
+
// Detect against the bundled binary when that is the only `claude` there, so
|
|
340
|
+
// the prediction still holds; the bridge does its own detection regardless.
|
|
341
|
+
const probePath = agent === "claude" ? agentPath ?? bundledClaude(claudeExt) : null;
|
|
342
|
+
const { sessions, incomplete, detail: probeDetail } = await findSessions(agent, folder, deps.probes(env, probePath));
|
|
343
|
+
const ranked = rankSessions(sessions, host);
|
|
344
|
+
// **`--session <pid>` is pre-checked here AND honoured again by the bridge,
|
|
345
|
+
// and the two are independent on purpose.** The URI is one-way: nothing comes
|
|
346
|
+
// back, so the CLI can never report the bridge's verdict. This check catches a
|
|
347
|
+
// stale pick before an editor is disturbed at all; the bridge's own check is
|
|
348
|
+
// the strict one, because it knows which terminals are ITS window's and this
|
|
349
|
+
// process only knows which VS Code flavour a pid hangs off. A pid that passes
|
|
350
|
+
// here can still be `session-gone` there, and the bridge says so in its
|
|
351
|
+
// notification — that is not a disagreement, it is the narrower question.
|
|
352
|
+
let session;
|
|
353
|
+
if (pick === undefined) {
|
|
354
|
+
session = ranked[0] ?? null;
|
|
355
|
+
}
|
|
356
|
+
else if (pick.kind === "new") {
|
|
357
|
+
session = null;
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
session = ranked.find((found) => found.pid === pick.pid) ?? null;
|
|
361
|
+
if (session === null) {
|
|
362
|
+
return refuse("session-gone", sessionGone(pick.pid, agent, host, ranked, incomplete, probeDetail));
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
const uri = delegateUri(spec.vscode.scheme, { folder, agent, mode, text, session: pick });
|
|
366
|
+
const agentName = nameOf(agent);
|
|
367
|
+
const claudeExtInstalled = mode === "extension" && agent === "claude" ? claudeExt !== undefined : true;
|
|
368
|
+
// The bridge decides; this is the same detection it runs, so the prediction
|
|
369
|
+
// is honest and the wording says whose call it is. One tense throughout —
|
|
370
|
+
// `would` in a dry run, plain past/present otherwise.
|
|
371
|
+
const hand = dryRun ? "Would hand this to" : "Handed to";
|
|
372
|
+
const asked = pick?.kind !== "new"
|
|
373
|
+
? ""
|
|
374
|
+
: ranked.length === 0
|
|
375
|
+
? " A fresh session was asked for; none was running there anyway."
|
|
376
|
+
: " A fresh session was asked for, so the running one is not reused.";
|
|
377
|
+
const core = session !== null
|
|
378
|
+
? `${hand} the Pharos bridge in ${name}, which ${dryRun ? "would send" : "sends"} it to the `
|
|
379
|
+
+ `${agentName} session there${describeStatus(session)}.`
|
|
380
|
+
: mode === "extension"
|
|
381
|
+
? `${hand} the Pharos bridge in ${name}, which ${dryRun ? "would open" : "opens"} it in the `
|
|
382
|
+
+ "Claude Code extension."
|
|
383
|
+
+ (claudeExtInstalled ? "" : " That extension is not installed there, so the bridge falls back to an integrated terminal.")
|
|
384
|
+
: `${hand} the Pharos bridge in ${name}, which ${dryRun ? "would start" : "starts"} ${agentName} `
|
|
385
|
+
+ `in an integrated terminal in ${folder}.`;
|
|
386
|
+
// A deliberate new session makes "a session may exist that was not seen"
|
|
387
|
+
// beside the point: one was not wanted. So the two notes are exclusive.
|
|
388
|
+
const detail = pick?.kind === "new"
|
|
389
|
+
? `${core}${asked}`
|
|
390
|
+
: session === null && incomplete
|
|
391
|
+
? `${core} Detection was incomplete (${probeDetail ?? "a probe failed"}); a running session may exist that could not be found.`
|
|
392
|
+
: core;
|
|
393
|
+
if (!dryRun) {
|
|
394
|
+
try {
|
|
395
|
+
await deps.open(uri);
|
|
396
|
+
}
|
|
397
|
+
catch (error) {
|
|
398
|
+
throw new CliError(`\`open\` could not hand the URI to ${name}: ${messageOf(error)}`, "internal", EXIT_FAILED, { host, uri });
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return succeed({
|
|
402
|
+
action: session !== null ? "sent" : "launched",
|
|
403
|
+
session: report(session),
|
|
404
|
+
detail,
|
|
405
|
+
uri,
|
|
406
|
+
...(dryRun ? { sessions: ranked.map((found, index) => toRow(found, index === 0)) } : {}),
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Terminal.app — measured on Terminal 2.15 with Claude Code 2.1.268.
|
|
411
|
+
*
|
|
412
|
+
* `do script … in tab` writes to the tab's tty as typed input and follows it
|
|
413
|
+
* with a return, which the running agent's input box submits. A multi-line
|
|
414
|
+
* prompt is wrapped in bracketed paste so it lands as one message (see
|
|
415
|
+
* `delegate/quote.ts`). With no session in a Terminal tab, a window is opened
|
|
416
|
+
* running the agent with the prompt as its first message.
|
|
417
|
+
*
|
|
418
|
+
* Both are Apple Events. The first time, macOS asks whether the RESPONSIBLE
|
|
419
|
+
* process — Pharos.app when the app ran this, your terminal when you did —
|
|
420
|
+
* may control Terminal; a refusal comes back as `-1743` and is reported as
|
|
421
|
+
* `automation-denied` with the Settings pane named.
|
|
422
|
+
*/
|
|
423
|
+
async function delegateToTerminal(agent, folder, text, agentPath, env, deps, dryRun, pick, refuse, succeed) {
|
|
424
|
+
const { sessions, incomplete, detail: probeDetail } = await findSessions(agent, folder, deps.probes(env, agent === "claude" ? agentPath : null));
|
|
425
|
+
const ranked = rankSessions(sessions, "terminal");
|
|
426
|
+
const rows = () => ranked.map((found, index) => toRow(found, index === 0));
|
|
427
|
+
let session;
|
|
428
|
+
if (pick === undefined) {
|
|
429
|
+
session = ranked[0] ?? null;
|
|
430
|
+
}
|
|
431
|
+
else if (pick.kind === "new") {
|
|
432
|
+
session = null;
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
session = ranked.find((found) => found.pid === pick.pid) ?? null;
|
|
436
|
+
if (session === null) {
|
|
437
|
+
return refuse("session-gone", sessionGone(pick.pid, agent, "terminal", ranked, incomplete, probeDetail));
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
const agentName = nameOf(agent);
|
|
441
|
+
// `rankSessions` already dropped tty-less sessions, so `session` is a real
|
|
442
|
+
// send target. A found session tells us where it is; `[...new Set(…)]` so two
|
|
443
|
+
// sessions in one app do not read as "Navarch and Navarch".
|
|
444
|
+
const elsewhere = sessions.filter((found) => found.host !== "terminal");
|
|
445
|
+
const elsewhereApps = [
|
|
446
|
+
...new Set(elsewhere.map((found) => (found.host === null ? "another app" : HOSTS[found.host].name))),
|
|
447
|
+
];
|
|
448
|
+
const elsewhereNote = elsewhereApps.length === 0 || pick?.kind === "new"
|
|
449
|
+
? ""
|
|
450
|
+
: ` A ${agentName} session on this folder is running in ${elsewhereApps.join(" and ")}, not in Terminal.`;
|
|
451
|
+
// Both of these answer "why did you not use a running session", which is not
|
|
452
|
+
// a question when a fresh one was asked for.
|
|
453
|
+
const incompleteNote = session === null && incomplete && pick?.kind !== "new"
|
|
454
|
+
? ` Detection was incomplete (${probeDetail ?? "a probe failed"}); a running session may exist that could not be found.`
|
|
455
|
+
: "";
|
|
456
|
+
const askedNote = pick?.kind !== "new"
|
|
457
|
+
? ""
|
|
458
|
+
: ranked.length === 0
|
|
459
|
+
? " A fresh session was asked for; none was running in Terminal anyway."
|
|
460
|
+
: ` A fresh session was asked for, so the ${ranked.length === 1 ? "one" : String(ranked.length)} already `
|
|
461
|
+
+ `running in Terminal ${ranked.length === 1 ? "was" : "were"} left alone.`;
|
|
462
|
+
if (session !== null && session.tty !== null) {
|
|
463
|
+
if (dryRun) {
|
|
464
|
+
return succeed({
|
|
465
|
+
action: "sent",
|
|
466
|
+
session: report(session),
|
|
467
|
+
detail: `Would type the prompt into the ${agentName} session in Terminal${describeStatus(session)}.`,
|
|
468
|
+
sessions: rows(),
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
const result = await appleEvent(deps, SEND_TO_TAB_SCRIPT, [session.tty, asTypedInput(text)], refuse);
|
|
472
|
+
if (typeof result !== "string")
|
|
473
|
+
return result;
|
|
474
|
+
if (result.trim() === "sent") {
|
|
475
|
+
return succeed({
|
|
476
|
+
action: "sent",
|
|
477
|
+
session: report(session),
|
|
478
|
+
detail: `Sent to the ${agentName} session in Terminal${describeStatus(session)}.`,
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
// The process tree says Terminal, but no window of this Terminal has a tab
|
|
482
|
+
// on that tty — a session in a tab that was closed, or a Terminal this
|
|
483
|
+
// instance cannot see.
|
|
484
|
+
//
|
|
485
|
+
// **Which way that falls depends on whether a session was NAMED.** Without
|
|
486
|
+
// `--session` a new window is the honest outcome and the detail says why;
|
|
487
|
+
// with it, opening a window would be exactly the silent substitution
|
|
488
|
+
// `--session` exists to prevent, so it refuses instead — and this is the
|
|
489
|
+
// case the pre-check cannot catch, because only Terminal knows its tabs.
|
|
490
|
+
if (pick?.kind === "pid") {
|
|
491
|
+
return refuse("session-gone", `${agentName} session ${session.pid} is still attributed to Terminal, but no Terminal tab holds its `
|
|
492
|
+
+ `tty ${session.tty} — the tab was closed, or it belongs to a Terminal this process cannot see. `
|
|
493
|
+
+ "Nothing was sent and no window was opened, because a chosen session is a choice. Re-read the "
|
|
494
|
+
+ "inventory with `pharos delegate --list`, or pass `--session new` to start a fresh session.");
|
|
495
|
+
}
|
|
496
|
+
const launched = await launch(deps, folder, agentPath, text, refuse);
|
|
497
|
+
if (typeof launched !== "string")
|
|
498
|
+
return launched;
|
|
499
|
+
return succeed({
|
|
500
|
+
action: "launched",
|
|
501
|
+
session: null,
|
|
502
|
+
detail: `Opened a new Terminal window in ${folder} running ${agentName} with the prompt, because the `
|
|
503
|
+
+ `${agentName} session attributed to Terminal (pid ${session.pid}) holds no tab on tty `
|
|
504
|
+
+ `${session.tty} that could be typed into.`,
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
const opened = dryRun ? "Would open" : "Opened";
|
|
508
|
+
const detail = `${opened} a new Terminal window in ${folder} running ${agentName} with the prompt.`
|
|
509
|
+
+ `${askedNote}${elsewhereNote}${incompleteNote}`;
|
|
510
|
+
if (dryRun) {
|
|
511
|
+
return succeed({ action: "launched", session: null, detail, sessions: rows() });
|
|
512
|
+
}
|
|
513
|
+
const launched = await launch(deps, folder, agentPath, text, refuse);
|
|
514
|
+
if (typeof launched !== "string")
|
|
515
|
+
return launched;
|
|
516
|
+
return succeed({ action: "launched", session: null, detail });
|
|
517
|
+
}
|
|
518
|
+
async function launch(deps, folder, agentPath, text, refuse) {
|
|
519
|
+
return appleEvent(deps, LAUNCH_SCRIPT, [launchCommand(folder, agentPath, text)], refuse);
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Run one AppleScript, turning the Automation refusal into its reason id and
|
|
523
|
+
* anything else into the CLI's ordinary failure.
|
|
524
|
+
*
|
|
525
|
+
* `-1743` is `errAEEventNotPermitted`: the responsible process is not allowed
|
|
526
|
+
* to send Apple Events to Terminal. It is the one error that is a setting
|
|
527
|
+
* rather than a fault, so it is the one that gets a stable id.
|
|
528
|
+
*/
|
|
529
|
+
async function appleEvent(deps, source, args, refuse) {
|
|
530
|
+
try {
|
|
531
|
+
return await deps.osascript(source, args);
|
|
532
|
+
}
|
|
533
|
+
catch (error) {
|
|
534
|
+
const message = messageOf(error);
|
|
535
|
+
if (/-1743\b/.test(message) || /not authori[sz]ed to send apple events/i.test(message)) {
|
|
536
|
+
return refuse("automation-denied", "macOS refused to let this process control Terminal (Apple Event error -1743). Allow it "
|
|
537
|
+
+ "in System Settings ▸ Privacy & Security ▸ Automation: under the app that ran this "
|
|
538
|
+
+ "command — Pharos when the app did, your terminal app when you did — switch on "
|
|
539
|
+
+ "Terminal, then try again. If no prompt ever appeared, the app was denied once and "
|
|
540
|
+
+ "macOS does not ask twice.");
|
|
541
|
+
}
|
|
542
|
+
throw new CliError(`Terminal did not take the Apple Event: ${message}`, "internal", EXIT_FAILED);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
function describeStatus(session) {
|
|
546
|
+
const parts = [session.status ?? "status unknown", `pid ${session.pid}`];
|
|
547
|
+
if (session.tty !== null)
|
|
548
|
+
parts.push(session.tty);
|
|
549
|
+
return ` (${parts.join(", ")})`;
|
|
550
|
+
}
|
|
551
|
+
function report(session) {
|
|
552
|
+
if (session === null)
|
|
553
|
+
return null;
|
|
554
|
+
return { pid: session.pid, cwd: session.cwd, name: session.name, status: session.status, tty: session.tty };
|
|
555
|
+
}
|
|
556
|
+
function emitOutcome(io, pretty, outcome) {
|
|
557
|
+
return pretty ? emitText(io, outcome.detail) : emit(io, outcome);
|
|
558
|
+
}
|
|
559
|
+
function emitRefusal(io, pretty, refusal) {
|
|
560
|
+
if (pretty)
|
|
561
|
+
io.stdout(`${refusal.reason}: ${refusal.detail}`);
|
|
562
|
+
else
|
|
563
|
+
io.stdout(JSON.stringify(refusal, undefined, 2));
|
|
564
|
+
return EXIT_USAGE;
|
|
565
|
+
}
|
|
566
|
+
function oneOf(value, flag, allowed, guard) {
|
|
567
|
+
const given = (value ?? "").trim();
|
|
568
|
+
if (given === "")
|
|
569
|
+
throw usageError(`${flag} is required: one of ${allowed.join(", ")}.`, { flag, allowed });
|
|
570
|
+
if (!guard(given)) {
|
|
571
|
+
throw usageError(`${flag} takes one of ${allowed.join(", ")}, not ${JSON.stringify(given)}.`, {
|
|
572
|
+
flag,
|
|
573
|
+
given,
|
|
574
|
+
allowed,
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
return given;
|
|
578
|
+
}
|
|
579
|
+
function messageOf(error) {
|
|
580
|
+
return error instanceof Error ? error.message : String(error);
|
|
581
|
+
}
|
|
582
|
+
//# sourceMappingURL=delegate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delegate.js","sourceRoot":"","sources":["../../src/commands/delegate.ts"],"names":[],"mappings":"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"}
|
|
@@ -207,6 +207,14 @@ export declare function authCheck(base: Omit<Check, "ok" | "install">, accounts:
|
|
|
207
207
|
* is a real fault with a real fix, and the fix is named for the fault.
|
|
208
208
|
*/
|
|
209
209
|
export declare function repoAccessCheck(client: GitHubClient, bindings: readonly RepoBinding[], configPath: string): Promise<Check>;
|
|
210
|
+
/**
|
|
211
|
+
* Where a bare command name actually resolves, by walking `PATH` in order.
|
|
212
|
+
*
|
|
213
|
+
* Deliberately not `which`: spawning a shell to answer this would inherit a
|
|
214
|
+
* DIFFERENT environment from the one the probes just ran in, which is the exact
|
|
215
|
+
* class of mistake this command exists to catch.
|
|
216
|
+
*/
|
|
217
|
+
export declare function resolveOnPath(executable: string, env: NodeJS.ProcessEnv): Promise<string | null>;
|
|
210
218
|
/**
|
|
211
219
|
* The mark beside one repository — and there are **three** of them, not two.
|
|
212
220
|
*
|