@selesai/code 0.1.19 → 0.2.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 (157) 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/models.json +143 -39
  26. package/dist/defaults/settings.json +2 -29
  27. package/dist/extensions/package.json +5 -4
  28. package/dist/extensions/pi-intercom/index.ts +12 -5
  29. package/dist/extensions/pi-powerline-footer/index.ts +4 -1
  30. package/dist/extensions/pi-powerline-footer/tps.ts +286 -0
  31. package/dist/extensions/pi-powerline-footer/welcome.ts +47 -46
  32. package/dist/extensions/pi-subagents/README.md +12 -5
  33. package/dist/extensions/pi-subagents/agents/context-builder.md +2 -2
  34. package/dist/extensions/pi-subagents/agents/researcher.md +4 -5
  35. package/dist/extensions/pi-subagents/package.json +8 -5
  36. package/dist/extensions/pi-subagents/prompts/parallel-context-build.md +1 -1
  37. package/dist/extensions/pi-subagents/prompts/parallel-handoff-plan.md +1 -1
  38. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +1 -1
  39. package/dist/extensions/pi-subagents/src/agents/agents.ts +3 -3
  40. package/dist/extensions/pi-subagents/src/extension/control-notices.ts +1 -1
  41. package/dist/extensions/pi-subagents/src/extension/doctor.ts +3 -3
  42. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +1 -1
  43. package/dist/extensions/pi-subagents/src/extension/index.ts +29 -2
  44. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +2 -2
  45. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +72 -13
  46. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +1 -1
  47. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +1 -1
  48. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +85 -41
  49. package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +1 -1
  50. package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +1 -1
  51. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +46 -3
  52. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +2 -2
  53. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +1 -3
  54. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +2 -2
  55. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +18 -18
  56. package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +24 -24
  57. package/dist/extensions/pi-subagents/src/runs/shared/spawn-timing.ts +46 -0
  58. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +2 -2
  59. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +4 -4
  60. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +1 -1
  61. package/dist/extensions/pi-subagents/src/shared/types.ts +6 -6
  62. package/dist/extensions/pi-subagents/src/shared/utils.ts +3 -3
  63. package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +1 -1
  64. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +1 -1
  65. package/dist/extensions/pi-subagents/src/tui/render-helpers.ts +1 -1
  66. package/dist/extensions/pi-subagents/src/tui/render.ts +1 -1
  67. package/dist/extensions/pi-subagents/test/unit/spawn-timing.test.ts +45 -0
  68. package/dist/extensions/pi-subagents/tsconfig.runner.json +17 -0
  69. package/dist/extensions/pi-web-agent/package.json +31 -0
  70. package/dist/extensions/pi-web-agent/src/backends/config.ts +205 -0
  71. package/dist/extensions/pi-web-agent/src/backends/doctor.ts +136 -0
  72. package/dist/extensions/pi-web-agent/src/backends/factory.ts +152 -0
  73. package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +25 -0
  74. package/dist/extensions/pi-web-agent/src/cache/ttl-cache.ts +28 -0
  75. package/dist/extensions/pi-web-agent/src/changelog-notice.ts +133 -0
  76. package/dist/extensions/pi-web-agent/src/commands/web-agent-config.ts +946 -0
  77. package/dist/extensions/pi-web-agent/src/extension.ts +126 -0
  78. package/dist/extensions/pi-web-agent/src/extract/readability.ts +118 -0
  79. package/dist/extensions/pi-web-agent/src/fetch/browser-resolution.ts +199 -0
  80. package/dist/extensions/pi-web-agent/src/fetch/firecrawl-fetch.ts +100 -0
  81. package/dist/extensions/pi-web-agent/src/fetch/headless-fetch.ts +117 -0
  82. package/dist/extensions/pi-web-agent/src/fetch/http-fetch.ts +67 -0
  83. package/dist/extensions/pi-web-agent/src/orchestration/answer-synthesizer.ts +60 -0
  84. package/dist/extensions/pi-web-agent/src/orchestration/candidate-selector.ts +50 -0
  85. package/dist/extensions/pi-web-agent/src/orchestration/direct-url.ts +52 -0
  86. package/dist/extensions/pi-web-agent/src/orchestration/evidence-quality.ts +105 -0
  87. package/dist/extensions/pi-web-agent/src/orchestration/evidence-ranker.ts +45 -0
  88. package/dist/extensions/pi-web-agent/src/orchestration/index.ts +28 -0
  89. package/dist/extensions/pi-web-agent/src/orchestration/query-planner.ts +47 -0
  90. package/dist/extensions/pi-web-agent/src/orchestration/research-orchestrator.ts +376 -0
  91. package/dist/extensions/pi-web-agent/src/orchestration/research-types.ts +64 -0
  92. package/dist/extensions/pi-web-agent/src/orchestration/research-worker.ts +181 -0
  93. package/dist/extensions/pi-web-agent/src/orchestration/source-profile.ts +101 -0
  94. package/dist/extensions/pi-web-agent/src/orchestration/stop-decider.ts +81 -0
  95. package/dist/extensions/pi-web-agent/src/presentation/config-store.ts +208 -0
  96. package/dist/extensions/pi-web-agent/src/presentation/config.ts +75 -0
  97. package/dist/extensions/pi-web-agent/src/presentation/explore-presentation.ts +61 -0
  98. package/dist/extensions/pi-web-agent/src/presentation/fetch-presentation.ts +54 -0
  99. package/dist/extensions/pi-web-agent/src/presentation/search-presentation.ts +41 -0
  100. package/dist/extensions/pi-web-agent/src/presentation/select-view.ts +20 -0
  101. package/dist/extensions/pi-web-agent/src/presentation/types.ts +63 -0
  102. package/dist/extensions/pi-web-agent/src/search/brave.ts +114 -0
  103. package/dist/extensions/pi-web-agent/src/search/duckduckgo.ts +72 -0
  104. package/dist/extensions/pi-web-agent/src/search/searxng.ts +96 -0
  105. package/dist/extensions/pi-web-agent/src/tools/web-explore.ts +71 -0
  106. package/dist/extensions/pi-web-agent/src/tools/web-fetch-headless.ts +31 -0
  107. package/dist/extensions/pi-web-agent/src/tools/web-fetch.ts +31 -0
  108. package/dist/extensions/pi-web-agent/src/tools/web-search.ts +157 -0
  109. package/dist/extensions/pi-web-agent/src/types.ts +88 -0
  110. package/dist/extensions/ponytail/index.js +189 -0
  111. package/dist/extensions/ponytail/package.json +8 -0
  112. package/dist/extensions/ponytail/ponytail-config.cjs +122 -0
  113. package/dist/extensions/ponytail/ponytail-instructions.cjs +94 -0
  114. package/dist/extensions/ponytail/test/extension.test.js +167 -0
  115. package/dist/extensions/ponytail/test/helpers.test.js +92 -0
  116. package/dist/extensions/question/constants.ts +38 -0
  117. package/dist/extensions/question/dialog-adapter.ts +74 -0
  118. package/dist/extensions/question/helpers.ts +102 -0
  119. package/dist/extensions/question/index.ts +671 -0
  120. package/dist/extensions/question/navigation.ts +14 -0
  121. package/dist/extensions/question/package.json +18 -0
  122. package/dist/extensions/question/question-list.ts +498 -0
  123. package/dist/extensions/question/row-layout.ts +162 -0
  124. package/dist/extensions/question/schemas.ts +69 -0
  125. package/dist/extensions/question/selection-mode.ts +49 -0
  126. package/dist/extensions/question/shortcuts.ts +53 -0
  127. package/dist/extensions/question/tests/helpers.test.ts +178 -0
  128. package/dist/extensions/question/tests/question-list.test.ts +230 -0
  129. package/dist/extensions/question/tests/row-layout.test.ts +136 -0
  130. package/dist/extensions/question/tests/shortcuts.test.ts +85 -0
  131. package/dist/extensions/question/tests/ui-protocol.test.ts +143 -0
  132. package/dist/extensions/question/tui-adapter.ts +33 -0
  133. package/dist/extensions/question/types.ts +102 -0
  134. package/dist/extensions/question/ui-protocol.ts +46 -0
  135. package/dist/extensions/tokenin-onboarding.ts +265 -2
  136. package/dist/extensions/web-agent-onboarding.ts +222 -0
  137. package/dist/extensions/workflow/adapter.ts +588 -0
  138. package/dist/extensions/workflow/extension.ts +24 -0
  139. package/dist/extensions/workflow/modes/prototype.ts +156 -0
  140. package/dist/extensions/workflow/modes/quick.ts +138 -0
  141. package/dist/extensions/workflow/package.json +17 -0
  142. package/dist/extensions/workflow/state-machine.ts +386 -0
  143. package/dist/index.d.ts +1 -1
  144. package/dist/index.d.ts.map +1 -1
  145. package/dist/index.js +1 -1
  146. package/dist/index.js.map +1 -1
  147. package/dist/modes/interactive/interactive-mode.d.ts +2 -0
  148. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  149. package/dist/modes/interactive/interactive-mode.js +57 -13
  150. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  151. package/dist/utils/mime.d.ts.map +1 -1
  152. package/dist/utils/mime.js +24 -1
  153. package/dist/utils/mime.js.map +1 -1
  154. package/docs/docs.json +4 -0
  155. package/docs/workflows.md +206 -0
  156. package/package.json +5 -1
  157. package/README.md +0 -198
@@ -22,12 +22,13 @@ export interface LoadedCounts {
22
22
  // ═══════════════════════════════════════════════════════════════════════════
23
23
 
24
24
  const PI_LOGO = [
25
- "██████████ ",
26
- "████ ████ ",
27
- "████ ████ ",
28
- "████████ ████",
29
- "████ ████",
30
- "████ ████",
25
+ "███ ███ █ ███ ███ ███ █",
26
+ "█ █ █ █ █ █ █ █",
27
+ "█ █ █ █ █ █ █ █",
28
+ "███ ███ █ ███ ███ ███ █",
29
+ " █ █ █ █ █ █ █ █",
30
+ " █ █ █ █ █ █ █ █",
31
+ "███ ███ ███ ███ ███ █ █ █",
31
32
  ];
32
33
 
33
34
  const GRADIENT_COLORS = [
@@ -89,7 +90,7 @@ interface WelcomeData {
89
90
 
90
91
  function buildLeftColumn(data: WelcomeData, colWidth: number): string[] {
91
92
  const logoColored = PI_LOGO.map((line) => gradientLine(line));
92
-
93
+
93
94
  return [
94
95
  "",
95
96
  centerText(bold("Welcome back!"), colWidth),
@@ -104,7 +105,7 @@ function buildLeftColumn(data: WelcomeData, colWidth: number): string[] {
104
105
  function buildRightColumn(data: WelcomeData, colWidth: number): string[] {
105
106
  const hChar = "─";
106
107
  const separator = ` ${dim(hChar.repeat(colWidth - 2))}`;
107
-
108
+
108
109
  // Session lines
109
110
  const sessionLines: string[] = [];
110
111
  if (data.recentSessions.length === 0) {
@@ -116,12 +117,12 @@ function buildRightColumn(data: WelcomeData, colWidth: number): string[] {
116
117
  );
117
118
  }
118
119
  }
119
-
120
+
120
121
  // Loaded counts lines
121
122
  const countLines: string[] = [];
122
123
  const { contextFiles, extensions, skills, promptTemplates } = data.loadedCounts;
123
124
  const itemPrefix = dim("- ");
124
-
125
+
125
126
  if (contextFiles > 0 || extensions > 0 || skills > 0 || promptTemplates > 0) {
126
127
  if (contextFiles > 0) {
127
128
  countLines.push(` ${itemPrefix}${fgOnly("gitClean", `${contextFiles}`)} context file${contextFiles !== 1 ? "s" : ""}`);
@@ -138,7 +139,7 @@ function buildRightColumn(data: WelcomeData, colWidth: number): string[] {
138
139
  } else {
139
140
  countLines.push(` ${dim("No extensions loaded")}`);
140
141
  }
141
-
142
+
142
143
  return [
143
144
  ` ${bold(fgOnly("accent", "Tips"))}`,
144
145
  ` ${dim("/")} for commands`,
@@ -155,46 +156,46 @@ function buildRightColumn(data: WelcomeData, colWidth: number): string[] {
155
156
  }
156
157
 
157
158
  function renderWelcomeBox(
158
- data: WelcomeData,
159
- termWidth: number,
159
+ data: WelcomeData,
160
+ termWidth: number,
160
161
  bottomLine: string,
161
162
  ): string[] {
162
163
  // Minimum width for two-column layout: leftCol(26) + separator(3) + minRightCol(15) = 44
163
164
  const minLayoutWidth = 44;
164
-
165
+
165
166
  // If terminal is too narrow for the layout, return empty (skip welcome box)
166
167
  if (termWidth < minLayoutWidth) {
167
168
  return [];
168
169
  }
169
-
170
+
170
171
  const minWidth = 76;
171
172
  const maxWidth = 96;
172
173
  // Clamp to termWidth to prevent crash on narrow terminals
173
174
  const boxWidth = Math.min(termWidth, Math.max(minWidth, Math.min(termWidth - 2, maxWidth)));
174
175
  const leftCol = 26;
175
176
  const rightCol = Math.max(1, boxWidth - leftCol - 3); // Ensure rightCol is at least 1
176
-
177
+
177
178
  const hChar = "─";
178
179
  const v = dim("│");
179
180
  const tl = dim("╭");
180
181
  const tr = dim("╮");
181
182
  const bl = dim("╰");
182
183
  const br = dim("╯");
183
-
184
+
184
185
  const leftLines = buildLeftColumn(data, leftCol);
185
186
  const rightLines = buildRightColumn(data, rightCol);
186
-
187
+
187
188
  const lines: string[] = [];
188
-
189
+
189
190
  // Top border with title
190
- const title = " pi agent ";
191
+ const title = "SelesaiCode";
191
192
  const titlePrefix = dim(hChar.repeat(3));
192
193
  const titleStyled = titlePrefix + fgOnly("model", title);
193
194
  const titleVisLen = 3 + visibleWidth(title);
194
195
  const afterTitle = boxWidth - 2 - titleVisLen;
195
196
  const afterTitleText = afterTitle > 0 ? dim(hChar.repeat(afterTitle)) : "";
196
197
  lines.push(tl + titleStyled + afterTitleText + tr);
197
-
198
+
198
199
  // Content rows
199
200
  const maxRows = Math.max(leftLines.length, rightLines.length);
200
201
  for (let i = 0; i < maxRows; i++) {
@@ -202,10 +203,10 @@ function renderWelcomeBox(
202
203
  const right = fitToWidth(rightLines[i] ?? "", rightCol);
203
204
  lines.push(v + left + v + right + v);
204
205
  }
205
-
206
+
206
207
  // Bottom border
207
208
  lines.push(bl + bottomLine + br);
208
-
209
+
209
210
  return lines;
210
211
  }
211
212
 
@@ -214,7 +215,7 @@ function renderWelcomeBox(
214
215
  // ═══════════════════════════════════════════════════════════════════════════
215
216
 
216
217
  /**
217
- * Welcome overlay component for pi agent.
218
+ * Welcome overlay component for SelesaiCode.
218
219
  * Displays a branded splash screen with logo, tips, and loaded counts.
219
220
  */
220
221
  export class WelcomeComponent implements Component {
@@ -242,12 +243,12 @@ export class WelcomeComponent implements Component {
242
243
  if (termWidth < minLayoutWidth) {
243
244
  return [];
244
245
  }
245
-
246
+
246
247
  const minWidth = 76;
247
248
  const maxWidth = 96;
248
249
  // Clamp to termWidth to prevent crash on narrow terminals
249
250
  const boxWidth = Math.min(termWidth, Math.max(minWidth, Math.min(termWidth - 2, maxWidth)));
250
-
251
+
251
252
  // Bottom line with countdown
252
253
  const countdownText = ` Press any key to continue (${this.countdown}s) `;
253
254
  const countdownStyled = dim(countdownText);
@@ -256,10 +257,10 @@ export class WelcomeComponent implements Component {
256
257
  const leftPad = Math.floor((bottomContentWidth - countdownVisLen) / 2);
257
258
  const rightPad = bottomContentWidth - countdownVisLen - leftPad;
258
259
  const hChar = "─";
259
- const bottomLine = dim(hChar.repeat(Math.max(0, leftPad))) +
260
- countdownStyled +
260
+ const bottomLine = dim(hChar.repeat(Math.max(0, leftPad))) +
261
+ countdownStyled +
261
262
  dim(hChar.repeat(Math.max(0, rightPad)));
262
-
263
+
263
264
  return renderWelcomeBox(this.data, termWidth, bottomLine);
264
265
  }
265
266
  }
@@ -288,18 +289,18 @@ export class WelcomeHeader implements Component {
288
289
  if (termWidth < minLayoutWidth) {
289
290
  return [];
290
291
  }
291
-
292
+
292
293
  const minWidth = 76;
293
294
  const maxWidth = 96;
294
295
  // Clamp to termWidth to prevent crash on narrow terminals
295
296
  const boxWidth = Math.min(termWidth, Math.max(minWidth, Math.min(termWidth - 2, maxWidth)));
296
297
  const hChar = "─";
297
-
298
+
298
299
  // Bottom line with column separator (leftCol=26, rightCol=boxWidth-29)
299
300
  const leftCol = 26;
300
301
  const rightCol = Math.max(1, boxWidth - leftCol - 3);
301
302
  const bottomLine = dim(hChar.repeat(leftCol)) + dim("┴") + dim(hChar.repeat(rightCol));
302
-
303
+
303
304
  const lines = renderWelcomeBox(this.data, termWidth, bottomLine);
304
305
  if (lines.length > 0) {
305
306
  lines.push(""); // Add empty line for spacing only if we rendered content
@@ -335,7 +336,7 @@ function logDiscoveryError(scope: string, error: unknown): void {
335
336
  export function discoverLoadedCounts(): LoadedCounts {
336
337
  const homeDir = process.env.HOME || process.env.USERPROFILE || osHomedir();
337
338
  const cwd = process.cwd();
338
-
339
+
339
340
  let contextFiles = 0;
340
341
  let extensions = 0;
341
342
  let skills = 0;
@@ -348,7 +349,7 @@ export function discoverLoadedCounts(): LoadedCounts {
348
349
  join(cwd, ".pi", "AGENTS.md"),
349
350
  join(cwd, ".claude", "AGENTS.md"),
350
351
  ];
351
-
352
+
352
353
  for (const path of agentsMdPaths) {
353
354
  if (existsSync(path)) contextFiles++;
354
355
  }
@@ -463,9 +464,9 @@ export function discoverLoadedCounts(): LoadedCounts {
463
464
  join(cwd, ".pi", "skills"),
464
465
  join(cwd, "skills"),
465
466
  ];
466
-
467
+
467
468
  const countedSkills = new Set<string>();
468
-
469
+
469
470
  for (const dir of skillDirs) {
470
471
  if (existsSync(dir)) {
471
472
  try {
@@ -497,9 +498,9 @@ export function discoverLoadedCounts(): LoadedCounts {
497
498
  join(cwd, ".pi", "commands"),
498
499
  join(cwd, ".claude", "commands"),
499
500
  ];
500
-
501
+
501
502
  const countedTemplates = new Set<string>();
502
-
503
+
503
504
  function countTemplatesInDir(dir: string) {
504
505
  if (!existsSync(dir)) return;
505
506
  try {
@@ -525,7 +526,7 @@ export function discoverLoadedCounts(): LoadedCounts {
525
526
  logDiscoveryError(`Failed to scan prompt template dir ${dir}`, error);
526
527
  }
527
528
  }
528
-
529
+
529
530
  for (const dir of templateDirs) {
530
531
  countTemplatesInDir(dir);
531
532
  }
@@ -538,14 +539,14 @@ export function discoverLoadedCounts(): LoadedCounts {
538
539
  */
539
540
  export function getRecentSessions(maxCount: number = 3): RecentSession[] {
540
541
  const homeDir = process.env.HOME || process.env.USERPROFILE || osHomedir();
541
-
542
+
542
543
  const sessionsDirs = [
543
544
  join(homeDir, ".pi", "agent", "sessions"),
544
545
  join(homeDir, ".pi", "sessions"),
545
546
  ];
546
-
547
+
547
548
  const sessions: { name: string; mtime: number }[] = [];
548
-
549
+
549
550
  function scanDir(dir: string) {
550
551
  if (!existsSync(dir)) return;
551
552
  try {
@@ -573,15 +574,15 @@ export function getRecentSessions(maxCount: number = 3): RecentSession[] {
573
574
  logDiscoveryError(`Failed to scan sessions dir ${dir}`, error);
574
575
  }
575
576
  }
576
-
577
+
577
578
  for (const sessionsDir of sessionsDirs) {
578
579
  scanDir(sessionsDir);
579
580
  }
580
-
581
+
581
582
  if (sessions.length === 0) return [];
582
-
583
+
583
584
  sessions.sort((a, b) => b.mtime - a.mtime);
584
-
585
+
585
586
  const seen = new Set<string>();
586
587
  const uniqueSessions: typeof sessions = [];
587
588
  for (const s of sessions) {
@@ -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>);