@anhlp/alp 0.0.1-beta.4 → 0.0.1-beta.7
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 +11 -412
- package/bin/alp.js +3 -0
- package/package.json +11 -103
- package/dist/THIRD-PARTY-NOTICES.txt +0 -626
- package/dist/acp.js +0 -19936
- package/dist/alpd.js +0 -49562
- package/docs/modular-monorepo.md +0 -214
- package/packages/cli/README.md +0 -7
- package/packages/cli/dist/THIRD-PARTY-NOTICES.txt +0 -651
- package/packages/cli/dist/acp/agent.d.ts +0 -37
- package/packages/cli/dist/acp/agent.js +0 -489
- package/packages/cli/dist/acp/main.d.ts +0 -4
- package/packages/cli/dist/acp/main.js +0 -23
- package/packages/cli/dist/acp.js +0 -19936
- package/packages/cli/dist/alp-web/THIRD-PARTY-NOTICES.txt +0 -2590
- package/packages/cli/dist/alp-web/alp-boundary.json +0 -15
- package/packages/cli/dist/alp-web/apple-touch-icon.png +0 -0
- package/packages/cli/dist/alp-web/assets/TerminalPanel-DLuoa74B.css +0 -1
- package/packages/cli/dist/alp-web/assets/TerminalPanel-PrU2l3u5.js +0 -16
- package/packages/cli/dist/alp-web/assets/index-BJdBTDFX.css +0 -1
- package/packages/cli/dist/alp-web/assets/index-DpfiPv5s.js +0 -52
- package/packages/cli/dist/alp-web/favicon-attention.svg +0 -6
- package/packages/cli/dist/alp-web/favicon-running.svg +0 -6
- package/packages/cli/dist/alp-web/favicon.svg +0 -5
- package/packages/cli/dist/alp-web/index.html +0 -20
- package/packages/cli/dist/alp-web.js +0 -9640
- package/packages/cli/dist/alpd.js +0 -49562
- package/packages/cli/dist/backup.d.ts +0 -4
- package/packages/cli/dist/backup.js +0 -146
- package/packages/cli/dist/build-manifest.json +0 -240
- package/packages/cli/dist/cli.d.ts +0 -2
- package/packages/cli/dist/cli.js +0 -30
- package/packages/cli/dist/daemon.d.ts +0 -35
- package/packages/cli/dist/daemon.js +0 -126
- package/packages/cli/dist/index.d.ts +0 -1
- package/packages/cli/dist/index.js +0 -5
- package/packages/cli/dist/interfaces.d.ts +0 -24
- package/packages/cli/dist/interfaces.js +0 -156
- package/packages/cli/dist/library.d.ts +0 -140
- package/packages/cli/dist/library.js +0 -319
- package/packages/cli/dist/paths.d.ts +0 -3
- package/packages/cli/dist/paths.js +0 -18
- package/packages/cli/dist/projects.d.ts +0 -9
- package/packages/cli/dist/projects.js +0 -159
- package/packages/cli/dist/schedules.d.ts +0 -2
- package/packages/cli/dist/schedules.js +0 -45
- package/packages/cli/dist/sessions.d.ts +0 -43
- package/packages/cli/dist/sessions.js +0 -458
- package/packages/cli/dist/tasks.d.ts +0 -29
- package/packages/cli/dist/tasks.js +0 -345
- package/packages/cli/dist/terminal.d.ts +0 -8
- package/packages/cli/dist/terminal.js +0 -79
- package/packages/cli/dist/usage.d.ts +0 -3
- package/packages/cli/dist/usage.js +0 -78
- package/packages/cli/dist/web-service.d.ts +0 -38
- package/packages/cli/dist/web-service.js +0 -119
- package/packages/client/README.md +0 -29
- package/packages/client/dist/acp-probe.d.ts +0 -44
- package/packages/client/dist/acp-probe.js +0 -37
- package/packages/client/dist/antigravity-probe.d.ts +0 -34
- package/packages/client/dist/antigravity-probe.js +0 -95
- package/packages/client/dist/command.d.ts +0 -5
- package/packages/client/dist/command.js +0 -33
- package/packages/client/dist/doctor.d.ts +0 -13
- package/packages/client/dist/doctor.js +0 -587
- package/packages/client/dist/index.d.ts +0 -151
- package/packages/client/dist/index.js +0 -533
- package/packages/client/dist/integration-lock.d.ts +0 -35
- package/packages/client/dist/integration-lock.js +0 -179
- package/packages/client/dist/ipc.d.ts +0 -42
- package/packages/client/dist/ipc.js +0 -69
- package/packages/client/dist/library-test.d.ts +0 -94
- package/packages/client/dist/library-test.js +0 -37
- package/packages/client/dist/mcp-probe.d.ts +0 -24
- package/packages/client/dist/mcp-probe.js +0 -147
- package/packages/client/dist/portable.d.ts +0 -19
- package/packages/client/dist/portable.js +0 -33
- package/packages/client/dist/prompt.d.ts +0 -32
- package/packages/client/dist/prompt.js +0 -59
- package/packages/client/dist/render.d.ts +0 -6
- package/packages/client/dist/render.js +0 -120
- package/packages/client/dist/rpc/client.d.ts +0 -82
- package/packages/client/dist/rpc/client.js +0 -292
- package/packages/client/dist/rpc/errors.d.ts +0 -42
- package/packages/client/dist/rpc/errors.js +0 -34
- package/packages/client/dist/rpc/framing.d.ts +0 -21
- package/packages/client/dist/rpc/framing.js +0 -57
- package/packages/client/dist/rpc/handshake.d.ts +0 -19
- package/packages/client/dist/rpc/handshake.js +0 -8
- package/packages/client/dist/rpc/reconnect.d.ts +0 -97
- package/packages/client/dist/rpc/reconnect.js +0 -227
- package/packages/client/dist/rpc/registry.d.ts +0 -211
- package/packages/client/dist/rpc/registry.js +0 -145
- package/packages/client/dist/rpc/timers.d.ts +0 -11
- package/packages/client/dist/rpc/timers.js +0 -11
- package/packages/client/dist/service.d.ts +0 -50
- package/packages/client/dist/service.js +0 -143
- package/packages/client/dist/setup.d.ts +0 -2
- package/packages/client/dist/setup.js +0 -146
- package/packages/client/dist/supervise.d.ts +0 -14
- package/packages/client/dist/supervise.js +0 -87
- package/packages/client/dist/websocket.d.ts +0 -51
- package/packages/client/dist/websocket.js +0 -190
- package/packages/core/README.md +0 -7
- package/packages/core/dist/adapter.d.ts +0 -20
- package/packages/core/dist/adapter.js +0 -30
- package/packages/core/dist/atomic.d.ts +0 -2
- package/packages/core/dist/atomic.js +0 -28
- package/packages/core/dist/backup.d.ts +0 -27
- package/packages/core/dist/backup.js +0 -681
- package/packages/core/dist/beads.d.ts +0 -65
- package/packages/core/dist/beads.js +0 -213
- package/packages/core/dist/delegation.d.ts +0 -2
- package/packages/core/dist/delegation.js +0 -32
- package/packages/core/dist/errors.d.ts +0 -4
- package/packages/core/dist/errors.js +0 -11
- package/packages/core/dist/formulas.d.ts +0 -25
- package/packages/core/dist/formulas.js +0 -201
- package/packages/core/dist/hook-run.d.ts +0 -44
- package/packages/core/dist/hook-run.js +0 -60
- package/packages/core/dist/hooks.d.ts +0 -35
- package/packages/core/dist/hooks.js +0 -30
- package/packages/core/dist/index.d.ts +0 -31
- package/packages/core/dist/index.js +0 -65
- package/packages/core/dist/init.d.ts +0 -30
- package/packages/core/dist/init.js +0 -89
- package/packages/core/dist/library-edit.d.ts +0 -93
- package/packages/core/dist/library-edit.js +0 -368
- package/packages/core/dist/library.d.ts +0 -28
- package/packages/core/dist/library.js +0 -108
- package/packages/core/dist/log.d.ts +0 -37
- package/packages/core/dist/log.js +0 -156
- package/packages/core/dist/migrations.d.ts +0 -9
- package/packages/core/dist/migrations.js +0 -95
- package/packages/core/dist/models.d.ts +0 -11
- package/packages/core/dist/models.js +0 -44
- package/packages/core/dist/permissions.d.ts +0 -14
- package/packages/core/dist/permissions.js +0 -229
- package/packages/core/dist/profiles.d.ts +0 -27
- package/packages/core/dist/profiles.js +0 -122
- package/packages/core/dist/promptsafe.d.ts +0 -1
- package/packages/core/dist/promptsafe.js +0 -13
- package/packages/core/dist/providers.d.ts +0 -90
- package/packages/core/dist/providers.js +0 -101
- package/packages/core/dist/resolver.d.ts +0 -41
- package/packages/core/dist/resolver.js +0 -240
- package/packages/core/dist/safe-path.d.ts +0 -2
- package/packages/core/dist/safe-path.js +0 -24
- package/packages/core/dist/shell.d.ts +0 -16
- package/packages/core/dist/shell.js +0 -22
- package/packages/core/dist/state-schema.d.ts +0 -9
- package/packages/core/dist/state-schema.js +0 -54
- package/packages/core/dist/task-rows.d.ts +0 -47
- package/packages/core/dist/task-rows.js +0 -45
- package/packages/core/dist/tasks.d.ts +0 -128
- package/packages/core/dist/tasks.js +0 -835
- package/packages/core/dist/teams.d.ts +0 -80
- package/packages/core/dist/teams.js +0 -159
- package/packages/core/dist/template-path.d.ts +0 -2
- package/packages/core/dist/template-path.js +0 -10
- package/packages/core/dist/trust.d.ts +0 -8
- package/packages/core/dist/trust.js +0 -47
- package/packages/core/dist/types.d.ts +0 -51
- package/packages/core/dist/upgrade.d.ts +0 -10
- package/packages/core/dist/upgrade.js +0 -200
- package/packages/core/dist/user-settings.d.ts +0 -6
- package/packages/core/dist/user-settings.js +0 -72
- package/packages/core/dist/user-worktree.d.ts +0 -29
- package/packages/core/dist/user-worktree.js +0 -242
- package/packages/core/dist/validation.d.ts +0 -17
- package/packages/core/dist/validation.js +0 -296
- package/packages/core/dist/verify.d.ts +0 -15
- package/packages/core/dist/verify.js +0 -123
- package/packages/core/dist/workflow.d.ts +0 -45
- package/packages/core/dist/workflow.js +0 -33
- package/templates/ALP.md +0 -52
- package/templates/agents/lead/AGENT.md +0 -90
- package/templates/agents/main/AGENT.md +0 -150
- package/templates/agents/oracle/AGENT.md +0 -44
- package/templates/agents/peer/AGENT.md +0 -55
- package/templates/agents/reviewer/AGENT.md +0 -80
- package/templates/agents/supervisor/AGENT.md +0 -72
- package/templates/providers/antigravity.json +0 -6
- package/templates/providers/opencode.json +0 -7
- package/templates/role-skills.json +0 -8
- package/templates/skills/bug-loop/SKILL.md +0 -44
- package/templates/skills/bug-loop/references/test-proof.md +0 -25
- package/templates/skills/goal-griller/SKILL.md +0 -49
- package/templates/skills/prompt-leverage/SKILL.md +0 -37
- package/templates/skills/prompt-leverage/references/brief-template.md +0 -27
- package/templates/skills/sequence-execution-plan/SKILL.md +0 -42
- package/templates/skills/sequence-execution-plan/references/plan-template.md +0 -22
- package/templates/skills/smart-commits/SKILL.md +0 -40
- package/templates/skills/xia/SKILL.md +0 -42
- package/templates/teams/cafe/HOUSE_RULES.md +0 -1
- package/templates/teams/cafe/team.json +0 -15
- package/templates/teams/pho/HOUSE_RULES.md +0 -1
- package/templates/teams/pho/team.json +0 -14
|
@@ -1,345 +0,0 @@
|
|
|
1
|
-
// packages/cli/src/tasks.js
|
|
2
|
-
import { spawn } from "node:child_process";
|
|
3
|
-
import { access, readFile, writeFile } from "node:fs/promises";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { parseArgs } from "node:util";
|
|
6
|
-
import { exportBeads, importBeads, parseJsonl } from "@anhlp/alp-core/beads";
|
|
7
|
-
import { findFormula, formulaDirs, listFormulas, pourFormula } from "@anhlp/alp-core/formulas";
|
|
8
|
-
import { describeVerification } from "@anhlp/alp-core/verify";
|
|
9
|
-
import { ago } from "@anhlp/alp-client/render";
|
|
10
|
-
import { parse as toml } from "smol-toml";
|
|
11
|
-
import { addGate, blockersOf, checkGates, childrenOf, closeTask, compactTasks, createTask, describeGate, gateOpen, epicReport, gatesOf, linkTask, listTasks, loadTasks, readyTasks, reopenTask, resolveGate, summarize, TASKS_DIR, updateTask } from "@anhlp/alp-core/tasks";
|
|
12
|
-
import { alpHome } from "@anhlp/alp-client/index";
|
|
13
|
-
import { UsageError } from "./usage.js";
|
|
14
|
-
var STATUS_MARK = { open: "\u25CB", in_progress: "\u25D0", review: "\u25D1", closed: "\u25CF" };
|
|
15
|
-
async function taskProject(directory) {
|
|
16
|
-
const root = path.resolve(directory ?? process.cwd());
|
|
17
|
-
try {
|
|
18
|
-
await access(path.join(root, ".alp"));
|
|
19
|
-
} catch {
|
|
20
|
-
throw new Error(`${root} is not an ALP project (no .alp directory); run alp init, or pass --project`);
|
|
21
|
-
}
|
|
22
|
-
return root;
|
|
23
|
-
}
|
|
24
|
-
function taskRow(task, tasks) {
|
|
25
|
-
const row = summarize(task, tasks);
|
|
26
|
-
const extra = [
|
|
27
|
-
row.blockedBy ? `blocked by ${row.blockedBy.join(", ")}` : "",
|
|
28
|
-
row.gates ? `waits on ${row.gates.join("; ")}` : "",
|
|
29
|
-
row.assignee ? `@${row.assignee}` : "",
|
|
30
|
-
row.labels ? row.labels.map((label) => `#${label}`).join(" ") : ""
|
|
31
|
-
].filter(Boolean).join(" ");
|
|
32
|
-
return `${STATUS_MARK[task.status]} ${task.id.padEnd(10)} P${task.priority} ${task.type.padEnd(7)} ${task.status.padEnd(11)} ${task.title}${extra ? ` ${extra}` : ""}`;
|
|
33
|
-
}
|
|
34
|
-
function warnUnreadable(errors) {
|
|
35
|
-
for (const { file, error } of errors) console.error(`alp: skipped ${file}: ${error}`);
|
|
36
|
-
}
|
|
37
|
-
async function tasksCommand(args) {
|
|
38
|
-
if (args[0] === "gates" || args[0] === "compact") return taskMaintenance([args[0]], args.slice(1));
|
|
39
|
-
if (args[0] === "export" || args[0] === "import") return beads(args[0], args.slice(1));
|
|
40
|
-
const { values, positionals } = parseArgs({ args, allowPositionals: true, options: {
|
|
41
|
-
all: { type: "boolean" },
|
|
42
|
-
status: { type: "string" },
|
|
43
|
-
label: { type: "string" },
|
|
44
|
-
project: { type: "string" },
|
|
45
|
-
json: { type: "boolean" }
|
|
46
|
-
} });
|
|
47
|
-
if (positionals.length > 1 || positionals.length && positionals[0] !== "ready") throw new UsageError();
|
|
48
|
-
const root = await taskProject(values.project);
|
|
49
|
-
const { tasks, errors } = await loadTasks(root);
|
|
50
|
-
warnUnreadable(errors);
|
|
51
|
-
const rows = positionals[0] === "ready" ? readyTasks(tasks) : listTasks(tasks, { status: values.status, label: values.label, all: values.all });
|
|
52
|
-
if (values.json) {
|
|
53
|
-
console.log(JSON.stringify(rows));
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
if (!rows.length) {
|
|
57
|
-
console.log(positionals[0] === "ready" ? "No task is ready" : `No tasks in ${path.join(root, TASKS_DIR)}`);
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
for (const task of rows) console.log(taskRow(task, tasks));
|
|
61
|
-
}
|
|
62
|
-
var gh = (args, { cwd }) => new Promise((resolve, reject) => {
|
|
63
|
-
const bin = process.env.ALP_GH_BIN ?? "gh";
|
|
64
|
-
const script = process.platform === "win32" && /\.[cm]?js$/i.test(bin);
|
|
65
|
-
const child = spawn(script ? process.execPath : bin, script ? [bin, ...args] : args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
66
|
-
let stdout = "";
|
|
67
|
-
let stderr = "";
|
|
68
|
-
child.stdout.on("data", (chunk) => {
|
|
69
|
-
stdout += chunk;
|
|
70
|
-
});
|
|
71
|
-
child.stderr.on("data", (chunk) => {
|
|
72
|
-
stderr += chunk;
|
|
73
|
-
});
|
|
74
|
-
child.on("error", (error) => reject(error.code === "ENOENT" ? new Error("gh is not installed or not on PATH") : error));
|
|
75
|
-
child.on("close", (code) => code === 0 ? resolve(stdout) : reject(new Error(stderr.trim() || `gh exited with ${code}`)));
|
|
76
|
-
});
|
|
77
|
-
async function taskMaintenance([command], args) {
|
|
78
|
-
const { values, positionals: rest } = parseArgs({ args, allowPositionals: true, options: {
|
|
79
|
-
project: { type: "string" },
|
|
80
|
-
json: { type: "boolean" },
|
|
81
|
-
days: { type: "string" },
|
|
82
|
-
"dry-run": { type: "boolean" }
|
|
83
|
-
} });
|
|
84
|
-
if (rest.length) throw new UsageError();
|
|
85
|
-
const root = await taskProject(values.project);
|
|
86
|
-
if (command === "compact") {
|
|
87
|
-
const days = values.days === void 0 ? 30 : Number(values.days);
|
|
88
|
-
const changed = await compactTasks(root, { days, dryRun: values["dry-run"] }, "user");
|
|
89
|
-
if (values.json) {
|
|
90
|
-
console.log(JSON.stringify(changed));
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
if (!changed.length) {
|
|
94
|
-
console.log(`No task closed more than ${days} days ago is left to compact`);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
for (const { id, before, after } of changed) console.log(`${id} ${before} \u2192 ${after} characters`);
|
|
98
|
-
console.log(`${values["dry-run"] ? "Would compact" : "Compacted"} ${changed.length} closed ${changed.length === 1 ? "task" : "tasks"}`);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
const checked = await checkGates(root, gh);
|
|
102
|
-
const { tasks } = await loadTasks(root);
|
|
103
|
-
const open = tasks.filter((task) => task.status !== "closed").flatMap((task) => task.gates.filter((gate) => gateOpen(gate)).map((gate) => ({ task, gate })));
|
|
104
|
-
if (values.json) {
|
|
105
|
-
console.log(JSON.stringify({ ...checked, open: open.map(({ task, gate }) => ({ task: task.id, ...gate })) }));
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
for (const { task, gate, detail } of checked.cleared) console.log(`\u2713 ${task} ${gate} cleared: ${detail}`);
|
|
109
|
-
for (const { task, gate, error } of checked.errors) console.error(`alp: could not check ${task} ${gate}: ${error}`);
|
|
110
|
-
if (!open.length) {
|
|
111
|
-
console.log("No open gates");
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
for (const { task, gate } of open) {
|
|
115
|
-
const state = checked.pending.find((entry) => entry.task === task.id && entry.gate === gate.id)?.detail;
|
|
116
|
-
console.log(`\u23F8 ${task.id} ${describeGate(gate)}${state ? ` (${state})` : ""} ${task.title}`);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
async function beads(command, args) {
|
|
120
|
-
const { values, positionals } = parseArgs({ args, allowPositionals: true, options: {
|
|
121
|
-
project: { type: "string" },
|
|
122
|
-
output: { type: "string", short: "o" },
|
|
123
|
-
"dry-run": { type: "boolean" },
|
|
124
|
-
json: { type: "boolean" }
|
|
125
|
-
} });
|
|
126
|
-
const root = await taskProject(values.project);
|
|
127
|
-
if (command === "export") {
|
|
128
|
-
if (positionals.length || values["dry-run"]) throw new UsageError();
|
|
129
|
-
const { tasks, errors: errors2 } = await loadTasks(root);
|
|
130
|
-
warnUnreadable(errors2);
|
|
131
|
-
const text = exportBeads(tasks).map((record) => JSON.stringify(record)).join("\n") + (tasks.length ? "\n" : "");
|
|
132
|
-
if (values.output) {
|
|
133
|
-
await writeFile(values.output, text);
|
|
134
|
-
console.error(`Exported ${tasks.length} ${tasks.length === 1 ? "task" : "tasks"} to ${values.output}`);
|
|
135
|
-
} else {
|
|
136
|
-
process.stdout.write(text);
|
|
137
|
-
}
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
if (positionals.length > 1 || values.output) throw new UsageError();
|
|
141
|
-
const file = positionals[0] ?? path.join(root, ".beads", "issues.jsonl");
|
|
142
|
-
const { records, errors } = parseJsonl(await readFile(file, "utf8"));
|
|
143
|
-
const report = await importBeads(root, records, { dryRun: values["dry-run"], by: "user" });
|
|
144
|
-
report.skipped.push(...errors);
|
|
145
|
-
if (values.json) {
|
|
146
|
-
console.log(JSON.stringify(report));
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
const verb = values["dry-run"] ? "Would import" : "Imported";
|
|
150
|
-
for (const { id, from } of report.created) console.log(`+ ${id}${id !== from ? ` (from ${from})` : ""}`);
|
|
151
|
-
for (const { id, from } of report.updated) console.log(`~ ${id}${id !== from ? ` (from ${from})` : ""}`);
|
|
152
|
-
for (const { line, reason } of report.skipped.sort((a, b) => a.line - b.line)) console.error(`alp: skipped line ${line}: ${reason}`);
|
|
153
|
-
for (const warning of report.warnings) console.error(`alp: ${warning}`);
|
|
154
|
-
console.log(`${verb} ${file}: ${report.created.length} created, ${report.updated.length} updated, ${report.skipped.length} skipped`);
|
|
155
|
-
}
|
|
156
|
-
async function formulaCommand([action, ...args]) {
|
|
157
|
-
const { values, positionals } = parseArgs({ args, allowPositionals: true, options: {
|
|
158
|
-
project: { type: "string" },
|
|
159
|
-
var: { type: "string", multiple: true },
|
|
160
|
-
parent: { type: "string" },
|
|
161
|
-
"dry-run": { type: "boolean" },
|
|
162
|
-
json: { type: "boolean" }
|
|
163
|
-
} });
|
|
164
|
-
const root = await taskProject(values.project);
|
|
165
|
-
const home = alpHome();
|
|
166
|
-
if (action === "list") {
|
|
167
|
-
if (positionals.length) throw new UsageError();
|
|
168
|
-
const found = await listFormulas(root, home, { toml });
|
|
169
|
-
if (values.json) {
|
|
170
|
-
console.log(JSON.stringify(found));
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
if (!found.length) {
|
|
174
|
-
console.log(`No formulas in ${formulaDirs(root, home).join(", ")}`);
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
for (const entry of found) console.log(entry.error ? `\u2717 ${entry.name} ${entry.file}: ${entry.error}` : `${entry.name} ${entry.formula.steps.length} steps${entry.formula.description ? ` ${entry.formula.description.split("\n")[0]}` : ""}`);
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
if (positionals.length !== 1) throw new UsageError();
|
|
181
|
-
const { formula, file } = await findFormula(root, home, positionals[0], { toml });
|
|
182
|
-
if (action === "show") {
|
|
183
|
-
if (values.json) {
|
|
184
|
-
console.log(JSON.stringify(formula));
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
console.log(`${formula.formula}${formula.version ? ` v${formula.version}` : ""} ${file}`);
|
|
188
|
-
if (formula.description) console.log(` ${formula.description}`);
|
|
189
|
-
for (const [name, spec] of Object.entries(formula.vars)) console.log(` --var ${name}=\u2026${spec.required ? " (required)" : spec.default !== void 0 ? ` (default ${spec.default})` : ""}${spec.description ? ` ${spec.description}` : ""}`);
|
|
190
|
-
for (const step of formula.steps) console.log(` ${step.id}${step.type === "human" ? " [you]" : step.type !== "task" ? ` [${step.type}]` : ""}: ${step.title}${step.needs.length ? ` after ${step.needs.join(", ")}` : ""}`);
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
if (action !== "pour") throw new UsageError();
|
|
194
|
-
const given = {};
|
|
195
|
-
for (const entry of values.var ?? []) {
|
|
196
|
-
const at = entry.indexOf("=");
|
|
197
|
-
if (at < 1) throw new UsageError();
|
|
198
|
-
given[entry.slice(0, at)] = entry.slice(at + 1);
|
|
199
|
-
}
|
|
200
|
-
const { epic, tasks } = await pourFormula(root, formula, given, "user", { dryRun: values["dry-run"], ...values.parent ? { parent: values.parent } : {} });
|
|
201
|
-
if (values.json) {
|
|
202
|
-
console.log(JSON.stringify({ epic, tasks }));
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
console.log(`${values["dry-run"] ? "Would pour" : "Poured"} ${formula.formula} as ${epic.id} ${epic.title}`);
|
|
206
|
-
const all = [epic, ...tasks];
|
|
207
|
-
for (const task of tasks) console.log(` ${taskRow(task, all)}`);
|
|
208
|
-
}
|
|
209
|
-
var repeated = { type: "string", multiple: true };
|
|
210
|
-
async function taskCommand([action, ...args]) {
|
|
211
|
-
const { values, positionals } = parseArgs({ args, allowPositionals: true, options: {
|
|
212
|
-
description: { type: "string", short: "d" },
|
|
213
|
-
priority: { type: "string", short: "p" },
|
|
214
|
-
type: { type: "string", short: "t" },
|
|
215
|
-
label: { ...repeated, short: "l" },
|
|
216
|
-
path: repeated,
|
|
217
|
-
parent: { type: "string" },
|
|
218
|
-
after: repeated,
|
|
219
|
-
related: repeated,
|
|
220
|
-
from: { type: "string" },
|
|
221
|
-
title: { type: "string" },
|
|
222
|
-
message: { type: "string", short: "m" },
|
|
223
|
-
reason: { type: "string" },
|
|
224
|
-
unverified: { type: "string" },
|
|
225
|
-
project: { type: "string" },
|
|
226
|
-
json: { type: "boolean" },
|
|
227
|
-
human: { type: "string" },
|
|
228
|
-
timer: { type: "string" },
|
|
229
|
-
pr: { type: "string" },
|
|
230
|
-
run: { type: "string" }
|
|
231
|
-
} });
|
|
232
|
-
const root = await taskProject(values.project);
|
|
233
|
-
const fields = {
|
|
234
|
-
...values.description !== void 0 ? { description: values.description } : {},
|
|
235
|
-
...values.priority !== void 0 ? { priority: values.priority } : {},
|
|
236
|
-
...values.type !== void 0 ? { type: values.type } : {},
|
|
237
|
-
...values.label ? { labels: values.label } : {},
|
|
238
|
-
...values.path ? { paths: values.path } : {}
|
|
239
|
-
};
|
|
240
|
-
let task;
|
|
241
|
-
if (action === "add") {
|
|
242
|
-
const title = positionals.join(" ").trim();
|
|
243
|
-
if (!title) throw new UsageError();
|
|
244
|
-
task = await createTask(root, { title, ...fields, parent: values.parent, blockedBy: values.after, related: values.related, discoveredFrom: values.from }, "user");
|
|
245
|
-
} else if (action === "show") {
|
|
246
|
-
if (positionals.length !== 1) throw new UsageError();
|
|
247
|
-
const { tasks: tasks2, errors } = await loadTasks(root);
|
|
248
|
-
warnUnreadable(errors);
|
|
249
|
-
task = tasks2.find((candidate) => candidate.id === positionals[0]);
|
|
250
|
-
if (!task) throw new Error(`No task ${positionals[0]} in ${path.join(root, TASKS_DIR)}`);
|
|
251
|
-
if (values.json) {
|
|
252
|
-
console.log(JSON.stringify(task));
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
printTask(task, tasks2);
|
|
256
|
-
return;
|
|
257
|
-
} else if (action === "report") {
|
|
258
|
-
if (positionals.length !== 1) throw new UsageError();
|
|
259
|
-
const { tasks: tasks2, errors } = await loadTasks(root);
|
|
260
|
-
warnUnreadable(errors);
|
|
261
|
-
const report = epicReport(positionals[0], tasks2);
|
|
262
|
-
console.log(values.json ? JSON.stringify(report) : report.text);
|
|
263
|
-
return;
|
|
264
|
-
} else if (action === "edit") {
|
|
265
|
-
if (positionals.length !== 1) throw new UsageError();
|
|
266
|
-
task = await updateTask(root, positionals[0], { ...fields, ...values.title !== void 0 ? { title: values.title } : {}, note: values.message }, "user");
|
|
267
|
-
} else if (action === "close") {
|
|
268
|
-
if (positionals.length !== 1) throw new UsageError();
|
|
269
|
-
task = await closeTask(root, positionals[0], { reason: values.reason, summary: values.message, unverified: values.unverified }, "user");
|
|
270
|
-
} else if (action === "reopen") {
|
|
271
|
-
if (positionals.length !== 1) throw new UsageError();
|
|
272
|
-
task = await reopenTask(root, positionals[0], { note: values.message }, "user");
|
|
273
|
-
} else if (action === "dep") {
|
|
274
|
-
const [change, id, ...rest] = positionals;
|
|
275
|
-
if (!["add", "rm"].includes(change) || !id || rest.length || !(values.after || values.parent || values.related)) throw new UsageError();
|
|
276
|
-
const links = { ...values.after ? { blockedBy: values.after } : {}, ...values.parent ? { parent: values.parent } : {}, ...values.related ? { related: values.related } : {} };
|
|
277
|
-
task = await linkTask(root, id, change === "add" ? { add: links } : { remove: links }, "user");
|
|
278
|
-
} else if (action === "gate") {
|
|
279
|
-
const [change, id, gate, ...rest] = positionals;
|
|
280
|
-
const kinds = ["human", "timer", "pr", "run"].filter((kind) => values[kind] !== void 0);
|
|
281
|
-
if (change === "add" && id && !gate && kinds.length === 1) {
|
|
282
|
-
const kind = kinds[0];
|
|
283
|
-
task = await addGate(root, id, kind === "human" ? { kind, note: values.human } : kind === "timer" ? { kind, until: values.timer } : { kind: `gh:${kind}`, ref: values[kind] }, "user");
|
|
284
|
-
} else if ((change === "clear" || change === "rm") && id && gate && !rest.length && !kinds.length) {
|
|
285
|
-
task = await resolveGate(root, id, gate, { by: "user", note: values.message, remove: change === "rm" });
|
|
286
|
-
} else {
|
|
287
|
-
throw new UsageError();
|
|
288
|
-
}
|
|
289
|
-
} else {
|
|
290
|
-
throw new UsageError();
|
|
291
|
-
}
|
|
292
|
-
if (values.json) {
|
|
293
|
-
console.log(JSON.stringify(task));
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
const { tasks } = await loadTasks(root);
|
|
297
|
-
console.log(`${{ add: "Created", close: "Closed", reopen: "Reopened" }[action] ?? "Updated"} ${TASKS_DIR}/${task.id}.json`);
|
|
298
|
-
if (action === "gate") for (const gate of task.gates.filter((entry) => gateOpen(entry))) console.log(` \u23F8 ${describeGate(gate)}`);
|
|
299
|
-
console.log(taskRow(task, tasks));
|
|
300
|
-
if (action === "close" && tasks.some((entry) => entry.parent === task.id)) console.log(`
|
|
301
|
-
${epicReport(task.id, tasks).text}`);
|
|
302
|
-
}
|
|
303
|
-
function printTask(task, tasks) {
|
|
304
|
-
console.log(`${STATUS_MARK[task.status]} ${task.id} ${task.title}`);
|
|
305
|
-
console.log(` ${task.type}, P${task.priority}, ${task.status}${task.assignee ? ` with ${task.assignee.agent}` : ""}; created by ${task.createdBy} ${ago(task.createdAt)} ago, rev ${task.rev}`);
|
|
306
|
-
if (task.description) console.log(`
|
|
307
|
-
${task.description.replace(/\n/g, "\n ")}
|
|
308
|
-
`);
|
|
309
|
-
const blockers = task.status === "closed" ? [] : blockersOf(task, tasks);
|
|
310
|
-
const relations = [
|
|
311
|
-
task.parent && `parent ${task.parent}`,
|
|
312
|
-
task.blockedBy.length && `after ${task.blockedBy.join(", ")}${blockers.length ? ` (open: ${blockers.join(", ")})` : ""}`,
|
|
313
|
-
task.discoveredFrom && `found during ${task.discoveredFrom}`,
|
|
314
|
-
task.related.length && `related ${task.related.join(", ")}`
|
|
315
|
-
].filter(Boolean);
|
|
316
|
-
if (relations.length) console.log(` ${relations.join("; ")}`);
|
|
317
|
-
for (const gate of task.gates) console.log(` ${gateOpen(gate) ? "\u23F8" : "\u2713"} gate ${describeGate(gate)}${gate.resolved ? ` (cleared by ${gate.resolved.by}${gate.resolved.note ? `: ${gate.resolved.note}` : ""})` : ""}`);
|
|
318
|
-
const inherited = gatesOf(task, tasks).filter((label) => label.startsWith("t-"));
|
|
319
|
-
if (task.status !== "closed" && inherited.length) console.log(` waits on its parent's gates: ${inherited.join("; ")}`);
|
|
320
|
-
if (task.compacted) console.log(` compacted ${task.compacted.at.slice(0, 10)} from ${task.compacted.chars} characters`);
|
|
321
|
-
if (task.labels.length) console.log(` labels: ${task.labels.join(", ")}`);
|
|
322
|
-
if (task.paths.length) console.log(` paths: ${task.paths.join(", ")}`);
|
|
323
|
-
for (const child of childrenOf(task.id, tasks)) console.log(` ${taskRow(child, tasks)}`);
|
|
324
|
-
if (task.verified) console.log(` ${task.verified.skipped ? "\u2013" : task.verified.passed ? "\u2713" : "\u2717"} ${describeVerification(task.verified)}${task.verified.where ? ` in the ${task.verified.where}` : ""}, ${ago(task.verified.at)} ago`);
|
|
325
|
-
if (task.closed) console.log(` closed ${task.closed.reason} by ${task.closed.by}${task.closed.summary ? `: ${task.closed.summary}` : ""}${task.closed.unverified ? ` (unverified: ${task.closed.unverified})` : ""}`);
|
|
326
|
-
for (const entry of task.log.slice(-10)) {
|
|
327
|
-
const { at, by, event, ...detail } = entry;
|
|
328
|
-
const text = Object.entries(detail).map(([key, value]) => `${key} ${Array.isArray(value) ? value.join(", ") : value}`).join("; ");
|
|
329
|
-
console.log(` ${at.slice(0, 16).replace("T", " ")} ${by} ${event}${text ? `: ${text}` : ""}`);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
export {
|
|
333
|
-
STATUS_MARK,
|
|
334
|
-
beads,
|
|
335
|
-
formulaCommand,
|
|
336
|
-
gh,
|
|
337
|
-
printTask,
|
|
338
|
-
repeated,
|
|
339
|
-
taskCommand,
|
|
340
|
-
taskMaintenance,
|
|
341
|
-
taskProject,
|
|
342
|
-
taskRow,
|
|
343
|
-
tasksCommand,
|
|
344
|
-
warnUnreadable
|
|
345
|
-
};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export function terminalCommand(args: any, { home, out }?: {
|
|
2
|
-
home?: string | undefined;
|
|
3
|
-
out?: {
|
|
4
|
-
(...data: any[]): void;
|
|
5
|
-
(message?: any, ...optionalParams: any[]): void;
|
|
6
|
-
} | undefined;
|
|
7
|
-
}): Promise<void>;
|
|
8
|
-
export function TERMINAL_WARNING(user?: string): string;
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
// packages/cli/src/terminal.js
|
|
2
|
-
import { randomUUID } from "node:crypto";
|
|
3
|
-
import { chmod, lstat, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
4
|
-
import os from "node:os";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import { alpHome } from "@anhlp/alp-client/index";
|
|
7
|
-
import { UsageError } from "./usage.js";
|
|
8
|
-
var TERMINAL_WARNING = (user = os.userInfo().username) => [
|
|
9
|
-
`A remote terminal runs a real shell on this computer as ${user}, with that account's full access:`,
|
|
10
|
-
"every file it can read or write, any program, and the network.",
|
|
11
|
-
"A workspace only picks the directory the shell starts in. It is NOT a sandbox.",
|
|
12
|
-
"Only gateway credentials that hold the terminal.exec permission can open one (never a default);",
|
|
13
|
-
"Paseo app devices paired with this host only after alp terminal allow --paseo."
|
|
14
|
-
].join("\n");
|
|
15
|
-
var file = (home) => path.join(home, "terminal.json");
|
|
16
|
-
async function read(home) {
|
|
17
|
-
const info = await lstat(file(home)).catch(() => void 0);
|
|
18
|
-
if (!info) return { exists: false, value: void 0, private: true };
|
|
19
|
-
const own = !process.getuid || info.uid === process.getuid();
|
|
20
|
-
const value = info.isFile() ? await readFile(file(home), "utf8").then(JSON.parse, () => void 0) : void 0;
|
|
21
|
-
return { exists: true, value, private: info.isFile() && own && !(info.mode & 63) };
|
|
22
|
-
}
|
|
23
|
-
async function write(home, value) {
|
|
24
|
-
await mkdir(home, { recursive: true, mode: 448 });
|
|
25
|
-
const temporary = `${file(home)}.${randomUUID().slice(0, 8)}.tmp`;
|
|
26
|
-
await writeFile(temporary, JSON.stringify(value, null, 2) + "\n", { mode: 384, flag: "wx" });
|
|
27
|
-
await chmod(temporary, 384);
|
|
28
|
-
await rename(temporary, file(home)).catch(async (error) => {
|
|
29
|
-
await rm(temporary, { force: true });
|
|
30
|
-
throw error;
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
async function terminalCommand(args, { home = alpHome(), out = console.log } = {}) {
|
|
34
|
-
const [action, ...rest] = args;
|
|
35
|
-
const json = rest.includes("--json");
|
|
36
|
-
const current = await read(home);
|
|
37
|
-
const limits = current.value && typeof current.value.limits === "object" && current.value.limits ? { limits: current.value.limits } : {};
|
|
38
|
-
const paseo = rest.includes("--paseo");
|
|
39
|
-
const paseoBefore = current.private && current.value?.allowPaseoTerminal === true;
|
|
40
|
-
if (action === "allow") {
|
|
41
|
-
if (!rest.includes("--yes")) {
|
|
42
|
-
out(`${TERMINAL_WARNING()}
|
|
43
|
-
|
|
44
|
-
Run again with --yes to allow remote terminals on this host.`);
|
|
45
|
-
process.exitCode = 1;
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
const allowPaseoTerminal = paseo || paseoBefore;
|
|
49
|
-
await write(home, { version: 1, allowRemoteTerminal: true, ...allowPaseoTerminal ? { allowPaseoTerminal: true } : {}, ...limits });
|
|
50
|
-
out(json ? JSON.stringify({ allowRemoteTerminal: true, allowPaseoTerminal }) : `${TERMINAL_WARNING()}
|
|
51
|
-
|
|
52
|
-
Remote terminals are allowed on this host (${file(home)})${allowPaseoTerminal ? ", also for every Paseo app device paired with it" : ""}. alp terminal deny turns them off and ends every open one.`);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
if (action === "deny") {
|
|
56
|
-
if (paseo) {
|
|
57
|
-
const allowed = current.private && current.value?.allowRemoteTerminal === true;
|
|
58
|
-
await write(home, { version: 1, allowRemoteTerminal: allowed, ...limits });
|
|
59
|
-
out(json ? JSON.stringify({ allowRemoteTerminal: allowed, allowPaseoTerminal: false }) : "Paseo app devices can no longer open terminals on this host; the bridge ends the terminals it holds.");
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
await write(home, { version: 1, allowRemoteTerminal: false, ...limits });
|
|
63
|
-
out(json ? JSON.stringify({ allowRemoteTerminal: false, allowPaseoTerminal: false }) : "Remote terminals are off on this host; alpd ends every open terminal within 5 seconds.");
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
if (action === "status") {
|
|
67
|
-
const allowed = current.private && current.value?.version === 1 && current.value.allowRemoteTerminal === true;
|
|
68
|
-
const allowPaseoTerminal = allowed && current.value.allowPaseoTerminal === true;
|
|
69
|
-
const problem = current.exists && !current.private ? `${file(home)} is not a private file of this user, so terminals stay off` : void 0;
|
|
70
|
-
if (json) out(JSON.stringify({ allowRemoteTerminal: allowed, allowPaseoTerminal, ...limits, ...problem ? { problem } : {} }));
|
|
71
|
-
else out([`Remote terminals: ${allowed ? "allowed" : "off"}${allowPaseoTerminal ? " (also for paired Paseo app devices)" : ""}`, ...problem ? [problem] : [], ...allowed ? ["", TERMINAL_WARNING()] : []].join("\n"));
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
throw new UsageError();
|
|
75
|
-
}
|
|
76
|
-
export {
|
|
77
|
-
TERMINAL_WARNING,
|
|
78
|
-
terminalCommand
|
|
79
|
-
};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
export const USAGE: "Usage:\n alp <init|upgrade|update> [directory]\n alp setup [directory] [--runtime codex|claude|mix] [--prefer claude|codex]\n [--claude-model M] [--codex-model M] [--claude-supervisor M] [--codex-supervisor M]\n [--claude-oracle M] [--codex-oracle M] write Ph\u1EDF/Cafe's agent profiles to .alp/settings.json\n alp daemon <start|stop|restart>\n alp daemon status [--json] liveness and readiness; exit 0 ready, 3 not running, 4 not ready\n alp daemon <install|uninstall> run alpd as a login service that restarts after a crash\n alp acp serve ALP to an editor (Zed, JetBrains) over the Agent Client Protocol on stdio\n alp web [--print] open the ALP web app on this machine (alp-web, loopback); --print only prints its address\n alp web rotate give alp web a new token: open pages lose access; prints the new address\n alp web pair [--on|--off] the link that pairs Paseo's app on another device through the relay; --on or --off turns the relay on or off\n alp terminal <allow [--paseo] --yes|deny [--paseo]|status> [--json] remote terminals (a shell as you on this host; a workspace is not a sandbox), off by default\n alp doctor [--project DIR] [--fix] [--json] check this machine and project; --fix repairs what is safe to\n alp backup [-o FILE] [--project DIR]... [--no-projects] [--stop] [--json] sessions, settings, library and tasks in one file\n alp backup verify <file> [--json] | alp backup list [--json]\n alp restore <file> [--home-only] [--dry-run] [--stop] [--replace-newer] [--json] checks the whole backup first; keeps what it replaces\n alpd must be stopped for both; --stop stops it and starts it again after\n alp run [--agent A] [--team pho|cafe|ID] [--model M] [--mode read-only|workspace-write|full-access] [--thinking T] [--project DIR] [--json] <prompt>\n alp schedule create --session ID --at ISO_WITH_OFFSET --prompt TEXT [--project DIR] [--json]\n alp schedule list [--status pending|delivered|failed|cancelled] [--project DIR] [--json]\n alp schedule <show|cancel> ID [--project DIR] [--json] one-shot wake; timer gates only unblock tasks\n alp ps [--all]\n alp top [session] [--once]\n alp attach <session> [--json]\n alp send <session> [--prompt] [--json] <text>\n child default: user mail; --prompt: explicit new prompt to a live root or child\n alp questions [--json]\n alp answer <question> <text> | alp answer <question> --dismiss [--reason R]\n alp log <session> [--json]\n alp board [--project DIR] [--json]\n alp <agents|skills|mcp|hooks> [--project DIR] [--json] the library: built-in, ~/.alp and project entries\n alp providers [--json] ACP and Antigravity providers in your library\n alp teams [--project DIR] [--json] teams sessions run in: members, delegation, house rules\n alp agent <new|edit> <name> [--project [DIR]] [--from A] [-d text] [--provider P] [--model M] [--thinking T] [--mode M]\n [--skills a,b] [--mcp a,b] [--hooks a,b] [--instructions FILE]\n alp team <new|edit> <id> [--project [DIR]] [--from ID] [--label L] [-d text] [--main A] [--member name=role]...\n [--member-model name=M]... [--member-thinking name=T]... [--delegate owner=a,b]... [--max-peers N]\n [--supervisor A] [--supervisor-model M] [--supervisor-thinking T] [--no-supervisor] [--rules FILE]\n alp skill new <name> [--project [DIR]] [--from S] [--file FILE]\n alp mcp add <name> [--project [DIR]] (--command C [--arg A]... [--env K=V]... [--cwd D] | --url U [--header K=V]...)\n alp hook add <name> [--project [DIR]] --event E --command C [--blocking] [--timeout SEC] [--match-agent A] [--match-label L]\n alp provider add <id> --command C [--arg A]... [--env K=V]... [--label L] [-d text] [--models a,b] an ACP agent; use id antigravity for native agy\n alp provider edit antigravity --read-only-mode instructions|reject opt into prompt-only read-only for advisory roles\n alp <agent|team|skill|mcp|hook|provider> <rm|show> <name> [--project [DIR]] | <cp|mv> <from> <to> [--project [DIR]]\n alp <mcp|hook|provider> test <name> [--project [DIR]] list an MCP server's tools; run a hook once; initialize a provider\n without --project, changes go to your library in ~/.alp; built-in agents and teams are never changed\n alp trust [--project DIR] | --revoke [--project DIR] | --list [--json] whether the project's hooks may run\n alp permissions [--project DIR] [--json] each agent's permission profile\n alp permissions check <agent> \"<command>\" what that agent's profile says about a command\n alp tasks [ready] [--all] [--status S] [--label L] [--project DIR] [--json]\n alp tasks gates [--json] open gates; checks GitHub ones\n alp tasks compact [--days 30] [--dry-run]\n alp tasks export [-o file.jsonl] as beads JSONL\n alp tasks import [file.jsonl] [--dry-run] beads JSONL; default .beads/issues.jsonl\n alp formula list | show <name> | pour <name> [--var k=v]... [--parent ID] [--dry-run]\n alp task add <title> [-d text] [-p 0-4] [-t task|bug|feature|chore|epic] [--parent ID] [--after ID]... [-l label]... [--path P]... [--from ID]\n alp task show <id> [--json]\n alp task report <epic> [--json] what an epic came to: tasks, time, rework, verification\n alp task edit <id> [--title T] [-d text] [-p N] [-t type] [-l label]... [--path P]... [-m note]\n alp task close <id> [--reason done|wontfix|duplicate|superseded] [-m summary] [--unverified \"why\"]\n alp verify [--project DIR] [--task ID] [--json] run the project's verify commands; --task records the result\n alp task reopen <id> [-m note]\n alp task dep <add|rm> <id> [--after ID]... [--parent ID] [--related ID]...\n alp task gate add <id> --human \"question\" | --timer +2h|ISO | --pr N|owner/repo#N | --run N|owner/repo#N\n alp task gate <clear|rm> <id> <gate> [-m note]\n alp pause [codex|claude] [--now] [-m reason] | alp pause status hold delegation; --now parks running assignments\n alp resume [codex|claude] lift a pause; parked assignments continue\n alp language [name | --reset] the language agents and ALP write to you in; default Vietnamese\n alp recall <assignment|task> [--project DIR] [--json] <question> ask a finished assignment about its work\n alp interrupt <session>";
|
|
2
|
-
export class UsageError extends Error {
|
|
3
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
// packages/cli/src/usage.js
|
|
2
|
-
var USAGE = `Usage:
|
|
3
|
-
alp <init|upgrade|update> [directory]
|
|
4
|
-
alp setup [directory] [--runtime codex|claude|mix] [--prefer claude|codex]
|
|
5
|
-
[--claude-model M] [--codex-model M] [--claude-supervisor M] [--codex-supervisor M]
|
|
6
|
-
[--claude-oracle M] [--codex-oracle M] write Ph\u1EDF/Cafe's agent profiles to .alp/settings.json
|
|
7
|
-
alp daemon <start|stop|restart>
|
|
8
|
-
alp daemon status [--json] liveness and readiness; exit 0 ready, 3 not running, 4 not ready
|
|
9
|
-
alp daemon <install|uninstall> run alpd as a login service that restarts after a crash
|
|
10
|
-
alp acp serve ALP to an editor (Zed, JetBrains) over the Agent Client Protocol on stdio
|
|
11
|
-
alp web [--print] open the ALP web app on this machine (alp-web, loopback); --print only prints its address
|
|
12
|
-
alp web rotate give alp web a new token: open pages lose access; prints the new address
|
|
13
|
-
alp web pair [--on|--off] the link that pairs Paseo's app on another device through the relay; --on or --off turns the relay on or off
|
|
14
|
-
alp terminal <allow [--paseo] --yes|deny [--paseo]|status> [--json] remote terminals (a shell as you on this host; a workspace is not a sandbox), off by default
|
|
15
|
-
alp doctor [--project DIR] [--fix] [--json] check this machine and project; --fix repairs what is safe to
|
|
16
|
-
alp backup [-o FILE] [--project DIR]... [--no-projects] [--stop] [--json] sessions, settings, library and tasks in one file
|
|
17
|
-
alp backup verify <file> [--json] | alp backup list [--json]
|
|
18
|
-
alp restore <file> [--home-only] [--dry-run] [--stop] [--replace-newer] [--json] checks the whole backup first; keeps what it replaces
|
|
19
|
-
alpd must be stopped for both; --stop stops it and starts it again after
|
|
20
|
-
alp run [--agent A] [--team pho|cafe|ID] [--model M] [--mode read-only|workspace-write|full-access] [--thinking T] [--project DIR] [--json] <prompt>
|
|
21
|
-
alp schedule create --session ID --at ISO_WITH_OFFSET --prompt TEXT [--project DIR] [--json]
|
|
22
|
-
alp schedule list [--status pending|delivered|failed|cancelled] [--project DIR] [--json]
|
|
23
|
-
alp schedule <show|cancel> ID [--project DIR] [--json] one-shot wake; timer gates only unblock tasks
|
|
24
|
-
alp ps [--all]
|
|
25
|
-
alp top [session] [--once]
|
|
26
|
-
alp attach <session> [--json]
|
|
27
|
-
alp send <session> [--prompt] [--json] <text>
|
|
28
|
-
child default: user mail; --prompt: explicit new prompt to a live root or child
|
|
29
|
-
alp questions [--json]
|
|
30
|
-
alp answer <question> <text> | alp answer <question> --dismiss [--reason R]
|
|
31
|
-
alp log <session> [--json]
|
|
32
|
-
alp board [--project DIR] [--json]
|
|
33
|
-
alp <agents|skills|mcp|hooks> [--project DIR] [--json] the library: built-in, ~/.alp and project entries
|
|
34
|
-
alp providers [--json] ACP and Antigravity providers in your library
|
|
35
|
-
alp teams [--project DIR] [--json] teams sessions run in: members, delegation, house rules
|
|
36
|
-
alp agent <new|edit> <name> [--project [DIR]] [--from A] [-d text] [--provider P] [--model M] [--thinking T] [--mode M]
|
|
37
|
-
[--skills a,b] [--mcp a,b] [--hooks a,b] [--instructions FILE]
|
|
38
|
-
alp team <new|edit> <id> [--project [DIR]] [--from ID] [--label L] [-d text] [--main A] [--member name=role]...
|
|
39
|
-
[--member-model name=M]... [--member-thinking name=T]... [--delegate owner=a,b]... [--max-peers N]
|
|
40
|
-
[--supervisor A] [--supervisor-model M] [--supervisor-thinking T] [--no-supervisor] [--rules FILE]
|
|
41
|
-
alp skill new <name> [--project [DIR]] [--from S] [--file FILE]
|
|
42
|
-
alp mcp add <name> [--project [DIR]] (--command C [--arg A]... [--env K=V]... [--cwd D] | --url U [--header K=V]...)
|
|
43
|
-
alp hook add <name> [--project [DIR]] --event E --command C [--blocking] [--timeout SEC] [--match-agent A] [--match-label L]
|
|
44
|
-
alp provider add <id> --command C [--arg A]... [--env K=V]... [--label L] [-d text] [--models a,b] an ACP agent; use id antigravity for native agy
|
|
45
|
-
alp provider edit antigravity --read-only-mode instructions|reject opt into prompt-only read-only for advisory roles
|
|
46
|
-
alp <agent|team|skill|mcp|hook|provider> <rm|show> <name> [--project [DIR]] | <cp|mv> <from> <to> [--project [DIR]]
|
|
47
|
-
alp <mcp|hook|provider> test <name> [--project [DIR]] list an MCP server's tools; run a hook once; initialize a provider
|
|
48
|
-
without --project, changes go to your library in ~/.alp; built-in agents and teams are never changed
|
|
49
|
-
alp trust [--project DIR] | --revoke [--project DIR] | --list [--json] whether the project's hooks may run
|
|
50
|
-
alp permissions [--project DIR] [--json] each agent's permission profile
|
|
51
|
-
alp permissions check <agent> "<command>" what that agent's profile says about a command
|
|
52
|
-
alp tasks [ready] [--all] [--status S] [--label L] [--project DIR] [--json]
|
|
53
|
-
alp tasks gates [--json] open gates; checks GitHub ones
|
|
54
|
-
alp tasks compact [--days 30] [--dry-run]
|
|
55
|
-
alp tasks export [-o file.jsonl] as beads JSONL
|
|
56
|
-
alp tasks import [file.jsonl] [--dry-run] beads JSONL; default .beads/issues.jsonl
|
|
57
|
-
alp formula list | show <name> | pour <name> [--var k=v]... [--parent ID] [--dry-run]
|
|
58
|
-
alp task add <title> [-d text] [-p 0-4] [-t task|bug|feature|chore|epic] [--parent ID] [--after ID]... [-l label]... [--path P]... [--from ID]
|
|
59
|
-
alp task show <id> [--json]
|
|
60
|
-
alp task report <epic> [--json] what an epic came to: tasks, time, rework, verification
|
|
61
|
-
alp task edit <id> [--title T] [-d text] [-p N] [-t type] [-l label]... [--path P]... [-m note]
|
|
62
|
-
alp task close <id> [--reason done|wontfix|duplicate|superseded] [-m summary] [--unverified "why"]
|
|
63
|
-
alp verify [--project DIR] [--task ID] [--json] run the project's verify commands; --task records the result
|
|
64
|
-
alp task reopen <id> [-m note]
|
|
65
|
-
alp task dep <add|rm> <id> [--after ID]... [--parent ID] [--related ID]...
|
|
66
|
-
alp task gate add <id> --human "question" | --timer +2h|ISO | --pr N|owner/repo#N | --run N|owner/repo#N
|
|
67
|
-
alp task gate <clear|rm> <id> <gate> [-m note]
|
|
68
|
-
alp pause [codex|claude] [--now] [-m reason] | alp pause status hold delegation; --now parks running assignments
|
|
69
|
-
alp resume [codex|claude] lift a pause; parked assignments continue
|
|
70
|
-
alp language [name | --reset] the language agents and ALP write to you in; default Vietnamese
|
|
71
|
-
alp recall <assignment|task> [--project DIR] [--json] <question> ask a finished assignment about its work
|
|
72
|
-
alp interrupt <session>`;
|
|
73
|
-
var UsageError = class extends Error {
|
|
74
|
-
};
|
|
75
|
-
export {
|
|
76
|
-
USAGE,
|
|
77
|
-
UsageError
|
|
78
|
-
};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/** The alp-web service script beside this CLI; a clear error when this CLI was built without it. */
|
|
2
|
-
export function alpWebEntry(): string;
|
|
3
|
-
/**
|
|
4
|
-
* The process that owns alp web's lock, if it is proven safe to stop; else why not. `kind` says
|
|
5
|
-
* whether waiting can help: `transient` (an owner still starting has not published web.json yet),
|
|
6
|
-
* `foreign` (proven not to be the integration: another user's, another boot's, or a reused pid) or
|
|
7
|
-
* `unknown` (it cannot be proven either way, for example without ps or on Windows).
|
|
8
|
-
*
|
|
9
|
-
* The reuse proof compares the lock's wall-clock `startedAt` with the process's start from ps: a
|
|
10
|
-
* wall clock stepped back by more than two seconds after the lock was written could make a reused
|
|
11
|
-
* pid look older than the lock. A step forward only refuses.
|
|
12
|
-
* @param {string} home
|
|
13
|
-
* @returns {Promise<{ pid: number, app: unknown } | { reason: string, alive: boolean, kind?: 'transient' | 'foreign' | 'unknown' }>}
|
|
14
|
-
*/
|
|
15
|
-
export function webOwner(home: string): Promise<{
|
|
16
|
-
pid: number;
|
|
17
|
-
app: unknown;
|
|
18
|
-
} | {
|
|
19
|
-
reason: string;
|
|
20
|
-
alive: boolean;
|
|
21
|
-
kind?: "transient" | "foreign" | "unknown";
|
|
22
|
-
}>;
|
|
23
|
-
/**
|
|
24
|
-
* Stops the Paseo integration from before its rename when it still runs as integration `web` (its
|
|
25
|
-
* web.json has no `app: 'alp-web'`), so alp-web can take the lock and web.port. Returns the pid it
|
|
26
|
-
* stopped. A process that cannot be proven to be that integration is left alone.
|
|
27
|
-
* @param {string} home
|
|
28
|
-
*/
|
|
29
|
-
export function stopPreRenamePaseo(home: string): Promise<number | undefined>;
|
|
30
|
-
/**
|
|
31
|
-
* Stops whatever runs as integration `web` (alp-web, or the Paseo integration from before its
|
|
32
|
-
* rename), waiting up to `timeoutMs` for a starting owner to publish what proves it. Resolves once
|
|
33
|
-
* no live process owns the lock; refuses at once an owner that is foreign or cannot be proven.
|
|
34
|
-
* @param {string} home @param {number} [timeoutMs]
|
|
35
|
-
*/
|
|
36
|
-
export function stopWebService(home: string, timeoutMs?: number): Promise<number | undefined>;
|
|
37
|
-
/** The opening of the message for a web lock held by a process alp would not stop. @param {string} home */
|
|
38
|
-
export function refusal(home: string): string;
|