@anhlp/alp 0.0.1-beta.3 → 0.0.1-beta.6
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 +14 -410
- package/bin/alp.js +5 -0
- package/lib/launcher.js +136 -0
- package/package.json +19 -104
- package/dist/THIRD-PARTY-NOTICES.txt +0 -626
- package/dist/acp.js +0 -19903
- package/dist/alpd.js +0 -42558
- package/docs/modular-monorepo.md +0 -210
- package/packages/cli/README.md +0 -7
- package/packages/cli/dist/THIRD-PARTY-NOTICES.txt +0 -626
- 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 -19903
- package/packages/cli/dist/alpd.js +0 -42558
- 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 -142
- package/packages/cli/dist/cli.d.ts +0 -2
- package/packages/cli/dist/cli.js +0 -28
- 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 -16
- package/packages/cli/dist/interfaces.js +0 -96
- 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/sessions.d.ts +0 -41
- package/packages/cli/dist/sessions.js +0 -447
- package/packages/cli/dist/tasks.d.ts +0 -29
- package/packages/cli/dist/tasks.js +0 -345
- package/packages/cli/dist/usage.d.ts +0 -3
- package/packages/cli/dist/usage.js +0 -72
- package/packages/client/README.md +0 -24
- 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 -116
- package/packages/client/dist/index.js +0 -500
- 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 -18
- package/packages/client/dist/portable.js +0 -27
- 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/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 -12
- 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 -582
- 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 -30
- package/packages/core/dist/index.js +0 -63
- 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/validation.d.ts +0 -17
- package/packages/core/dist/validation.js +0 -295
- 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,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 local web app alpd serves; --print only prints its 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 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 ps [--all]\n alp top [session] [--once]\n alp attach <session> [--json]\n alp send <session> [--json] <text>\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,72 +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 local web app alpd serves; --print only prints its address
|
|
12
|
-
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
|
|
13
|
-
alp doctor [--project DIR] [--fix] [--json] check this machine and project; --fix repairs what is safe to
|
|
14
|
-
alp backup [-o FILE] [--project DIR]... [--no-projects] [--stop] [--json] sessions, settings, library and tasks in one file
|
|
15
|
-
alp backup verify <file> [--json] | alp backup list [--json]
|
|
16
|
-
alp restore <file> [--home-only] [--dry-run] [--stop] [--replace-newer] [--json] checks the whole backup first; keeps what it replaces
|
|
17
|
-
alpd must be stopped for both; --stop stops it and starts it again after
|
|
18
|
-
alp run [--agent A] [--team pho|cafe|ID] [--model M] [--mode read-only|workspace-write|full-access] [--thinking T] [--project DIR] [--json] <prompt>
|
|
19
|
-
alp ps [--all]
|
|
20
|
-
alp top [session] [--once]
|
|
21
|
-
alp attach <session> [--json]
|
|
22
|
-
alp send <session> [--json] <text>
|
|
23
|
-
alp questions [--json]
|
|
24
|
-
alp answer <question> <text> | alp answer <question> --dismiss [--reason R]
|
|
25
|
-
alp log <session> [--json]
|
|
26
|
-
alp board [--project DIR] [--json]
|
|
27
|
-
alp <agents|skills|mcp|hooks> [--project DIR] [--json] the library: built-in, ~/.alp and project entries
|
|
28
|
-
alp providers [--json] ACP and Antigravity providers in your library
|
|
29
|
-
alp teams [--project DIR] [--json] teams sessions run in: members, delegation, house rules
|
|
30
|
-
alp agent <new|edit> <name> [--project [DIR]] [--from A] [-d text] [--provider P] [--model M] [--thinking T] [--mode M]
|
|
31
|
-
[--skills a,b] [--mcp a,b] [--hooks a,b] [--instructions FILE]
|
|
32
|
-
alp team <new|edit> <id> [--project [DIR]] [--from ID] [--label L] [-d text] [--main A] [--member name=role]...
|
|
33
|
-
[--member-model name=M]... [--member-thinking name=T]... [--delegate owner=a,b]... [--max-peers N]
|
|
34
|
-
[--supervisor A] [--supervisor-model M] [--supervisor-thinking T] [--no-supervisor] [--rules FILE]
|
|
35
|
-
alp skill new <name> [--project [DIR]] [--from S] [--file FILE]
|
|
36
|
-
alp mcp add <name> [--project [DIR]] (--command C [--arg A]... [--env K=V]... [--cwd D] | --url U [--header K=V]...)
|
|
37
|
-
alp hook add <name> [--project [DIR]] --event E --command C [--blocking] [--timeout SEC] [--match-agent A] [--match-label L]
|
|
38
|
-
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
|
|
39
|
-
alp provider edit antigravity --read-only-mode instructions|reject opt into prompt-only read-only for advisory roles
|
|
40
|
-
alp <agent|team|skill|mcp|hook|provider> <rm|show> <name> [--project [DIR]] | <cp|mv> <from> <to> [--project [DIR]]
|
|
41
|
-
alp <mcp|hook|provider> test <name> [--project [DIR]] list an MCP server's tools; run a hook once; initialize a provider
|
|
42
|
-
without --project, changes go to your library in ~/.alp; built-in agents and teams are never changed
|
|
43
|
-
alp trust [--project DIR] | --revoke [--project DIR] | --list [--json] whether the project's hooks may run
|
|
44
|
-
alp permissions [--project DIR] [--json] each agent's permission profile
|
|
45
|
-
alp permissions check <agent> "<command>" what that agent's profile says about a command
|
|
46
|
-
alp tasks [ready] [--all] [--status S] [--label L] [--project DIR] [--json]
|
|
47
|
-
alp tasks gates [--json] open gates; checks GitHub ones
|
|
48
|
-
alp tasks compact [--days 30] [--dry-run]
|
|
49
|
-
alp tasks export [-o file.jsonl] as beads JSONL
|
|
50
|
-
alp tasks import [file.jsonl] [--dry-run] beads JSONL; default .beads/issues.jsonl
|
|
51
|
-
alp formula list | show <name> | pour <name> [--var k=v]... [--parent ID] [--dry-run]
|
|
52
|
-
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]
|
|
53
|
-
alp task show <id> [--json]
|
|
54
|
-
alp task report <epic> [--json] what an epic came to: tasks, time, rework, verification
|
|
55
|
-
alp task edit <id> [--title T] [-d text] [-p N] [-t type] [-l label]... [--path P]... [-m note]
|
|
56
|
-
alp task close <id> [--reason done|wontfix|duplicate|superseded] [-m summary] [--unverified "why"]
|
|
57
|
-
alp verify [--project DIR] [--task ID] [--json] run the project's verify commands; --task records the result
|
|
58
|
-
alp task reopen <id> [-m note]
|
|
59
|
-
alp task dep <add|rm> <id> [--after ID]... [--parent ID] [--related ID]...
|
|
60
|
-
alp task gate add <id> --human "question" | --timer +2h|ISO | --pr N|owner/repo#N | --run N|owner/repo#N
|
|
61
|
-
alp task gate <clear|rm> <id> <gate> [-m note]
|
|
62
|
-
alp pause [codex|claude] [--now] [-m reason] | alp pause status hold delegation; --now parks running assignments
|
|
63
|
-
alp resume [codex|claude] lift a pause; parked assignments continue
|
|
64
|
-
alp language [name | --reset] the language agents and ALP write to you in; default Vietnamese
|
|
65
|
-
alp recall <assignment|task> [--project DIR] [--json] <question> ask a finished assignment about its work
|
|
66
|
-
alp interrupt <session>`;
|
|
67
|
-
var UsageError = class extends Error {
|
|
68
|
-
};
|
|
69
|
-
export {
|
|
70
|
-
USAGE,
|
|
71
|
-
UsageError
|
|
72
|
-
};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# @anhlp/alp-client
|
|
2
|
-
|
|
3
|
-
The ALP RPC client: a portable JSON-RPC engine for Node, browsers and React Native, its
|
|
4
|
-
WebSocket and Node IPC transports, and the Node-only daemon discovery, supervision, services
|
|
5
|
-
and setup helpers.
|
|
6
|
-
|
|
7
|
-
- `@anhlp/alp-client/portable`: `AlpRpcClient`, errors, `hello`, `createReconnectingClient`,
|
|
8
|
-
NDJSON framing. No Node built-ins, `process` or `Buffer`; needs no polyfills.
|
|
9
|
-
- `@anhlp/alp-client/websocket`: `connectWebSocket` over the browser's, React Native's or an
|
|
10
|
-
injected WebSocket. Authentication is the caller's (the gateway's) business.
|
|
11
|
-
- `@anhlp/alp-client` (Node): everything above plus `connect`, `AlpClient`, `connectSocket`,
|
|
12
|
-
`ensureDaemon`, the private-socket checks and lock helpers, unchanged for existing callers.
|
|
13
|
-
- `@anhlp/alp-client/ipc` (Node): `createSocketTransport` for a Unix socket or named pipe.
|
|
14
|
-
|
|
15
|
-
Timeouts and aborts end only the caller's wait, and nothing is ever resent after a disconnect.
|
|
16
|
-
See [docs/alp/client-sdk.md](../../docs/alp/client-sdk.md) for the transport contract, the
|
|
17
|
-
request lifecycle, the old-to-new API table and what still waits on the protocol (Task 06) and
|
|
18
|
-
the gateway (Task 08).
|
|
19
|
-
|
|
20
|
-
`startIntegration` discovers an optional integration's descriptor and starts it detached with `--service`, so the entry writes its own log; discovery and the selected `ALP_HOME` are pinned by tests. Restarting is non-destructive: a daemon left running by an older install is reported as older than the current CLI and is never killed in place.
|
|
21
|
-
|
|
22
|
-
Build: `npm run build --workspace=@anhlp/alp-client`. Test: `npm run test --workspace=@anhlp/alp-client`.
|
|
23
|
-
|
|
24
|
-
Public imports use the package root and its explicitly exported subpaths. See [architecture, provider extension, compatibility and release instructions](../../docs/modular-monorepo.md).
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Starts an ACP provider once and runs initialize (ALPD §46), for `alp provider test`
|
|
3
|
-
* and the settings screen. It reports who the agent says it is and what it supports;
|
|
4
|
-
* a provider that needs a login usually says so here, in authMethods. With `discover`,
|
|
5
|
-
* it also opens a session in `cwd`, as Paseo does, to read the models and modes the agent
|
|
6
|
-
* offers (ALPD §65); an agent that offers none leaves them out.
|
|
7
|
-
* @param {{ command: string, args?: string[], env?: Record<string, string>, label?: string, id?: string }} provider
|
|
8
|
-
* @param {{ cwd?: string, timeoutMs?: number, discover?: boolean }} [options]
|
|
9
|
-
* @returns {Promise<{ protocolVersion: number, agent?: { name?: string, title?: string, version?: string }, loadSession: boolean, mcpHttp: boolean, authMethods: string[],
|
|
10
|
-
* models?: Array<{ id: string, label: string, description?: string }>, currentModel?: string, modes?: Array<{ id: string, label: string, description?: string }>, currentMode?: string }>}
|
|
11
|
-
*/
|
|
12
|
-
export function probeAcp(provider: {
|
|
13
|
-
command: string;
|
|
14
|
-
args?: string[];
|
|
15
|
-
env?: Record<string, string>;
|
|
16
|
-
label?: string;
|
|
17
|
-
id?: string;
|
|
18
|
-
}, { cwd, timeoutMs, discover }?: {
|
|
19
|
-
cwd?: string;
|
|
20
|
-
timeoutMs?: number;
|
|
21
|
-
discover?: boolean;
|
|
22
|
-
}): Promise<{
|
|
23
|
-
protocolVersion: number;
|
|
24
|
-
agent?: {
|
|
25
|
-
name?: string;
|
|
26
|
-
title?: string;
|
|
27
|
-
version?: string;
|
|
28
|
-
};
|
|
29
|
-
loadSession: boolean;
|
|
30
|
-
mcpHttp: boolean;
|
|
31
|
-
authMethods: string[];
|
|
32
|
-
models?: Array<{
|
|
33
|
-
id: string;
|
|
34
|
-
label: string;
|
|
35
|
-
description?: string;
|
|
36
|
-
}>;
|
|
37
|
-
currentModel?: string;
|
|
38
|
-
modes?: Array<{
|
|
39
|
-
id: string;
|
|
40
|
-
label: string;
|
|
41
|
-
description?: string;
|
|
42
|
-
}>;
|
|
43
|
-
currentMode?: string;
|
|
44
|
-
}>;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// packages/client/src/acp-probe.js
|
|
2
|
-
import { stdioSession } from "./mcp-probe.js";
|
|
3
|
-
async function probeAcp(provider, { cwd, timeoutMs = 2e4, discover = false } = {}) {
|
|
4
|
-
const session = stdioSession({ command: provider.command, args: provider.args ?? [], env: provider.env ?? {} }, cwd, timeoutMs);
|
|
5
|
-
try {
|
|
6
|
-
const result = await session.request("initialize", {
|
|
7
|
-
protocolVersion: 1,
|
|
8
|
-
clientCapabilities: { fs: { readTextFile: false, writeTextFile: false }, terminal: false },
|
|
9
|
-
clientInfo: { name: "alp", title: "ALP", version: "1" }
|
|
10
|
-
});
|
|
11
|
-
if (result.protocolVersion !== 1) throw new Error(`${provider.label ?? provider.id} speaks ACP version ${result.protocolVersion}; ALP speaks version 1`);
|
|
12
|
-
const info = result.agentInfo;
|
|
13
|
-
const offered = discover ? await session.request("session/new", { cwd, mcpServers: [] }) : void 0;
|
|
14
|
-
const choices = (list) => Array.isArray(list) ? list.filter((item) => typeof (item?.modelId ?? item?.id) === "string").map((item) => ({ id: item.modelId ?? item.id, label: typeof item.name === "string" && item.name ? item.name : item.modelId ?? item.id, ...typeof item.description === "string" && item.description ? { description: item.description } : {} })) : void 0;
|
|
15
|
-
const config = offered?.configOptions?.find((option) => option.category === "model" && option.type === "select");
|
|
16
|
-
const modeConfig = offered?.configOptions?.find((option) => option.category === "mode" && option.type === "select");
|
|
17
|
-
const flatten = (options) => options?.flatMap((option) => option.options ?? [option]).map((option) => ({ ...option, id: option.value }));
|
|
18
|
-
const modelState = offered?.models ?? (config ? { availableModels: flatten(config.options), currentModelId: config.currentValue } : void 0);
|
|
19
|
-
const modeState = offered?.modes ?? (modeConfig ? { availableModes: flatten(modeConfig.options), currentModeId: modeConfig.currentValue } : void 0);
|
|
20
|
-
const models = choices(modelState?.availableModels);
|
|
21
|
-
const modes = choices(modeState?.availableModes);
|
|
22
|
-
return {
|
|
23
|
-
...models ? { models, ...typeof modelState.currentModelId === "string" ? { currentModel: modelState.currentModelId } : {} } : {},
|
|
24
|
-
...modes ? { modes, ...typeof modeState.currentModeId === "string" ? { currentMode: modeState.currentModeId } : {} } : {},
|
|
25
|
-
protocolVersion: result.protocolVersion,
|
|
26
|
-
...info ? { agent: { ...info.name ? { name: info.name } : {}, ...info.title ? { title: info.title } : {}, ...info.version ? { version: info.version } : {} } } : {},
|
|
27
|
-
loadSession: Boolean(result.agentCapabilities?.loadSession),
|
|
28
|
-
mcpHttp: Boolean(result.agentCapabilities?.mcpCapabilities?.http),
|
|
29
|
-
authMethods: (result.authMethods ?? []).map((method) => method?.name ?? method?.id).filter(Boolean)
|
|
30
|
-
};
|
|
31
|
-
} finally {
|
|
32
|
-
await session.close();
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
export {
|
|
36
|
-
probeAcp
|
|
37
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Probes Antigravity CLI for version, status and available models.
|
|
3
|
-
* @param {{ command?: string, args?: string[], env?: Record<string, string>, label?: string, id?: string, readOnlyMode?: 'instructions' | 'reject' }} [provider]
|
|
4
|
-
* @param {{ cwd?: string, timeoutMs?: number }} [options]
|
|
5
|
-
*/
|
|
6
|
-
export function probeAntigravity(provider?: {
|
|
7
|
-
command?: string;
|
|
8
|
-
args?: string[];
|
|
9
|
-
env?: Record<string, string>;
|
|
10
|
-
label?: string;
|
|
11
|
-
id?: string;
|
|
12
|
-
readOnlyMode?: "instructions" | "reject";
|
|
13
|
-
}, { cwd, timeoutMs }?: {
|
|
14
|
-
cwd?: string;
|
|
15
|
-
timeoutMs?: number;
|
|
16
|
-
}): Promise<{
|
|
17
|
-
version: string;
|
|
18
|
-
agent: {
|
|
19
|
-
name: string;
|
|
20
|
-
title: string;
|
|
21
|
-
version: string;
|
|
22
|
-
};
|
|
23
|
-
models: {
|
|
24
|
-
id: any;
|
|
25
|
-
label: any;
|
|
26
|
-
}[];
|
|
27
|
-
currentModel: any;
|
|
28
|
-
modes: {
|
|
29
|
-
id: string;
|
|
30
|
-
label: string;
|
|
31
|
-
description: string;
|
|
32
|
-
}[];
|
|
33
|
-
currentMode: string;
|
|
34
|
-
}>;
|