@anhlp/alp 0.0.0-beta.1 → 0.0.0-beta.2
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 +6 -4
- package/dist/acp.js +119 -22
- package/dist/alpd.js +1867 -741
- package/docs/modular-monorepo.md +2 -2
- package/package.json +5 -5
- package/packages/cli/dist/acp/agent.d.ts +11 -3
- package/packages/cli/dist/acp/agent.js +118 -19
- package/packages/cli/dist/acp/main.js +1 -1
- package/packages/cli/dist/acp.js +119 -22
- package/packages/cli/dist/alpd.js +1867 -741
- package/packages/cli/dist/backup.js +1 -1
- package/packages/cli/dist/build-manifest.json +4 -1
- package/packages/cli/dist/sessions.d.ts +2 -0
- package/packages/cli/dist/sessions.js +23 -1
- package/packages/core/dist/init.js +2 -1
- package/packages/core/dist/teams.d.ts +13 -2
- package/packages/core/dist/workflow.d.ts +35 -4
- package/packages/core/dist/workflow.js +14 -5
package/README.md
CHANGED
|
@@ -4,11 +4,13 @@ Provider-neutral filesystem agent resolution with a server-side Paseo provider.
|
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
|
-
The current release is the beta `0.0.0-beta.
|
|
7
|
+
The current release is the beta `0.0.0-beta.2` (until it is on npm, `@beta` installs
|
|
8
|
+
`0.0.0-beta.1`; check with `npm view @anhlp/alp dist-tags`): see the
|
|
8
9
|
[release notes](docs/alp/beta-release-notes.md) for what it includes and its known issues, and
|
|
9
10
|
[installing, upgrading and removing the beta](docs/alp/beta-install.md) for every step. Name the
|
|
10
|
-
beta when you install (`@beta`, or exactly `@0.0.0-beta.
|
|
11
|
-
installs
|
|
11
|
+
beta when you install (`@beta`, or exactly `@0.0.0-beta.2`); a plain `npm install -g @anhlp/alp`
|
|
12
|
+
installs whatever npm's `latest` tag points at, which moves to a new beta only after that
|
|
13
|
+
beta's post-publish checks.
|
|
12
14
|
|
|
13
15
|
Supported: Linux or macOS, Node.js 22 (22.12 or later) or 24, and a signed-in Codex CLI or
|
|
14
16
|
Claude Code on PATH. Windows and Node.js 26 are experimental; Node.js 20 is not supported.
|
|
@@ -332,7 +334,7 @@ Details: [ALPD §60](plans/reference/ALPD.md#60-alp-as-an-acp-agent-2026-10-10).
|
|
|
332
334
|
|
|
333
335
|
## Paseo
|
|
334
336
|
|
|
335
|
-
To use the published plugin, follow [the plugin's README](integrations/paseo/README.md) or [beta-install.md](docs/alp/beta-install.md#paseo-plugin): `paseo plugin add npm:@anhlp/alp-paseo@beta
|
|
337
|
+
To use the published plugin, follow [the plugin's README](integrations/paseo/README.md) or [beta-install.md](docs/alp/beta-install.md#paseo-plugin): `paseo plugin add npm:@anhlp/alp-paseo@beta` (from `0.0.0-beta.2`; in beta.1 the `npm:` source fails, [#111](https://github.com/phucanh08/alp/issues/111), so there run `npm install -g @anhlp/alp-paseo@beta`, then `paseo plugin add "$(npm root -g)/@anhlp/alp-paseo"`). The beta supports Paseo `>=0.11.1 <0.12.0`. See [installation and runtime behavior](docs/alp/paseo-plugin.md) and the historical [phase acceptance evidence](docs/alp/phase-2-5-results.md). The plugin was verified with Paseo 0.11.1 and live Codex and Claude Code permission changes before the beta; the beta's own runs are in [beta-scope.md](docs/alp/beta-scope.md) §6.
|
|
336
338
|
|
|
337
339
|
**Settings → ALP** manages your library of teams, agents, skills, MCP servers, hooks and ACP providers, and the **ALP project** workspace panel manages a project's overrides ([settings screen](docs/alp/paseo-plugin.md#alp-settings-and-the-project-panel)).
|
|
338
340
|
|
package/dist/acp.js
CHANGED
|
@@ -18552,8 +18552,10 @@ var AlpRpcError = class extends Error {
|
|
|
18552
18552
|
};
|
|
18553
18553
|
var ERROR = Object.freeze({ failed: 1e3, notFound: 1001, forbidden: 1003, conflict: 1004, unavailable: 1005, protocol: 1006 });
|
|
18554
18554
|
var RPC_ERROR = Object.freeze({ parseError: -32700, invalidRequest: -32600, methodNotFound: -32601, invalidParams: -32602 });
|
|
18555
|
-
var CAPABILITY = Object.freeze({ attachAfter: "attach.after", promptReceipts: "prompt.receipts", extensionMethods: "extension.methods", team: "team", task: "task", library: "library", settingsLanguage: "settings.language" });
|
|
18556
|
-
var
|
|
18555
|
+
var CAPABILITY = Object.freeze({ attachAfter: "attach.after", promptReceipts: "prompt.receipts", extensionMethods: "extension.methods", team: "team", task: "task", library: "library", settingsLanguage: "settings.language", sessionListPage: "session.list.page", questionWatch: "question.watch", questionWatchTurns: "question.watch.turns", workspaceFiles: "workspace.files", workspaceFilesRead: "workspace.files.read", promptImages: "prompt.images" });
|
|
18556
|
+
var PROMPT_IMAGES = Object.freeze({ mimeTypes: Object.freeze(["image/png", "image/jpeg", "image/gif", "image/webp"]), maxCount: 8, maxBytes: 5 * 1024 * 1024, maxTotalBytes: 11 * 1024 * 1024 });
|
|
18557
|
+
var RPC_METHODS = Object.freeze(["assignment.recall", "board.list", "catalog.get", "daemon.hello", "daemon.pause", "daemon.pauses", "daemon.resume", "daemon.shutdown", "daemon.status", "daemon.usage", "extension.register", "extension.unregister", "library.delete", "library.duplicate", "library.get", "library.list", "library.models", "library.rename", "library.save", "library.skills.set", "question.answer", "question.list", "question.watch", "session.archive", "session.attach", "session.close", "session.configure", "session.create", "session.get", "session.interrupt", "session.list", "session.log", "session.message", "session.preview", "session.prompt", "session.release", "session.rename", "session.status", "settings.language.get", "settings.language.set", "task.create", "task.gate.resolve", "task.list", "task.update", "team.list", "workspace.files.list", "workspace.files.read", "workspace.files.search"]);
|
|
18558
|
+
var WORKSPACE_FILES = Object.freeze({ maxReadBytes: 1024 * 1024, maxListEntries: 1e3, maxPathLength: 4096 });
|
|
18557
18559
|
|
|
18558
18560
|
// packages/client/src/rpc/errors.js
|
|
18559
18561
|
var BRAND = Symbol.for("@anhlp/alp-client/AlpClientError");
|
|
@@ -19323,6 +19325,7 @@ async function startDaemon({ home, entry, env = process.env, timeoutMs = 15e3 })
|
|
|
19323
19325
|
// packages/cli/src/acp/agent.ts
|
|
19324
19326
|
import { randomUUID } from "node:crypto";
|
|
19325
19327
|
import path4 from "node:path";
|
|
19328
|
+
var unlistedOf = ({ teams, team, teamLabel }) => teams.some((entry) => entry.id === team) ? void 0 : { id: team, label: teamLabel ?? (team === "custom" ? "Custom" : team) };
|
|
19326
19329
|
var MODES = [
|
|
19327
19330
|
{ id: "read-only", name: "Read only", description: "Agents read and search; nothing is changed" },
|
|
19328
19331
|
{ id: "workspace-write", name: "Workspace write", description: "Agents change files and run commands inside the project" },
|
|
@@ -19364,34 +19367,120 @@ ${resource.text}
|
|
|
19364
19367
|
}
|
|
19365
19368
|
return text.trim();
|
|
19366
19369
|
}
|
|
19370
|
+
function shown(file2, cwd) {
|
|
19371
|
+
if (!cwd || !path4.isAbsolute(file2)) return file2;
|
|
19372
|
+
const relative = path4.relative(cwd, file2);
|
|
19373
|
+
return relative && !relative.startsWith("..") && !path4.isAbsolute(relative) ? relative : file2;
|
|
19374
|
+
}
|
|
19367
19375
|
function toolKind(item) {
|
|
19368
|
-
const
|
|
19376
|
+
const detail = item.detail;
|
|
19377
|
+
switch (detail.type) {
|
|
19378
|
+
case "read":
|
|
19379
|
+
return "read";
|
|
19380
|
+
case "edit":
|
|
19381
|
+
case "write":
|
|
19382
|
+
return "edit";
|
|
19383
|
+
case "search":
|
|
19384
|
+
return detail.toolName === "web_search" ? "fetch" : "search";
|
|
19385
|
+
case "fetch":
|
|
19386
|
+
return "fetch";
|
|
19387
|
+
case "plan":
|
|
19388
|
+
return "think";
|
|
19389
|
+
case "sub_agent":
|
|
19390
|
+
case "plain_text":
|
|
19391
|
+
return "other";
|
|
19392
|
+
}
|
|
19393
|
+
const word = detail.type === "shell" ? String(detail.command ?? "").trim().split(/[\s{(]/)[0] : item.name;
|
|
19369
19394
|
if (/^(Read|NotebookRead|LS)$/.test(word)) return "read";
|
|
19370
19395
|
if (/^(Edit|MultiEdit|Write|NotebookEdit)$/.test(word)) return "edit";
|
|
19371
19396
|
if (/^(Grep|Glob)$/.test(word)) return "search";
|
|
19372
19397
|
if (/^(WebFetch|WebSearch)$/.test(word)) return "fetch";
|
|
19373
19398
|
if (/^(Skill|Task|TodoWrite)$/.test(word) || item.name.startsWith("alp_")) return "other";
|
|
19374
|
-
return
|
|
19375
|
-
}
|
|
19376
|
-
function toolTitle(item) {
|
|
19377
|
-
|
|
19378
|
-
|
|
19399
|
+
return detail.type === "shell" ? "execute" : "other";
|
|
19400
|
+
}
|
|
19401
|
+
function toolTitle(item, cwd) {
|
|
19402
|
+
const detail = item.detail;
|
|
19403
|
+
switch (detail.type) {
|
|
19404
|
+
case "shell":
|
|
19405
|
+
return clip(String(detail.command ?? "").split("\n")[0], 160);
|
|
19406
|
+
case "read":
|
|
19407
|
+
return clip(`Read ${shown(detail.filePath, cwd)}`, 160);
|
|
19408
|
+
case "edit":
|
|
19409
|
+
return clip(`Edit ${shown(detail.filePath, cwd)}`, 160);
|
|
19410
|
+
case "write":
|
|
19411
|
+
return clip(`Write ${shown(detail.filePath, cwd)}`, 160);
|
|
19412
|
+
case "search":
|
|
19413
|
+
return clip(`${detail.toolName === "web_search" ? "Search the web" : "Search"} ${detail.query}`, 160);
|
|
19414
|
+
case "fetch":
|
|
19415
|
+
return clip(`Fetch ${detail.url}`, 160);
|
|
19416
|
+
case "sub_agent":
|
|
19417
|
+
return clip(`${detail.subAgentType ?? "Sub-agent"}${detail.description ? `: ${detail.description.split("\n")[0]}` : ""}`, 160);
|
|
19418
|
+
case "plan":
|
|
19419
|
+
return "Plan";
|
|
19420
|
+
case "plain_text":
|
|
19421
|
+
return clip(`${item.name}${detail.label ? `: ${detail.label}` : ""}`, 160);
|
|
19422
|
+
}
|
|
19423
|
+
const input = detail.input ?? {};
|
|
19379
19424
|
if (item.name === "alp_delegate") return clip(`Delegate to ${input.agent ?? "an agent"}: ${String(input.task ?? "").split("\n")[0]}`, 160);
|
|
19380
19425
|
return clip(`${item.name} ${JSON.stringify(input)}`, 160);
|
|
19381
19426
|
}
|
|
19427
|
+
var bounded = (text) => text.length > OUTPUT_CHARS ? `${text.slice(0, OUTPUT_CHARS)}
|
|
19428
|
+
\u2026 (${text.length - OUTPUT_CHARS} more characters)` : text;
|
|
19382
19429
|
function toolOutput(item) {
|
|
19430
|
+
const detail = item.detail;
|
|
19431
|
+
const parts = [];
|
|
19383
19432
|
let text = "";
|
|
19384
|
-
|
|
19385
|
-
|
|
19386
|
-
|
|
19387
|
-
|
|
19433
|
+
switch (detail.type) {
|
|
19434
|
+
case "shell":
|
|
19435
|
+
text = detail.output ?? "";
|
|
19436
|
+
break;
|
|
19437
|
+
case "read":
|
|
19438
|
+
text = detail.content ?? "";
|
|
19439
|
+
break;
|
|
19440
|
+
case "edit":
|
|
19441
|
+
if (detail.newString !== void 0 || detail.oldString !== void 0) parts.push({ type: "diff", path: detail.filePath, oldText: detail.oldString ?? null, newText: detail.newString ?? "" });
|
|
19442
|
+
else if (detail.unifiedDiff) text = "```diff\n" + detail.unifiedDiff + (detail.unifiedDiff.endsWith("\n") ? "" : "\n") + "```";
|
|
19443
|
+
break;
|
|
19444
|
+
case "write":
|
|
19445
|
+
if (detail.content !== void 0) parts.push({ type: "diff", path: detail.filePath, oldText: null, newText: detail.content });
|
|
19446
|
+
break;
|
|
19447
|
+
case "search":
|
|
19448
|
+
text = detail.content ?? [...detail.filePaths ?? [], ...(detail.webResults ?? []).map((hit) => `${hit.title} \u2014 ${hit.url}`)].join("\n");
|
|
19449
|
+
break;
|
|
19450
|
+
case "fetch":
|
|
19451
|
+
text = detail.result ?? "";
|
|
19452
|
+
break;
|
|
19453
|
+
case "sub_agent":
|
|
19454
|
+
text = detail.log || detail.description || "";
|
|
19455
|
+
break;
|
|
19456
|
+
case "plan":
|
|
19457
|
+
text = detail.text;
|
|
19458
|
+
break;
|
|
19459
|
+
case "plain_text":
|
|
19460
|
+
text = detail.text ?? "";
|
|
19461
|
+
break;
|
|
19462
|
+
default: {
|
|
19463
|
+
const output = detail.output;
|
|
19464
|
+
text = Array.isArray(output) ? output.map((part) => typeof part?.text === "string" ? part.text : JSON.stringify(part)).join("\n") : output == null ? "" : typeof output === "string" ? output : JSON.stringify(output, null, 2);
|
|
19465
|
+
}
|
|
19388
19466
|
}
|
|
19389
19467
|
if (item.error) text = text ? `${text}
|
|
19390
19468
|
${item.error}` : item.error;
|
|
19391
|
-
if (
|
|
19392
|
-
|
|
19393
|
-
|
|
19394
|
-
|
|
19469
|
+
if (text) parts.push({ type: "content", content: { type: "text", text: bounded(text) } });
|
|
19470
|
+
return parts.map((part) => part.type === "diff" ? { ...part, newText: bounded(part.newText), ...part.oldText ? { oldText: bounded(part.oldText) } : {} } : part);
|
|
19471
|
+
}
|
|
19472
|
+
function toolInput(item) {
|
|
19473
|
+
const detail = item.detail;
|
|
19474
|
+
if (detail.type === "shell") return { command: detail.command, cwd: detail.cwd };
|
|
19475
|
+
if (detail.type === "unknown" || !["read", "edit", "write", "search", "fetch", "sub_agent", "plan", "plain_text"].includes(detail.type)) return detail.input;
|
|
19476
|
+
const { type: _type, content: _content, oldString: _old, newString: _new, unifiedDiff: _diff, result: _result, log: _log, text: _text, filePaths: _paths, webResults: _hits, ...rest } = detail;
|
|
19477
|
+
return rest;
|
|
19478
|
+
}
|
|
19479
|
+
function toolLocations(item) {
|
|
19480
|
+
const detail = item.detail;
|
|
19481
|
+
if (detail.type !== "read" && detail.type !== "edit" && detail.type !== "write") return void 0;
|
|
19482
|
+
const filePath = String(detail.filePath);
|
|
19483
|
+
return [{ path: filePath, ...detail.type === "read" && typeof detail.offset === "number" ? { line: detail.offset } : {} }];
|
|
19395
19484
|
}
|
|
19396
19485
|
var clip = (text, chars) => text.length > chars ? `${text.slice(0, chars - 1)}\u2026` : text;
|
|
19397
19486
|
var status = (state) => state === "running" ? "in_progress" : state;
|
|
@@ -19430,7 +19519,7 @@ function createAcpAgent(options) {
|
|
|
19430
19519
|
}
|
|
19431
19520
|
const say = (session, text) => send(session, { sessionUpdate: "agent_message_chunk", content: { type: "text", text } });
|
|
19432
19521
|
function configOptions(session) {
|
|
19433
|
-
const teams = session.opened ? session.
|
|
19522
|
+
const teams = session.opened ? choices(session).filter((team) => team.id === session.preview.team) : choices(session);
|
|
19434
19523
|
return [
|
|
19435
19524
|
{
|
|
19436
19525
|
id: "team",
|
|
@@ -19439,14 +19528,21 @@ function createAcpAgent(options) {
|
|
|
19439
19528
|
type: "select",
|
|
19440
19529
|
currentValue: session.preview.team,
|
|
19441
19530
|
description: session.opened ? "A session keeps its team; start a new one for another team" : "The team that works on this session",
|
|
19442
|
-
options:
|
|
19531
|
+
options: teams.map((team) => ({ value: team.id, name: team.label, ...team.description ? { description: team.description } : {} }))
|
|
19443
19532
|
},
|
|
19444
19533
|
{ id: "mode", name: "Permissions", category: "mode", type: "select", currentValue: session.preview.mode, options: MODES.map((mode) => ({ value: mode.id, name: mode.name, description: mode.description })) }
|
|
19445
19534
|
];
|
|
19446
19535
|
}
|
|
19536
|
+
function choices(session) {
|
|
19537
|
+
const { teams, team } = session.preview;
|
|
19538
|
+
const own2 = unlistedOf(session.preview);
|
|
19539
|
+
const first = session.unlisted && session.unlisted.id !== team && !teams.some((entry) => entry.id === session.unlisted.id) ? [session.unlisted] : [];
|
|
19540
|
+
return [...first, ...own2 ? [own2] : [], ...teams];
|
|
19541
|
+
}
|
|
19447
19542
|
const modeState = (session) => ({ currentModeId: session.preview.mode, availableModes: MODES });
|
|
19448
19543
|
function track(id, cwd, mcpServers, preview2, opened) {
|
|
19449
|
-
const
|
|
19544
|
+
const unlisted = unlistedOf(preview2);
|
|
19545
|
+
const session = { id, cwd, mcpServers, preview: preview2, opened, ...unlisted ? { unlisted } : {}, ours: /* @__PURE__ */ new Set(), texts: /* @__PURE__ */ new Map(), tools: /* @__PURE__ */ new Set(), questions: /* @__PURE__ */ new Map(), queue: Promise.resolve() };
|
|
19450
19546
|
sessions.set(id, session);
|
|
19451
19547
|
return session;
|
|
19452
19548
|
}
|
|
@@ -19544,7 +19640,8 @@ ${item2.text}`;
|
|
|
19544
19640
|
send(session, { sessionUpdate: "plan", entries: item2.items.map((entry) => ({ content: entry.text, priority: "medium", status: entry.status })) });
|
|
19545
19641
|
return;
|
|
19546
19642
|
case "tool_call": {
|
|
19547
|
-
const
|
|
19643
|
+
const locations = toolLocations(item2);
|
|
19644
|
+
const fields = { title: toolTitle(item2, session.cwd), kind: toolKind(item2), status: status(item2.status), content: toolOutput(item2), rawInput: toolInput(item2), ...locations ? { locations } : {} };
|
|
19548
19645
|
if (session.tools.has(item2.id)) send(session, { sessionUpdate: "tool_call_update", toolCallId: item2.id, ...fields });
|
|
19549
19646
|
else {
|
|
19550
19647
|
session.tools.add(item2.id);
|
|
@@ -19677,7 +19774,7 @@ ${item2.text}`;
|
|
|
19677
19774
|
if (params.configId === "mode") await setMode(session, value);
|
|
19678
19775
|
else if (params.configId === "team") {
|
|
19679
19776
|
if (session.opened && value !== session.preview.team) throw RequestError.invalidParams(void 0, "A session keeps its team; start a new one for another team");
|
|
19680
|
-
if (!session.
|
|
19777
|
+
if (!choices(session).some((team) => team.id === value)) throw RequestError.invalidParams(void 0, `Unknown team ${value}`);
|
|
19681
19778
|
session.preview = { ...await preview(session.cwd, session.mcpServers, value), mode: session.preview.mode };
|
|
19682
19779
|
} else throw RequestError.invalidParams(void 0, `Unknown option ${params.configId}`);
|
|
19683
19780
|
return { configOptions: configOptions(session) };
|
|
@@ -19706,7 +19803,7 @@ ${item2.text}`;
|
|
|
19706
19803
|
|
|
19707
19804
|
// packages/cli/src/acp/main.ts
|
|
19708
19805
|
async function runAcp({ daemonEntry }) {
|
|
19709
|
-
const version2 = true ? "0.0.0-beta.
|
|
19806
|
+
const version2 = true ? "0.0.0-beta.2" : "0.0.0";
|
|
19710
19807
|
const logger = createLogger({ component: "acp" });
|
|
19711
19808
|
const log = (message, fields) => logger.warn(message, fields);
|
|
19712
19809
|
const app = createAcpAgent({
|