@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
@@ -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
 
@@ -6,7 +6,7 @@ import type { Message } from "@earendil-works/pi-ai";
6
6
  import { writeAtomicJson } from "../../shared/atomic-json.ts";
7
7
  import { consumeInterruptRequest, watchAsyncControlInbox } from "./control-channel.ts";
8
8
  import { appendJsonl as appendRawJsonl, getArtifactPaths } from "../../shared/artifacts.ts";
9
- import { PI_CODING_AGENT_PACKAGE, getPiSpawnCommand, resolveInstalledPiPackageRoot } from "../shared/pi-spawn.ts";
9
+ import { SELESAI_PACKAGE, getSelesaiSpawnCommand, resolveInstalledSelesaiPackageRoot } from "../shared/pi-spawn.ts";
10
10
  import { captureSingleOutputSnapshot, finalizeSingleOutput, formatSavedOutputReference, resolveSingleOutput, type SingleOutputSnapshot } from "../shared/single-output.ts";
11
11
  import {
12
12
  type ActivityState,
@@ -81,6 +81,7 @@ import { resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.ts
81
81
  import { acceptanceFailureMessage, aggregateAcceptanceReport, evaluateAcceptance, formatAcceptancePrompt, stripAcceptanceReport } from "../shared/acceptance.ts";
82
82
  import { waitForImportedAsyncRoot } from "./chain-root-attachment.ts";
83
83
  import { appendRunnerStepsToStatus, consumeChainAppendRequests, countPendingChainAppendRequests } from "./chain-append.ts";
84
+ import { createSpawnTimingMarkers, emitSpawnTiming, type SpawnTimingMarkers } from "../shared/spawn-timing.ts";
84
85
 
85
86
  interface SubagentRunConfig {
86
87
  id: string;
@@ -133,7 +134,7 @@ interface StepResult {
133
134
 
134
135
  const ASYNC_INTERRUPT_SIGNAL: NodeJS.Signals = process.platform === "win32" ? "SIGBREAK" : "SIGUSR2";
135
136
  const DEFAULT_MAX_ASYNC_EVENTS_BYTES = 50 * 1024 * 1024;
136
- const ASYNC_EVENTS_MAX_BYTES_ENV = "PI_SUBAGENT_ASYNC_EVENTS_MAX_BYTES";
137
+ const ASYNC_EVENTS_MAX_BYTES_ENV = "SELESAI_SUBAGENT_ASYNC_EVENTS_MAX_BYTES";
137
138
  const TRUNCATED_EVENT_TYPE = "subagent.events.truncated";
138
139
  const TRUNCATION_MARKER_RESERVE_BYTES = 512;
139
140
 
@@ -261,6 +262,7 @@ interface ChildEventContext {
261
262
  runId: string;
262
263
  stepIndex: number;
263
264
  agent: string;
265
+ markers?: SpawnTimingMarkers;
264
266
  }
265
267
 
266
268
  interface ChildUsage {
@@ -313,10 +315,17 @@ function runPiStreaming(
313
315
  return new Promise((resolve) => {
314
316
  const outputStream = fs.createWriteStream(outputFile, { flags: "w" });
315
317
  const spawnEnv = { ...process.env, ...(env ?? {}), ...getSubagentDepthEnv(maxSubagentDepth) };
316
- const spawnSpec = getPiSpawnCommand(args, {
318
+ const markers = childEventContext ? createSpawnTimingMarkers() : undefined;
319
+ if (markers) {
320
+ emitSpawnTiming({ eventsPath: childEventContext.eventsPath, marker: "spawn_start", markers, runId: childEventContext.runId, stepIndex: childEventContext.stepIndex, agent: childEventContext.agent });
321
+ }
322
+ const spawnSpec = getSelesaiSpawnCommand(args, {
317
323
  ...(piPackageRoot ? { piPackageRoot } : {}),
318
324
  ...(piArgv1 ? { argv1: piArgv1 } : {}),
319
325
  });
326
+ if (markers) {
327
+ emitSpawnTiming({ eventsPath: childEventContext.eventsPath, marker: "spawn_command_resolved", markers, runId: childEventContext.runId, stepIndex: childEventContext.stepIndex, agent: childEventContext.agent });
328
+ }
320
329
  const child = spawn(spawnSpec.command, spawnSpec.args, {
321
330
  cwd,
322
331
  stdio: ["ignore", "pipe", "pipe"],
@@ -333,8 +342,22 @@ function runPiStreaming(
333
342
  let assistantError: string | undefined;
334
343
  let interrupted = false;
335
344
  let observedMutationAttempt = false;
345
+ let firstEventEmitted = false;
346
+ let firstJsonlEventEmitted = false;
336
347
  const rawStdoutLines: string[] = [];
337
348
 
349
+ const emitChildTiming = (marker: import("../shared/spawn-timing.ts").SpawnTimingMarker) => {
350
+ if (!markers || !childEventContext) return;
351
+ emitSpawnTiming({
352
+ eventsPath: childEventContext.eventsPath,
353
+ marker,
354
+ markers,
355
+ runId: childEventContext.runId,
356
+ stepIndex: childEventContext.stepIndex,
357
+ agent: childEventContext.agent,
358
+ });
359
+ };
360
+
338
361
  const writeOutputLine = (line: string) => {
339
362
  if (!line.trim()) return;
340
363
  outputStream.write(`${line}\n`);
@@ -368,6 +391,10 @@ function runPiStreaming(
368
391
  let event: ChildEvent;
369
392
  try {
370
393
  event = JSON.parse(line) as ChildEvent;
394
+ if (!firstJsonlEventEmitted) {
395
+ firstJsonlEventEmitted = true;
396
+ emitChildTiming("child_first_jsonl_event");
397
+ }
371
398
  } catch {
372
399
  rawStdoutLines.push(line);
373
400
  writeOutputLine(line);
@@ -438,6 +465,10 @@ function runPiStreaming(
438
465
  let settled = false;
439
466
  const clearStdioGuard = attachPostExitStdioGuard(child, { idleMs: 2000, hardMs: 8000 });
440
467
  child.stdout.on("data", (chunk: Buffer) => {
468
+ if (!firstEventEmitted) {
469
+ firstEventEmitted = true;
470
+ emitChildTiming("child_first_event");
471
+ }
441
472
  const text = chunk.toString();
442
473
  stdoutBuf += text;
443
474
  const lines = stdoutBuf.split("\n");
@@ -446,6 +477,10 @@ function runPiStreaming(
446
477
  });
447
478
 
448
479
  child.stderr.on("data", (chunk: Buffer) => {
480
+ if (!firstEventEmitted) {
481
+ firstEventEmitted = true;
482
+ emitChildTiming("child_first_event");
483
+ }
449
484
  processStderrText(chunk.toString());
450
485
  });
451
486
  registerInterrupt?.(() => {
@@ -526,14 +561,14 @@ function runPiStreaming(
526
561
  });
527
562
  }
528
563
 
529
- function resolvePiPackageRootFallback(): string {
530
- const root = resolveInstalledPiPackageRoot();
564
+ function resolveSelesaiPackageRootFallback(): string {
565
+ const root = resolveInstalledSelesaiPackageRoot();
531
566
  if (root) return root;
532
- throw new Error(`Could not resolve ${PI_CODING_AGENT_PACKAGE} package root`);
567
+ throw new Error(`Could not resolve ${SELESAI_PACKAGE} package root`);
533
568
  }
534
569
 
535
570
  async function exportSessionHtml(sessionFile: string, outputDir: string, piPackageRoot?: string): Promise<string> {
536
- const pkgRoot = piPackageRoot ?? resolvePiPackageRootFallback();
571
+ const pkgRoot = piPackageRoot ?? resolveSelesaiPackageRootFallback();
537
572
  const exportModulePath = path.join(pkgRoot, "dist", "core", "export-html", "index.js");
538
573
  const moduleUrl = pathToFileURL(exportModulePath).href;
539
574
  const mod = await import(moduleUrl);
@@ -752,7 +787,7 @@ async function runSingleStep(
752
787
  }
753
788
  const { args, env, tempDir } = buildPiArgs({
754
789
  parentSessionId: step.parentSessionId,
755
- baseArgs: ["--mode", "json", "-p"],
790
+ baseArgs: ["--offline", "--mode", "json", "-p"],
756
791
  task,
757
792
  sessionEnabled,
758
793
  sessionDir,
@@ -1056,7 +1091,7 @@ function ensureParallelProgressFile(cwd: string, group: Extract<RunnerStep, { pa
1056
1091
  writeInitialProgressFile(cwd);
1057
1092
  }
1058
1093
 
1059
- async function runSubagent(config: SubagentRunConfig): Promise<void> {
1094
+ export async function runSubagent(config: SubagentRunConfig): Promise<void> {
1060
1095
  const { id, steps, resultPath, cwd, placeholder, taskIndex, totalTasks, maxOutput, artifactsDir, artifactConfig } =
1061
1096
  config;
1062
1097
  let previousOutput = "";
@@ -2419,40 +2454,49 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
2419
2454
  }
2420
2455
  }
2421
2456
 
2422
- const configArg = process.argv[2];
2423
- if (configArg) {
2457
+ export async function runSubagentFromConfigFile(cfgPath: string): Promise<void> {
2458
+ const configJson = fs.readFileSync(cfgPath, "utf-8");
2459
+ const config = JSON.parse(configJson) as SubagentRunConfig;
2424
2460
  try {
2425
- const configJson = fs.readFileSync(configArg, "utf-8");
2426
- const config = JSON.parse(configJson) as SubagentRunConfig;
2427
- try {
2428
- fs.unlinkSync(configArg);
2429
- } catch {
2430
- // Temp config cleanup is best effort.
2431
- }
2432
- runSubagent(config).catch((runErr) => {
2433
- console.error("Subagent runner error:", runErr);
2434
- process.exit(1);
2435
- });
2436
- } catch (err) {
2437
- console.error("Subagent runner error:", err);
2438
- process.exit(1);
2461
+ fs.unlinkSync(cfgPath);
2462
+ } catch {
2463
+ // Temp config cleanup is best effort.
2439
2464
  }
2440
- } else {
2441
- let input = "";
2442
- process.stdin.setEncoding("utf-8");
2443
- process.stdin.on("data", (chunk) => {
2444
- input += chunk;
2445
- });
2446
- process.stdin.on("end", () => {
2447
- try {
2448
- const config = JSON.parse(input) as SubagentRunConfig;
2449
- runSubagent(config).catch((runErr) => {
2450
- console.error("Subagent runner error:", runErr);
2451
- process.exit(1);
2452
- });
2453
- } catch (err) {
2465
+ await runSubagent(config);
2466
+ }
2467
+
2468
+ function isRunnerMainModule(): boolean {
2469
+ try {
2470
+ return import.meta.url === pathToFileURL(process.argv[1] ?? "").href;
2471
+ } catch {
2472
+ return false;
2473
+ }
2474
+ }
2475
+
2476
+ if (!runnerConfigPath && isRunnerMainModule()) {
2477
+ const configArg = process.argv[2];
2478
+ if (configArg) {
2479
+ runSubagentFromConfigFile(configArg).catch((err) => {
2454
2480
  console.error("Subagent runner error:", err);
2455
2481
  process.exit(1);
2456
- }
2457
- });
2482
+ });
2483
+ } else {
2484
+ let input = "";
2485
+ process.stdin.setEncoding("utf-8");
2486
+ process.stdin.on("data", (chunk) => {
2487
+ input += chunk;
2488
+ });
2489
+ process.stdin.on("end", () => {
2490
+ try {
2491
+ const config = JSON.parse(input) as SubagentRunConfig;
2492
+ runSubagent(config).catch((err) => {
2493
+ console.error("Subagent runner error:", err);
2494
+ process.exit(1);
2495
+ });
2496
+ } catch (err) {
2497
+ console.error("Subagent runner error:", err);
2498
+ process.exit(1);
2499
+ }
2500
+ });
2501
+ }
2458
2502
  }
@@ -5,7 +5,7 @@
5
5
  * Supports runtime editing of templates, output paths, reads lists, and progress toggle.
6
6
  */
7
7
 
8
- import type { Theme } from "@earendil-works/pi-coding-agent";
8
+ import type { Theme } from "@selesai/code";
9
9
  import type { Component, TUI } from "@earendil-works/pi-tui";
10
10
  import { matchesKey, visibleWidth, truncateToWidth } from "@earendil-works/pi-tui";
11
11
  import type { AgentConfig } from "../../agents/agents.ts";
@@ -5,7 +5,7 @@
5
5
  import * as fs from "node:fs";
6
6
  import * as path from "node:path";
7
7
  import type { AgentToolResult } from "@earendil-works/pi-agent-core";
8
- import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
8
+ import type { ExtensionContext } from "@selesai/code";
9
9
  import type { AgentConfig } from "../../agents/agents.ts";
10
10
  import { ChainClarifyComponent, type ChainClarifyResult, type BehaviorOverride } from "./chain-clarify.ts";
11
11
  import { toModelInfo, type ModelInfo } from "../../shared/model-info.ts";
@@ -44,10 +44,11 @@ import {
44
44
  } from "../../shared/utils.ts";
45
45
  import { buildSkillInjection, resolveSkillsWithFallback } from "../../agents/skills.ts";
46
46
  import { evaluateCompletionMutationGuard } from "../shared/completion-guard.ts";
47
- import { getPiSpawnCommand } from "../shared/pi-spawn.ts";
47
+ import { getSelesaiSpawnCommand } from "../shared/pi-spawn.ts";
48
48
  import { createJsonlWriter } from "../../shared/jsonl-writer.ts";
49
49
  import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.ts";
50
50
  import { applyThinkingSuffix, buildPiArgs, cleanupTempDir } from "../shared/pi-args.ts";
51
+ import { createSpawnTimingMarkers, emitSpawnTiming } from "../shared/spawn-timing.ts";
51
52
  import { readStructuredOutput } from "../shared/structured-output.ts";
52
53
  import { captureSingleOutputSnapshot, formatSavedOutputReference, injectOutputPathSystemPrompt, resolveSingleOutput, validateFileOnlyOutputMode, type SingleOutputSnapshot } from "../shared/single-output.ts";
53
54
  import {
@@ -182,7 +183,7 @@ async function runSingleAttempt(
182
183
  ): Promise<SingleResult> {
183
184
  const modelArg = applyThinkingSuffix(model, agent.thinking);
184
185
  const { args, env: sharedEnv, tempDir } = buildPiArgs({
185
- baseArgs: ["--mode", "json", "-p"],
186
+ baseArgs: ["--offline", "--mode", "json", "-p"],
186
187
  task,
187
188
  sessionEnabled: shared.sessionEnabled,
188
189
  sessionDir: options.sessionDir,
@@ -278,7 +279,24 @@ async function runSingleAttempt(
278
279
  let observedMutationAttempt = false;
279
280
 
280
281
  const exitCode = await new Promise<number>((resolve) => {
281
- const spawnSpec = getPiSpawnCommand(args);
282
+ const markers = createSpawnTimingMarkers();
283
+ const spawnSpec = getSelesaiSpawnCommand(args);
284
+ emitSpawnTiming({
285
+ eventsPath: shared.jsonlPath,
286
+ marker: "spawn_start",
287
+ markers,
288
+ runId: options.runId,
289
+ stepIndex: options.index ?? 0,
290
+ agent: agent.name,
291
+ });
292
+ emitSpawnTiming({
293
+ eventsPath: shared.jsonlPath,
294
+ marker: "spawn_command_resolved",
295
+ markers,
296
+ runId: options.runId,
297
+ stepIndex: options.index ?? 0,
298
+ agent: agent.name,
299
+ });
282
300
  const proc = spawn(spawnSpec.command, spawnSpec.args, {
283
301
  cwd: options.cwd ?? runtimeCwd,
284
302
  env: spawnEnv,
@@ -286,6 +304,8 @@ async function runSingleAttempt(
286
304
  windowsHide: true,
287
305
  });
288
306
  const jsonlWriter = createJsonlWriter(shared.jsonlPath, proc.stdout);
307
+ let firstEventEmitted = false;
308
+ let firstJsonlEventEmitted = false;
289
309
  let buf = "";
290
310
  let processClosed = false;
291
311
  let settled = false;
@@ -498,12 +518,27 @@ async function runSingleAttempt(
498
518
  emitUpdateSnapshot(output || "(running...)");
499
519
  };
500
520
 
521
+ const emitTiming = (marker: import("../shared/spawn-timing.ts").SpawnTimingMarker) => {
522
+ emitSpawnTiming({
523
+ eventsPath: shared.jsonlPath,
524
+ marker,
525
+ markers,
526
+ runId: options.runId,
527
+ stepIndex: options.index ?? 0,
528
+ agent: agent.name,
529
+ });
530
+ };
531
+
501
532
  const processLine = (line: string) => {
502
533
  if (!line.trim()) return;
503
534
  jsonlWriter.writeLine(line);
504
535
  let evt: { type?: string; message?: Message; toolName?: string; args?: unknown };
505
536
  try {
506
537
  evt = JSON.parse(line) as { type?: string; message?: Message; toolName?: string; args?: unknown };
538
+ if (!firstJsonlEventEmitted) {
539
+ firstJsonlEventEmitted = true;
540
+ emitTiming("child_first_jsonl_event");
541
+ }
507
542
  } catch {
508
543
  // Non-JSON stdout lines are expected; only structured events are parsed.
509
544
  return;
@@ -650,12 +685,20 @@ async function runSingleAttempt(
650
685
 
651
686
  const clearStdioGuard = attachPostExitStdioGuard(proc, { idleMs: 2000, hardMs: 8000 });
652
687
  proc.stdout.on("data", (d) => {
688
+ if (!firstEventEmitted) {
689
+ firstEventEmitted = true;
690
+ emitTiming("child_first_event");
691
+ }
653
692
  buf += d.toString();
654
693
  const lines = buf.split("\n");
655
694
  buf = lines.pop() || "";
656
695
  lines.forEach(processLine);
657
696
  });
658
697
  proc.stderr.on("data", (d) => {
698
+ if (!firstEventEmitted) {
699
+ firstEventEmitted = true;
700
+ emitTiming("child_first_event");
701
+ }
659
702
  stderrBuf += d.toString();
660
703
  });
661
704
  proc.on("exit", () => {
@@ -2,7 +2,7 @@ import { randomUUID } from "node:crypto";
2
2
  import * as fs from "node:fs";
3
3
  import * as path from "node:path";
4
4
  import type { AgentToolResult } from "@earendil-works/pi-agent-core";
5
- import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
5
+ import type { ExtensionAPI, ExtensionContext } from "@selesai/code";
6
6
  import { type AgentConfig, type AgentScope } from "../../agents/agents.ts";
7
7
  import { getArtifactsDir } from "../../shared/artifacts.ts";
8
8
  import { ChainClarifyComponent, type ChainClarifyResult } from "./chain-clarify.ts";
@@ -3035,7 +3035,7 @@ export function createSubagentExecutor(deps: ExecutorDeps): {
3035
3035
  parentStepIndex: nestedParentAddress.parentStepIndex,
3036
3036
  depth: nestedParentAddress.depth,
3037
3037
  path: nestedParentAddress.path,
3038
- ownerIntercomTarget: process.env.PI_SUBAGENT_INTERCOM_SESSION_NAME,
3038
+ ownerIntercomTarget: process.env.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME,
3039
3039
  leafIntercomTarget,
3040
3040
  intercomTarget: leafIntercomTarget,
3041
3041
  ownerState: state === "running" ? "live" : "gone",
@@ -59,9 +59,7 @@ const READ_ONLY_BUILTIN_TOOLS = new Set([
59
59
  "grep",
60
60
  "find",
61
61
  "ls",
62
- "web_search",
63
- "fetch_content",
64
- "get_search_content",
62
+ "web_explore",
65
63
  "intercom",
66
64
  "contact_supervisor",
67
65
  ]);
@@ -802,8 +802,8 @@ export function nestedSummaryFromAsyncStatus(status: AsyncStatus, asyncDir: stri
802
802
 
803
803
  export function nestedArtifactEnv(rootRunId: string, parentRunId: string): Record<string, string> {
804
804
  return {
805
- PI_SUBAGENT_NESTED_ROOT_RUN_ID: rootRunId,
806
- PI_SUBAGENT_NESTED_PARENT_RUN_ID: parentRunId,
805
+ SELESAI_SUBAGENT_NESTED_ROOT_RUN_ID: rootRunId,
806
+ SELESAI_SUBAGENT_NESTED_PARENT_RUN_ID: parentRunId,
807
807
  };
808
808
  }
809
809
 
@@ -11,21 +11,21 @@ const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"];
11
11
  const TASK_ARG_LIMIT = 8000;
12
12
  const PROMPT_RUNTIME_EXTENSION_PATH = path.join(path.dirname(fileURLToPath(import.meta.url)), "subagent-prompt-runtime.ts");
13
13
  const FANOUT_CHILD_EXTENSION_PATH = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "extension", "fanout-child.ts");
14
- export const SUBAGENT_CHILD_ENV = "PI_SUBAGENT_CHILD";
15
- export const SUBAGENT_ORCHESTRATOR_TARGET_ENV = "PI_SUBAGENT_ORCHESTRATOR_TARGET";
16
- export const SUBAGENT_RUN_ID_ENV = "PI_SUBAGENT_RUN_ID";
17
- export const SUBAGENT_CHILD_AGENT_ENV = "PI_SUBAGENT_CHILD_AGENT";
18
- export const SUBAGENT_CHILD_INDEX_ENV = "PI_SUBAGENT_CHILD_INDEX";
19
- export const SUBAGENT_FANOUT_CHILD_ENV = "PI_SUBAGENT_FANOUT_CHILD";
20
- export const SUBAGENT_PARENT_EVENT_SINK_ENV = "PI_SUBAGENT_PARENT_EVENT_SINK";
21
- export const SUBAGENT_PARENT_CONTROL_INBOX_ENV = "PI_SUBAGENT_PARENT_CONTROL_INBOX";
22
- export const SUBAGENT_PARENT_ROOT_RUN_ID_ENV = "PI_SUBAGENT_PARENT_ROOT_RUN_ID";
23
- export const SUBAGENT_PARENT_RUN_ID_ENV = "PI_SUBAGENT_PARENT_RUN_ID";
24
- export const SUBAGENT_PARENT_CHILD_INDEX_ENV = "PI_SUBAGENT_PARENT_CHILD_INDEX";
25
- export const SUBAGENT_PARENT_DEPTH_ENV = "PI_SUBAGENT_PARENT_DEPTH";
26
- export const SUBAGENT_PARENT_PATH_ENV = "PI_SUBAGENT_PARENT_PATH";
27
- export const SUBAGENT_PARENT_CAPABILITY_TOKEN_ENV = "PI_SUBAGENT_PARENT_CAPABILITY_TOKEN";
28
- export const SUBAGENT_PARENT_SESSION_ENV = "PI_SUBAGENT_PARENT_SESSION";
14
+ export const SUBAGENT_CHILD_ENV = "SELESAI_SUBAGENT_CHILD";
15
+ export const SUBAGENT_ORCHESTRATOR_TARGET_ENV = "SELESAI_SUBAGENT_ORCHESTRATOR_TARGET";
16
+ export const SUBAGENT_RUN_ID_ENV = "SELESAI_SUBAGENT_RUN_ID";
17
+ export const SUBAGENT_CHILD_AGENT_ENV = "SELESAI_SUBAGENT_CHILD_AGENT";
18
+ export const SUBAGENT_CHILD_INDEX_ENV = "SELESAI_SUBAGENT_CHILD_INDEX";
19
+ export const SUBAGENT_FANOUT_CHILD_ENV = "SELESAI_SUBAGENT_FANOUT_CHILD";
20
+ export const SUBAGENT_PARENT_EVENT_SINK_ENV = "SELESAI_SUBAGENT_PARENT_EVENT_SINK";
21
+ export const SUBAGENT_PARENT_CONTROL_INBOX_ENV = "SELESAI_SUBAGENT_PARENT_CONTROL_INBOX";
22
+ export const SUBAGENT_PARENT_ROOT_RUN_ID_ENV = "SELESAI_SUBAGENT_PARENT_ROOT_RUN_ID";
23
+ export const SUBAGENT_PARENT_RUN_ID_ENV = "SELESAI_SUBAGENT_PARENT_RUN_ID";
24
+ export const SUBAGENT_PARENT_CHILD_INDEX_ENV = "SELESAI_SUBAGENT_PARENT_CHILD_INDEX";
25
+ export const SUBAGENT_PARENT_DEPTH_ENV = "SELESAI_SUBAGENT_PARENT_DEPTH";
26
+ export const SUBAGENT_PARENT_PATH_ENV = "SELESAI_SUBAGENT_PARENT_PATH";
27
+ export const SUBAGENT_PARENT_CAPABILITY_TOKEN_ENV = "SELESAI_SUBAGENT_PARENT_CAPABILITY_TOKEN";
28
+ export const SUBAGENT_PARENT_SESSION_ENV = "SELESAI_SUBAGENT_PARENT_SESSION";
29
29
 
30
30
  interface BuildPiArgsInput {
31
31
  parentSessionId?: string;
@@ -196,10 +196,10 @@ export function buildPiArgs(input: BuildPiArgsInput): BuildPiArgsResult {
196
196
  env[SUBAGENT_PARENT_CAPABILITY_TOKEN_ENV] = fanoutAuthorized
197
197
  ? input.parentCapabilityToken ?? process.env[SUBAGENT_PARENT_CAPABILITY_TOKEN_ENV] ?? ""
198
198
  : "";
199
- env.PI_SUBAGENT_INHERIT_PROJECT_CONTEXT = input.inheritProjectContext ? "1" : "0";
200
- env.PI_SUBAGENT_INHERIT_SKILLS = input.inheritSkills ? "1" : "0";
199
+ env.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT = input.inheritProjectContext ? "1" : "0";
200
+ env.SELESAI_SUBAGENT_INHERIT_SKILLS = input.inheritSkills ? "1" : "0";
201
201
  if (input.intercomSessionName) {
202
- env.PI_SUBAGENT_INTERCOM_SESSION_NAME = input.intercomSessionName;
202
+ env.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME = input.intercomSessionName;
203
203
  }
204
204
  if (input.orchestratorIntercomTarget) {
205
205
  env[SUBAGENT_ORCHESTRATOR_TARGET_ENV] = input.orchestratorIntercomTarget;