raga-cli 0.9.0 → 0.10.1

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 (46) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +14 -3
  3. package/bundled-skills/bundle.json +9 -9
  4. package/bundled-skills/docs/guide/01-setup.md +1 -1
  5. package/bundled-skills/skills/peak/SKILL.md +1 -1
  6. package/bundled-skills/skills/peak/references/peak-setup/SKILL.md +1 -1
  7. package/bundled-skills/skills/peak/references/raga-runtime/SKILL.md +3 -3
  8. package/bundled-skills/skills/peak/references/raga-runtime/raga_runtime.py +12 -5
  9. package/bundled-skills/skills/raga-artifacts/artifact.mjs +5 -0
  10. package/dist/bundle/chunks/agent-attach-ZCS2QGIU.js +9 -0
  11. package/dist/bundle/chunks/chunk-2VHBGANP.js +1359 -0
  12. package/dist/bundle/chunks/chunk-4OPO7UJ6.js +4 -0
  13. package/dist/bundle/chunks/{chunk-ENUUAC3O.js → chunk-A4342OQJ.js} +9 -9
  14. package/dist/bundle/chunks/{chunk-OPPYO2IE.js → chunk-ABE5B2U7.js} +1 -1
  15. package/dist/bundle/chunks/{chunk-P2QCWBFM.js → chunk-D2SEW6VC.js} +1 -1
  16. package/dist/bundle/chunks/chunk-FTQDEUXY.js +242 -0
  17. package/dist/bundle/chunks/chunk-HRI5E2Y3.js +2 -0
  18. package/dist/bundle/chunks/{chunk-S5J3UB5O.js → chunk-JNHUOSVT.js} +1 -1
  19. package/dist/bundle/chunks/chunk-K22YTJFL.js +3 -0
  20. package/dist/bundle/chunks/chunk-MXJNFS34.js +47 -0
  21. package/dist/bundle/chunks/{chunk-NP6TH6UT.js → chunk-NXGZMUQX.js} +3 -48
  22. package/dist/bundle/chunks/{chunk-JQDZ4Z7L.js → chunk-NYFFOHME.js} +1 -1
  23. package/dist/bundle/chunks/chunk-P2EB6CEF.js +6 -0
  24. package/dist/bundle/chunks/{chunk-KNY3PXQI.js → chunk-SK25JXS4.js} +1 -1
  25. package/dist/bundle/chunks/chunk-ZJUHXUHP.js +2 -0
  26. package/dist/bundle/chunks/{cli-QLDCDYOR.js → cli-XZ774I3U.js} +1 -1
  27. package/dist/bundle/chunks/{easter-egg-3d-NPDBBPPF.js → easter-egg-3d-XWC5XWQO.js} +1 -1
  28. package/dist/bundle/chunks/{execute-WPTMS4XG.js → execute-7BWE4ZV3.js} +1 -1
  29. package/dist/bundle/chunks/runtime-K76CFDG5.js +2 -0
  30. package/dist/bundle/chunks/virtual-modules-3XOMQWV6.js +2 -0
  31. package/dist/bundle/cli-runtime.js +1 -1
  32. package/dist/bundle/index.js +1 -1
  33. package/dist/bundle/raga-runtime.js +1 -1
  34. package/dist/bundle/rpc-entry.js +1 -1
  35. package/docs/cli.md +2 -0
  36. package/package.json +1 -1
  37. package/python/raga_rlm/__init__.py +10 -2
  38. package/schemas/keybindings.schema.json +36 -0
  39. package/schemas/settings.schema.json +60 -1
  40. package/schemas/theme.schema.json +2 -2
  41. package/dist/bundle/chunks/chunk-3MNXTBQ3.js +0 -2
  42. package/dist/bundle/chunks/chunk-F7LFZTHT.js +0 -1591
  43. package/dist/bundle/chunks/chunk-RFPFZTK2.js +0 -7
  44. package/dist/bundle/chunks/chunk-RP2WKNT7.js +0 -4
  45. package/dist/bundle/chunks/runtime-N5MUH2WA.js +0 -2
  46. package/dist/bundle/chunks/virtual-modules-4I6Y6DPQ.js +0 -2
package/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ## [0.10.1](https://github.com/mr-jones123/raga/compare/raga-v0.10.0...raga-v0.10.1) (2026-11-01)
2
+
3
+ ### Bug Fixes
4
+
5
+ * install raga with its own installer instead of pi's ([e7816db](https://github.com/mr-jones123/raga/commit/e7816db595936716a08febd2a5a9ac7d91fcfca2))
6
+
7
+ ## [0.10.0](https://github.com/mr-jones123/raga/compare/raga-v0.9.0...raga-v0.10.0) (2026-11-01)
8
+
9
+ ### Features
10
+
11
+ * assign models to subagent roles with /agent-setup ([937ae97](https://github.com/mr-jones123/raga/commit/937ae97887bae82215579de3966d23886d8e8d15))
12
+ * open subagents as named sessions from /agents in the TUI or Rex panes ([8cba5d3](https://github.com/mr-jones123/raga/commit/8cba5d360d3f9c9ee0d5fd76652ae53c41f04b21))
13
+
14
+ ### Bug Fixes
15
+
16
+ * **artifacts:** keep headless Chrome away from the macOS login keychain ([2c65a35](https://github.com/mr-jones123/raga/commit/2c65a3562a0354cbb20618aac4ddedf919ff08c0))
17
+ * keep Raga updates and user-facing guidance on Raga ([8ff9209](https://github.com/mr-jones123/raga/commit/8ff9209ed94681e1c254a496515dd561e7b58590))
18
+ * pick role models in a full-screen list inside /agent-setup ([df1e642](https://github.com/mr-jones123/raga/commit/df1e64234b170472d18c286140d472717699d916))
19
+ * return partial child work when the turn budget is exhausted ([0383bc1](https://github.com/mr-jones123/raga/commit/0383bc1485b8b039d0d5b9628b8ecc12d680a426))
20
+
1
21
  ## [0.9.0](https://github.com/mr-jones123/raga/compare/raga-v0.8.0...raga-v0.9.0) (2026-10-31)
2
22
 
3
23
  ### Features
package/README.md CHANGED
@@ -27,15 +27,21 @@ The RLM runtime works end to end. The adaptive layer, which lets the harness rew
27
27
  | Goal and metric loop (`--goal`, `--gate`, `--metric`) | Not started |
28
28
  | Native engineering skills (pstack, no-mistakes) | Not started |
29
29
 
30
- The packages still use pi's names (`@earendil-works/pi-*`). The `raga` command keeps its own user directory, `~/.raga/agent`, for logins, settings, sessions, skills, extensions, and packages. Set `RAGA_CODING_AGENT_DIR` to move it. It does not read `~/.pi/agent` or the shared `~/.agents/skills` folder, so an existing pi setup does not carry over. The `pi` command still uses `~/.pi/agent`.
30
+ User-facing commands and messages use Raga branding. The SDK packages retain their upstream names (`@earendil-works/pi-*`); imports, extension APIs, and protocol identifiers are not renamed. The `raga` command keeps its own user directory, `~/.raga/agent`, for logins, settings, sessions, skills, extensions, and packages. Set `RAGA_CODING_AGENT_DIR` to move it. It does not read `~/.pi/agent` or the shared `~/.agents/skills` folder, so an existing pi setup does not carry over. The `pi` command still uses `~/.pi/agent`.
31
31
 
32
32
  ## Run it
33
33
 
34
- Raga needs Node.js 22.19 or newer, `uv`, and an AI provider that pi supports. Install it from npm:
34
+ Raga needs Node.js 22.19 or newer, `uv`, and an AI provider that pi supports. On macOS, Linux, or WSL, the installer sets these up, asks you to log in, and offers to install Bend for the `bend` skill:
35
+
36
+ ```bash
37
+ curl -fsSL https://raw.githubusercontent.com/mr-jones123/raga/main/install.sh | sh
38
+ ```
39
+
40
+ Or install it from npm:
35
41
 
36
42
  ```bash
37
43
  npm install -g raga-cli
38
- raga
44
+ raga --login
39
45
  ```
40
46
 
41
47
  ### Update
@@ -86,6 +92,10 @@ On macOS and Linux, `/local-models` searches Hugging Face, asks before downloadi
86
92
 
87
93
  `/diff` opens a read-only Git review dashboard. Browse changes by category (tests, modules, GitHub workflows, documentation, dependencies, configuration), inspect staged or working-tree changes, or pick a commit from history. Open a file to scroll its diff, and toggle to its full contents without leaving raga. See [docs/DIFF.md](docs/DIFF.md) for controls.
88
94
 
95
+ ## Subagents
96
+
97
+ Each `rlm_query` child is its own named Raga session with its own Python kernel. Run `/agents` to see them in a dashboard (name, state, model, tokens, cost, turns) and open one to read its cells or steer it. Optionally, Rex shows one pane per subagent. Run `/agent-setup` to choose which model each workflow role (such as `arena runners` or `bug-fix`) uses. See [docs/AGENTS.md](docs/AGENTS.md).
98
+
89
99
  ## What the model does in RLM mode
90
100
 
91
101
  The kernel already exists when the model's first turn starts. Each `python` call runs a cell, and variables stay defined for the whole session. The model sees at most `rlm.outputLimit` characters of each cell's output. The full output stays in `cells`.
@@ -132,6 +142,7 @@ print(counts.most_common(5))
132
142
  |---|---|
133
143
  | [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | How the pi base works and where raga's layers attach. |
134
144
  | [docs/RLM.md](docs/RLM.md) | The RLM runtime reference. |
145
+ | [docs/AGENTS.md](docs/AGENTS.md) | Subagent sessions, the `/agents` dashboard, and Rex panes. |
135
146
  | [docs/PROGRESS.md](docs/PROGRESS.md) | Milestones, status, and decisions. |
136
147
  | [docs/BENCHMARKS.md](docs/BENCHMARKS.md) | Benchmark tasks and results. |
137
148
  | [docs/LOCAL-MODELS.md](docs/LOCAL-MODELS.md) | Search, download, and run local Hugging Face models with llama.cpp or MLX. |
@@ -105,7 +105,7 @@
105
105
  },
106
106
  {
107
107
  "path": "docs/guide/01-setup.md",
108
- "sha256": "56e67d324cc46c3bde1cc6c909e8b627ab11c6fdc31e0e9e8b38c38aad3f8037",
108
+ "sha256": "dc1bf7425558e5bb5a8d464f55b6dea40825aab1821fd6493cd44682bb2e1f94",
109
109
  "source": "pstack/docs/guide/01-setup.md",
110
110
  "sourceSha256": "384655bdecc713122ca69a485723c58462002a1d512415e94e48597d0dce2fa5",
111
111
  "adaptation": "raga native setup guide"
@@ -679,7 +679,7 @@
679
679
  },
680
680
  {
681
681
  "path": "skills/peak/references/peak-setup/SKILL.md",
682
- "sha256": "f2989def1dc7f2112e8583de961d8865f20fd6333cacab05f9a64ee0399c7681",
682
+ "sha256": "5015abcbbb917dd931b131ec107c8b27b1264990db3f556967446b6c61b2445b",
683
683
  "source": "pstack/skills/setup-pstack/SKILL.md",
684
684
  "sourceSha256": "b45512f6ca5e96e81681984683b7472bfe892581da3a89a73cca4159438f29ed",
685
685
  "adaptation": "raga execution adaptation of skills/peak/references/peak-setup/SKILL.md"
@@ -882,16 +882,16 @@
882
882
  },
883
883
  {
884
884
  "path": "skills/peak/references/raga-runtime/raga_runtime.py",
885
- "sha256": "bb2d22512d55f9acf9e2480efc6aa55f8e28ccd3d9a8e98f5c14a1ee591f7538",
885
+ "sha256": "aee7412788daf1b7114f8d9fe96051ef4db7aa9cd43443319a68425c3467045e",
886
886
  "source": "raga native Python adapter",
887
- "sourceSha256": "bb2d22512d55f9acf9e2480efc6aa55f8e28ccd3d9a8e98f5c14a1ee591f7538",
887
+ "sourceSha256": "aee7412788daf1b7114f8d9fe96051ef4db7aa9cd43443319a68425c3467045e",
888
888
  "adaptation": "raga native Python adapter"
889
889
  },
890
890
  {
891
891
  "path": "skills/peak/references/raga-runtime/SKILL.md",
892
- "sha256": "5249166b9afe12ecd202971f5dba602b1a0826b6089b5630488cfda510de0440",
892
+ "sha256": "53a3f75e3611316a3e1a6f402989dc89ef309bc511fa624dacdf5266ef3279c7",
893
893
  "source": "raga native adaptation",
894
- "sourceSha256": "5249166b9afe12ecd202971f5dba602b1a0826b6089b5630488cfda510de0440",
894
+ "sourceSha256": "53a3f75e3611316a3e1a6f402989dc89ef309bc511fa624dacdf5266ef3279c7",
895
895
  "adaptation": "raga native adaptation"
896
896
  },
897
897
  {
@@ -1414,7 +1414,7 @@
1414
1414
  },
1415
1415
  {
1416
1416
  "path": "skills/peak/SKILL.md",
1417
- "sha256": "f3feb010706f5e125ef7b95059c1c939bf86c366ffc62f3b5d50faba3e864e94",
1417
+ "sha256": "b8062baa06a1e870f988b155b16f82b8cac383e31085b1370431c84d6c29b662",
1418
1418
  "source": "pstack/skills/poteto-mode/SKILL.md",
1419
1419
  "sourceSha256": "2755f102e7a6d0496b429d1031a22fb353e1f3d523543367caeaae5c4ed6f544",
1420
1420
  "adaptation": "raga native delegation policy"
@@ -1428,9 +1428,9 @@
1428
1428
  },
1429
1429
  {
1430
1430
  "path": "skills/raga-artifacts/artifact.mjs",
1431
- "sha256": "a1affbf90bedc1809654b715d746ee2691de896043b919222d3cb35dd5369cc1",
1431
+ "sha256": "e1ac1f55af91b00dc8c542d80a9dc536868cb7d909aa5b42c606e4d76ad09535",
1432
1432
  "source": "raga native adaptation",
1433
- "sourceSha256": "a1affbf90bedc1809654b715d746ee2691de896043b919222d3cb35dd5369cc1",
1433
+ "sourceSha256": "e1ac1f55af91b00dc8c542d80a9dc536868cb7d909aa5b42c606e4d76ad09535",
1434
1434
  "adaptation": "raga native adaptation"
1435
1435
  },
1436
1436
  {
@@ -1,3 +1,3 @@
1
1
  # Set up the bundled workflows
2
2
 
3
- Every initialized instance already contains this pinned portable bundle. There is no plugin installation step. Read [the native runtime](../../skills/peak/references/raga-runtime/SKILL.md), then [configure model roles](../../skills/peak/references/peak-setup/SKILL.md) through a candidate revision. A null role inherits the session model. Verify available tools with capability_report before choosing a terminal, browser, or formal-verification workflow. Optional integrations require explicit setup. Start with /skill:peak and a goal with observable acceptance criteria.
3
+ Every initialized instance already contains this pinned portable bundle. There is no plugin installation step. Read [the native runtime](../../skills/peak/references/raga-runtime/SKILL.md), then assign models to roles: run `/agent-setup` in an ordinary session, or [configure model roles](../../skills/peak/references/peak-setup/SKILL.md) through a candidate revision in an instance session. A null role inherits the session model. Verify available tools with capability_report before choosing a terminal, browser, or formal-verification workflow. Optional integrations require explicit setup. Start with /skill:peak and a goal with observable acceptance criteria.
@@ -127,7 +127,7 @@ Peak, `bend`, and `raga-artifacts` are the installed skills. `bend` handles Bend
127
127
 
128
128
  **Use `spec: "poteto-agent"` for any subagent you spawn inside a playbook step** (code-writing delegates, ad-hoc helpers). The chat that receives `/peak` runs the playbook. Never spawn a `poteto-agent` to run the playbook itself. Routed workflow references (`how`, `why`, `interrogate`, `reflect`, `swarm`) choose a native specification and configured model for review. Respect what the reference prescribes, don't override to `poteto-agent`.
129
129
 
130
- **Defaults for every run_child call.** Use the pinned resource root and one of worker, poteto-agent, or comment-sicko. Read-only reviewers use read_only=True. Writing children use read_only=False, details=True. Run independent calls with asyncio.gather. Select models from agents/model-roles.json. Null inherits the parent. Same-family seats are not model-diverse.
130
+ **Defaults for every run_child call.** Use the pinned resource root and one of worker, poteto-agent, or comment-sicko. Read-only reviewers use read_only=True. Writing children use read_only=False, details=True. Run independent calls with asyncio.gather. Select models by role with run_child(..., role=..., seat=...) and agent_roles(); see raga-runtime. Null inherits the parent. Same-family seats are not model-diverse.
131
131
 
132
132
  **Match the model to the job.** Use real configured provider/model selectors. The runtime does not accept separate effort, speed, cloud environment, or resume fields. Include each seat's configured selector in its assignment. Report an unavailable selector rather than substitute another model.
133
133
 
@@ -3,7 +3,7 @@ name: peak-setup
3
3
  description: Configure real native model selectors for the bundled engineering workflows through a candidate harness revision.
4
4
  ---
5
5
 
6
- Read [the native Python adapter](../raga-runtime/SKILL.md) before executing this workflow. Authoring targets candidate revisions. Children use run_child, not an external agent service.
6
+ Read [the native Python adapter](../raga-runtime/SKILL.md) before executing this workflow. Call `harness_mode()` first. In an ordinary session, model roles are user settings: ask the user to run the `/agent-setup` command, which lists available models, sets the reasoning budget, and assigns each role and panel seat. Do not edit settings files yourself. The rest of this workflow is for instance sessions. Authoring targets candidate revisions. Children use run_child, not an external agent service.
7
7
 
8
8
  # Configure native model roles
9
9
 
@@ -12,7 +12,7 @@ Use the Python tool. It owns one persistent kernel per session. Load this adapte
12
12
 
13
13
  `await context.history(offset=0, limit=None)` reads only this session's history. Use explicitly provided current-instance records for historical research. Never scan another project's home or transcripts. `await llm_query(prompt, system=None, model=None)` is a one-shot model call. `await llm_batch(prompts, system=None, model=None)` runs independent one-shot calls.
14
14
 
15
- Load `raga_runtime.py` beside this skill with `exec(await read(absolute_helper_path), globals())`, then call `await run_child(spec, task, resource_root, context_data=None, model=None, max_turns=None, read_only=True, details=False)`. Independent calls run with `await asyncio.gather(...)`. A context value is data, never a permission grant.
15
+ Load `raga_runtime.py` beside this skill with `exec(await read(absolute_helper_path), globals())`, then call `await run_child(spec, task, resource_root, context_data=None, model=None, max_turns=None, read_only=True, details=False, role=None, seat=None)`. Independent calls run with `await asyncio.gather(...)`. A context value is data, never a permission grant.
16
16
 
17
17
  ## Pick the session mode first
18
18
 
@@ -28,11 +28,11 @@ In an ordinary session, the resource root is the `bundled-skills` directory thre
28
28
  - `instance` and `memory` calls do not exist. Candidate authoring, child patches, integration workspaces, instance memory, and no-mistakes need instance mode. Skip those steps and report them as unavailable in ordinary mode.
29
29
  - Commit, branch, and push only when the user asks. Preserve unrelated changes in the shared checkout.
30
30
 
31
- Child specifications are in `../../../agents/`. `poteto-agent` carries the engineering style. `comment-sicko` reviews comments. `worker` handles general tasks. Model selectors are real provider/model strings from the configured registry. `None` inherits the parent. Role settings live in `agents/model-roles.json` in a candidate revision. When different review seats resolve to the same family, report that the review is not model-diverse. Do not invent aliases or silently replace a rejected model.
31
+ Child specifications are in `../../../agents/`. `poteto-agent` carries the engineering style. `comment-sicko` reviews comments. `worker` handles general tasks. Model selectors are real provider/model strings from the configured registry. `None` inherits the parent. Roles pick models: `await agent_roles()` returns the table children resolve against, which is the user's `/agent-setup` choices in an ordinary session and the pinned revision's `agents/model-roles.json` in an instance session. Wherever a workflow says to take a model from a line of `agents/model-roles.json`, read that line from `agent_roles()` instead and launch each seat with `run_child(..., role=line, seat=i)`, omitting `seat` for a single-value role and leaving `model` unset. The host applies the assigned model and reasoning budget. A panel role's list length sets how many seats to run. When different review seats resolve to the same family, report that the review is not model-diverse. Do not invent aliases or silently replace a rejected model.
32
32
 
33
33
  `answer['content']` and `answer['ready'] = True` return a child result. The native `rlm_query` API returns text by default. `details=True` returns the supervisor's workspace and change evidence. Never promise a worktree from a plain text answer.
34
34
 
35
- Only the documented run_child parameters are supported. Inherited spec labels select one of the three native specifications. Tool-schema, environment, cloud branch, background, resume, effort, and file-attachment fields from other agents are not launch arguments. Read-only review does not remove ordinary sandboxed inspection tools. Configure real model selectors in agents/model-roles.json. Null inherits. A rejected selector is a prerequisite failure, never permission to choose an unapproved substitute.
35
+ Only the documented run_child parameters are supported. Inherited spec labels select one of the three native specifications. Tool-schema, environment, cloud branch, background, resume, effort, and file-attachment fields from other agents are not launch arguments. Read-only review does not remove ordinary sandboxed inspection tools. Users assign models with `/agent-setup` in ordinary sessions, or a candidate revision of agents/model-roles.json in instance sessions. Null inherits. A rejected selector is a prerequisite failure, never permission to choose an unapproved substitute.
36
36
 
37
37
  In instance mode, use `await instance.child_patch(workspace_id)` to collect a child's owned change and patch. Use `await instance.integrate(workspace_ids, command, args, timeout_ms=120000)` for one supervisor-owned integration workspace and combined verification after each merge. Inspect its accepted result and returned patch before applying changes to the root workspace. Do not create or remove Git worktrees from worker shell commands. Git administration is deliberately hidden. Portable prose that requests branches or worktrees means these supervisor APIs, not raw Git worktree mutation.
38
38
 
@@ -11,7 +11,13 @@ def harness_mode():
11
11
  return "instance" if os.environ.get("RAGA_INSTANCE_ID") else "ordinary"
12
12
 
13
13
 
14
- async def run_child(spec, task, resource_root, context_data=None, model=None, max_turns=None, read_only=True, details=False):
14
+ async def agent_roles():
15
+ """Role table children resolve against: /agent-setup choices in ordinary sessions, the pinned agents/model-roles.json in instance sessions."""
16
+ from raga_rlm import host_request
17
+ return await host_request({"type": "agent.roles"})
18
+
19
+
20
+ async def run_child(spec, task, resource_root, context_data=None, model=None, max_turns=None, read_only=True, details=False, role=None, seat=None):
15
21
  if spec not in ("worker", "poteto-agent", "comment-sicko"):
16
22
  raise ValueError("Unknown bundled child specification")
17
23
  if not read_only and not details:
@@ -28,12 +34,13 @@ async def run_child(spec, task, resource_root, context_data=None, model=None, ma
28
34
  for name in definition["skills"]:
29
35
  path = root + ("/skills/peak/SKILL.md" if name == "peak" else "/skills/peak/references/" + name + "/SKILL.md")
30
36
  instructions += "\n\n" + await read(path)
31
- roles = json.loads(await read(root + "/agents/model-roles.json"))
32
- if model is None:
33
- model = roles.get(definition["modelRole"])
37
+ if model is None and role is None:
38
+ role = definition["modelRole"]
34
39
  notice = "\n\n" + ORDINARY_READ_ONLY if ordinary else ""
35
40
  prompt = instructions + "\n\nPinned resource root: " + root + notice + "\n\n# Assignment\n" + task
36
- return await rlm_query(prompt, context=context_data, model=model, max_turns=max_turns, read_only=read_only, details=details)
41
+ if model is not None:
42
+ role, seat = None, None
43
+ return await rlm_query(prompt, context=context_data, model=model, max_turns=max_turns, read_only=read_only, details=details, role=role, seat=seat)
37
44
 
38
45
  async def capability_report():
39
46
  commands = {
@@ -79,6 +79,11 @@ function chromeProcess(chrome, htmlPath, extraArgs) {
79
79
  "--no-first-run",
80
80
  "--no-default-browser-check",
81
81
  "--disable-extensions",
82
+ // Without these, macOS Chrome asks the login keychain for "Chrome Safe Storage" even in a throwaway profile.
83
+ "--use-mock-keychain",
84
+ "--password-store=basic",
85
+ "--disable-sync",
86
+ "--disable-background-networking",
82
87
  `--user-data-dir=${profile}`,
83
88
  "--virtual-time-budget=5000",
84
89
  ...extraArgs,
@@ -0,0 +1,9 @@
1
+ import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
+ import{AssistantMessageComponent,BashExecutionComponent,BranchSummaryMessageComponent,CHILD_AGENT_PROTOCOL_VERSION,CompactionSummaryMessageComponent,CustomEditor,CustomMessageComponent,FORWARDED_CHILD_AGENT_EVENTS,KeybindingsManager,SettingsManager,ToolExecutionComponent,UserMessageComponent,createChatViewport,createInteractiveTui,formatTokens,requestTerminalColors,withBuiltInRenderers}from"./chunk-FTQDEUXY.js";import"./chunk-NXGZMUQX.js";import{Container,SYSTEM_THEME_NAME,Spacer,TruncatedText,VStack,getEditorTheme,getMarkdownTheme,getTerminalTheme,initTheme,isViewportTUI,markTerminalColorsPending,resolveThemeSetting,setCapabilityOverrides,setKeybindings,setTerminalColors,setTheme,theme,truncateToWidth}from"./chunk-A4342OQJ.js";import"./chunk-5AGIVGSV.js";import"./chunk-HRI5E2Y3.js";import"./chunk-K22YTJFL.js";import"./chunk-D2SEW6VC.js";import"./chunk-6QGV3IWD.js";import{getAgentDir}from"./chunk-SK25JXS4.js";import"./chunk-JXWJOIH4.js";import{createConnection}from"node:net";import{stripVTControlCharacters}from"node:util";var AGENT_ATTACH_USAGE="Usage: raga agent-attach --socket <path> --agent <id>",AGENT_ATTACH_DISCONNECTED="Disconnected: the Raga session that owns this subagent ended.",RECONNECT_DELAY_MS=2e3,MAX_SERVER_LINE_CHARS=64*1024*1024,RETRYABLE_CONNECT_ERRORS=new Set(["ECONNREFUSED","ENOENT"]);function parseAgentAttachArgs(args){let values={};for(let index=0;index<args.length;index++){let arg=args[index],key=arg==="--socket"?"socket":arg==="--agent"?"agent":void 0;if(!key)throw new Error(`Unknown option: ${sanitizeTerminalText(arg)}`);if(values[key]!==void 0)throw new Error(`Duplicate option: ${arg}`);let value=args[++index];if(value===void 0||value===""||value.startsWith("--"))throw new Error(`Missing value for ${arg}`);values[key]=value}if(values.socket===void 0)throw new Error("Missing --socket");if(values.agent===void 0)throw new Error("Missing --agent");return{socket:values.socket,agent:values.agent}}function sanitizeTerminalText(text,multiline=!1){return(multiline?text.replace(/\r\n/g,`
3
+ `):text.replace(/[\r\n\t]+/g," ")).replace(/[\x00-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069]/g,char=>{if(multiline&&(char===`
4
+ `||char===" "))return char;let code=char.charCodeAt(0);return code<=255?`\\x${code.toString(16).padStart(2,"0")}`:`\\u${code.toString(16).padStart(4,"0")}`})}function sanitizeJson(value){if(typeof value=="string")return sanitizeTerminalText(value,!0);if(Array.isArray(value))return value.map(sanitizeJson);if(value&&typeof value=="object"){let result={};for(let[key,item]of Object.entries(value))result[sanitizeTerminalText(key)]=sanitizeJson(item);return result}return value}var isRecord=value=>typeof value=="object"&&value!==null&&!Array.isArray(value),isStringArray=value=>Array.isArray(value)&&value.every(item=>typeof item=="string"),isContent=value=>Array.isArray(value)&&value.every(item=>isRecord(item)&&typeof item.type=="string"),forwardedEvents=new Set(FORWARDED_CHILD_AGENT_EVENTS);function isAgentInfo(value){if(!isRecord(value)||!isRecord(value.usage))return!1;let usage=value.usage;return["id","name","rootSessionId","model","status"].every(key=>typeof value[key]=="string")&&typeof value.turns=="number"&&typeof value.maxTurns=="number"&&["input","output","cost"].every(key=>typeof usage[key]=="number")}function isAgentMessage(value){if(!isRecord(value)||typeof value.role!="string")return!1;switch(value.role){case"assistant":return isContent(value.content)&&value.content.every(block=>block.type!=="toolCall"||typeof block.id=="string"&&typeof block.name=="string");case"toolResult":return typeof value.toolCallId=="string"&&isContent(value.content);case"user":case"custom":return typeof value.content=="string"||isContent(value.content);case"bashExecution":return typeof value.command=="string"&&(value.output===void 0||typeof value.output=="string");default:return!0}}var isToolResult=value=>isRecord(value)&&isContent(value.content);function isForwardedEvent(event){if(typeof event.type!="string"||!forwardedEvents.has(event.type))return!1;switch(event.type){case"queue_update":return isStringArray(event.steering)&&isStringArray(event.followUp);case"message_start":case"message_update":case"message_end":return isAgentMessage(event.message);case"tool_execution_start":return typeof event.toolCallId=="string"&&typeof event.toolName=="string";case"tool_execution_update":return typeof event.toolCallId=="string"&&isToolResult(event.partialResult);case"tool_execution_end":return typeof event.toolCallId=="string"&&isToolResult(event.result);default:return!0}}function stripResultAnsi(result){if(!(!isRecord(result)||!Array.isArray(result.content)))for(let block of result.content)isRecord(block)&&block.type==="text"&&typeof block.text=="string"&&(block.text=stripVTControlCharacters(block.text))}function stripMessageAnsi(message){isRecord(message)&&(message.role==="toolResult"?stripResultAnsi(message):message.role==="bashExecution"&&typeof message.output=="string"&&(message.output=stripVTControlCharacters(message.output)))}function parseServerMessage(line){let raw;try{raw=JSON.parse(line)}catch{return}if(isRecord(raw)){if(Array.isArray(raw.messages))for(let item of raw.messages)stripMessageAnsi(item);isRecord(raw.event)&&(stripMessageAnsi(raw.event.message),stripResultAnsi(raw.event.partialResult),stripResultAnsi(raw.event.result))}let message=sanitizeJson(raw);if(isRecord(message)){switch(message.type){case"welcome":if(!isAgentInfo(message.agent)||!Array.isArray(message.messages)||!message.messages.every(isAgentMessage)||(message.streaming??=null,message.streaming!==null&&!isAgentMessage(message.streaming))||!isStringArray(message.pendingToolCallIds))return;break;case"agent":if(!isAgentInfo(message.agent))return;break;case"event":if(!isRecord(message.event)||!isForwardedEvent(message.event))return;break;case"error":if(typeof message.message!="string")return;break;default:return}return message}}function createLineReader(maxChars,onLine){let parts=[],length=0;return chunk=>{let start=0;for(let index=chunk.indexOf(`
5
+ `);index!==-1;index=chunk.indexOf(`
6
+ `,start)){if(length+index-start>maxChars)return!1;let piece=chunk.slice(start,index),line=parts.length>0?parts.join("")+piece:piece;parts=[],length=0,start=index+1,onLine(line)}if(start<chunk.length){if(length+=chunk.length-start,length>maxChars)return!1;parts.push(chunk.slice(start))}return!0}}var statusText=agent=>agent.busy&&agent.status!=="running"?`${agent.status}, responding`:agent.status;function formatAttachHeader(agent){return sanitizeTerminalText(`${agent.name} \xB7 ${statusText(agent)} \xB7 ${agent.model} \xB7 subagent of ${agent.rootSessionId.slice(0,8)}`)}function formatAttachFooter(agent){let usage=agent.usage;return sanitizeTerminalText(`${agent.model} \xB7 \u2191${formatTokens(usage.input)} \u2193${formatTokens(usage.output)} tokens \xB7 $${usage.cost.toFixed(3)} \xB7 turns ${agent.turns}/${agent.maxTurns} \xB7 ${statusText(agent)}`)}var Line=class{build;constructor(build){this.build=build}render(width){let text=this.build();return text?[truncateToWidth(text,Math.max(0,width))]:[]}invalidate(){}},AgentAttachView=class{header;chat=new Container;pending=new Container;status;footer;agent;connection="connecting";ui;settings;notice;lastError;fatalError;expanded=!1;streamingComponent;pendingTools=new Map;constructor(ui,settings={}){this.ui=ui,this.settings=settings,this.header=new Line(()=>this.agent?theme.bold(theme.fg("accent",formatAttachHeader(this.agent))):theme.fg("dim","Connecting...")),this.status=new Line(()=>this.connection==="failed"?theme.fg("error",`Error: ${this.fatalError??""}`):this.connection==="disconnected"?theme.fg("warning",AGENT_ATTACH_DISCONNECTED):this.notice?theme.fg(this.notice.color,this.notice.text):""),this.footer=new Line(()=>this.agent?theme.fg("dim",formatAttachFooter(this.agent)):"")}setNotice(text,color="dim"){this.notice=text===void 0?void 0:{text:sanitizeTerminalText(text),color},this.ui.requestRender()}setConnected(connected){this.connection!=="failed"&&(this.connection=connected?"connected":"disconnected",this.ui.requestRender())}setFailed(message){this.connection="failed",this.fatalError=sanitizeTerminalText(message),this.ui.requestRender()}toggleExpanded(){this.expanded=!this.expanded;for(let child of this.chat.children)(child instanceof ToolExecutionComponent||child instanceof CustomMessageComponent||child instanceof BashExecutionComponent||child instanceof CompactionSummaryMessageComponent||child instanceof BranchSummaryMessageComponent)&&child.setExpanded(this.expanded);this.ui.requestRender()}apply(message){try{this.applyMessage(message)}catch(error){this.setNotice(`Could not show a server ${message.type} message: ${error instanceof Error?error.message:String(error)}`,"error")}this.ui.requestRender()}applyMessage(message){switch(message.type){case"welcome":this.agent=message.agent,this.notice=void 0,this.lastError=void 0,this.renderWelcome(message.messages,message.streaming,message.pendingToolCallIds);break;case"agent":this.agent=message.agent;break;case"event":this.handleEvent(message.event);break;case"error":if(message.message!==this.lastError){this.lastError=message.message,this.chat.addChild(new Spacer(1));let text=sanitizeTerminalText(message.message);this.chat.addChild(new TruncatedText(theme.fg("error",`Error: ${text}`),1,0))}break}}markdownTheme(){return{...getMarkdownTheme(),codeBlockIndent:this.settings.codeBlockIndent??" "}}outputPad(){return this.settings.outputPad??1}createToolComponent(name,id,args){let component=new ToolExecutionComponent(name,id,args,{showImages:this.settings.showImages??!0,imageWidthCells:this.settings.imageWidthCells,outputPad:this.outputPad()},withBuiltInRenderers(name,void 0),this.ui,this.settings.cwd??process.cwd());return component.setExpanded(this.expanded),this.chat.addChild(component),component}createAssistantComponent(message){return new AssistantMessageComponent(message,this.settings.hideThinkingBlock??!1,this.markdownTheme(),"Thinking...",this.outputPad())}renderWelcome(messages,streaming,pendingIds){this.chat.clear(),this.pending.clear(),this.pendingTools.clear(),this.streamingComponent=void 0;let rendered=new Map;for(let message of messages)if(message.role==="assistant"){this.addMessage(message);for(let content of message.content){if(content.type!=="toolCall")continue;let component=this.createToolComponent(content.name,content.id,content.arguments);if(message.stopReason==="aborted"||message.stopReason==="error"){let text=message.stopReason==="aborted"?"Operation aborted":message.errorMessage||"Error";component.updateResult({content:[{type:"text",text}],isError:!0})}else rendered.set(content.id,component)}}else if(message.role==="toolResult"){let component=rendered.get(message.toolCallId);component&&(component.updateResult(message),rendered.delete(message.toolCallId))}else this.addMessage(message);for(let[id,component]of rendered)this.pendingTools.set(id,component);streaming?.role==="assistant"&&(this.startStreaming(streaming),this.updateStreaming(streaming));for(let id of pendingIds)this.pendingTools.get(id)?.markExecutionStarted()}startStreaming(message){this.streamingComponent=this.createAssistantComponent(),this.chat.addChild(this.streamingComponent),this.streamingComponent.updateContent(message,!0)}updateStreaming(message){if(this.streamingComponent){this.streamingComponent.updateContent(message,!0);for(let content of message.content){if(content.type!=="toolCall")continue;let existing=this.pendingTools.get(content.id);existing?existing.updateArgs(content.arguments):this.pendingTools.set(content.id,this.createToolComponent(content.name,content.id,content.arguments))}}}handleEvent(event){switch(event.type){case"agent_start":this.pendingTools.clear();break;case"queue_update":if(this.pending.clear(),event.steering.length>0||event.followUp.length>0){this.pending.addChild(new Spacer(1));for(let text of event.steering){let line=sanitizeTerminalText(text);this.pending.addChild(new TruncatedText(theme.fg("dim",`Steering: ${line}`),1,0))}for(let text of event.followUp){let line=sanitizeTerminalText(text);this.pending.addChild(new TruncatedText(theme.fg("dim",`Follow-up: ${line}`),1,0))}}break;case"message_start":event.message.role==="custom"||event.message.role==="user"?this.addMessage(event.message):event.message.role==="assistant"&&this.startStreaming(event.message);break;case"message_update":event.message.role==="assistant"&&this.updateStreaming(event.message);break;case"message_end":{let message=event.message;if(message.role!=="assistant"||!this.streamingComponent)break;if(message.stopReason==="aborted"&&(message.errorMessage="Operation aborted"),this.streamingComponent.updateContent(message,!1),message.stopReason==="aborted"||message.stopReason==="error"){let text=message.errorMessage||"Error";for(let component of this.pendingTools.values())component.updateResult({content:[{type:"text",text}],isError:!0});this.pendingTools.clear()}else for(let component of this.pendingTools.values())component.setArgsComplete();this.streamingComponent=void 0;break}case"tool_execution_start":{if(event.parentToolCallId)break;let component=this.pendingTools.get(event.toolCallId);component||(component=this.createToolComponent(event.toolName,event.toolCallId,event.args),this.pendingTools.set(event.toolCallId,component)),component.markExecutionStarted();break}case"tool_execution_update":this.pendingTools.get(event.toolCallId)?.updateResult({...event.partialResult,isError:!1},!0);break;case"tool_execution_end":{let component=this.pendingTools.get(event.toolCallId);component&&(component.updateResult({...event.result,isError:event.isError,durationMs:event.durationMs}),this.pendingTools.delete(event.toolCallId));break}case"agent_end":this.streamingComponent&&(this.chat.removeChild(this.streamingComponent),this.streamingComponent=void 0),this.pendingTools.clear();break;case"turn_start":case"turn_end":break}}addMessage(message){let pad=this.outputPad();switch(message.role){case"bashExecution":{let component=new BashExecutionComponent(message.command,this.ui,message.excludeFromContext,pad);message.output&&component.appendOutput(message.output),component.setComplete(message.exitCode,message.cancelled,message.truncated?{truncated:!0}:void 0,message.fullOutputPath),component.setExpanded(this.expanded),this.chat.addChild(component);break}case"custom":{if(!message.display)break;let component=new CustomMessageComponent(message,void 0,this.markdownTheme(),pad);component.setExpanded(this.expanded),this.chat.addChild(component);break}case"compactionSummary":{this.chat.addChild(new Spacer(1));let component=new CompactionSummaryMessageComponent(message,this.markdownTheme(),pad);component.setExpanded(this.expanded),this.chat.addChild(component);break}case"branchSummary":{this.chat.addChild(new Spacer(1));let component=new BranchSummaryMessageComponent(message,this.markdownTheme(),pad);component.setExpanded(this.expanded),this.chat.addChild(component);break}case"user":{let text=typeof message.content=="string"?message.content:message.content.filter(content=>content.type==="text").map(content=>content.text).join("");if(!text)break;this.chat.children.length>0&&this.chat.addChild(new Spacer(1)),this.chat.addChild(new UserMessageComponent(text,this.markdownTheme(),pad));break}case"assistant":this.chat.addChild(this.createAssistantComponent(message));break;default:break}}},AttachConnection=class{options;handlers;reconnectDelayMs;socket;timer;closed=!1;constructor(options,handlers,reconnectDelayMs=RECONNECT_DELAY_MS){this.options=options,this.handlers=handlers,this.reconnectDelayMs=reconnectDelayMs}connect(){if(this.closed)return;let socket=createConnection(this.options.socket);this.socket=socket,socket.setEncoding("utf8");let connected=!1,welcomed=!1,push=createLineReader(MAX_SERVER_LINE_CHARS,line=>{if(this.socket!==socket||!line.trim())return;let message=parseServerMessage(line);if(!message){this.handlers.invalid?.();return}if(message.type==="welcome")welcomed=!0;else if(message.type==="error"&&!welcomed){this.fail(message.message);return}this.handlers.message(message)});socket.on("connect",()=>{connected=!0,this.handlers.connected(!0),this.send({type:"hello",version:CHILD_AGENT_PROTOCOL_VERSION,agentId:this.options.agent})}),socket.on("data",chunk=>{push(chunk)||this.fail("The Raga session sent a message larger than 64 MiB.")}),socket.on("error",error=>{!connected&&!RETRYABLE_CONNECT_ERRORS.has(error.code??"")&&this.fail(`Cannot connect to the subagent socket: ${error.message}`)}),socket.on("close",()=>{this.socket===socket&&(this.socket=void 0,this.handlers.connected(!1),this.closed||(this.timer=setTimeout(()=>this.connect(),this.reconnectDelayMs)))})}send(message){let socket=this.socket;return!socket||socket.destroyed||!socket.writable||socket.connecting?!1:(socket.write(`${JSON.stringify(message)}
7
+ `),!0)}close(){this.closed=!0,this.timer&&clearTimeout(this.timer),this.socket?.destroy(),this.socket=void 0}fail(message){this.closed||(this.close(),this.handlers.failed(message))}};async function runAgentAttach(args){let options;try{options=parseAgentAttachArgs(args)}catch(error){process.stderr.write(`${error instanceof Error?error.message:String(error)}
8
+ ${AGENT_ATTACH_USAGE}
9
+ `),process.exitCode=2;return}let settings=SettingsManager.create(process.cwd(),getAgentDir(),{projectTrusted:!1});setCapabilityOverrides(settings.getTerminalCapabilityOverrides()),markTerminalColorsPending(),initTheme(resolveThemeSetting(settings.getThemeSetting(),getTerminalTheme())??SYSTEM_THEME_NAME);let keybindings=KeybindingsManager.create();setKeybindings(keybindings);let ui=createInteractiveTui({tuiMode:"fullscreen",showHardwareCursor:settings.getShowHardwareCursor(),logDirectory:getAgentDir()}),view=new AgentAttachView(ui,{hideThinkingBlock:settings.getHideThinkingBlock(),outputPad:settings.getOutputPad(),showImages:settings.getShowImages(),imageWidthCells:settings.getImageWidthCells(),codeBlockIndent:settings.getCodeBlockIndent(),cwd:process.cwd()}),editor=new CustomEditor(ui,getEditorTheme(),keybindings,{paddingX:settings.getEditorPaddingX(),autocompleteMaxVisible:settings.getAutocompleteMaxVisible()}),viewport=createChatViewport({document:view.chat,pendingMessages:view.pending,status:view.status,editor,footer:view.footer,scrollbar:settings.getFullscreenScrollbar(),scrollbarTrackStyle:text=>theme.fg("scrollbarTrack",text),scrollbarThumbStyle:text=>theme.fg("scrollbarThumb",text)}),root=new VStack([{component:view.header,basis:"auto",grow:0,shrink:0,minSize:1},{component:viewport.root,basis:0,grow:1,shrink:1,minSize:1}]);ui.addChild(root),isViewportTUI(ui)&&ui.setLayoutRoot(root);let connection=new AttachConnection(options,{message:message=>view.apply(message),connected:connected=>view.setConnected(connected),failed:message=>view.setFailed(message),invalid:()=>view.setNotice("Ignored an invalid message from the Raga session.","warning")}),finish=()=>{},finished=new Promise(resolve=>{finish=resolve}),signals=["SIGINT","SIGTERM","SIGHUP"],onSignal=()=>finish();for(let signal of signals)process.on(signal,onSignal);editor.onAction("app.clear",()=>finish()),editor.onCtrlD=()=>finish(),editor.onEscape=()=>{editor.setText(""),ui.requestRender()},editor.onAction("app.tools.expand",()=>view.toggleExpanded()),editor.onSubmit=text=>{if(text.trim()){if(!view.agent?.promptable){editor.setText(text),view.setNotice("read-only: this subagent does not accept messages.","dim");return}if(!connection.send({type:"prompt",text})){editor.setText(text),view.setNotice("Not connected; your message was kept.","warning");return}editor.addToHistory(text),view.setNotice(void 0)}},ui.setFocus(editor),ui.start();try{requestTerminalColors(ui,colors=>{setTerminalColors(colors),setTheme(resolveThemeSetting(settings.getThemeSetting(),getTerminalTheme())??SYSTEM_THEME_NAME),ui.invalidate(),ui.requestRender()}).catch(()=>{}),connection.connect(),ui.requestRender(),await finished}finally{for(let signal of signals)process.off(signal,onSignal);connection.close(),process.stdout.on("error",()=>{});try{ui.stop()}catch{}}}export{AGENT_ATTACH_DISCONNECTED,AGENT_ATTACH_USAGE,AgentAttachView,AttachConnection,MAX_SERVER_LINE_CHARS,createLineReader,formatAttachFooter,formatAttachHeader,parseAgentAttachArgs,parseServerMessage,runAgentAttach,sanitizeTerminalText};