@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
package/README.md
CHANGED
|
@@ -1,418 +1,22 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @anhlp/alp
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
The current release is the beta `0.0.1-beta.3` (until it is on npm, `@beta` installs
|
|
8
|
-
`0.0.0-beta.2`; check with `npm view @anhlp/alp dist-tags`): see the
|
|
9
|
-
[release notes](docs/alp/beta-release-notes.md) for what it includes and its known issues, and
|
|
10
|
-
[installing, upgrading and removing the beta](docs/alp/beta-install.md) for every step. Name the
|
|
11
|
-
beta when you install (`@beta`, or exactly `@0.0.1-beta.3`); 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.
|
|
14
|
-
|
|
15
|
-
Supported: Linux or macOS, Node.js 22 (22.12 or later) or 24, and a signed-in Codex CLI or
|
|
16
|
-
Claude Code on PATH. Windows and Node.js 26 are experimental; Node.js 20 is not supported.
|
|
3
|
+
The `alp` command of [ALP](https://github.com/phucanh08/alp). This package is a small launcher:
|
|
4
|
+
npm installs the ALP executable for your machine as one optional dependency,
|
|
5
|
+
`@anhlp/alp-<os>-<arch>` (darwin-arm64, darwin-x64, linux-x64, linux-arm64 (glibc), win32-x64),
|
|
6
|
+
and `alp` runs it with your arguments. Nothing is downloaded after install.
|
|
17
7
|
|
|
18
8
|
```sh
|
|
19
9
|
npm install -g @anhlp/alp@beta
|
|
20
|
-
alp
|
|
21
|
-
alp daemon start
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
Choose the models Phở and Cafe run on in a project, for Codex only, Claude only, or a mix:
|
|
25
|
-
|
|
26
|
-
```sh
|
|
27
|
-
alp setup # select boxes: runtime, which provider first, then Save / Change a model
|
|
28
|
-
alp setup --runtime codex # Codex only
|
|
29
|
-
alp setup --runtime claude # Claude only
|
|
30
|
-
alp setup --runtime mix # both, Claude first
|
|
31
|
-
alp setup --runtime mix --prefer codex --codex-model gpt-6-sol --claude-oracle claude-fable-5-1
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Setup writes `team.pho` and `team.cafe` into the project's `.alp/settings.json`
|
|
35
|
-
(running `alp init` first when there is none) and keeps the rest of the file. Main runs
|
|
36
|
-
on one model, of the preferred provider. Lead and reviewer take `--claude-model` /
|
|
37
|
-
`--codex-model`, the supervisor `--claude-supervisor` / `--codex-supervisor`, and the
|
|
38
|
-
oracle `--claude-oracle` / `--codex-oracle`; in mix each lists both providers, the
|
|
39
|
-
preferred one first, and an only mode lists its own. Peers get `claude:*` and/or
|
|
40
|
-
`codex:*`: any model of the enabled providers, chosen with its effort for each task by
|
|
41
|
-
whoever assigns it. Defaults: Opus 5.5 / GPT-6.1 Sol at high, Sonnet 5 / GPT-6 Luna at
|
|
42
|
-
medium, Fable 5.1 at high / GPT-6 Astra at low (the only effort it takes). Setup does
|
|
43
|
-
not install CLIs, log in or call models: run `alp doctor` for that. New sessions use
|
|
44
|
-
the profiles; running sessions keep theirs.
|
|
45
|
-
|
|
46
|
-
The package provides the `alp` command and `alpd`, the per-user daemon that runs ALP sessions. To view and drive sessions in Paseo, also install the [Paseo plugin](integrations/paseo/README.md).
|
|
47
|
-
|
|
48
|
-
## Initialize a project
|
|
49
|
-
|
|
50
|
-
Run `alp init [directory]` (or `node /path/to/alp/packages/cli/dist/cli.js init [directory]` when running a source checkout after `npm run build`). The directory defaults to the current working directory.
|
|
51
|
-
|
|
52
|
-
When the Paseo plugin opens an ALP session in a repository that lacks `ALP.md` or `.alp/settings.json`, it performs this initialization automatically. Initialization fills missing scaffold files and never replaces existing files, so partial and customized ALP setups are preserved.
|
|
53
|
-
|
|
54
|
-
Initialization creates `ALP.md` and `.alp/settings.json`. The six agents `main`, `lead`, `peer`, `oracle`, `reviewer` and `supervisor` are built into ALP and follow its updates; a project does not copy them. To change one, make an agent of the same name in your library (`~/.alp/agents/`) or in the project (`.alp/agents/`); see [agent library](docs/alp/agent-library.md). Main owns delivery; Phở lets main implement or call peer, while Cafe assigns technical execution to lead. Oracle and reviewer provide read-only advice and review; the supervisor reviews main's process after each turn.
|
|
55
|
-
|
|
56
|
-
The default settings select main with the Phở team. Main runs on Opus 5.5 with high effort and full access unless settings or the caller choose otherwise. Paseo exposes an `alp_delegate` tool that executes real child sessions and returns their evidence. See [Phở and Cafe teams](docs/alp/team-workflow.md).
|
|
57
|
-
|
|
58
|
-
Six [role skills](docs/alp/role-skills.md) cover intake, research, planning, delegation briefs, bug diagnosis, and commit packaging. They live in your skill library in `$ALP_HOME` (default `~/.alp`), seeded on first use, together with `role-skills.json`, which assigns six to main, five to lead and three to peer. Edit either freely: app updates replace only library files you have not changed. Each agent selects directly from its skills and loads contents only when needed.
|
|
59
|
-
|
|
60
|
-
Repeated runs fill in missing files and preserve existing file contents, including custom settings. Conflicting filesystem entry types cause an error; files already created before an error remain available for a later retry. Run `npm run test:init` to verify initialization independently.
|
|
61
|
-
|
|
62
|
-
For projects created with an earlier scaffold, run `alp upgrade [directory]` (or the built CLI above). This backs up and updates recognized original instructions, adds team settings, renames the old `smart`/`supervised` profiles to `pho`/`cafe`, and archives project copies of skills that still match the shipped ones, so the library applies. Copies of the built-in agents that are still as ALP shipped them are put away too, so the project uses the built-ins; a copy you edited, or added skills, MCP servers or hooks to, stays as the project's override. The old shipped graph migrates to Cafe; custom graphs and customized instructions/skills remain unchanged.
|
|
63
|
-
|
|
64
|
-
## Development
|
|
65
|
-
|
|
66
|
-
Use Node 22 (22.12 or later) or 24 and an npm version compatible with your Node installation:
|
|
67
|
-
|
|
68
|
-
```sh
|
|
69
|
-
npm ci
|
|
70
|
-
npm run check
|
|
71
|
-
npm test
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
`npm test` builds every workspace and runs the hermetic suites (unit and integration together, each file once) in a throwaway `ALP_HOME`. `npm run build` builds only the core CLI, daemon, ACP and runtime bundles; `npm run build:paseo` builds the optional plugin. The runtime in `packages/runtime/src` owns native harnesses, sessions, delegation, and mail without importing Paseo; `alpd` hosts it, and the plugin is a viewer over the daemon ([design](plans/reference/ALPD.md)).
|
|
75
|
-
|
|
76
|
-
Tests are split by owner:
|
|
77
|
-
|
|
78
|
-
| Group | Location | Run |
|
|
79
|
-
| --- | --- | --- |
|
|
80
|
-
| Unit and package-level contract | `packages/<name>/tests/` (plugin: `integrations/paseo/tests/`) | `npm test -w @anhlp/alp-core` (or `-runtime`, `-client`, `-daemon`, `-cli`, `-protocol`, `@anhlp/alp-paseo`); all at once: `npm run test:unit` |
|
|
81
|
-
| Integration (several packages, CLI processes, repository checks) | `test/integration/` | `npm run test:integration` |
|
|
82
|
-
| E2E (live providers, opt-in) | `test/e2e/` | `npm run test:e2e` or one of `test:e2e:*` |
|
|
83
|
-
| Shared fixtures such as fake transports | `test/support/` | imported by package and integration tests |
|
|
84
|
-
|
|
85
|
-
`npm test` runs unit and integration; `npm run test:all` adds E2E. A package test imports only its own package and the packages it declares as dependencies; `npm run check:boundaries` and `test/integration/layout.test.js` enforce that. The core packages (protocol, core, runtime, client, daemon, cli) test without installing Paseo.
|
|
86
|
-
|
|
87
|
-
Runtime tests drive scripted agents from `test/support/fake-agent.js` instead of Codex or Claude: they call ALP tools, report context fill, hand off slowly, crash mid-turn or hit a usage limit on cue. `packages/client/tests/golden.test.js` compares what `alp log`, `alp ps` and `alp task report` print with `packages/client/tests/golden/*.txt`; after checking an intended change, accept it with `ALP_UPDATE_GOLDEN=1 npm test -w @anhlp/alp-client`.
|
|
88
|
-
|
|
89
|
-
## Project files
|
|
90
|
-
|
|
91
|
-
```text
|
|
92
|
-
your-project/
|
|
93
|
-
ALP.md
|
|
94
|
-
.alp/
|
|
95
|
-
settings.json
|
|
96
|
-
tasks/ # one JSON file per task; commit it with the project
|
|
97
|
-
agents/ # optional: project agents, and overrides of built-in or library ones
|
|
98
|
-
your-agent/AGENT.md
|
|
99
|
-
your-agent/agent.json
|
|
100
|
-
skills/ mcp/ hooks/ # optional: project entries; each overrides a library entry of its name
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
`alp agents`, `alp skills`, `alp mcp` and `alp hooks` list what a project can use: ALP's built-ins, your library in `~/.alp`, and the project's own entries, with what each overrides and which agents use it. `alp agent|team|skill|mcp|hook new|edit|cp|mv|rm` change them, in your library or with `--project` in the project, and `alp mcp test` and `alp hook test` try one out ([editing](docs/alp/agent-library.md#editing)).
|
|
104
|
-
|
|
105
|
-
`alp init` now writes editable `team.pho` and `team.cafe` choices into
|
|
106
|
-
`.alp/settings.json`, taking a snapshot of your current user team configuration.
|
|
107
|
-
`alp upgrade` migrates the old `profile` key to `team` and adds these team settings to older projects, backs up the settings it changes,
|
|
108
|
-
and converts earlier single-model choices to lists without changing their values.
|
|
109
|
-
Every agent (main, lead, peer, reviewer, supervisor, oracle, or a custom member) has
|
|
110
|
-
`profiles`: a list of `"provider:model:effort"` (the effort may be left out), or
|
|
111
|
-
`"provider:*"` for any model of that provider. Main and oracle name their models, and
|
|
112
|
-
main runs on exactly one. Include both providers for dual-lens oracle advice:
|
|
113
|
-
|
|
114
|
-
```json
|
|
115
|
-
{
|
|
116
|
-
"workflow": { "mode": "cafe", "maxPeers": 2 },
|
|
117
|
-
"team": {
|
|
118
|
-
"cafe": {
|
|
119
|
-
"main": { "profiles": ["claude:claude-opus-5-5:high"], "autocompact": "auto" },
|
|
120
|
-
"lead": { "profiles": ["claude:claude-opus-5-5:high", "codex:gpt-6.1-sol:high"] },
|
|
121
|
-
"peer": { "profiles": ["claude:*", "codex:*"], "autocompact": 200000 },
|
|
122
|
-
"oracle": { "profiles": ["claude:claude-fable-5-1:high", "codex:gpt-6-astra:low"] }
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
An agent that runs by itself (main, the supervisor) starts on its first profile, at its
|
|
129
|
-
effort or else its team's. When main or lead assigns work to an agent with several
|
|
130
|
-
profiles or a `provider:*`, such as a peer, it picks a model they offer and an effort
|
|
131
|
-
that model takes for each task, by its difficulty, risk and the autonomy it needs, and
|
|
132
|
-
says why; a listed effort is only the usual one. ALP refuses an assignment without both
|
|
133
|
-
or with a model they do not offer. An agent with one named profile runs on it. A list
|
|
134
|
-
does not enable automatic fallback. Oracle still requires an explicit lens selection.
|
|
135
|
-
An effort a model does not take is refused (GPT-6 Astra takes only low). The earlier
|
|
136
|
-
form, `{ "provider", "model", "effort" }`, still works; `alp upgrade` rewrites it as
|
|
137
|
-
`"provider:model:effort"`.
|
|
138
|
-
|
|
139
|
-
`autocompact` belongs to the agent, beside `profiles`, and applies to every model in
|
|
140
|
-
its list. A whole number from 100000 to 1000000 requests compaction at that many tokens
|
|
141
|
-
on Codex, or sets Claude's native auto-compact window (Claude can compact earlier to
|
|
142
|
-
reserve response space). The model's capacity still applies. `"auto"` or omission
|
|
143
|
-
keeps the agent's existing native/context defaults. The same field is supported in
|
|
144
|
-
`agent.json`; a numeric project setting takes precedence. 200000 here is an example,
|
|
145
|
-
not a shipped default. New and upgraded configurations use `"auto"`.
|
|
146
|
-
|
|
147
|
-
Unspecified agents keep the team's choices. Explicit session/delegation model and
|
|
148
|
-
effort win, then project team choices, then the older `runtime` settings, then
|
|
149
|
-
team and agent defaults. Run `alp setup` again to rewrite Phở and Cafe's profiles, or
|
|
150
|
-
edit the file to change one agent. Only configured oracle lenses are available, and an
|
|
151
|
-
unavailable lens is reported rather than substituted.
|
|
152
|
-
|
|
153
|
-
Example `.alp/settings.json`:
|
|
154
|
-
|
|
155
|
-
```json
|
|
156
|
-
{
|
|
157
|
-
"defaultAgent": "main",
|
|
158
|
-
"workflow": { "mode": "pho" },
|
|
159
|
-
"runtime": { "provider": "codex", "model": "gpt-5.6-sol", "reasoning": "low" }
|
|
160
|
-
}
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
`workflow.mode` names a team: `pho`, `cafe` or your own (`smart` and `supervised`, Phở and Cafe's names before 0.4, are still accepted); `workflow.supervisor: false` turns the supervisor off. `runtime.provider` selects `codex` or `claude` behind the ALP Paseo plugin; the Paseo provider ID itself is `alp`. Without `runtime.provider` and `runtime.model`, main runs on `claude:claude-opus-5-5` with `high` effort; setting either replaces that default. `runtime.model` is passed through to the selected native harness, so it accepts any model name supported by that installed Codex or Claude Code version. Core treats these strings as provider-neutral data. An agent's `agent.json` can pick its own provider, model, thinking and mode, and name the skills, MCP servers and hooks it uses ([agent library](docs/alp/agent-library.md)). ALP runs hooks itself at its own events, the same for Codex and Claude; a project's hooks run after you trust the workspace once ([hooks](docs/alp/agent-library.md#hooks)). Besides Codex and Claude, an agent can run on any agent that speaks the Agent Client Protocol, such as Gemini CLI or opencode (experimental in the beta), added to your library with `alp provider add` or in the web app's Providers settings ([ACP providers](docs/alp/agent-library.md#acp-providers)).
|
|
164
|
-
|
|
165
|
-
For example, select Claude Code and one of its model aliases in `.alp/settings.json`:
|
|
166
|
-
|
|
167
|
-
```json
|
|
168
|
-
{
|
|
169
|
-
"defaultAgent": "main",
|
|
170
|
-
"workflow": { "mode": "pho", "maxPeers": 2 },
|
|
171
|
-
"runtime": { "provider": "claude", "model": "sonnet", "reasoning": "high" }
|
|
172
|
-
}
|
|
10
|
+
alp --version
|
|
173
11
|
```
|
|
174
12
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
"permissions": {
|
|
181
|
-
"profiles": { "review": { "base": "read-only", "allow": ["Bash(npm test:*)"], "deny": ["Bash(rm:*)"] } },
|
|
182
|
-
"agents": { "reviewer": "review" }
|
|
183
|
-
}
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
On Claude, read-only and workspace-write profiles also put Bash in the OS sandbox, so a read-only reviewer can run tests that only read. With `"workdir": "copy"` an agent works in a disposable copy of your tree, where it may build and test without touching yours. `alp permissions` shows each agent's profile, and `alp permissions check <agent> "<command>"` tests a rule. Details: [Permission profiles](docs/alp/team-workflow.md#permission-profiles).
|
|
187
|
-
|
|
188
|
-
Use `resolveAgent(projectRoot, { agent: 'your-agent' })` from `src/core/resolver.js` to resolve an agent without starting a runtime. Explicit selection overrides settings; missing settings default to `main`. There is no central agent registry.
|
|
189
|
-
|
|
190
|
-
## Daemon and CLI
|
|
191
|
-
|
|
192
|
-
`alpd` hosts ALP sessions for all projects of a user. After `npm run build`:
|
|
193
|
-
|
|
194
|
-
```sh
|
|
195
|
-
alp daemon start # or: status [--json] | stop | restart | install | uninstall (install: experimental)
|
|
196
|
-
alp doctor [--fix] # what ALP needs here, what earlier runs left behind, and what alpd's log and readiness say; only --fix repairs
|
|
197
|
-
alp backup --stop # sessions, settings, library and the projects' tasks in one file; also: verify | list
|
|
198
|
-
alp restore FILE --stop # checks the whole backup first, keeps what it replaces; --dry-run changes nothing
|
|
199
|
-
alp run --team cafe "Your task" # streams the agent tree; Ctrl-C interrupts
|
|
200
|
-
alp ps [--all] # live sessions as a tree; --all adds closed ones
|
|
201
|
-
alp top [session] # live dashboard: who runs, who waits, questions, worktrees, leases
|
|
202
|
-
alp attach <session> # follow a running tree, or print a closed one
|
|
203
|
-
alp send <session> "More context" # resumes a closed root first; to an agent, mail from you
|
|
204
|
-
alp questions # questions agents asked you
|
|
205
|
-
alp answer <question> "Your answer" # or: --dismiss [--reason R]
|
|
206
|
-
alp log <session> # delegations, mail, handoffs, worktrees, pins and questions of a tree
|
|
207
|
-
alp board [--project DIR] # the project board: claims, decisions and findings
|
|
208
|
-
alp tasks [ready] # the project's tasks; ready: what nothing blocks
|
|
209
|
-
alp task add "Title" -p 1 --after t-91c2 # also: show | edit | close | reopen | dep
|
|
210
|
-
alp formula pour release --var version=0.4.0 # also: list | show; tasks export | import for beads
|
|
211
|
-
alp verify [--task t-77e0] # run the project's verify commands; --task records the result
|
|
212
|
-
alp recall <assignment|task> "Why did you…?" # ask a finished assignment about its work
|
|
213
|
-
alp pause [codex|claude] [--now] # hold delegation; --now parks running assignments
|
|
214
|
-
alp resume [codex|claude] # parked assignments continue
|
|
215
|
-
alp interrupt <session>
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
You talk with main. Main can ask you a question with `alp_ask` without ending its turn; `run`, `attach` and `send` show it and, in a terminal, read the answer, and `alp answer` answers from anywhere by question id or a unique prefix. In Paseo the question appears as a question prompt. Other agents do not talk to you unless you write to them first with `alp send <agent session>`; ALP then tells the agent that assigned them, and they may ask you questions too.
|
|
219
|
-
|
|
220
|
-
Agents on one project share a board, even when they belong to different trees. Each one claims the paths it is about to change, and an overlapping claim from another tree is refused. Agents also pin decisions and findings, which reach other agents that are working and start every new assignment. `alp board` shows the board.
|
|
221
|
-
|
|
222
|
-
Each project keeps its tasks in `.alp/tasks`, one JSON file per task, modelled on [beads](https://github.com/gastownhall/beads): types, priorities 0–4, `blockedBy`, epic parents, and a ready list of open tasks that nothing blocks. Only you and main create or change tasks: you with `alp task`, main with its `alp_task` tool. Other agents read them and report work they find to their requester. Main gives a task to lead or peer with `alp_delegate { taskId }`: the task starts, its paths are claimed, and the handoff moves it to review until main accepts it. Each of main's turns starts with what waits for review and what is ready, and Paseo shows the tasks a session worked on as a task list. When every child of an epic is closed, main closes the epic, and you get a report of what it came to: tasks, time, rework and verification. `alp task report <epic>` shows it at any time.
|
|
223
|
-
|
|
224
|
-
A gate holds a task back until it clears:
|
|
225
|
-
- `human`: you approve it with `alp task gate clear` or in Paseo.
|
|
226
|
-
- `timer`: a time passes.
|
|
227
|
-
- `gh:pr`: a pull request merges.
|
|
228
|
-
- `gh:run`: a workflow run succeeds.
|
|
229
|
-
|
|
230
|
-
Formulas are workflow templates, as in beads: a `<name>.formula.toml` (or `.json`) file in `.alp/formulas`, `$ALP_HOME/formulas` or `.beads/formulas` lists steps with `needs` and `{{vars}}`. `alp formula pour release --var version=0.4.0`, or main with `alp_task pour`, turns one into an epic with a task per step; a `human` step waits for your approval. `alp tasks export` and `alp tasks import` move tasks to and from beads' JSONL (`bd export` / `bd import`, default `.beads/issues.jsonl`).
|
|
231
|
-
|
|
232
|
-
`alp tasks gates` and main's turns check the GitHub gates. `alp tasks compact` shrinks tasks closed more than 30 days ago. In Paseo, each workspace has a **Tasks** panel: you approve gates, add tasks, and accept or reopen them there. The CLI writes the files directly, so it works without alpd.
|
|
233
|
-
|
|
234
|
-
`ALP_HOME` selects the daemon's directory (default `~/.alp`); `ALP_RUN_LOG_DIR` overrides where assignment logs go (default `$ALP_HOME/runs`). alpd records sessions, their timelines, and prompt receipts under `$ALP_HOME/state`, project boards under `$ALP_HOME/boards`, and its own location in `$ALP_HOME/alpd.json`. After a restart, or a crash, a root can be resumed with `send` or imported into Paseo; work that was running is marked `daemon_restarted`. A task an assignment held goes back to open at main's next turn, with the branch that kept the assignment's work, and main's task list shows it as interrupted.
|
|
235
|
-
|
|
236
|
-
With `"verify": { "test": "npm test" }` (also `setup`, `typecheck`) in `.alp/settings.json`, alpd runs the project's checks itself:
|
|
237
|
-
- before `alp_merge` applies a worktree change; if they fail, nothing is applied and main can fix the change with `alp_delegate { continueFrom }`;
|
|
238
|
-
- in the checkout after a shared writer finishes;
|
|
239
|
-
- on demand with `alp_verify` or `alp verify`.
|
|
240
|
-
|
|
241
|
-
The result is recorded on the task, and an agent cannot close a task as done after a failed check without saying why. A timed-out command gets SIGTERM before SIGKILL, `idleSec` stops a silent one, and a step exiting 75 counts as could-not-run (skipped), not failed. Details: [Verification gates](docs/alp/team-workflow.md#verification-gates).
|
|
242
|
-
|
|
243
|
-
`alp_delegate { continueFrom: assignmentId }` also continues a finished Codex or Claude shared assignment while its record is retained (14 days). It creates a new assignment in the same checkout, carrying the previous brief and handoff, and preserves an external `writeRoot`. It does not reopen the old conversation or restore a file snapshot. Running or parked assignments must finish or be canceled first. Older records without this context can be continued by delegating again with their handoff; shared changes need no merge or discard.
|
|
244
|
-
|
|
245
|
-
When recovering an assignment saved by an older ALP version, an effort no longer accepted by the current model catalog falls back to that model's default. ALP tells the requester and records the change in the run log. Newly requested unsupported efforts are still rejected.
|
|
246
|
-
|
|
247
|
-
Text one agent wrote reaches another without `<system-reminder>` tags, so a peer cannot pose as the harness.
|
|
248
|
-
|
|
249
|
-
Work survives alpd: after a crash, `alp daemon stop` or `alp daemon restart`, the next alpd reopens trees that were working, by itself, and their assignments continue with their thread, worktree and task. When a Codex or Claude process dies under a session, ALP restarts it and the session continues; three restarts in a row with no progress end it. `alp daemon install` (experimental in the beta) runs alpd as a login service (launchd on macOS, systemd on Linux) that starts it again after a crash. Details: [Crashes and restarts](docs/alp/team-workflow.md#crashes-and-restarts).
|
|
250
|
-
|
|
251
|
-
`alp backup` writes your sessions, timelines, receipts, settings, library and the projects' tasks to one checked file, and `alp restore` puts them back only after checking all of it, keeping what it replaced so the restore can be undone; an interrupted restore is rolled back. alpd migrates an older state when an upgrade needs it, after saving a backup, and an older ALP refuses state a newer one wrote instead of changing it. Session trees unused for 30 days are deleted, but never while one of them is live or a prompt receipt of theirs (7 days) is still honoured. Codex and Claude keep their own threads, which a backup does not hold. Details: [Backups, restores, upgrades and recovery](docs/alp/data-recovery.md).
|
|
252
|
-
|
|
253
|
-
When a runtime hits its usage limit, ALP pauses it by itself. Assignments the limit stopped are parked instead of failed, and every open session shows a notice saying when the limit resets. Agents on the other runtime keep working. alpd asks the paused runtime every minute, and at once when an agent delegates to it. It resumes the runtime as soon as the runtime says the limit lifted, and the parked assignments continue. With `"limits": { "autoResume": false }` in `$ALP_HOME/settings.json`, ALP only tells you, and `alp resume codex` continues. Details: [Pause and usage limits](docs/alp/team-workflow.md#pause-and-usage-limits).
|
|
254
|
-
|
|
255
|
-
Agents and ALP write to you in the language set in Settings → ALP → General → Language, or with `alp language English`; unset, it is Vietnamese. That covers replies, questions, approval requests and notices. Details: [The user's language](docs/alp/team-workflow.md#the-users-language).
|
|
256
|
-
|
|
257
|
-
Finished assignments stay recallable for 14 days: main, or the agent that assigned one, asks it with `alp_recall` why it did something, and you ask with `alp recall <assignment|task> "question"`. ALP forks the assignment's session read-only, asks, and drops the fork; the question never changes the assignment's own session. ALP keeps the native threads of assignments for this, and deletes them after 14 days. The Paseo plugin keeps the same daemon running while Paseo runs: it starts alpd with Paseo and again whenever alpd goes down, except after `alp daemon stop`, and its sessions reconnect.
|
|
258
|
-
|
|
259
|
-
## The web app
|
|
260
|
-
|
|
261
|
-
The optional `@anhlp/alp-paseo` package serves the ALP web app as a separate process, on this machine only (loopback). The core `@anhlp/alp` distribution includes no Paseo SDK or web app; ALP 0.10.0 and earlier bundled it. This is not the standalone app in `apps/web`, which is deferred and not published. Install the plugin once to keep using the existing web commands:
|
|
262
|
-
|
|
263
|
-
```sh
|
|
264
|
-
npm install -g @anhlp/alp-paseo@beta
|
|
265
|
-
alp-web-integration --register # register in the selected ALP_HOME (also discoverable on PATH)
|
|
266
|
-
alp web # opens http://127.0.0.1:7433 with its access token
|
|
267
|
-
alp web --print # prints the address instead
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
The app is [Paseo](https://github.com/getpaseo/paseo)'s web app (Apache 2.0), built from a pinned commit with ALP's patches (`paseo-web/`) and run over alpd, so it looks and works like Paseo:
|
|
271
|
-
|
|
272
|
-
- **Sidebar:** your projects and their workspaces, with their branch, pins, labels and unread marks. Add a project by typing its folder or browsing to it (Add project → Browse folders); a new workspace starts with its first agent.
|
|
273
|
-
- **Agents:** each session is an agent of the provider ALP, its team (Phở, Cafe, …) as the model. The timeline streams main's replies and tool calls; questions from the team are cards to answer; History and Find in chat search past sessions. The team members are the agent's subagents, each with its own timeline.
|
|
274
|
-
- **ALP's own parts:** the Tasks panel and screen, the ALP project panel and the ALP settings screen (Settings → Plugins → alp-provider) come from ALP's Paseo plugin, which alpd runs.
|
|
275
|
-
- **Changes and Files:** the checkout's diff, uncommitted or against its base branch, and its files, read-only.
|
|
276
|
-
- **Usage:** the sidebar Usage button and Settings → Usage show Codex and Claude account limits, plan names and reset windows. ALP's Usage workspace panel and plugin settings also show paused runtimes and parked assignment counts. Reads are cached for 30 seconds; Refresh requests fresh data. Missing provider data is shown as unavailable. These are account-wide provider limits, not ALP token costs.
|
|
277
|
-
- What Paseo has and ALP not yet (terminals, committing and pushing, worktrees from the app, voice, …) says "Tính năng đang phát triển" (in your language) when used.
|
|
278
|
-
|
|
279
|
-
The web app listens on 127.0.0.1 only. The page needs the token `alp web` puts in its address (kept in `~/.alp/web.json`), and the integration refuses requests for another host name and sockets from another site. `"web": { "port": 8000 }` in `~/.alp/settings.json` moves it, and `"web": { "enabled": false }` turns it off. In a checkout of this repository, build the app with `npm run build:web` (it clones Paseo into `.cache/paseo-web`). Details: [ALPD §62](plans/reference/ALPD.md#62-the-alp-web-app-on-paseos-app-2026-10-10).
|
|
280
|
-
|
|
281
|
-
### Paseo's app on your phone (experimental)
|
|
282
|
-
|
|
283
|
-
Relay pairing is experimental in the beta and off by default. The integration can also reach alpd from [Paseo](https://paseo.sh)'s own app on another device, through Paseo's relay (`relay.paseo.sh`):
|
|
284
|
-
|
|
285
|
-
```sh
|
|
286
|
-
alp web pair --on # turns the relay on and prints the pairing link
|
|
287
|
-
alp web pair # the link again; --off turns the relay off
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
Or in the web app: Settings → your host → Pair device → Enable relay, then scan the QR code with Paseo's app. Traffic between the device and alpd is end-to-end encrypted; the relay only passes it on. The link carries alpd's public key, not its token: when Paseo's app asks for a password, give it the token (the part after `#token=` in `alp web --print`). The relay stays off until you turn it on; `"web": { "relay": { "endpoint": "host:port" } }` points the integration at another relay. Paseo's app shows ALP's sessions and teams, and answers what ALP has not built yet as an error. Details: [ALPD §64](plans/reference/ALPD.md#64-paseos-relay-and-its-app-on-another-device-2026-10-12).
|
|
291
|
-
|
|
292
|
-
## Antigravity CLI (experimental)
|
|
293
|
-
|
|
294
|
-
The Antigravity and ACP providers (OpenCode, Gemini CLI) are experimental in the beta. With `agy` installed and signed in:
|
|
295
|
-
|
|
296
|
-
```sh
|
|
297
|
-
alp provider test antigravity
|
|
298
|
-
alp run --model antigravity:gemini-3.8-flash-high --mode full-access "Describe this project"
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
A main profile can select `antigravity:gemini-3.8-flash-high` too. By default this adapter supports full access only. To run oracle, reviewer and supervisor on Antigravity, explicitly enable instruction-based read-only behavior:
|
|
302
|
-
|
|
303
|
-
```sh
|
|
304
|
-
alp provider edit antigravity --read-only-mode instructions
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
This stores `"readOnlyMode": "instructions"` in your library's provider configuration. ALP keeps advisory sessions read-only for its own tools and tells the agent to avoid changing files or external state, while the native agy process still runs with full access. This is a prompt constraint, not an OS sandbox or filesystem protection. It applies to new sessions; ALP does not downgrade an existing full-access AGY process to read-only. Use `--read-only-mode reject` to restore the default rejection. Workspace-write, review copies and custom permission rules remain unsupported.
|
|
308
|
-
|
|
309
|
-
MCP tools supplied by the project or editor are connected separately for each AGY session over stdio or streamable HTTP, then exposed through ALP's MCP bridge. The tool aliases and descriptions identify their original server. Commands, environment variables and HTTP authorization headers stay out of agy's global configuration. MCP resources and prompts are not forwarded through this tool bridge; configure a server directly in agy if you need those capabilities.
|
|
310
|
-
|
|
311
|
-
OpenCode (`opencode acp`) and Antigravity (`agy`) are added to your library by default, including on upgrades. Settings → Providers shows a switch at the end of each row to enable or disable them. Install and sign in to the corresponding CLI to use it; an absent CLI is shown as not installed. Existing commands, model settings and disabled switches are preserved across upgrades. OpenCode models use `acp:opencode/<model>`. To change a default command, use `alp provider edit opencode --command /path/to/opencode --arg acp` or `alp provider edit antigravity --command /path/to/agy`.
|
|
312
|
-
|
|
313
|
-
ALP installs one `alp` MCP launcher in `~/.gemini/config/mcp_config.json`, preserving other entries. Each agy process inherits its own socket and token; neither is saved in that file. The launcher remains available across sessions and exposes no ALP tools outside an ALP process. Invalid configuration and a conflicting user-owned `alp` entry cause an error without overwriting the file.
|
|
314
|
-
|
|
315
|
-
## Editors (ACP, experimental)
|
|
316
|
-
|
|
317
|
-
`alp acp` is experimental in the beta. It serves ALP over the [Agent Client Protocol](https://agentclientprotocol.com) on stdio, so an editor such as Zed or a JetBrains IDE can use ALP as its agent. In Zed's `settings.json`:
|
|
318
|
-
|
|
319
|
-
```json
|
|
320
|
-
{
|
|
321
|
-
"agent_servers": {
|
|
322
|
-
"ALP": { "type": "custom", "command": "alp", "args": ["acp"], "env": {} }
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
- Each editor thread is an ALP session in its project, worked by a team. Choose the team (Phở, Cafe, or your own) and the permission mode in the thread's options before the first prompt; the team is fixed after that.
|
|
328
|
-
- Main's replies, commands and tool calls stream into the thread, and so do the steps its team reports back after the prompt ended. Delegations show as tool calls.
|
|
329
|
-
- When an agent asks you something, the question appears in the thread: reply with `/answer <text>`, or `/dismiss`.
|
|
330
|
-
- Stop cancels main's turn and the work it started. Closing the editor leaves running work to finish in alpd; the thread's history lists ALP sessions of the project, and opening one shows its history.
|
|
331
|
-
- MCP servers the editor offers are given to the agents beside their own.
|
|
332
|
-
|
|
333
|
-
Details: [ALPD §60](plans/reference/ALPD.md#60-alp-as-an-acp-agent-2026-10-10).
|
|
334
|
-
|
|
335
|
-
## Paseo
|
|
336
|
-
|
|
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 plugin supports Paseo `>=0.11.1 <0.13.0` (`0.0.0-beta.2` and earlier: `<0.12.0`, so Paseo 0.12 needs `0.0.1-beta.3` or later). 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.
|
|
338
|
-
|
|
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)).
|
|
340
|
-
|
|
341
|
-
### Build and add the plugin to Paseo
|
|
342
|
-
|
|
343
|
-
This section builds the plugin from a checkout of this repository. Prerequisites: Node.js 22 (22.12 or later) or 24, Paseo 0.11.1 or later, up to 0.12.x (the Tasks panel needs the 0.11.1 plugin client API), and a logged-in Codex CLI and/or Claude Code installation. Set `ALP_CODEX_BIN` or `ALP_CLAUDE_BIN` to an absolute native executable path when it is not available on `PATH`.
|
|
344
|
-
|
|
345
|
-
Install dependencies, type-check the plugin, and build its server bundle:
|
|
346
|
-
|
|
347
|
-
```sh
|
|
348
|
-
npm ci
|
|
349
|
-
npm run check
|
|
350
|
-
npm run build:paseo
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
The build output is written to `integrations/paseo/server/dist/index.js`. Paseo plugins are trusted, unsandboxed code, so enable plugins only on a daemon where you trust this repository. In Paseo, open **Settings → Plugins** and turn on **Enable plugins**.
|
|
354
|
-
|
|
355
|
-
For a headless daemon, run `paseo daemon status --json` to find its `home`, set the root `pluginsEnabled` field in `<home>/config.json` to `true`, preserve the rest of the file, then apply the change:
|
|
356
|
-
|
|
357
|
-
```sh
|
|
358
|
-
paseo reload --json
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
Paseo requires an absolute path when adding a local plugin. From the repository root, run one of the following commands.
|
|
362
|
-
|
|
363
|
-
PowerShell:
|
|
364
|
-
|
|
365
|
-
```powershell
|
|
366
|
-
paseo plugin add (Resolve-Path .\integrations\paseo).Path
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
macOS/Linux:
|
|
370
|
-
|
|
371
|
-
```sh
|
|
372
|
-
paseo plugin add "$(pwd)/integrations/paseo"
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
Confirm that `alp-provider` is running and that the `alp` provider is available:
|
|
376
|
-
|
|
377
|
-
```sh
|
|
378
|
-
paseo plugin ls
|
|
379
|
-
paseo provider models alp
|
|
380
|
-
```
|
|
381
|
-
|
|
382
|
-
After changing the plugin source, rebuild and reload the installed plugin:
|
|
383
|
-
|
|
384
|
-
```sh
|
|
385
|
-
npm run check
|
|
386
|
-
npm run build:paseo
|
|
387
|
-
paseo plugin reload alp-provider
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
If loading fails, inspect the plugin process output with `paseo plugin logs alp-provider`. A full daemon restart is not required for source changes.
|
|
391
|
-
|
|
392
|
-
### Phở and Cafe
|
|
393
|
-
|
|
394
|
-
New projects default to Phở: main works directly or delegates to peer. Cafe
|
|
395
|
-
keeps main as supervisor while lead implements or delegates. In both, main runs on
|
|
396
|
-
Opus 5.5 with high effort and full access, and starts a supervisor on Sonnet 5
|
|
397
|
-
that reviews its process after each turn and asks main about mistakes; main records
|
|
398
|
-
lessons it follows in later sessions. Main can distill recurring lessons into a
|
|
399
|
-
skill for the roles it chooses, and open or comment on GitHub issues of the
|
|
400
|
-
project or of ALP; the user approves each skill and each post first. Both use read-only oracle/reviewer. Phở and Cafe
|
|
401
|
-
are ALP's built-in teams; you can make your own, with its own main, members,
|
|
402
|
-
delegation and house rules ([teams](docs/alp/agent-library.md#teams)). Select the
|
|
403
|
-
team in the Paseo model picker, with `alp run --team`, or in
|
|
404
|
-
`.alp/settings.json` → `workflow.mode`; `alp teams` lists them. The default concurrent peer limit is 2;
|
|
405
|
-
raise `workflow.maxPeers` only at the user's request. Writers in the shared checkout
|
|
406
|
-
run one at a time, across all sessions; writing peers can run in parallel in their own
|
|
407
|
-
git worktrees (`isolation: "worktree"`) and are merged with `alp_merge`. Oracle runs
|
|
408
|
-
on Fable (`claude:claude-fable-5-1`) or Astra (`codex:gpt-6-astra`); main may ask
|
|
409
|
-
both in parallel for two opinions. Runtime catalog and available plan/usage snapshots
|
|
410
|
-
inform coordination. See [team configuration and migration](docs/alp/team-workflow.md).
|
|
411
|
-
|
|
412
|
-
## Modular monorepo development
|
|
413
|
-
|
|
414
|
-
ALP is organized into npm workspaces for protocol, core, runtime, daemon, client, CLI, a reserved TUI, and the Paseo integration. See [package boundaries, build/test/release commands and the Rust migration seam](docs/modular-monorepo.md). Existing commands and checkout entry points remain compatible.
|
|
13
|
+
If `alp` says the executable for this machine is not installed, npm skipped optional
|
|
14
|
+
dependencies (`--omit=optional`): reinstall with `--include=optional`, or install the executable
|
|
15
|
+
directly from [GitHub Releases](https://github.com/phucanh08/alp/releases) with `install.sh`
|
|
16
|
+
(`install.ps1` on Windows). Update an npm install with npm (`npm install -g @anhlp/alp@beta`);
|
|
17
|
+
`alp update` updates only an executable installed from GitHub Releases.
|
|
415
18
|
|
|
416
|
-
|
|
19
|
+
The libraries (`@anhlp/alp-core`, `-protocol`, `-runtime`, `-client`, `-daemon`, `-cli`) and the
|
|
20
|
+
Paseo plugin (`@anhlp/alp-paseo`) stay JavaScript packages.
|
|
417
21
|
|
|
418
|
-
|
|
22
|
+
Apache-2.0; see LICENSE and NOTICE.
|
package/bin/alp.js
ADDED
package/lib/launcher.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// The `alp` command of the npm package @anhlp/alp (t-cd7f): a launcher, not ALP itself. npm installs
|
|
2
|
+
// the ALP executable for this machine as one optional dependency, @anhlp/alp-<os>-<arch>; this file
|
|
3
|
+
// finds it and runs it with the same arguments, stdio, exit code and signal. Plain Node, no
|
|
4
|
+
// dependencies, no postinstall download.
|
|
5
|
+
import { spawn } from 'node:child_process';
|
|
6
|
+
import { existsSync } from 'node:fs';
|
|
7
|
+
import { createRequire } from 'node:module';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
|
|
10
|
+
export const RELEASES_URL = 'https://github.com/phucanh08/alp/releases';
|
|
11
|
+
export const INSTALL_SH = 'curl -fsSL https://github.com/phucanh08/alp/releases/latest/download/install.sh | sh';
|
|
12
|
+
|
|
13
|
+
/** The platform packages, keyed by `${process.platform}-${process.arch}`. Linux builds are glibc only. */
|
|
14
|
+
export const PLATFORM_PACKAGES = Object.freeze({
|
|
15
|
+
'darwin-arm64': '@anhlp/alp-darwin-arm64',
|
|
16
|
+
'darwin-x64': '@anhlp/alp-darwin-x64',
|
|
17
|
+
'linux-x64': '@anhlp/alp-linux-x64',
|
|
18
|
+
'linux-arm64': '@anhlp/alp-linux-arm64',
|
|
19
|
+
'win32-x64': '@anhlp/alp-win32-x64',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
/** Whether this Linux runs glibc (Node reports its runtime glibc version; musl reports none). */
|
|
23
|
+
export function isGlibc(report = () => process.report?.getReport?.()) {
|
|
24
|
+
try { return Boolean(/** @type {any} */ (report())?.header?.glibcVersionRuntime); } catch { return false; }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The platform package for a machine, or why there is none.
|
|
29
|
+
* @param {{ platform?: string, arch?: string, glibc?: () => boolean }} [machine]
|
|
30
|
+
* @returns {{ name: string, executable: string } | { error: string }}
|
|
31
|
+
*/
|
|
32
|
+
export function platformPackage({ platform = process.platform, arch = process.arch, glibc = isGlibc } = {}) {
|
|
33
|
+
const key = `${platform}-${arch}`;
|
|
34
|
+
const name = PLATFORM_PACKAGES[key];
|
|
35
|
+
if (!name) return { error: `ALP has no build for ${key}; supported: ${Object.keys(PLATFORM_PACKAGES).join(', ')}.` };
|
|
36
|
+
if (platform === 'linux' && !glibc()) return { error: `ALP's Linux builds need glibc; this ${key} system uses another C library (musl, as on Alpine).` };
|
|
37
|
+
return { name, executable: platform === 'win32' ? 'alp.exe' : 'alp' };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The ALP executable installed beside this package, or an error message for the user.
|
|
42
|
+
* @param {{ platform?: string, arch?: string, glibc?: () => boolean, resolve?: (request: string) => string, exists?: (file: string) => boolean }} [options]
|
|
43
|
+
* @returns {{ binary: string, name: string } | { error: string }}
|
|
44
|
+
*/
|
|
45
|
+
export function findBinary({ resolve = createRequire(import.meta.url).resolve, exists = existsSync, ...machine } = {}) {
|
|
46
|
+
const wanted = platformPackage(machine);
|
|
47
|
+
// No executable exists for this machine: only the JavaScript CLI can run here.
|
|
48
|
+
if ('error' in wanted) return { error: `alp: ${wanted.error}\nRun the JavaScript CLI instead (Node 22.12 or later; it also provides \`alp\`): npm uninstall -g @anhlp/alp && npm install -g @anhlp/alp-cli@beta\n(${RELEASES_URL})` };
|
|
49
|
+
let manifest;
|
|
50
|
+
try { manifest = resolve(`${wanted.name}/package.json`); } catch {
|
|
51
|
+
return { error: missingMessage(`${wanted.name}, the ALP executable for this machine, is not installed (npm skips optional dependencies with --omit=optional or --no-optional).`) };
|
|
52
|
+
}
|
|
53
|
+
const binary = path.join(path.dirname(manifest), 'bin', wanted.executable);
|
|
54
|
+
if (!exists(binary)) return { error: missingMessage(`${wanted.name} is installed but has no ${path.join('bin', wanted.executable)}; reinstall it.`) };
|
|
55
|
+
return { binary, name: wanted.name };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** @param {string} reason */
|
|
59
|
+
export function missingMessage(reason) {
|
|
60
|
+
return [
|
|
61
|
+
`alp: ${reason}`,
|
|
62
|
+
'Reinstall with optional dependencies: npm install -g @anhlp/alp@beta --include=optional',
|
|
63
|
+
`Or install the ALP executable directly: ${INSTALL_SH}`,
|
|
64
|
+
`(Windows: install.ps1; every build: ${RELEASES_URL})`,
|
|
65
|
+
].join('\n');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Whether a terminal is attached (any of stdin, stdout, stderr): its keyboard signals reach the whole foreground group. */
|
|
69
|
+
export const onTerminal = (proc = process) => Boolean(proc.stdin?.isTTY || proc.stdout?.isTTY || proc.stderr?.isTTY);
|
|
70
|
+
|
|
71
|
+
/** Signals the launcher outlives so the executable decides what they mean. */
|
|
72
|
+
const HANDLED = ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT', 'SIGBREAK', 'SIGUSR1', 'SIGUSR2'];
|
|
73
|
+
/** The terminal's keyboard signals: a terminal sends them to the whole foreground process group, the executable included. */
|
|
74
|
+
const KEYBOARD = new Set(['SIGINT', 'SIGQUIT', 'SIGBREAK']);
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Whether a signal the launcher received must be passed on. Signals sent to the launcher alone
|
|
78
|
+
* (kill <pid>, a supervisor) are. The terminal's Ctrl-C/Ctrl-\ already reached the executable, so
|
|
79
|
+
* passing it on would deliver it twice. On Windows the console delivers Ctrl-C/Ctrl-Break to every
|
|
80
|
+
* process attached to it, and kill() there only terminates, so nothing is passed on.
|
|
81
|
+
*/
|
|
82
|
+
export function forwards(signal, { platform = process.platform, tty = onTerminal() } = {}) {
|
|
83
|
+
if (platform === 'win32') return false;
|
|
84
|
+
return !(KEYBOARD.has(signal) && tty);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Runs `binary` with `args` and inherited stdio. Resolves with how it ended: `{ code }` or `{ signal }`.
|
|
89
|
+
* The launcher stays alive on the signals it handles and passes them on as `forwards` says; the
|
|
90
|
+
* executable decides what they mean, and the launcher only reports how it ended.
|
|
91
|
+
* @param {string} binary @param {string[]} args
|
|
92
|
+
* @param {{ spawn?: typeof spawn, process?: NodeJS.Process, platform?: string, tty?: boolean }} [options]
|
|
93
|
+
* @returns {Promise<{ code: number } | { signal: NodeJS.Signals }>}
|
|
94
|
+
*/
|
|
95
|
+
export function run(binary, args, { spawn: start = spawn, process: proc = process, platform = process.platform, tty = onTerminal() } = {}) {
|
|
96
|
+
return new Promise(resolve => {
|
|
97
|
+
const child = start(binary, args, { stdio: 'inherit', windowsHide: false });
|
|
98
|
+
let started = false;
|
|
99
|
+
child.once('spawn', () => { started = true; });
|
|
100
|
+
const handlers = new Map();
|
|
101
|
+
const release = () => { for (const [signal, handler] of handlers) proc.removeListener(signal, handler); };
|
|
102
|
+
for (const signal of HANDLED) {
|
|
103
|
+
const handler = () => { if (forwards(signal, { platform, tty })) try { child.kill(signal); } catch {} };
|
|
104
|
+
try { proc.on(signal, handler); handlers.set(signal, handler); } catch {}
|
|
105
|
+
}
|
|
106
|
+
child.on('error', error => {
|
|
107
|
+
// After the executable started, an error (a failed kill) changes nothing: its exit decides.
|
|
108
|
+
if (started) return;
|
|
109
|
+
release();
|
|
110
|
+
proc.stderr.write(`alp: could not run ${binary}: ${error.message}\n${missingMessage('the ALP executable could not start.')}\n`);
|
|
111
|
+
resolve({ code: 1 });
|
|
112
|
+
});
|
|
113
|
+
child.once('exit', (code, signal) => {
|
|
114
|
+
release();
|
|
115
|
+
resolve(signal ? { signal } : { code: code ?? 1 });
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** The launcher's main: find the executable, run it, end as it ended. */
|
|
121
|
+
export async function main(args = process.argv.slice(2)) {
|
|
122
|
+
const found = findBinary();
|
|
123
|
+
if ('error' in found) {
|
|
124
|
+
process.stderr.write(`${found.error}\n`);
|
|
125
|
+
process.exitCode = 1;
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const end = await run(found.binary, args);
|
|
129
|
+
if ('signal' in end) {
|
|
130
|
+
// End by the same signal, so a shell sees what the child saw; exit 128+n if it does not kill us.
|
|
131
|
+
try { process.kill(process.pid, end.signal); } catch {}
|
|
132
|
+
const number = (await import('node:os')).constants.signals[end.signal] ?? 0;
|
|
133
|
+
process.exit(128 + number);
|
|
134
|
+
}
|
|
135
|
+
process.exit(end.code);
|
|
136
|
+
}
|