@selesai/code 0.1.19 → 0.2.0

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 (156) hide show
  1. package/dist/agents/architect.md +4 -3
  2. package/dist/agents/builder.md +5 -4
  3. package/dist/agents/commentator.md +3 -2
  4. package/dist/agents/explorer.md +4 -4
  5. package/dist/agents/recapper.md +4 -3
  6. package/dist/config.d.ts +6 -7
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +7 -9
  9. package/dist/config.js.map +1 -1
  10. package/dist/core/agent-session.d.ts.map +1 -1
  11. package/dist/core/agent-session.js +3 -1
  12. package/dist/core/agent-session.js.map +1 -1
  13. package/dist/core/compaction/compaction.d.ts.map +1 -1
  14. package/dist/core/compaction/compaction.js +18 -24
  15. package/dist/core/compaction/compaction.js.map +1 -1
  16. package/dist/core/extensions/loader.d.ts.map +1 -1
  17. package/dist/core/extensions/loader.js +2 -0
  18. package/dist/core/extensions/loader.js.map +1 -1
  19. package/dist/core/extensions/types.d.ts +8 -1
  20. package/dist/core/extensions/types.d.ts.map +1 -1
  21. package/dist/core/extensions/types.js.map +1 -1
  22. package/dist/core/skills.d.ts.map +1 -1
  23. package/dist/core/skills.js +25 -11
  24. package/dist/core/skills.js.map +1 -1
  25. package/dist/defaults/settings.json +2 -29
  26. package/dist/extensions/package.json +5 -4
  27. package/dist/extensions/pi-intercom/index.ts +12 -5
  28. package/dist/extensions/pi-powerline-footer/index.ts +4 -1
  29. package/dist/extensions/pi-powerline-footer/tps.ts +286 -0
  30. package/dist/extensions/pi-powerline-footer/welcome.ts +47 -46
  31. package/dist/extensions/pi-subagents/README.md +12 -5
  32. package/dist/extensions/pi-subagents/agents/context-builder.md +2 -2
  33. package/dist/extensions/pi-subagents/agents/researcher.md +4 -5
  34. package/dist/extensions/pi-subagents/package.json +8 -5
  35. package/dist/extensions/pi-subagents/prompts/parallel-context-build.md +1 -1
  36. package/dist/extensions/pi-subagents/prompts/parallel-handoff-plan.md +1 -1
  37. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +1 -1
  38. package/dist/extensions/pi-subagents/src/agents/agents.ts +3 -3
  39. package/dist/extensions/pi-subagents/src/extension/control-notices.ts +1 -1
  40. package/dist/extensions/pi-subagents/src/extension/doctor.ts +3 -3
  41. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +1 -1
  42. package/dist/extensions/pi-subagents/src/extension/index.ts +29 -2
  43. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +2 -2
  44. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +72 -13
  45. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +1 -1
  46. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +1 -1
  47. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +85 -41
  48. package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +1 -1
  49. package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +1 -1
  50. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +46 -3
  51. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +2 -2
  52. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +1 -3
  53. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +2 -2
  54. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +18 -18
  55. package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +24 -24
  56. package/dist/extensions/pi-subagents/src/runs/shared/spawn-timing.ts +46 -0
  57. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +2 -2
  58. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +4 -4
  59. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +1 -1
  60. package/dist/extensions/pi-subagents/src/shared/types.ts +6 -6
  61. package/dist/extensions/pi-subagents/src/shared/utils.ts +3 -3
  62. package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +1 -1
  63. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +1 -1
  64. package/dist/extensions/pi-subagents/src/tui/render-helpers.ts +1 -1
  65. package/dist/extensions/pi-subagents/src/tui/render.ts +1 -1
  66. package/dist/extensions/pi-subagents/test/unit/spawn-timing.test.ts +45 -0
  67. package/dist/extensions/pi-subagents/tsconfig.runner.json +17 -0
  68. package/dist/extensions/pi-web-agent/package.json +31 -0
  69. package/dist/extensions/pi-web-agent/src/backends/config.ts +205 -0
  70. package/dist/extensions/pi-web-agent/src/backends/doctor.ts +136 -0
  71. package/dist/extensions/pi-web-agent/src/backends/factory.ts +152 -0
  72. package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +25 -0
  73. package/dist/extensions/pi-web-agent/src/cache/ttl-cache.ts +28 -0
  74. package/dist/extensions/pi-web-agent/src/changelog-notice.ts +133 -0
  75. package/dist/extensions/pi-web-agent/src/commands/web-agent-config.ts +946 -0
  76. package/dist/extensions/pi-web-agent/src/extension.ts +126 -0
  77. package/dist/extensions/pi-web-agent/src/extract/readability.ts +118 -0
  78. package/dist/extensions/pi-web-agent/src/fetch/browser-resolution.ts +199 -0
  79. package/dist/extensions/pi-web-agent/src/fetch/firecrawl-fetch.ts +100 -0
  80. package/dist/extensions/pi-web-agent/src/fetch/headless-fetch.ts +117 -0
  81. package/dist/extensions/pi-web-agent/src/fetch/http-fetch.ts +67 -0
  82. package/dist/extensions/pi-web-agent/src/orchestration/answer-synthesizer.ts +60 -0
  83. package/dist/extensions/pi-web-agent/src/orchestration/candidate-selector.ts +50 -0
  84. package/dist/extensions/pi-web-agent/src/orchestration/direct-url.ts +52 -0
  85. package/dist/extensions/pi-web-agent/src/orchestration/evidence-quality.ts +105 -0
  86. package/dist/extensions/pi-web-agent/src/orchestration/evidence-ranker.ts +45 -0
  87. package/dist/extensions/pi-web-agent/src/orchestration/index.ts +28 -0
  88. package/dist/extensions/pi-web-agent/src/orchestration/query-planner.ts +47 -0
  89. package/dist/extensions/pi-web-agent/src/orchestration/research-orchestrator.ts +376 -0
  90. package/dist/extensions/pi-web-agent/src/orchestration/research-types.ts +64 -0
  91. package/dist/extensions/pi-web-agent/src/orchestration/research-worker.ts +181 -0
  92. package/dist/extensions/pi-web-agent/src/orchestration/source-profile.ts +101 -0
  93. package/dist/extensions/pi-web-agent/src/orchestration/stop-decider.ts +81 -0
  94. package/dist/extensions/pi-web-agent/src/presentation/config-store.ts +208 -0
  95. package/dist/extensions/pi-web-agent/src/presentation/config.ts +75 -0
  96. package/dist/extensions/pi-web-agent/src/presentation/explore-presentation.ts +61 -0
  97. package/dist/extensions/pi-web-agent/src/presentation/fetch-presentation.ts +54 -0
  98. package/dist/extensions/pi-web-agent/src/presentation/search-presentation.ts +41 -0
  99. package/dist/extensions/pi-web-agent/src/presentation/select-view.ts +20 -0
  100. package/dist/extensions/pi-web-agent/src/presentation/types.ts +63 -0
  101. package/dist/extensions/pi-web-agent/src/search/brave.ts +114 -0
  102. package/dist/extensions/pi-web-agent/src/search/duckduckgo.ts +72 -0
  103. package/dist/extensions/pi-web-agent/src/search/searxng.ts +96 -0
  104. package/dist/extensions/pi-web-agent/src/tools/web-explore.ts +71 -0
  105. package/dist/extensions/pi-web-agent/src/tools/web-fetch-headless.ts +31 -0
  106. package/dist/extensions/pi-web-agent/src/tools/web-fetch.ts +31 -0
  107. package/dist/extensions/pi-web-agent/src/tools/web-search.ts +157 -0
  108. package/dist/extensions/pi-web-agent/src/types.ts +88 -0
  109. package/dist/extensions/ponytail/index.js +189 -0
  110. package/dist/extensions/ponytail/package.json +8 -0
  111. package/dist/extensions/ponytail/ponytail-config.cjs +122 -0
  112. package/dist/extensions/ponytail/ponytail-instructions.cjs +94 -0
  113. package/dist/extensions/ponytail/test/extension.test.js +167 -0
  114. package/dist/extensions/ponytail/test/helpers.test.js +92 -0
  115. package/dist/extensions/question/constants.ts +38 -0
  116. package/dist/extensions/question/dialog-adapter.ts +74 -0
  117. package/dist/extensions/question/helpers.ts +102 -0
  118. package/dist/extensions/question/index.ts +671 -0
  119. package/dist/extensions/question/navigation.ts +14 -0
  120. package/dist/extensions/question/package.json +18 -0
  121. package/dist/extensions/question/question-list.ts +498 -0
  122. package/dist/extensions/question/row-layout.ts +162 -0
  123. package/dist/extensions/question/schemas.ts +69 -0
  124. package/dist/extensions/question/selection-mode.ts +49 -0
  125. package/dist/extensions/question/shortcuts.ts +53 -0
  126. package/dist/extensions/question/tests/helpers.test.ts +178 -0
  127. package/dist/extensions/question/tests/question-list.test.ts +230 -0
  128. package/dist/extensions/question/tests/row-layout.test.ts +136 -0
  129. package/dist/extensions/question/tests/shortcuts.test.ts +85 -0
  130. package/dist/extensions/question/tests/ui-protocol.test.ts +143 -0
  131. package/dist/extensions/question/tui-adapter.ts +33 -0
  132. package/dist/extensions/question/types.ts +102 -0
  133. package/dist/extensions/question/ui-protocol.ts +46 -0
  134. package/dist/extensions/tokenin-onboarding.ts +265 -2
  135. package/dist/extensions/web-agent-onboarding.ts +222 -0
  136. package/dist/extensions/workflow/adapter.ts +588 -0
  137. package/dist/extensions/workflow/extension.ts +24 -0
  138. package/dist/extensions/workflow/modes/prototype.ts +156 -0
  139. package/dist/extensions/workflow/modes/quick.ts +138 -0
  140. package/dist/extensions/workflow/package.json +17 -0
  141. package/dist/extensions/workflow/state-machine.ts +386 -0
  142. package/dist/index.d.ts +1 -1
  143. package/dist/index.d.ts.map +1 -1
  144. package/dist/index.js +1 -1
  145. package/dist/index.js.map +1 -1
  146. package/dist/modes/interactive/interactive-mode.d.ts +2 -0
  147. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  148. package/dist/modes/interactive/interactive-mode.js +57 -13
  149. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  150. package/dist/utils/mime.d.ts.map +1 -1
  151. package/dist/utils/mime.js +24 -1
  152. package/dist/utils/mime.js.map +1 -1
  153. package/docs/docs.json +4 -0
  154. package/docs/workflows.md +206 -0
  155. package/package.json +5 -1
  156. package/README.md +0 -198
@@ -523,11 +523,7 @@ Project discovery also reads legacy `.agents/**/*.md` files. Nested subdirectori
523
523
 
524
524
  Builtin agents load at the lowest priority, so a user or project agent with the same name overrides them. They do not pin a provider model; they inherit your current Pi default model unless you set `subagents.agentOverrides.<name>.model`. `oracle` is an advisory reviewer that critiques direction and proposes an execution prompt without editing files. `worker` is the implementation agent for normal tasks and approved oracle handoffs.
525
525
 
526
- The `researcher` builtin uses `web_search`, `fetch_content`, and `get_search_content`; those require [pi-web-access](https://github.com/nicobailon/pi-web-access):
527
-
528
- ```bash
529
- pi install npm:pi-web-access
530
- ```
526
+ The `researcher` and `context-builder` builtins use `web_explore`, provided by the bundled [`pi-web-agent`](https://github.com/demigodmode/pi-web-agent) extension (`src/extensions/pi-web-agent`) — no external install is required. Brave Search is optional: on first run you will be prompted for a Brave API key (get one at <https://api.dashboard.search.brave.com/app/keys>), or you can set `webAgent.braveApiKey` in `~/.selesai/agent/settings.json` directly. If you skip Brave, `web_explore` falls back to the default DuckDuckGo backend (no key needed).
531
527
 
532
528
  ### Builtin overrides
533
529
 
@@ -1235,6 +1231,16 @@ export PI_SUBAGENT_MAX_DEPTH=0
1235
1231
 
1236
1232
  `PI_SUBAGENT_DEPTH` is internal and propagated automatically. Do not set it manually.
1237
1233
 
1234
+ ## Building the async runner
1235
+
1236
+ The async runner can be pre-transpiled to JavaScript so background runs do not pay the jiti TypeScript JIT cost. To build it:
1237
+
1238
+ ```bash
1239
+ npm run build:runner
1240
+ ```
1241
+
1242
+ This writes `dist/runner/runs/background/subagent-runner.js` and its dependencies. The launch path automatically prefers the compiled runner when it exists and falls back to the previous `node jiti subagent-runner.ts` path otherwise. Set `SELESAI_SUBAGENT_RUNNER_USE_JITI=1` to force the old jiti path for troubleshooting.
1243
+
1238
1244
  ## Events
1239
1245
 
1240
1246
  Async events:
@@ -1285,6 +1291,7 @@ The main runtime files are:
1285
1291
  | `src/runs/foreground/chain-execution.ts` / `src/agents/chain-serializer.ts` | Chain orchestration and `.chain.md` parsing. |
1286
1292
  | `src/shared/settings.ts` | Chain behavior, instructions, and config helpers. |
1287
1293
  | `src/runs/shared/worktree.ts` | Git worktree isolation. |
1294
+ | `src/runs/shared/spawn-timing.ts` | Spawn latency timing probes. |
1288
1295
  | `src/intercom/intercom-bridge.ts` | Runtime intercom bridge instructions and diagnostics. |
1289
1296
  | `src/extension/schemas.ts` / `src/shared/types.ts` | Tool schemas, shared types, and event constants. |
1290
1297
  | `test/unit/` / `test/integration/` | Unit and loader-based integration tests. |
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: context-builder
3
3
  description: Analyzes requirements and codebase, generates context and meta-prompt
4
- tools: read, grep, find, ls, bash, write, web_search, intercom
4
+ tools: read, grep, find, ls, bash, write, web_explore, intercom
5
5
  thinking: medium
6
6
  systemPromptMode: replace
7
7
  inheritProjectContext: true
@@ -18,7 +18,7 @@ Working rules:
18
18
  - Search the codebase for relevant files, patterns, dependencies, and constraints.
19
19
  - Read every file needed to fully understand the issue, not just the first matching symbol. Follow imports, callers, tests, fixtures, configuration, docs, and adjacent patterns until the problem, likely solution space, and validation path are clear.
20
20
  - If a referenced URL, issue, PR, plan, design doc, or local file is part of the request, read or fetch it before writing the handoff.
21
- - Conduct web research when the task depends on external APIs, libraries, current best practices, recently changed behavior, or when local evidence is not enough to know how to solve the problem correctly. Use `web_search` if it is available; otherwise use whatever equivalent research capability is available.
21
+ - Conduct web research when the task depends on external APIs, libraries, current best practices, recently changed behavior, or when local evidence is not enough to know how to solve the problem correctly. Use `web_explore` (it handles search, fetch, and source ranking internally; call again with a narrower query for follow-ups).
22
22
  - Keep searching or researching until you can state the likely implementation approach, risks, and validation with evidence. If a gap remains, call it out explicitly instead of implying certainty.
23
23
  - Write the requested output files clearly and concretely.
24
24
  - Prefer distilled, high-signal context over exhaustive dumps, but do not omit a relevant file or source just to keep the handoff short.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: researcher
3
3
  description: Autonomous web researcher — searches, evaluates, and synthesizes a focused research brief
4
- tools: read, write, web_search, fetch_content, get_search_content, intercom
4
+ tools: read, write, web_explore, intercom
5
5
  thinking: medium
6
6
  systemPromptMode: replace
7
7
  inheritProjectContext: true
@@ -16,12 +16,11 @@ Given a question or topic, run focused web research and produce a concise, well-
16
16
 
17
17
  Working rules:
18
18
  - Break the problem into 2-4 distinct research angles.
19
- - Use `web_search` with `queries` so the search covers multiple angles instead of one generic query.
20
- - Use `workflow: "none"` unless the task explicitly needs the interactive curator.
21
- - Read the search results first. Then fetch full content only for the most promising source URLs.
19
+ - Use `web_explore` for each angle; it handles search, fetch, source ranking, and headless escalation internally. One call covers search + fetch + ranking.
20
+ - For follow-ups or gaps after the first pass, call `web_explore` again with a narrower query instead of fetching URLs manually.
22
21
  - Prefer primary sources, official docs, specs, benchmarks, and direct evidence over commentary.
23
22
  - Drop stale, redundant, or SEO-heavy sources.
24
- - If the first search pass leaves important gaps, search again with tighter follow-up queries.
23
+ - If the first explore pass leaves important gaps, explore again with tighter follow-up queries.
25
24
 
26
25
  Search strategy:
27
26
  - direct answer query
@@ -16,7 +16,8 @@
16
16
  "keywords": [
17
17
  "pi-package",
18
18
  "pi",
19
- "pi-coding-agent",
19
+ "selesai",
20
+ "selesai-code",
20
21
  "subagents",
21
22
  "ai",
22
23
  "agents",
@@ -27,6 +28,7 @@
27
28
  },
28
29
  "files": [
29
30
  "src/**/*.ts",
31
+ "dist/runner/**/*",
30
32
  "*.mjs",
31
33
  "agents/",
32
34
  "skills/**/*",
@@ -38,7 +40,8 @@
38
40
  "test": "npm run test:unit",
39
41
  "test:unit": "node --experimental-strip-types --test test/unit/*.test.ts",
40
42
  "test:integration": "node --experimental-transform-types --import ./test/support/register-loader.mjs --test test/integration/*.test.ts",
41
- "test:all": "npm run test:unit && npm run test:integration"
43
+ "test:all": "npm run test:unit && npm run test:integration",
44
+ "build:runner": "tsc -p tsconfig.runner.json"
42
45
  },
43
46
  "pi": {
44
47
  "extensions": [
@@ -57,7 +60,7 @@
57
60
  "peerDependencies": {
58
61
  "@earendil-works/pi-agent-core": "*",
59
62
  "@earendil-works/pi-ai": "*",
60
- "@earendil-works/pi-coding-agent": "*"
63
+ "@selesai/code": "*"
61
64
  },
62
65
  "peerDependenciesMeta": {
63
66
  "@earendil-works/pi-agent-core": {
@@ -66,7 +69,7 @@
66
69
  "@earendil-works/pi-ai": {
67
70
  "optional": true
68
71
  },
69
- "@earendil-works/pi-coding-agent": {
72
+ "@selesai/code": {
70
73
  "optional": true
71
74
  }
72
75
  },
@@ -78,6 +81,6 @@
78
81
  "devDependencies": {
79
82
  "@earendil-works/pi-agent-core": "0.74.0",
80
83
  "@earendil-works/pi-ai": "0.74.0",
81
- "@earendil-works/pi-coding-agent": "0.74.0"
84
+ "@selesai/code": "0.74.0"
82
85
  }
83
86
  }
@@ -34,7 +34,7 @@ Choose two or three strong builders based on the request. Prefer three only when
34
34
  Adapt the angles when the request calls for it:
35
35
  - Issue or PR URL: include issue requirements, acceptance criteria, linked discussion, and likely affected files.
36
36
  - Plan file: include plan consistency, missing context, implementation sequence, and validation readiness.
37
- - External API/library work: include current docs or primary sources through `web_search` when needed.
37
+ - External API/library work: include current docs or primary sources through `web_explore` when needed.
38
38
  - Large refactor: include module boundaries, dependency direction, migration/cutover risks, and testability.
39
39
  - UI/product work: include user flow, accessibility, copy, visual constraints, and implementation touchpoints.
40
40
 
@@ -34,7 +34,7 @@ Role guidance:
34
34
  External reference researcher:
35
35
  - Study linked projects, docs, issues, examples, source code, or prompt guidance.
36
36
  - Identify the behavior, API, implementation files, constraints, and transferable ideas.
37
- - Conduct web research if needed. Use `web_search` if it is available; otherwise use whatever equivalent research capability is available.
37
+ - Conduct web research if needed. Use `web_explore` (it handles search, fetch, and source ranking internally; call again with a narrower query for follow-ups).
38
38
  - Return source links, repo paths, key evidence, risks, and what matters for this implementation.
39
39
 
40
40
  Local context-builder:
@@ -1,7 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import type { AgentToolResult } from "@earendil-works/pi-agent-core";
4
- import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
4
+ import type { ExtensionContext } from "@selesai/code";
5
5
  import {
6
6
  type AgentConfig,
7
7
  type AgentScope,
@@ -1217,10 +1217,10 @@ function resolveNearestProjectChainDirs(cwd: string): { readDirs: string[]; pref
1217
1217
  }
1218
1218
  const BUILTIN_AGENTS_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "agents");
1219
1219
 
1220
- export const EXTRA_AGENT_DIRS_ENV = "PI_SUBAGENT_EXTRA_AGENT_DIRS";
1220
+ export const EXTRA_AGENT_DIRS_ENV = "SELESAI_SUBAGENT_EXTRA_AGENT_DIRS";
1221
1221
 
1222
1222
  // Additional read-only directories to scan for agent definitions, supplied by the
1223
- // launcher via PI_SUBAGENT_EXTRA_AGENT_DIRS (PATH-style, split on os/path delimiter).
1223
+ // launcher via SELESAI_SUBAGENT_EXTRA_AGENT_DIRS (PATH-style, split on os/path delimiter).
1224
1224
  // Lets a hermetic wrapper (e.g. a Nix-store install) expose bundled agents without
1225
1225
  // copying or symlinking them into the writable agent dir. Loaded as "user" source,
1226
1226
  // at lower precedence than agents the user placed in their own agent dir.
@@ -1373,7 +1373,7 @@ export function discoverAgentsAll(cwd: string): {
1373
1373
  ...projectChainDiagnostics,
1374
1374
  ];
1375
1375
 
1376
- const userDir = process.env.PI_CODING_AGENT_DIR ? userDirOld : fs.existsSync(userDirNew) ? userDirNew : userDirOld;
1376
+ const userDir = process.env.SELESAI_CODING_AGENT_DIR ? userDirOld : fs.existsSync(userDirNew) ? userDirNew : userDirOld;
1377
1377
 
1378
1378
  return { builtin, package: packageAgents, user, project, chains, chainDiagnostics, userDir, projectDir, userChainDir, projectChainDir, userSettingsPath, projectSettingsPath };
1379
1379
  }
@@ -1,4 +1,4 @@
1
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
1
+ import type { ExtensionAPI } from "@selesai/code";
2
2
  import { controlNotificationKey, formatControlNoticeMessage } from "../runs/shared/subagent-control.ts";
3
3
  import type { ControlEvent, SubagentState } from "../shared/types.ts";
4
4
 
@@ -170,15 +170,15 @@ function formatIntercomDiagnostic(diagnostic: IntercomBridgeDiagnostic, context:
170
170
 
171
171
  function formatPermissionSystemSection(): string[] {
172
172
  const lines: string[] = [];
173
- const parentSession = process.env["PI_SUBAGENT_PARENT_SESSION"] ?? "";
173
+ const parentSession = process.env["SELESAI_SUBAGENT_PARENT_SESSION"] ?? "";
174
174
  const trimmed = parentSession.trim();
175
175
  if (trimmed) {
176
176
  lines.push(`- parent session: set (${trimmed})`);
177
177
  } else {
178
178
  lines.push("- parent session: not set — ask forwarding from subprocess children will not reach a parent UI");
179
179
  }
180
- const isChild = process.env["PI_SUBAGENT_CHILD"] === "1";
181
- lines.push(`- subagent process: ${isChild ? "yes (PI_SUBAGENT_CHILD=1)" : "no"}`);
180
+ const isChild = process.env["SELESAI_SUBAGENT_CHILD"] === "1";
181
+ lines.push(`- subagent process: ${isChild ? "yes (SELESAI_SUBAGENT_CHILD=1)" : "no"}`);
182
182
  // Whether pi-permission-system is installed and where it stores config is
183
183
  // outside pi-subagents' control, so we only report the forwarding signal we
184
184
  // own. Run `pi list` to confirm the permission extension is installed.
@@ -1,7 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as os from "node:os";
3
3
  import * as path from "node:path";
4
- import type { ExtensionAPI, ToolDefinition } from "@earendil-works/pi-coding-agent";
4
+ import type { ExtensionAPI, ToolDefinition } from "@selesai/code";
5
5
  import { discoverAgents } from "../agents/agents.ts";
6
6
  import { getArtifactsDir } from "../shared/artifacts.ts";
7
7
  import { createSubagentExecutor, type SubagentParamsLike } from "../runs/foreground/subagent-executor.ts";
@@ -15,8 +15,9 @@
15
15
  import * as fs from "node:fs";
16
16
  import * as os from "node:os";
17
17
  import * as path from "node:path";
18
+ import { fileURLToPath, pathToFileURL } from "node:url";
18
19
  import type { AgentToolResult } from "@earendil-works/pi-agent-core";
19
- import { type ExtensionAPI, type ExtensionContext, type ToolDefinition } from "@earendil-works/pi-coding-agent";
20
+ import { type ExtensionAPI, type ExtensionContext, type ToolDefinition } from "@selesai/code";
20
21
  import { Box, Container, Spacer, Text, truncateToWidth, visibleWidth, wrapTextWithAnsi, type Component } from "@earendil-works/pi-tui";
21
22
  import { discoverAgents } from "../agents/agents.ts";
22
23
  import { cleanupAllArtifactDirs, cleanupOldArtifacts, getArtifactsDir } from "../shared/artifacts.ts";
@@ -59,6 +60,32 @@ import {
59
60
 
60
61
  export { loadConfig } from "./config.ts";
61
62
 
63
+ function resolveRunnerScript(): string {
64
+ const srcDir = path.dirname(fileURLToPath(import.meta.url));
65
+ const candidates = [
66
+ path.join(srcDir, "..", "runs", "background", "subagent-runner.js"),
67
+ path.join(srcDir, "..", "..", "dist", "runner", "runs", "background", "subagent-runner.js"),
68
+ path.join(srcDir, "..", "runs", "background", "subagent-runner.ts"),
69
+ ];
70
+ for (const candidate of candidates) {
71
+ if (fs.existsSync(candidate)) return candidate;
72
+ }
73
+ throw new Error("Could not resolve subagent-runner script");
74
+ }
75
+
76
+ const runnerConfigPath = process.env.SELESAI_SUBAGENT_RUNNER_CONFIG;
77
+ if (runnerConfigPath) {
78
+ (async () => {
79
+ const runnerScript = resolveRunnerScript();
80
+ const runnerModule = await import(pathToFileURL(runnerScript).href);
81
+ await runnerModule.runSubagentFromConfigFile(runnerConfigPath);
82
+ process.exit(0);
83
+ })().catch((error) => {
84
+ console.error("Subagent runner hook failed:", error);
85
+ process.exit(1);
86
+ });
87
+ }
88
+
62
89
  /**
63
90
  * Derive subagent session base directory from parent session file.
64
91
  * If parent session is ~/.pi/agent/sessions/abc123.jsonl,
@@ -564,7 +591,7 @@ DIAGNOSTICS:
564
591
  const resetSessionState = (ctx: ExtensionContext) => {
565
592
  state.baseCwd = ctx.cwd;
566
593
  state.currentSessionId = resolveCurrentSessionId(ctx.sessionManager);
567
- // Set PI_SUBAGENT_PARENT_SESSION for permission-system forwarding.
594
+ // Set SELESAI_SUBAGENT_PARENT_SESSION for permission-system forwarding.
568
595
  // Only set in the root session (the interactive UI session), not in
569
596
  // child subagent processes — children inherit the parent's value
570
597
  // through the process environment at spawn time and must not overwrite
@@ -1,7 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as os from "node:os";
3
3
  import * as path from "node:path";
4
- import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
4
+ import type { ExtensionAPI, ExtensionContext } from "@selesai/code";
5
5
  import { BUILTIN_AGENT_NAMES } from "../agents/agents.ts";
6
6
  import { findModelInfo, getSupportedThinkingLevels, splitKnownThinkingSuffix, toModelInfo } from "../shared/model-info.ts";
7
7
  import { getAgentDir } from "../shared/utils.ts";
@@ -323,7 +323,7 @@ async function probeModel(
323
323
  if (typeof pi.exec !== "function") {
324
324
  return { status: "skipped", message: "pi.exec is unavailable in this runtime." };
325
325
  }
326
- const result = await pi.exec("pi", ["-p", "--model", fullId, "--no-tools", 'Reply with exactly "OK".'], {
326
+ const result = await pi.exec("selesai", ["-p", "--model", fullId, "--no-tools", 'Reply with exactly "OK".'], {
327
327
  cwd: os.tmpdir(),
328
328
  timeout: 45_000,
329
329
  } as Record<string, unknown>);
@@ -8,14 +8,15 @@ import * as os from "node:os";
8
8
  import * as path from "node:path";
9
9
  import { fileURLToPath } from "node:url";
10
10
  import { createRequire } from "node:module";
11
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
11
+ import type { ExtensionAPI } from "@selesai/code";
12
12
  import type { AgentConfig } from "../../agents/agents.ts";
13
13
  import { applyThinkingSuffix } from "../shared/pi-args.ts";
14
14
  import { injectOutputPathSystemPrompt, injectSingleOutputInstruction, normalizeSingleOutputOverride, resolveSingleOutputPath, validateFileOnlyOutputMode } from "../shared/single-output.ts";
15
15
  import { buildChainInstructions, isDynamicParallelStep, isParallelStep, resolveStepBehavior, suppressProgressForReadOnlyTask, writeInitialProgressFile, type ChainStep, type ResolvedStepBehavior, type SequentialStep, type StepOverrides } from "../../shared/settings.ts";
16
16
  import type { RunnerStep } from "../shared/parallel-utils.ts";
17
- import { resolvePiPackageRoot } from "../shared/pi-spawn.ts";
17
+ import { getSelesaiSpawnCommand, resolveSelesaiPackageRoot } from "../shared/pi-spawn.ts";
18
18
  import { buildSkillInjection, normalizeSkillInput, resolveSkillsWithFallback } from "../../agents/skills.ts";
19
+ import { createSpawnTimingMarkers, emitSpawnTiming } from "../shared/spawn-timing.ts";
19
20
  import { resolveChildCwd } from "../../shared/utils.ts";
20
21
  import { buildModelCandidates, resolveModelCandidate, resolveSubagentModelOverride, type AvailableModelInfo, type ParentModel } from "../shared/model-fallback.ts";
21
22
  import { resolveEffectiveThinking } from "../../shared/model-info.ts";
@@ -43,7 +44,7 @@ import { nestedResultsPath, resolveInheritedNestedRouteFromEnv, resolveNestedPar
43
44
  import type { ImportedAsyncRoot } from "./chain-root-attachment.ts";
44
45
 
45
46
  const require = createRequire(import.meta.url);
46
- const piPackageRoot = resolvePiPackageRoot();
47
+ const piPackageRoot = resolveSelesaiPackageRoot();
47
48
 
48
49
  function resolveJitiCliFromPackageJson(packageJsonPath: string): string | undefined {
49
50
  if (!fs.existsSync(packageJsonPath)) return undefined;
@@ -204,7 +205,7 @@ export function formatAsyncStartedMessage(headline: string): string {
204
205
  * Check if jiti is available for async execution
205
206
  */
206
207
  export function isAsyncAvailable(): boolean {
207
- return jitiCliPath !== undefined;
208
+ return resolveRunnerScript() !== undefined || getSelesaiSpawnCommand(["--offline", "--mode", "json", "-p"], { ...(piPackageRoot ? { piPackageRoot } : {}) }).command !== "" || jitiCliPath !== undefined;
208
209
  }
209
210
 
210
211
  function resolveAsyncRunnerNodeCommand(): string {
@@ -215,14 +216,63 @@ function resolveAsyncRunnerNodeCommand(): string {
215
216
  return process.platform === "win32" ? "node.exe" : "node";
216
217
  }
217
218
 
218
- /**
219
- * Spawn the async runner process
220
- */
221
- function spawnRunner(cfg: object, suffix: string, cwd: string): { pid?: number; error?: string } {
219
+ function resolveRunnerScript(): string | undefined {
220
+ const localDir = path.dirname(fileURLToPath(import.meta.url));
221
+ const candidates = [
222
+ piPackageRoot ? path.join(piPackageRoot, "dist/runner/runs/background/subagent-runner.js") : undefined,
223
+ path.join(localDir, "../../../dist/runner/runs/background/subagent-runner.js"),
224
+ path.join(localDir, "subagent-runner.ts"),
225
+ ].filter((candidate): candidate is string => Boolean(candidate));
226
+ for (const candidate of candidates) {
227
+ if (fs.existsSync(candidate)) return candidate;
228
+ }
229
+ return undefined;
230
+ }
231
+
232
+ type AsyncRunnerSpawnMode = "compiled" | "cli" | "jiti";
233
+
234
+ function resolveAsyncRunnerSpawnMode(): AsyncRunnerSpawnMode {
235
+ if (process.env.SELESAI_SUBAGENT_RUNNER_USE_JITI === "1") return "jiti";
236
+ const runnerScript = resolveRunnerScript();
237
+ if (runnerScript?.endsWith(".js")) return "compiled";
238
+ return "cli";
239
+ }
240
+
241
+ interface SpawnCommandSpec {
242
+ command: string;
243
+ args: string[];
244
+ env?: Record<string, string | undefined>;
245
+ }
246
+
247
+ function buildAsyncRunnerSpawnSpec(cfgPath: string): SpawnCommandSpec | { error: string } {
248
+ const mode = resolveAsyncRunnerSpawnMode();
249
+ if (mode === "compiled") {
250
+ const runnerScript = resolveRunnerScript();
251
+ if (!runnerScript) return { error: "compiled async runner script could not be resolved" };
252
+ return { command: resolveAsyncRunnerNodeCommand(), args: [runnerScript, cfgPath] };
253
+ }
254
+ if (mode === "cli") {
255
+ const spawnSpec = getSelesaiSpawnCommand(["--offline", "--mode", "json", "-p"], {
256
+ ...(piPackageRoot ? { piPackageRoot } : {}),
257
+ });
258
+ return {
259
+ command: spawnSpec.command,
260
+ args: spawnSpec.args,
261
+ env: { ...process.env, SELESAI_SUBAGENT_RUNNER_CONFIG: cfgPath },
262
+ };
263
+ }
222
264
  if (!jitiCliPath) {
223
265
  return { error: "upstream jiti for TypeScript execution could not be found; ensure package dependencies are installed" };
224
266
  }
267
+ const runnerScript = resolveRunnerScript();
268
+ if (!runnerScript) return { error: "async runner script could not be resolved" };
269
+ return { command: resolveAsyncRunnerNodeCommand(), args: [jitiCliPath, runnerScript, cfgPath] };
270
+ }
225
271
 
272
+ /**
273
+ * Spawn the async runner process
274
+ */
275
+ function spawnRunner(cfg: object, suffix: string, cwd: string): { pid?: number; error?: string } {
226
276
  try {
227
277
  const cwdStats = fs.statSync(cwd);
228
278
  if (!cwdStats.isDirectory()) {
@@ -235,14 +285,23 @@ function spawnRunner(cfg: object, suffix: string, cwd: string): { pid?: number;
235
285
  fs.mkdirSync(TEMP_ROOT_DIR, { recursive: true });
236
286
  const cfgPath = getAsyncConfigPath(suffix);
237
287
  fs.writeFileSync(cfgPath, JSON.stringify(cfg));
238
- const runner = path.join(path.dirname(fileURLToPath(import.meta.url)), "subagent-runner.ts");
239
- const nodeCommand = resolveAsyncRunnerNodeCommand();
288
+ const asyncDir = (cfg as { asyncDir?: string }).asyncDir;
289
+ const eventsPath = asyncDir ? path.join(asyncDir, "events.jsonl") : undefined;
290
+ const markers = createSpawnTimingMarkers();
291
+ emitSpawnTiming({ eventsPath, marker: "spawn_start", markers, runId: suffix });
292
+
293
+ const spec = buildAsyncRunnerSpawnSpec(cfgPath);
294
+ if ("error" in spec) {
295
+ return { error: spec.error };
296
+ }
297
+ emitSpawnTiming({ eventsPath, marker: "spawn_command_resolved", markers, runId: suffix });
240
298
 
241
- const proc = spawn(nodeCommand, [jitiCliPath, runner, cfgPath], {
299
+ const proc = spawn(spec.command, spec.args, {
242
300
  cwd,
243
301
  detached: true,
244
302
  stdio: "ignore",
245
303
  windowsHide: true,
304
+ ...(spec.env ? { env: spec.env } : {}),
246
305
  });
247
306
  proc.on("error", (error) => {
248
307
  console.error(`[pi-subagents] async spawn failed: ${error.message}`);
@@ -663,7 +722,7 @@ export function executeAsyncChain(
663
722
  path: nestedAddress.path,
664
723
  asyncDir,
665
724
  pid: spawnResult.pid,
666
- ownerIntercomTarget: process.env.PI_SUBAGENT_INTERCOM_SESSION_NAME,
725
+ ownerIntercomTarget: process.env.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME,
667
726
  leafIntercomTarget: childIntercomTargets?.[0],
668
727
  intercomTarget: childIntercomTargets?.[0],
669
728
  ownerState: "live",
@@ -879,7 +938,7 @@ export function executeAsyncSingle(
879
938
  path: nestedAddress.path,
880
939
  asyncDir,
881
940
  pid: spawnResult.pid,
882
- ownerIntercomTarget: process.env.PI_SUBAGENT_INTERCOM_SESSION_NAME,
941
+ ownerIntercomTarget: process.env.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME,
883
942
  leafIntercomTarget: childIntercomTarget?.(agent, 0),
884
943
  intercomTarget: childIntercomTarget?.(agent, 0),
885
944
  ownerState: "live",
@@ -1,4 +1,4 @@
1
- import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
1
+ import type { ExtensionAPI, ExtensionContext } from "@selesai/code";
2
2
  import * as fs from "node:fs";
3
3
  import * as path from "node:path";
4
4
  import { renderWidget, widgetRenderKey } from "../../tui/render.ts";
@@ -2,7 +2,7 @@
2
2
  * Subagent completion notifications.
3
3
  */
4
4
 
5
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
5
+ import type { ExtensionAPI } from "@selesai/code";
6
6
  import { buildCompletionKey, getGlobalSeenMap, markSeenWithTtl } from "./completion-dedupe.ts";
7
7
  import { SUBAGENT_ASYNC_COMPLETE_EVENT } from "../../shared/types.ts";
8
8