@join-pantheon/cli 0.26.5 → 0.28.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 +54 -1
- package/dist/agents.js +83 -5
- package/dist/cli.js +83 -13
- package/dist/client.js +25 -3
- package/dist/doctor.js +47 -6
- package/dist/hooks-install.js +46 -1
- package/dist/install.js +29 -4
- package/dist/kiro-files.js +56 -0
- package/dist/machine.js +5 -1
- package/dist/measure.js +31 -3
- package/dist/network.js +394 -0
- package/dist/notice.js +3 -1
- package/dist/notify.js +15 -3
- package/dist/persona.js +1 -1
- package/dist/profile.js +4 -1
- package/dist/run-failure.js +1 -0
- package/dist/setup-guide.js +1 -1
- package/dist/tray.js +1 -1
- package/dist/update-check.js +2 -1
- package/dist/upgrade.js +2 -1
- package/dist/which.js +5 -3
- package/dist/worker.js +10 -3
- package/package.json +2 -1
package/dist/notice.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { decisionPrompt, decisionTitle } from "./decision-ui.js";
|
|
2
|
-
export const TOOL_LABELS = { "claude-code": "Claude Code", codex: "Codex", cursor: "Cursor", copilot: "Copilot", grok: "Grok" };
|
|
2
|
+
export const TOOL_LABELS = { "claude-code": "Claude Code", codex: "Codex", cursor: "Cursor", copilot: "Copilot", kiro: "Kiro", grok: "Grok" };
|
|
3
3
|
export const APP_TOOLS = [
|
|
4
4
|
{ id: "cursor-app", label: "Cursor app", kind: "app", bundle: "com.todesktop.230313mzl4w4u92", deeplink: "cursor://anysphere.cursor-deeplink/prompt?text={prompt}" },
|
|
5
5
|
{ id: "claude-app", label: "Claude app · question copied", kind: "app", bundle: "com.anthropic.claudefordesktop" },
|
|
@@ -67,6 +67,8 @@ const agentLabel = (agent) => {
|
|
|
67
67
|
return "Cursor";
|
|
68
68
|
if (a.includes("copilot"))
|
|
69
69
|
return "Copilot";
|
|
70
|
+
if (a.includes("kiro"))
|
|
71
|
+
return "Kiro";
|
|
70
72
|
return null;
|
|
71
73
|
};
|
|
72
74
|
function whoLine(from, agent, ts, now) {
|
package/dist/notify.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import { chosenApproval } from "./install.js";
|
|
2
|
+
import { toolsAllowed } from "./tools.js";
|
|
1
3
|
import { readFileSync, writeFileSync, existsSync, mkdirSync, rmSync } from "node:fs";
|
|
2
4
|
import { homedir, platform } from "node:os";
|
|
3
5
|
import { dirname, join, resolve } from "node:path";
|
|
4
6
|
import { fileURLToPath } from "node:url";
|
|
5
7
|
import { whichPantheon } from "./service.js";
|
|
6
8
|
import { detectForHooks, agentById } from "./agents.js";
|
|
7
|
-
import { codexHookState, cursorHookState, copilotHookState, installCodexHooks, installCursorHooks, installCopilotHooks, removeCodexHooks, removeCursorHooks, removeCopilotHooks, } from "./hooks-install.js";
|
|
9
|
+
import { codexHookState, cursorHookState, copilotHookState, kiroHookState, installCodexHooks, installCursorHooks, installCopilotHooks, installKiroHooks, removeCodexHooks, removeCursorHooks, removeCopilotHooks, removeKiroHooks, } from "./hooks-install.js";
|
|
8
10
|
export const HOOK_MARKER = "pantheon hook";
|
|
9
|
-
export const HOOK_RE = /(?:pantheon(?:\.cmd|\.exe|\.bat)?"?\s+hook\s|cli\.js"?\s+hook\s+(?:stop|prompt|end|codex-stop|copilot-stop|cursor-stop)\b)/i;
|
|
11
|
+
export const HOOK_RE = /(?:pantheon(?:\.cmd|\.exe|\.bat)?"?\s+hook\s|cli\.js"?\s+hook\s+(?:stop|prompt|end|codex-stop|copilot-stop|cursor-stop|kiro-stop|kiro-prompt)\b)/i;
|
|
10
12
|
export const isOurHookCommand = (cmd) => !!cmd && (cmd.includes(HOOK_MARKER) || HOOK_RE.test(cmd));
|
|
11
13
|
export const hookBin = (bin) => (/\s/.test(bin) ? `"${bin}"` : bin);
|
|
12
14
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
@@ -108,6 +110,9 @@ export function agentHookStates(projectDir = process.cwd(), only) {
|
|
|
108
110
|
const copilot = copilotHookState(scope, projectDir);
|
|
109
111
|
if (copilot.installed)
|
|
110
112
|
out.push(copilot);
|
|
113
|
+
const kiro = kiroHookState(scope, projectDir);
|
|
114
|
+
if (kiro.installed)
|
|
115
|
+
out.push(kiro);
|
|
111
116
|
}
|
|
112
117
|
const byAgent = new Map();
|
|
113
118
|
for (const s of out) {
|
|
@@ -133,6 +138,8 @@ export function repairHook(home) {
|
|
|
133
138
|
missing.push(id);
|
|
134
139
|
if (id === "copilot" && !copilotHookState(intent.scope, projectDir).installed)
|
|
135
140
|
missing.push(id);
|
|
141
|
+
if (id === "kiro" && !kiroHookState(intent.scope, projectDir).installed)
|
|
142
|
+
missing.push(id);
|
|
136
143
|
}
|
|
137
144
|
if (!missing.length)
|
|
138
145
|
return null;
|
|
@@ -184,7 +191,7 @@ export function installHooks(scope, projectDir = process.cwd(), only) {
|
|
|
184
191
|
? only.map((id) => agentById(id)).filter((b) => !!b)
|
|
185
192
|
: available;
|
|
186
193
|
if (!pick.length) {
|
|
187
|
-
throw new Error("no agent found — install claude, codex, cursor-agent, or
|
|
194
|
+
throw new Error("no agent found — install claude, codex, cursor-agent, copilot, or kiro-cli, or open a project that already uses one");
|
|
188
195
|
}
|
|
189
196
|
const lines = [];
|
|
190
197
|
const agents = [];
|
|
@@ -206,6 +213,10 @@ export function installHooks(scope, projectDir = process.cwd(), only) {
|
|
|
206
213
|
lines.push(...installCopilotHooks(bin, scope, projectDir));
|
|
207
214
|
agents.push("copilot");
|
|
208
215
|
}
|
|
216
|
+
else if (backend.id === "kiro") {
|
|
217
|
+
lines.push(...installKiroHooks(bin, scope, projectDir, toolsAllowed(chosenApproval())));
|
|
218
|
+
agents.push("kiro");
|
|
219
|
+
}
|
|
209
220
|
}
|
|
210
221
|
lines.push(` effect when your agent tries to finish, it checks whether a peer is waiting`, ` on you — and keeps going instead of leaving them hanging.`, ` it also reports when a turn starts and ends, so a worker can tell`, ` an idle editor from one you are actually using.`);
|
|
211
222
|
return { lines, agents };
|
|
@@ -219,6 +230,7 @@ export function removeHook(projectDir = process.cwd()) {
|
|
|
219
230
|
out.push(...removeCodexHooks(projectDir));
|
|
220
231
|
out.push(...removeCursorHooks(projectDir));
|
|
221
232
|
out.push(...removeCopilotHooks(projectDir));
|
|
233
|
+
out.push(...removeKiroHooks(projectDir));
|
|
222
234
|
return out.length ? out : [" nothing installed"];
|
|
223
235
|
}
|
|
224
236
|
function removeClaudeHook(projectDir = process.cwd()) {
|
package/dist/persona.js
CHANGED
|
@@ -170,7 +170,7 @@ export const PERSONA_TEMPLATE = `---
|
|
|
170
170
|
# wake_by: alice, bob # only these peers' requests are handled by this persona
|
|
171
171
|
# kinds: ANSWER, ACCEPT # ANSWER (asks), ACCEPT (verdicts), REVISE (objections), CONTINUE (replies/deliveries)
|
|
172
172
|
# goals: launch-* # only goals whose id or title matches
|
|
173
|
-
# agent: auto # claude-code | codex | cursor | copilot | auto
|
|
173
|
+
# agent: auto # claude-code | codex | cursor | copilot | kiro | auto
|
|
174
174
|
---
|
|
175
175
|
Say how this worker should behave when it is woken while you are away — what it
|
|
176
176
|
should take on, what it should refuse, and where its judgment ends and yours
|
package/dist/profile.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { CONFIG_DIR } from "./config.js";
|
|
4
|
-
export const AGENT_SURFACES = ["codex", "claude-code", "cursor", "copilot"];
|
|
4
|
+
export const AGENT_SURFACES = ["codex", "claude-code", "cursor", "copilot", "kiro"];
|
|
5
5
|
export const SURFACE_BUNDLE_IDS = {
|
|
6
6
|
codex: "com.openai.codex",
|
|
7
7
|
"claude-code": "com.anthropic.claudefordesktop",
|
|
8
8
|
cursor: "com.todesktop.230313mzl4w4u92",
|
|
9
9
|
copilot: "com.microsoft.VSCode",
|
|
10
|
+
kiro: "com.amazon.codewhisperer",
|
|
10
11
|
};
|
|
11
12
|
export const profilePath = (home = CONFIG_DIR) => join(home, "profile.json");
|
|
12
13
|
export function isAgentSurface(value) {
|
|
@@ -17,6 +18,8 @@ export function surfaceFromAgent(agent) {
|
|
|
17
18
|
return "cursor";
|
|
18
19
|
if (agent && /copilot/i.test(agent))
|
|
19
20
|
return "copilot";
|
|
21
|
+
if (agent && /kiro/i.test(agent))
|
|
22
|
+
return "kiro";
|
|
20
23
|
if (agent && /claude/i.test(agent))
|
|
21
24
|
return "claude-code";
|
|
22
25
|
return "codex";
|
package/dist/run-failure.js
CHANGED
|
@@ -5,6 +5,7 @@ export const SIGN_IN_FIX = {
|
|
|
5
5
|
codex: "run `codex login`",
|
|
6
6
|
cursor: "run `cursor-agent login`",
|
|
7
7
|
copilot: "run `copilot login` (or `gh auth login` — copilot uses gh's sign-in too)",
|
|
8
|
+
kiro: "run `kiro-cli login` (or set KIRO_API_KEY)",
|
|
8
9
|
};
|
|
9
10
|
const sh = (dir, ...args) => execFileSync("git", ["-C", dir, ...args], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 5_000 }).trim();
|
|
10
11
|
export const gitProbe = {
|
package/dist/setup-guide.js
CHANGED
|
@@ -195,7 +195,7 @@ export async function runGuide(io, ctx, deps = {}, preset = {}) {
|
|
|
195
195
|
: "only people you approve by hand (pantheon admit <name> --may-wake)"}`);
|
|
196
196
|
io.say(` • Alerts: ${shortAlert(a.notifications).toLowerCase()}`);
|
|
197
197
|
io.say(` • Approval: ${a.approval === "approve"
|
|
198
|
-
? "your agent sends to teammates in your name without asking each time (Claude Code, Cursor and
|
|
198
|
+
? "your agent sends to teammates in your name without asking each time (Claude Code, Cursor, Codex, and Kiro's IDE and pantheon agent; Copilot asks once per tool per folder)"
|
|
199
199
|
: "your agent asks you before each send, goal and claim; reading and waiting never prompt"}`);
|
|
200
200
|
io.say(` • Decisions: ${a.decides.length ? `you personally decide ${a.decides.join(", ")}` : "none reserved for you — your agent may decide; add an area when one comes up"}`);
|
|
201
201
|
if (a.wake !== "no" && ctx.project)
|
package/dist/tray.js
CHANGED
|
@@ -144,7 +144,7 @@ async function trayStatusOne(cfg) {
|
|
|
144
144
|
];
|
|
145
145
|
const profile = loadProfile(cfg);
|
|
146
146
|
const surface = profile.agent.primary_surface;
|
|
147
|
-
const surfaceName = surface === "claude-code" ? "Claude" : surface === "cursor" ? "Cursor" : surface === "copilot" ? "Copilot" : "Codex";
|
|
147
|
+
const surfaceName = surface === "claude-code" ? "Claude" : surface === "cursor" ? "Cursor" : surface === "copilot" ? "Copilot" : surface === "kiro" ? "Kiro" : "Codex";
|
|
148
148
|
const rawWorkerState = workerState();
|
|
149
149
|
return {
|
|
150
150
|
configured: true,
|
package/dist/update-check.js
CHANGED
|
@@ -5,6 +5,7 @@ import { CONFIG_DIR } from "./config.js";
|
|
|
5
5
|
import { repoRoot, PKG_NAME } from "./upgrade.js";
|
|
6
6
|
import { VERSION } from "./version.js";
|
|
7
7
|
import { npmSpawn } from "./which.js";
|
|
8
|
+
import { proxyEnvFor } from "./network.js";
|
|
8
9
|
export function semverGt(x, y) {
|
|
9
10
|
const p = (s) => s.split(".").map((n) => Number(n) || 0);
|
|
10
11
|
const [a, b] = [p(x), p(y)];
|
|
@@ -81,7 +82,7 @@ export function defaultDeps(home) {
|
|
|
81
82
|
},
|
|
82
83
|
npmLatest: () => {
|
|
83
84
|
try {
|
|
84
|
-
const s = npmSpawn(["view", PKG_NAME, "version"]);
|
|
85
|
+
const s = npmSpawn(["view", PKG_NAME, "version"], undefined, undefined, proxyEnvFor());
|
|
85
86
|
return execFileSync(s.command, s.args, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 4000, ...s.options }).trim() || null;
|
|
86
87
|
}
|
|
87
88
|
catch {
|
package/dist/upgrade.js
CHANGED
|
@@ -4,6 +4,7 @@ import { dirname, join } from "node:path";
|
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { installForUser } from "./install.js";
|
|
6
6
|
import { npmSpawn } from "./which.js";
|
|
7
|
+
import { proxyEnvFor } from "./network.js";
|
|
7
8
|
import { relayProc, workerProc, notifierProc, menubarProc } from "./machine.js";
|
|
8
9
|
export function repoRoot() {
|
|
9
10
|
return join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
@@ -30,7 +31,7 @@ export function rewireVia(root, fallback, run = (file, args) => execFileSync(pro
|
|
|
30
31
|
export function defaultDeps() {
|
|
31
32
|
const git = (root, ...args) => execFileSync("git", ["-C", root, ...args], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
|
|
32
33
|
const npm = (args, opts) => {
|
|
33
|
-
const s = npmSpawn(args);
|
|
34
|
+
const s = npmSpawn(args, undefined, undefined, proxyEnvFor());
|
|
34
35
|
return execFileSync(s.command, s.args, { encoding: "utf8", ...opts, ...s.options });
|
|
35
36
|
};
|
|
36
37
|
return {
|
package/dist/which.js
CHANGED
|
@@ -76,10 +76,12 @@ export function spawnShape(binary, os = platform()) {
|
|
|
76
76
|
return { command: binary, shell: false };
|
|
77
77
|
return { command: binary, shell: /\.(cmd|bat)$/i.test(binary) };
|
|
78
78
|
}
|
|
79
|
-
export function npmSpawn(args, os = platform(), resolveNpm = () => which("npm", os)) {
|
|
79
|
+
export function npmSpawn(args, os = platform(), resolveNpm = () => which("npm", os), proxyEnv = {}) {
|
|
80
|
+
const env = Object.keys(proxyEnv).length ? { env: { ...process.env, ...proxyEnv } } : {};
|
|
80
81
|
if (!isWindows(os))
|
|
81
|
-
return { command: "npm", args: [...args], options: {} };
|
|
82
|
-
|
|
82
|
+
return { command: "npm", args: [...args], options: { ...env } };
|
|
83
|
+
const s = agentSpawn(resolveNpm() ?? "npm.cmd", args, os);
|
|
84
|
+
return { ...s, options: { ...s.options, ...env } };
|
|
83
85
|
}
|
|
84
86
|
const cmdQuote = (a) => (/[\s"&|<>^()]/.test(a) || a === "" ? `"${a.replace(/"/g, '\\"')}"` : a);
|
|
85
87
|
export function agentSpawn(binary, args, os = platform()) {
|
package/dist/worker.js
CHANGED
|
@@ -4,7 +4,7 @@ import { mkdirSync, writeFileSync, existsSync, readFileSync } from "node:fs";
|
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { join, resolve } from "node:path";
|
|
6
6
|
import { PantheonClient } from "./client.js";
|
|
7
|
-
import { headlessSpawn, materializeSpawnFiles, chooseAgent, describeChoice } from "./agents.js";
|
|
7
|
+
import { headlessSpawn, materializeSpawnFiles, chooseAgent, describeChoice, unattendedRefusal } from "./agents.js";
|
|
8
8
|
import { agentSpawn } from "./which.js";
|
|
9
9
|
import { VERSION } from "./version.js";
|
|
10
10
|
import { applyAnswer, loadPolicy, mayAsk, needsSelfUpgrade, recordAsk, savePolicy, useGrant, } from "./worker-policy.js";
|
|
@@ -19,7 +19,11 @@ import { diagnoseRun, gitProbe } from "./run-failure.js";
|
|
|
19
19
|
import { installedTools, preferredTool } from "./notifier.js";
|
|
20
20
|
import { loadPersonas, matchPersona, personaByName, personaMatches, effectivePolicy, personaBrief, describePersona, } from "./persona.js";
|
|
21
21
|
import { isContinuationFor, LIMITS, shouldDeferToHuman } from "./protocol.js";
|
|
22
|
-
|
|
22
|
+
import { proxyEnvFor } from "./network.js";
|
|
23
|
+
const git = (cwd, ...args) => {
|
|
24
|
+
const px = proxyEnvFor();
|
|
25
|
+
return execFileSync("git", args, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], ...(Object.keys(px).length ? { env: { ...process.env, ...px } } : {}) }).trim();
|
|
26
|
+
};
|
|
23
27
|
const CLOCK_SKEW_MS = 5_000;
|
|
24
28
|
const isRepo = (cwd) => {
|
|
25
29
|
try {
|
|
@@ -583,7 +587,7 @@ export class Worker {
|
|
|
583
587
|
let command;
|
|
584
588
|
let agentId;
|
|
585
589
|
let args;
|
|
586
|
-
let env = { ...process.env };
|
|
590
|
+
let env = { ...process.env, ...proxyEnvFor() };
|
|
587
591
|
try {
|
|
588
592
|
const runHome = this.runHome();
|
|
589
593
|
agentId = this.opts.agentCmd ? "claude-code" : undefined;
|
|
@@ -604,6 +608,9 @@ export class Worker {
|
|
|
604
608
|
this.opts.log(` agent ${said}`);
|
|
605
609
|
this.lastAgentSaid = said;
|
|
606
610
|
}
|
|
611
|
+
const refused = unattendedRefusal(choice);
|
|
612
|
+
if (refused)
|
|
613
|
+
throw new Error(refused);
|
|
607
614
|
const plan = headlessSpawn({ backend: choice.backend, binary: choice.binary, prompt: brief, worktree, cfg: this.cfg, branch, allowBash, runHome });
|
|
608
615
|
materializeSpawnFiles(worktree, plan);
|
|
609
616
|
({ command, args, env } = { command: plan.command, args: plan.args, env: { ...env, ...plan.env } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@join-pantheon/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Let your coding agent collaborate directly with your teammates' agents — ask, agree an interface, and deliver, without a human relaying messages.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
25
|
+
"undici": "^7.29.1",
|
|
25
26
|
"ws": "^8.18.0",
|
|
26
27
|
"zod": "^3.23.8"
|
|
27
28
|
},
|