@anhlp/alp 0.0.1-beta.3 → 0.0.1-beta.4

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.
Files changed (54) hide show
  1. package/README.md +18 -16
  2. package/dist/acp.js +37 -4
  3. package/dist/alpd.js +10350 -3346
  4. package/docs/modular-monorepo.md +17 -13
  5. package/package.json +8 -6
  6. package/packages/cli/dist/THIRD-PARTY-NOTICES.txt +25 -0
  7. package/packages/cli/dist/acp/main.js +1 -1
  8. package/packages/cli/dist/acp.js +37 -4
  9. package/packages/cli/dist/alp-web/THIRD-PARTY-NOTICES.txt +2590 -0
  10. package/packages/cli/dist/alp-web/alp-boundary.json +15 -0
  11. package/packages/cli/dist/alp-web/apple-touch-icon.png +0 -0
  12. package/packages/cli/dist/alp-web/assets/TerminalPanel-DLuoa74B.css +1 -0
  13. package/packages/cli/dist/alp-web/assets/TerminalPanel-PrU2l3u5.js +16 -0
  14. package/packages/cli/dist/alp-web/assets/index-BJdBTDFX.css +1 -0
  15. package/packages/cli/dist/alp-web/assets/index-DpfiPv5s.js +52 -0
  16. package/packages/cli/dist/alp-web/favicon-attention.svg +6 -0
  17. package/packages/cli/dist/alp-web/favicon-running.svg +6 -0
  18. package/packages/cli/dist/alp-web/favicon.svg +5 -0
  19. package/packages/cli/dist/alp-web/index.html +20 -0
  20. package/packages/cli/dist/alp-web.js +9640 -0
  21. package/packages/cli/dist/alpd.js +10350 -3346
  22. package/packages/cli/dist/backup.js +2 -2
  23. package/packages/cli/dist/build-manifest.json +99 -1
  24. package/packages/cli/dist/cli.js +4 -2
  25. package/packages/cli/dist/interfaces.d.ts +9 -1
  26. package/packages/cli/dist/interfaces.js +99 -39
  27. package/packages/cli/dist/schedules.d.ts +2 -0
  28. package/packages/cli/dist/schedules.js +45 -0
  29. package/packages/cli/dist/sessions.d.ts +3 -1
  30. package/packages/cli/dist/sessions.js +22 -11
  31. package/packages/cli/dist/terminal.d.ts +8 -0
  32. package/packages/cli/dist/terminal.js +79 -0
  33. package/packages/cli/dist/usage.d.ts +1 -1
  34. package/packages/cli/dist/usage.js +8 -2
  35. package/packages/cli/dist/web-service.d.ts +38 -0
  36. package/packages/cli/dist/web-service.js +119 -0
  37. package/packages/client/README.md +6 -1
  38. package/packages/client/dist/index.d.ts +37 -2
  39. package/packages/client/dist/index.js +55 -22
  40. package/packages/client/dist/integration-lock.d.ts +35 -0
  41. package/packages/client/dist/integration-lock.js +179 -0
  42. package/packages/client/dist/portable.d.ts +1 -0
  43. package/packages/client/dist/portable.js +7 -1
  44. package/packages/client/dist/rpc/registry.d.ts +211 -0
  45. package/packages/client/dist/rpc/registry.js +145 -0
  46. package/packages/client/dist/supervise.d.ts +2 -0
  47. package/packages/client/dist/supervise.js +4 -4
  48. package/packages/core/dist/backup.js +103 -4
  49. package/packages/core/dist/index.d.ts +1 -0
  50. package/packages/core/dist/index.js +2 -0
  51. package/packages/core/dist/migrations.js +1 -1
  52. package/packages/core/dist/user-worktree.d.ts +29 -0
  53. package/packages/core/dist/user-worktree.js +242 -0
  54. package/packages/core/dist/validation.js +3 -2
package/README.md CHANGED
@@ -201,6 +201,7 @@ alp ps [--all] # live sessions as a tree; --all adds closed ones
201
201
  alp top [session] # live dashboard: who runs, who waits, questions, worktrees, leases
202
202
  alp attach <session> # follow a running tree, or print a closed one
203
203
  alp send <session> "More context" # resumes a closed root first; to an agent, mail from you
204
+ alp send <live-session> --prompt "Continue with this instruction" # explicit new prompt, including a recovery child
204
205
  alp questions # questions agents asked you
205
206
  alp answer <question> "Your answer" # or: --dismiss [--reason R]
206
207
  alp log <session> # delegations, mail, handoffs, worktrees, pins and questions of a tree
@@ -215,6 +216,8 @@ alp resume [codex|claude] # parked assignments continue
215
216
  alp interrupt <session>
216
217
  ```
217
218
 
219
+ `alp send <child> --prompt <text>` explicitly prompts an existing live child and follows only its output. An active turn refuses this new prompt; default root send keeps its steering behavior. It does not replay the saved recovery continuation; supply the instruction you want it to follow. Existing queued mail is consumed by the ordinary runtime once. The existing runtime prompt rules remain authoritative; this command does not lift provider pauses. Default child `alp send` remains user mail and does not unpark manual recovery. `alp resume` only continues sessions parked for the matching provider or global pause; manual and legacy recovery need an explicit prompt.
220
+
218
221
  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
222
 
220
223
  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.
@@ -258,36 +261,35 @@ Finished assignments stay recallable for 14 days: main, or the agent that assign
258
261
 
259
262
  ## The web app
260
263
 
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:
264
+ `alp web` opens ALP's own web app (`apps/web`) on this machine. It ships in the CLI (`@anhlp/alp`, `@anhlp/alp-cli`); you do not need Paseo or its plugin:
262
265
 
263
266
  ```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 # starts the alp-web service if needed and opens its address with its access token
267
268
  alp web --print # prints the address instead
269
+ alp web rotate # replaces the access token; open pages lose access
268
270
  ```
269
271
 
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:
272
+ `alp web` runs the `alp-web` service: one listener on `127.0.0.1` at `web.port` (default 7433; if it is busy, the next nine ports are tried) that serves the app's files and an embedded ALP gateway. The address is `http://127.0.0.1:<port>/#token=alpgw1.…`. The token is a gateway credential that alp-web keeps in `~/.alp/web/credentials.json`, apart from the standalone `alp-gateway` and its `credential list`. The page takes the token out of the address at once and keeps it only in that tab's session storage, so a reload reconnects and a new tab needs the link again. alp-web keeps alpd running (`ALP_SUPERVISE=0` turns that off) and records its pid, port and token in `~/.alp/web.json`.
271
273
 
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.
274
+ - **What the token may do:** sessions, projects and adding projects (`session.read`/`write`, `project.read`/`write`, `workspace.write`). File reading, attachments, terminals and changing a live session's team are off until you add them: `"web": { "permissions": ["files.read", "attachments.write"] }` in `~/.alp/settings.json`. If one entry is not a permission, alp-web warns and ignores the whole list; an entry that is not a lowercase name with dots (such as `"files-read"`) makes the whole `settings.json` invalid, so both alpd and alp-web ignore all of it (alp-web's `web.port` included, alpd's own settings too) and log `ALP_SETTINGS_INVALID`.
275
+ - **Which projects:** the projects alpd knows, and the folder `alp web` ran in when it started the service, if that folder is an ALP project (it has `.alp/`). New projects are added while alp-web runs; open pages reconnect by themselves.
276
+ - **Settings:** `web.port`, `web.permissions` and `"web": { "enabled": false }` (turns `alp web` off). alp-web reads them when it starts; `alp daemon stop` does not stop it. To apply a change, stop the process whose pid `~/.alp/web.json` names (`kill <pid>` on macOS and Linux, `taskkill /PID <pid>` on Windows), then run `alp web`; `alp web rotate` also restarts it, with a new token.
277
+ - **Coming from the Paseo-based `alp web`:** the first `alp web` stops the old Paseo integration if it still holds `integrations/web.lock` (only when it is provably your process from this boot) and copies its token and server id to `~/.alp/paseo.json`, unless that file exists, so paired devices keep working.
278
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).
279
+ The app's features and limits: [docs/alp/web.md](docs/alp/web.md). macOS is the primary platform. `alp web` is untested on Windows: CI runs its tests on Linux and macOS only (a Windows trial found credential-file writes failing now and then with `EPERM`). On Windows, `alp web rotate` and the upgrade takeover do not stop a running alp-web for you: end the pid in `~/.alp/web.json` (`taskkill /PID <pid>`) first.
280
280
 
281
281
  ### Paseo's app on your phone (experimental)
282
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`):
283
+ The optional `@anhlp/alp-paseo` package is the Paseo plugin and the Paseo integration, which runs as integration `paseo` (`~/.alp/integrations/paseo.lock`, `~/.alp/paseo.json`) on a port the system picks, never `web.port`. It no longer carries Paseo's web app: ALP's patched build of it (`paseo-web/`) was removed once `alp web` served ALP's own app (t-55ce.3). Relay pairing is experimental in the beta and off by default. The integration can reach alpd from [Paseo](https://paseo.sh)'s own app on another device, through Paseo's relay (`relay.paseo.sh`):
284
284
 
285
285
  ```sh
286
+ npm install -g @anhlp/alp-paseo@beta
287
+ alp-paseo-integration --register # register in the selected ALP_HOME (also discoverable on PATH)
286
288
  alp web pair --on # turns the relay on and prints the pairing link
287
289
  alp web pair # the link again; --off turns the relay off
288
290
  ```
289
291
 
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).
292
+ Open the link on the device that runs 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 password `alp web pair` prints (the token in `~/.alp/paseo.json`). 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. `alp-web-integration` remains an alias of `alp-paseo-integration`, and `ALP_WEB_INTEGRATION` of `ALP_PASEO_INTEGRATION`, for one release; a home registered with the old name (`integrations/web.json`) still starts the integration, with a hint to re-register. Details: [ALPD §64](plans/reference/ALPD.md#64-paseos-relay-and-its-app-on-another-device-2026-10-12).
291
293
 
292
294
  ## Antigravity CLI (experimental)
293
295
 
@@ -334,7 +336,7 @@ Details: [ALPD §60](plans/reference/ALPD.md#60-alp-as-an-acp-agent-2026-10-10).
334
336
 
335
337
  ## Paseo
336
338
 
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.
339
+ 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 on `main` declares Paseo `>=0.11.1 <1.0.0`; the published `0.0.1-beta.3` declares `>=0.11.1 <0.13.0`, and `0.0.0-beta.2` and earlier `<0.12.0` (so Paseo 0.12 needs `0.0.1-beta.3` or later, and Paseo 0.13 needs a release after `0.0.1-beta.3`). 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
340
 
339
341
  **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
342
 
@@ -415,4 +417,4 @@ ALP is organized into npm workspaces for protocol, core, runtime, daemon, client
415
417
 
416
418
  ## License
417
419
 
418
- ALP is licensed under the [Apache License 2.0](LICENSE); see [NOTICE](NOTICE). Packages that bundle third-party code ship a `THIRD-PARTY-NOTICES.txt`. The `alp web` app in `@anhlp/alp-paseo` is Paseo's web app (Apache-2.0, © Mohamed Boudra) with ALP's patches; see that package's `NOTICE`. The web app's third-party licences are in `server/dist/web-app/THIRD-PARTY-NOTICES.txt`.
420
+ ALP is licensed under the [Apache License 2.0](LICENSE); see [NOTICE](NOTICE). Packages that bundle third-party code ship a `THIRD-PARTY-NOTICES.txt`. The `alp web` app's third-party licences are in `dist/alp-web/THIRD-PARTY-NOTICES.txt` of `@anhlp/alp-cli` (`packages/cli/dist/alp-web/` in `@anhlp/alp`). `@anhlp/alp-paseo` includes code taken from Paseo (Apache-2.0, © Mohamed Boudra) and ships Paseo's licence as `LICENSE.paseo.txt`; see that package's `NOTICE`. Its bundled third-party licences are in `server/dist/THIRD-PARTY-NOTICES.txt`.
package/dist/acp.js CHANGED
@@ -18552,10 +18552,40 @@ 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", libraryProjectWrite: "library.project.write", settingsLanguage: "settings.language", sessionListPage: "session.list.page", questionWatch: "question.watch", questionWatchTurns: "question.watch.turns", workspaceFiles: "workspace.files", workspaceFilesRead: "workspace.files.read", promptImages: "prompt.images" });
18555
+ var CAPABILITY = Object.freeze({ sessionInterruptTurn: "session.interrupt.turn", attachAfter: "attach.after", sessionHistory: "session.history", workspaceRegistry: "workspace.registry", workspaceWorktree: "workspace.worktree", workspaceGit: "workspace.git", promptReceipts: "prompt.receipts", extensionMethods: "extension.methods", team: "team", task: "task", library: "library", libraryProjectWrite: "library.project.write", settingsLanguage: "settings.language", sessionListPage: "session.list.page", questionWatch: "question.watch", questionWatchTurns: "question.watch.turns", sessionAttention: "session.attention", workspaceFiles: "workspace.files", workspaceFilesRead: "workspace.files.read", promptImages: "prompt.images", schedule: "schedule", attachments: "attachments", sessionFork: "session.fork", sessionRewind: "session.rewind", sessionReload: "session.reload", sessionResumeCommand: "session.resumeCommand", sessionConfigureLive: "session.configure.live", terminal: "terminal" });
18556
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"]);
18557
+ var RPC_METHODS = Object.freeze(["assignment.recall", "attachment.abort", "attachment.begin", "attachment.chunk", "attachment.commit", "attachment.delete", "attachment.get", "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", "project.list", "project.register", "project.remove", "question.answer", "question.list", "question.watch", "registry.owner", "registry.worktree", "schedule.cancel", "schedule.create", "schedule.get", "schedule.list", "session.archive", "session.attach", "session.attention.clear", "session.close", "session.configure", "session.configure.preview", "session.create", "session.fork", "session.get", "session.history", "session.interrupt", "session.list", "session.log", "session.message", "session.preview", "session.prompt", "session.release", "session.reload", "session.rename", "session.resumeCommand", "session.rewind", "session.status", "settings.language.get", "settings.language.set", "task.create", "task.gate.resolve", "task.list", "task.update", "team.list", "terminal.attach", "terminal.close", "terminal.create", "terminal.input", "terminal.list", "terminal.resize", "terminal.revoke", "workspace.files.list", "workspace.files.read", "workspace.files.search", "workspace.get", "workspace.git.diff", "workspace.git.status", "workspace.list", "workspace.update", "workspace.worktree.create", "workspace.worktree.options", "workspace.worktree.remove"]);
18558
18558
  var WORKSPACE_FILES = Object.freeze({ maxReadBytes: 1024 * 1024, maxListEntries: 1e3, maxPathLength: 4096 });
18559
+ var WORKSPACE_GIT = Object.freeze({ maxFileBytes: 1024 * 1024, maxTotalBytes: 2 * 1024 * 1024, maxUntracked: 200, maxStatusFiles: 1e3, maxRefLength: 255 });
18560
+ var ATTACHMENTS = Object.freeze({
18561
+ maxObjectBytes: 20 * 1024 * 1024,
18562
+ maxPerPrompt: 8,
18563
+ maxPromptBytes: 40 * 1024 * 1024,
18564
+ maxChunkBytes: 256 * 1024,
18565
+ maxActiveUploads: 2,
18566
+ maxPrincipalBytes: 200 * 1024 * 1024,
18567
+ maxDaemonBytes: 1024 * 1024 * 1024,
18568
+ uploadTimeoutMs: 60 * 60 * 1e3,
18569
+ unreferencedRetentionMs: 24 * 60 * 60 * 1e3,
18570
+ releasedGraceMs: 7 * 24 * 60 * 60 * 1e3,
18571
+ maxNameBytes: 255
18572
+ });
18573
+ var TERMINAL = Object.freeze({
18574
+ maxPerPrincipal: 4,
18575
+ maxPerDaemon: 16,
18576
+ maxInputBytes: 64 * 1024,
18577
+ maxOutputFrameBytes: 64 * 1024,
18578
+ replayBytes: 1024 * 1024,
18579
+ idleMs: 30 * 60 * 1e3,
18580
+ maxLifetimeMs: 8 * 60 * 60 * 1e3,
18581
+ reconnectMs: 60 * 1e3,
18582
+ minCols: 2,
18583
+ maxCols: 500,
18584
+ minRows: 1,
18585
+ maxRows: 200
18586
+ });
18587
+ var TERMINAL_LIMIT_KEYS = Object.freeze(["maxPerPrincipal", "maxPerDaemon", "maxInputBytes", "maxOutputFrameBytes", "replayBytes", "idleMs", "maxLifetimeMs", "reconnectMs"]);
18588
+ var ATTACHMENT_CHUNK_OVERHEAD = 64 * 1024;
18559
18589
 
18560
18590
  // packages/client/src/rpc/errors.js
18561
18591
  var BRAND = Symbol.for("@anhlp/alp-client/AlpClientError");
@@ -19108,6 +19138,8 @@ function lockAlive(lock) {
19108
19138
  }
19109
19139
  }
19110
19140
  var AlpClient = class extends AlpRpcClient {
19141
+ /** Host features captured by connect's handshake. @type {readonly string[]} */
19142
+ capabilities = [];
19111
19143
  /**
19112
19144
  * @param {import('node:net').Socket} socket a connected or connecting socket; the client owns it
19113
19145
  * @param {import('./rpc/client.js').AlpRpcClientOptions & import('./ipc.js').SocketTransportOptions} [options]
@@ -19133,7 +19165,8 @@ async function openSocket(socketPath) {
19133
19165
  async function connect(socketPath, client = { name: "alp", version: "0" }, options = {}) {
19134
19166
  const connection = new AlpClient(await openSocket(socketPath), options);
19135
19167
  try {
19136
- await hello(connection, client);
19168
+ const greeting = await hello(connection, client);
19169
+ connection.capabilities = Object.freeze(Array.isArray(greeting.capabilities) ? greeting.capabilities.filter((value) => typeof value === "string") : []);
19137
19170
  } catch (error51) {
19138
19171
  connection.close();
19139
19172
  throw error51;
@@ -19886,7 +19919,7 @@ ${item2.text}`;
19886
19919
 
19887
19920
  // packages/cli/src/acp/main.ts
19888
19921
  async function runAcp({ daemonEntry }) {
19889
- const version2 = true ? "0.0.1-beta.3" : "0.0.0";
19922
+ const version2 = true ? "0.0.1-beta.4" : "0.0.0";
19890
19923
  const logger = createLogger({ component: "acp" });
19891
19924
  const log = (message, fields) => logger.warn(message, fields);
19892
19925
  const app = createAcpAgent({