pi-crew 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. package/AGENTS.md +57 -32
  2. package/CHANGELOG.md +466 -413
  3. package/LICENSE +21 -21
  4. package/NOTICE.md +16 -16
  5. package/README.md +323 -323
  6. package/docs/FEATURE_INTAKE.md +126 -0
  7. package/docs/HARNESS.md +86 -0
  8. package/docs/HARNESS_BACKLOG.md +41 -0
  9. package/docs/TEST_MATRIX.md +49 -0
  10. package/docs/actions-reference.md +595 -595
  11. package/docs/architecture.md +180 -180
  12. package/docs/code-review-2026-05-11.md +592 -0
  13. package/docs/commands-reference.md +347 -347
  14. package/docs/comparison-pi-subagents-vs-pi-crew.md +303 -0
  15. package/docs/decisions/0001-durable-state.md +41 -0
  16. package/docs/decisions/0002-child-process-for-async.md +42 -0
  17. package/docs/decisions/0003-depth-guard.md +36 -0
  18. package/docs/decisions/0004-execfile-over-exec.md +34 -0
  19. package/docs/decisions/0005-no-parameter-properties.md +49 -0
  20. package/docs/decisions/0006-publish-bundled-esm.md +63 -0
  21. package/docs/decisions/0007-active-run-binary-index.md +54 -0
  22. package/docs/decisions/0008-child-pi-warm-pool.md +61 -0
  23. package/docs/decisions/README.md +23 -0
  24. package/docs/followup-plan-2026-05-12.md +463 -0
  25. package/docs/followup-review-2026-05-12.md +297 -0
  26. package/docs/followup-review-round3-2026-05-12.md +342 -0
  27. package/docs/followup-review-round4-2026-05-13.md +107 -0
  28. package/docs/implementation-plan-top3.md +333 -0
  29. package/docs/live-mailbox-runtime.md +36 -36
  30. package/docs/next-upgrade-roadmap.md +808 -808
  31. package/docs/oh-my-pi-research.md +509 -0
  32. package/docs/perf/baseline-2026-05.md +113 -0
  33. package/docs/perf/final-report-2026-05.md +206 -0
  34. package/docs/perf/sprint-1-report.md +71 -0
  35. package/docs/perf/sprint-2-report.md +81 -0
  36. package/docs/perf/sprint-2.5-report.md +53 -0
  37. package/docs/perf/sprint-3-report.md +36 -0
  38. package/docs/perf/sprint-4-report.md +47 -0
  39. package/docs/perf/sprint-5-report.md +51 -0
  40. package/docs/perf/sprint-6-report.md +94 -0
  41. package/docs/perf/sprint-7-report.md +74 -0
  42. package/docs/perf/upgrade-plan-2026-05.md +147 -0
  43. package/docs/pi-subagents3-deep-analysis.md +508 -0
  44. package/docs/product/README.md +31 -0
  45. package/docs/product/platform.md +27 -0
  46. package/docs/product/runtime-safety.md +37 -0
  47. package/docs/product/team-run.md +39 -0
  48. package/docs/product/team-tool.md +37 -0
  49. package/docs/publishing.md +65 -65
  50. package/docs/resource-formats.md +134 -134
  51. package/docs/runtime-analysis-child-vs-live.md +171 -0
  52. package/docs/runtime-flow.md +148 -148
  53. package/docs/runtime-migration-in-process-analysis.md +250 -0
  54. package/docs/stories/README.md +30 -0
  55. package/docs/stories/backlog.md +36 -0
  56. package/docs/templates/decision.md +27 -0
  57. package/docs/templates/story.md +44 -0
  58. package/docs/templates/validation-report.md +32 -0
  59. package/docs/usage.md +238 -238
  60. package/index.ts +7 -6
  61. package/install.mjs +65 -65
  62. package/package.json +107 -99
  63. package/schema.json +222 -222
  64. package/skills/child-pi-spawning/SKILL.md +213 -0
  65. package/skills/context-artifact-hygiene/SKILL.md +32 -0
  66. package/skills/event-log-tracing/SKILL.md +299 -0
  67. package/skills/git-master/SKILL.md +225 -24
  68. package/skills/live-agent-lifecycle/SKILL.md +192 -0
  69. package/skills/mailbox-interactive/SKILL.md +300 -19
  70. package/skills/model-routing-context/SKILL.md +94 -0
  71. package/skills/multi-perspective-review/SKILL.md +88 -0
  72. package/skills/read-only-explorer/SKILL.md +250 -26
  73. package/skills/safe-bash/SKILL.md +307 -21
  74. package/skills/verification-before-done/SKILL.md +11 -2
  75. package/skills/widget-rendering/SKILL.md +258 -0
  76. package/skills/workspace-isolation/SKILL.md +202 -0
  77. package/skills/worktree-isolation/SKILL.md +202 -18
  78. package/src/adapters/claude-adapter.ts +25 -25
  79. package/src/adapters/codex-adapter.ts +21 -21
  80. package/src/adapters/cursor-adapter.ts +17 -17
  81. package/src/adapters/export-util.ts +137 -137
  82. package/src/adapters/index.ts +15 -15
  83. package/src/adapters/registry.ts +18 -18
  84. package/src/adapters/types.ts +23 -23
  85. package/src/agents/agent-config.ts +38 -38
  86. package/src/agents/agent-serializer.ts +38 -38
  87. package/src/agents/discover-agents.ts +121 -118
  88. package/src/config/config.ts +740 -858
  89. package/src/config/defaults.ts +96 -96
  90. package/src/config/drift-detector.ts +211 -211
  91. package/src/config/markers.ts +327 -327
  92. package/src/config/resilient-parser.ts +109 -108
  93. package/src/config/suggestions.ts +74 -74
  94. package/src/config/types.ts +199 -0
  95. package/src/extension/async-notifier.ts +123 -89
  96. package/src/extension/autonomous-policy.ts +169 -169
  97. package/src/extension/cross-extension-rpc.ts +104 -103
  98. package/src/extension/help.ts +47 -47
  99. package/src/extension/import-index.ts +69 -69
  100. package/src/extension/management.ts +395 -382
  101. package/src/extension/notification-router.ts +116 -116
  102. package/src/extension/notification-sink.ts +51 -51
  103. package/src/extension/project-init.ts +168 -168
  104. package/src/extension/register.ts +859 -668
  105. package/src/extension/registration/artifact-cleanup.ts +15 -15
  106. package/src/extension/registration/command-utils.ts +54 -54
  107. package/src/extension/registration/commands.ts +559 -452
  108. package/src/extension/registration/compaction-guard.ts +125 -125
  109. package/src/extension/registration/subagent-helpers.ts +102 -102
  110. package/src/extension/registration/subagent-tools.ts +220 -158
  111. package/src/extension/registration/team-tool.ts +159 -98
  112. package/src/extension/registration/viewers.ts +29 -0
  113. package/src/extension/result-watcher.ts +128 -128
  114. package/src/extension/run-bundle-schema.ts +89 -89
  115. package/src/extension/run-export.ts +73 -73
  116. package/src/extension/run-import.ts +84 -84
  117. package/src/extension/run-index.ts +94 -94
  118. package/src/extension/run-maintenance.ts +142 -142
  119. package/src/extension/session-summary.ts +8 -8
  120. package/src/extension/team-manager-command.ts +96 -95
  121. package/src/extension/team-recommendation.ts +188 -188
  122. package/src/extension/team-tool/api.ts +5 -2
  123. package/src/extension/team-tool/cancel.ts +224 -209
  124. package/src/extension/team-tool/config-patch.ts +36 -36
  125. package/src/extension/team-tool/context.ts +60 -60
  126. package/src/extension/team-tool/doctor.ts +242 -242
  127. package/src/extension/team-tool/handle-settings.ts +421 -195
  128. package/src/extension/team-tool/inspect.ts +41 -41
  129. package/src/extension/team-tool/lifecycle-actions.ts +139 -139
  130. package/src/extension/team-tool/parallel-dispatch.ts +156 -156
  131. package/src/extension/team-tool/plan.ts +19 -19
  132. package/src/extension/team-tool/respond.ts +112 -111
  133. package/src/extension/team-tool/run.ts +246 -228
  134. package/src/extension/team-tool/status.ts +110 -110
  135. package/src/extension/team-tool-types.ts +13 -13
  136. package/src/extension/team-tool.ts +16 -4
  137. package/src/extension/tool-result.ts +16 -16
  138. package/src/extension/validate-resources.ts +77 -77
  139. package/src/hooks/registry.ts +61 -61
  140. package/src/hooks/types.ts +40 -40
  141. package/src/i18n.ts +184 -184
  142. package/src/observability/correlation.ts +35 -35
  143. package/src/observability/event-to-metric.ts +68 -68
  144. package/src/observability/exporters/adapter.ts +30 -30
  145. package/src/observability/exporters/otlp-exporter.ts +106 -92
  146. package/src/observability/exporters/prometheus-exporter.ts +54 -54
  147. package/src/observability/metric-registry.ts +87 -87
  148. package/src/observability/metric-retention.ts +54 -54
  149. package/src/observability/metric-sink.ts +81 -56
  150. package/src/observability/metrics-primitives.ts +167 -167
  151. package/src/prompt/prompt-runtime.ts +72 -72
  152. package/src/runtime/adaptive-plan.ts +338 -0
  153. package/src/runtime/agent-control.ts +169 -169
  154. package/src/runtime/agent-memory.ts +72 -72
  155. package/src/runtime/agent-observability.ts +114 -114
  156. package/src/runtime/async-marker.ts +26 -26
  157. package/src/runtime/async-runner.ts +153 -79
  158. package/src/runtime/attention-events.ts +28 -28
  159. package/src/runtime/auto-resume.ts +100 -100
  160. package/src/runtime/background-runner.ts +122 -88
  161. package/src/runtime/cancellation.ts +61 -61
  162. package/src/runtime/capability-inventory.ts +116 -116
  163. package/src/runtime/child-pi-pool.ts +68 -0
  164. package/src/runtime/child-pi.ts +541 -463
  165. package/src/runtime/code-summary.ts +247 -247
  166. package/src/runtime/compaction-summary.ts +271 -271
  167. package/src/runtime/concurrency.ts +58 -58
  168. package/src/runtime/crash-recovery.ts +317 -301
  169. package/src/runtime/crew-agent-records.ts +379 -281
  170. package/src/runtime/crew-agent-runtime.ts +60 -60
  171. package/src/runtime/cross-extension-rpc.ts +72 -0
  172. package/src/runtime/custom-tools/irc-tool.ts +201 -201
  173. package/src/runtime/custom-tools/submit-result-tool.ts +90 -90
  174. package/src/runtime/deadletter.ts +47 -47
  175. package/src/runtime/delivery-coordinator.ts +176 -176
  176. package/src/runtime/delta-conflict.ts +360 -360
  177. package/src/runtime/diagnostic-export.ts +102 -102
  178. package/src/runtime/direct-run.ts +35 -35
  179. package/src/runtime/effectiveness.ts +82 -81
  180. package/src/runtime/errors/crew-errors.ts +166 -0
  181. package/src/runtime/event-stream-bridge.ts +92 -92
  182. package/src/runtime/foreground-control.ts +82 -82
  183. package/src/runtime/green-contract.ts +46 -46
  184. package/src/runtime/group-join.ts +234 -106
  185. package/src/runtime/heartbeat-watcher.ts +145 -124
  186. package/src/runtime/iteration-hooks.ts +267 -264
  187. package/src/runtime/live-agent-control.ts +88 -88
  188. package/src/runtime/live-agent-manager.ts +377 -179
  189. package/src/runtime/live-control-realtime.ts +36 -36
  190. package/src/runtime/live-session-runtime.ts +676 -599
  191. package/src/runtime/loop-gates.ts +129 -129
  192. package/src/runtime/manifest-cache.ts +263 -263
  193. package/src/runtime/mcp-proxy.ts +113 -113
  194. package/src/runtime/metric-parser.ts +40 -40
  195. package/src/runtime/model-fallback.ts +282 -274
  196. package/src/runtime/model-resolver.ts +118 -0
  197. package/src/runtime/output-validator.ts +187 -187
  198. package/src/runtime/overflow-recovery.ts +175 -175
  199. package/src/runtime/parallel-research.ts +44 -44
  200. package/src/runtime/parallel-utils.ts +156 -156
  201. package/src/runtime/parent-guard.ts +80 -80
  202. package/src/runtime/phase-progress.ts +217 -217
  203. package/src/runtime/pi-args.ts +165 -165
  204. package/src/runtime/pi-json-output.ts +111 -111
  205. package/src/runtime/pi-spawn.ts +167 -167
  206. package/src/runtime/policy-engine.ts +79 -79
  207. package/src/runtime/post-checks.ts +125 -122
  208. package/src/runtime/post-exit-stdio-guard.ts +86 -86
  209. package/src/runtime/process-status.ts +97 -73
  210. package/src/runtime/progress-event-coalescer.ts +43 -43
  211. package/src/runtime/recovery-recipes.ts +74 -74
  212. package/src/runtime/retry-executor.ts +81 -81
  213. package/src/runtime/role-permission.ts +39 -39
  214. package/src/runtime/run-tracker.ts +99 -0
  215. package/src/runtime/runtime-policy.ts +21 -0
  216. package/src/runtime/runtime-resolver.ts +94 -90
  217. package/src/runtime/scheduler.ts +294 -0
  218. package/src/runtime/semaphore.ts +131 -131
  219. package/src/runtime/sensitive-paths.ts +92 -92
  220. package/src/runtime/session-usage.ts +79 -79
  221. package/src/runtime/settings-store.ts +103 -0
  222. package/src/runtime/sidechain-output.ts +29 -29
  223. package/src/runtime/skill-instructions.ts +222 -222
  224. package/src/runtime/stale-reconciler.ts +198 -189
  225. package/src/runtime/streaming-output.ts +47 -0
  226. package/src/runtime/subagent-manager.ts +404 -395
  227. package/src/runtime/subprocess-tool-registry.ts +67 -67
  228. package/src/runtime/task-display.ts +38 -38
  229. package/src/runtime/task-graph-scheduler.ts +122 -122
  230. package/src/runtime/task-graph.ts +207 -207
  231. package/src/runtime/task-output-context.ts +177 -177
  232. package/src/runtime/task-packet.ts +93 -93
  233. package/src/runtime/task-quality.ts +207 -207
  234. package/src/runtime/task-runner/capabilities.ts +78 -78
  235. package/src/runtime/task-runner/live-executor.ts +131 -113
  236. package/src/runtime/task-runner/progress.ts +119 -119
  237. package/src/runtime/task-runner/prompt-builder.ts +139 -139
  238. package/src/runtime/task-runner/prompt-pipeline.ts +64 -64
  239. package/src/runtime/task-runner/result-utils.ts +14 -14
  240. package/src/runtime/task-runner/run-projection.ts +103 -103
  241. package/src/runtime/task-runner/state-helpers.ts +22 -22
  242. package/src/runtime/task-runner.ts +469 -458
  243. package/src/runtime/team-runner.ts +693 -945
  244. package/src/runtime/usage-tracker.ts +71 -0
  245. package/src/runtime/worker-heartbeat.ts +21 -21
  246. package/src/runtime/worker-startup.ts +57 -57
  247. package/src/runtime/workflow-state.ts +187 -187
  248. package/src/runtime/yield-handler.ts +190 -189
  249. package/src/schema/config-schema.ts +172 -168
  250. package/src/schema/team-tool-schema.ts +126 -125
  251. package/src/schema/validation-types.ts +151 -148
  252. package/src/skills/discover-skills.ts +67 -67
  253. package/src/skills/skill-templates.ts +374 -374
  254. package/src/state/active-run-registry.ts +227 -191
  255. package/src/state/artifact-store.ts +130 -129
  256. package/src/state/atomic-write.ts +262 -178
  257. package/src/state/blob-store.ts +116 -116
  258. package/src/state/contracts.ts +111 -111
  259. package/src/state/event-log-rotation.ts +161 -158
  260. package/src/state/event-log.ts +383 -240
  261. package/src/state/event-reconstructor.ts +217 -217
  262. package/src/state/jsonl-writer.ts +82 -82
  263. package/src/state/locks.ts +146 -148
  264. package/src/state/mailbox.ts +446 -405
  265. package/src/state/state-store.ts +364 -351
  266. package/src/state/task-claims.ts +44 -44
  267. package/src/state/types.ts +285 -285
  268. package/src/state/usage.ts +29 -29
  269. package/src/subagents/async-entry.ts +1 -1
  270. package/src/subagents/index.ts +3 -3
  271. package/src/subagents/live/control.ts +1 -1
  272. package/src/subagents/live/manager.ts +1 -1
  273. package/src/subagents/live/realtime.ts +1 -1
  274. package/src/subagents/live/session-runtime.ts +1 -1
  275. package/src/subagents/manager.ts +1 -1
  276. package/src/subagents/spawn.ts +1 -1
  277. package/src/teams/discover-teams.ts +116 -116
  278. package/src/teams/team-config.ts +27 -27
  279. package/src/teams/team-serializer.ts +38 -38
  280. package/src/types/diff.d.ts +18 -18
  281. package/src/ui/agent-management-overlay.ts +144 -144
  282. package/src/ui/crew-widget.ts +487 -370
  283. package/src/ui/dashboard-panes/agents-pane.ts +109 -28
  284. package/src/ui/dashboard-panes/cancellation-pane.ts +42 -42
  285. package/src/ui/dashboard-panes/capability-pane.ts +59 -59
  286. package/src/ui/dashboard-panes/health-pane.ts +30 -30
  287. package/src/ui/dashboard-panes/mailbox-pane.ts +35 -35
  288. package/src/ui/dashboard-panes/progress-pane.ts +30 -30
  289. package/src/ui/dashboard-panes/transcript-pane.ts +10 -10
  290. package/src/ui/heartbeat-aggregator.ts +63 -63
  291. package/src/ui/keybinding-map.ts +97 -94
  292. package/src/ui/live-conversation-overlay.ts +152 -0
  293. package/src/ui/live-run-sidebar.ts +180 -180
  294. package/src/ui/mascot.ts +442 -442
  295. package/src/ui/overlays/agent-picker-overlay.ts +57 -57
  296. package/src/ui/overlays/confirm-overlay.ts +58 -58
  297. package/src/ui/overlays/mailbox-compose-overlay.ts +144 -144
  298. package/src/ui/overlays/mailbox-compose-preview.ts +63 -63
  299. package/src/ui/overlays/mailbox-detail-overlay.ts +122 -122
  300. package/src/ui/pi-ui-compat.ts +57 -57
  301. package/src/ui/powerbar-publisher.ts +221 -197
  302. package/src/ui/render-scheduler.ts +216 -143
  303. package/src/ui/run-action-dispatcher.ts +118 -117
  304. package/src/ui/run-dashboard.ts +526 -464
  305. package/src/ui/run-event-bus.ts +208 -208
  306. package/src/ui/run-snapshot-cache.ts +826 -777
  307. package/src/ui/settings-overlay.ts +721 -0
  308. package/src/ui/snapshot-types.ts +86 -70
  309. package/src/ui/theme-adapter.ts +190 -190
  310. package/src/ui/tool-progress-formatter.ts +89 -0
  311. package/src/ui/transcript-cache.ts +94 -94
  312. package/src/ui/transcript-viewer.ts +335 -335
  313. package/src/utils/conflict-detect.ts +662 -0
  314. package/src/utils/env-filter.ts +30 -0
  315. package/src/utils/file-coalescer.ts +86 -86
  316. package/src/utils/frontmatter.ts +68 -68
  317. package/src/utils/fs-watch.ts +88 -31
  318. package/src/utils/gh-protocol.ts +479 -0
  319. package/src/utils/ids.ts +17 -17
  320. package/src/utils/incremental-reader.ts +104 -104
  321. package/src/utils/internal-error.ts +6 -6
  322. package/src/utils/names.ts +27 -27
  323. package/src/utils/paths.ts +102 -63
  324. package/src/utils/redaction.ts +44 -44
  325. package/src/utils/resolve-shell.ts +34 -0
  326. package/src/utils/safe-paths.ts +47 -47
  327. package/src/utils/scan-cache.ts +136 -136
  328. package/src/utils/sleep.ts +2 -1
  329. package/src/utils/sse-parser.ts +134 -134
  330. package/src/utils/task-name-generator.ts +337 -337
  331. package/src/utils/timings.ts +33 -33
  332. package/src/utils/visual.ts +243 -198
  333. package/src/workflows/discover-workflows.ts +139 -139
  334. package/src/workflows/validate-workflow.ts +40 -40
  335. package/src/workflows/workflow-config.ts +26 -26
  336. package/src/workflows/workflow-serializer.ts +32 -32
  337. package/src/worktree/branch-freshness.ts +45 -45
  338. package/src/worktree/cleanup.ts +75 -72
  339. package/src/worktree/worktree-manager.ts +188 -146
  340. package/teams/default.team.md +12 -12
  341. package/teams/fast-fix.team.md +11 -11
  342. package/teams/implementation.team.md +18 -18
  343. package/teams/parallel-research.team.md +14 -14
  344. package/teams/research.team.md +11 -11
  345. package/teams/review.team.md +12 -12
  346. package/tsconfig.json +19 -19
  347. package/workflows/default.workflow.md +30 -30
  348. package/workflows/fast-fix.workflow.md +23 -23
  349. package/workflows/implementation.workflow.md +43 -43
  350. package/workflows/parallel-research.workflow.md +46 -46
  351. package/workflows/research.workflow.md +22 -22
  352. package/workflows/review.workflow.md +30 -30
  353. package/skills/task-packet/SKILL.md +0 -28
  354. package/skills/verify-evidence/SKILL.md +0 -27
@@ -1,38 +1,38 @@
1
- import type { AgentConfig } from "./agent-config.ts";
2
-
3
- function line(key: string, value: string | boolean | string[] | undefined): string | undefined {
4
- if (value === undefined) return undefined;
5
- if (Array.isArray(value)) return `${key}: ${value.join(", ")}`;
6
- return `${key}: ${String(value)}`;
7
- }
8
-
9
- export function serializeAgent(agent: AgentConfig): string {
10
- const lines = [
11
- "---",
12
- `name: ${agent.name}`,
13
- `description: ${agent.description}`,
14
- line("model", agent.model),
15
- line("fallbackModels", agent.fallbackModels),
16
- line("thinking", agent.thinking),
17
- line("tools", agent.tools),
18
- agent.extensions !== undefined ? line("extensions", agent.extensions) ?? "extensions:" : undefined,
19
- line("skills", agent.skills),
20
- line("systemPromptMode", agent.systemPromptMode),
21
- line("inheritProjectContext", agent.inheritProjectContext),
22
- line("inheritSkills", agent.inheritSkills),
23
- line("memory", agent.memory),
24
- line("loadMode", agent.loadMode),
25
- line("defaultTools", agent.defaultTools ?? undefined),
26
- line("contextMode", agent.contextMode),
27
- line("triggers", agent.routing?.triggers),
28
- line("useWhen", agent.routing?.useWhen),
29
- line("avoidWhen", agent.routing?.avoidWhen),
30
- line("cost", agent.routing?.cost),
31
- line("category", agent.routing?.category),
32
- "---",
33
- "",
34
- agent.systemPrompt.trim(),
35
- "",
36
- ].filter((entry): entry is string => entry !== undefined);
37
- return lines.join("\n");
38
- }
1
+ import type { AgentConfig } from "./agent-config.ts";
2
+
3
+ function line(key: string, value: string | boolean | string[] | undefined): string | undefined {
4
+ if (value === undefined) return undefined;
5
+ if (Array.isArray(value)) return `${key}: ${value.join(", ")}`;
6
+ return `${key}: ${String(value)}`;
7
+ }
8
+
9
+ export function serializeAgent(agent: AgentConfig): string {
10
+ const lines = [
11
+ "---",
12
+ `name: ${agent.name}`,
13
+ `description: ${agent.description}`,
14
+ line("model", agent.model),
15
+ line("fallbackModels", agent.fallbackModels),
16
+ line("thinking", agent.thinking),
17
+ line("tools", agent.tools),
18
+ agent.extensions !== undefined ? line("extensions", agent.extensions) ?? "extensions:" : undefined,
19
+ line("skills", agent.skills),
20
+ line("systemPromptMode", agent.systemPromptMode),
21
+ line("inheritProjectContext", agent.inheritProjectContext),
22
+ line("inheritSkills", agent.inheritSkills),
23
+ line("memory", agent.memory),
24
+ line("loadMode", agent.loadMode),
25
+ line("defaultTools", agent.defaultTools ?? undefined),
26
+ line("contextMode", agent.contextMode),
27
+ line("triggers", agent.routing?.triggers),
28
+ line("useWhen", agent.routing?.useWhen),
29
+ line("avoidWhen", agent.routing?.avoidWhen),
30
+ line("cost", agent.routing?.cost),
31
+ line("category", agent.routing?.category),
32
+ "---",
33
+ "",
34
+ agent.systemPrompt.trim(),
35
+ "",
36
+ ].filter((entry): entry is string => entry !== undefined);
37
+ return lines.join("\n");
38
+ }
@@ -1,118 +1,121 @@
1
- import * as fs from "node:fs";
2
- import * as path from "node:path";
3
- import type { AgentConfig, ResourceSource } from "./agent-config.ts";
4
- import { loadConfig, type LoadedPiTeamsConfig } from "../config/config.ts";
5
- import { parseCsv, parseFrontmatter } from "../utils/frontmatter.ts";
6
- import { logInternalError } from "../utils/internal-error.ts";
7
- import { packageRoot, projectCrewRoot, userPiRoot } from "../utils/paths.ts";
8
-
9
- export interface AgentDiscoveryResult {
10
- builtin: AgentConfig[];
11
- user: AgentConfig[];
12
- project: AgentConfig[];
13
- }
14
-
15
- function parseCost(value: string | undefined): "free" | "cheap" | "expensive" | undefined {
16
- return value === "free" || value === "cheap" || value === "expensive" ? value : undefined;
17
- }
18
-
19
- function parseMemory(value: string | undefined): "user" | "project" | "local" | undefined {
20
- return value === "user" || value === "project" || value === "local" ? value : undefined;
21
- }
22
-
23
- function parseLoadMode(value: string | undefined): "essential" | "lean" | undefined {
24
- return value === "essential" || value === "lean" ? value : undefined;
25
- }
26
-
27
- function parseContextMode(value: string | undefined): "fresh" | "fork" | undefined {
28
- return value === "fresh" || value === "fork" ? value : undefined;
29
- }
30
-
31
- function parseAgentFile(filePath: string, source: ResourceSource): AgentConfig | undefined {
32
- try {
33
- const content = fs.readFileSync(filePath, "utf-8");
34
- const { frontmatter, body } = parseFrontmatter(content);
35
- const name = frontmatter.name?.trim() || path.basename(filePath, path.extname(filePath));
36
- const description = frontmatter.description?.trim() || "No description provided.";
37
- const triggers = parseCsv(frontmatter.triggers ?? frontmatter.trigger);
38
- const useWhen = parseCsv(frontmatter.useWhen);
39
- const avoidWhen = parseCsv(frontmatter.avoidWhen);
40
- const cost = parseCost(frontmatter.cost);
41
- const category = frontmatter.category?.trim() || undefined;
42
- return {
43
- name,
44
- description,
45
- source,
46
- filePath,
47
- systemPrompt: body.trim(),
48
- model: frontmatter.model === "false" ? undefined : frontmatter.model || undefined,
49
- fallbackModels: parseCsv(frontmatter.fallbackModels),
50
- thinking: frontmatter.thinking === "false" ? undefined : frontmatter.thinking || undefined,
51
- tools: parseCsv(frontmatter.tools),
52
- extensions: frontmatter.extensions === "" ? [] : parseCsv(frontmatter.extensions),
53
- skills: parseCsv(frontmatter.skills ?? frontmatter.skill),
54
- systemPromptMode: frontmatter.systemPromptMode === "append" ? "append" : "replace",
55
- inheritProjectContext: frontmatter.inheritProjectContext === "true",
56
- inheritSkills: frontmatter.inheritSkills === "true",
57
- memory: parseMemory(frontmatter.memory),
58
- loadMode: parseLoadMode(frontmatter.loadMode),
59
- defaultTools: frontmatter.defaultTools !== undefined ? parseCsv(frontmatter.defaultTools) ?? null : undefined,
60
- contextMode: parseContextMode(frontmatter.contextMode),
61
- maxTurns: (() => { const n = Number.parseInt(frontmatter.maxTurns, 10); return Number.isFinite(n) && n > 0 ? n : undefined; })(),
62
- disabled: frontmatter.disabled === "true" || frontmatter.enabled === "false",
63
- routing: triggers || useWhen || avoidWhen || cost || category ? { triggers, useWhen, avoidWhen, cost, category } : undefined,
64
- };
65
- } catch (error) {
66
- logInternalError("discoverAgents.parseAgentFile", error, `filePath=${filePath}`);
67
- return undefined;
68
- }
69
- }
70
-
71
- function readAgentDir(dir: string, source: ResourceSource): AgentConfig[] {
72
- if (!fs.existsSync(dir)) return [];
73
- return fs.readdirSync(dir)
74
- .filter((entry) => entry.endsWith(".md") && !entry.endsWith(".team.md") && !entry.endsWith(".workflow.md"))
75
- .map((entry) => parseAgentFile(path.join(dir, entry), source))
76
- .filter((agent): agent is AgentConfig => agent !== undefined)
77
- .sort((a, b) => a.name.localeCompare(b.name));
78
- }
79
-
80
- function applyAgentOverrides(agents: AgentConfig[], cwd: string, loadedConfig?: LoadedPiTeamsConfig): AgentConfig[] {
81
- const loaded = loadedConfig ?? loadConfig(cwd);
82
- const agentsConfig = loaded.config.agents;
83
- const overrides = agentsConfig?.overrides ?? {};
84
- return agents
85
- .filter((agent) => !(agentsConfig?.disableBuiltins && agent.source === "builtin"))
86
- .map((agent) => {
87
- const overrideEntry = Object.entries(overrides).find(([name]) => name.toLowerCase() === agent.name.toLowerCase());
88
- if (!overrideEntry) return agent;
89
- const [, override] = overrideEntry;
90
- return {
91
- ...agent,
92
- disabled: override.disabled ?? agent.disabled,
93
- model: override.model === false ? undefined : override.model ?? agent.model,
94
- fallbackModels: override.fallbackModels === false ? undefined : override.fallbackModels ?? agent.fallbackModels,
95
- thinking: override.thinking === false ? undefined : override.thinking ?? agent.thinking,
96
- tools: override.tools === false ? undefined : override.tools ?? agent.tools,
97
- skills: override.skills === false ? undefined : override.skills ?? agent.skills,
98
- override: { source: "config", path: loaded.path },
99
- };
100
- });
101
- }
102
-
103
- export function discoverAgents(cwd: string): AgentDiscoveryResult {
104
- const loaded = loadConfig(cwd);
105
- return {
106
- builtin: applyAgentOverrides(readAgentDir(path.join(packageRoot(), "agents"), "builtin"), cwd, loaded),
107
- user: applyAgentOverrides(readAgentDir(path.join(userPiRoot(), "agents"), "user"), cwd, loaded),
108
- project: applyAgentOverrides(readAgentDir(path.join(projectCrewRoot(cwd), "agents"), "project"), cwd, loaded),
109
- };
110
- }
111
-
112
- export function allAgents(discovery: AgentDiscoveryResult): AgentConfig[] {
113
- const byName = new Map<string, AgentConfig>();
114
- for (const agent of [...discovery.project, ...discovery.builtin, ...discovery.user]) {
115
- byName.set(agent.name.toLowerCase(), agent);
116
- }
117
- return [...byName.values()].filter((agent) => !agent.disabled).sort((a, b) => a.name.localeCompare(b.name));
118
- }
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import type { AgentConfig, ResourceSource } from "./agent-config.ts";
4
+ import { loadConfig, type LoadedPiTeamsConfig } from "../config/config.ts";
5
+ import { parseCsv, parseFrontmatter } from "../utils/frontmatter.ts";
6
+ import { logInternalError } from "../utils/internal-error.ts";
7
+ import { packageRoot, projectCrewRoot, userPiRoot } from "../utils/paths.ts";
8
+
9
+ export interface AgentDiscoveryResult {
10
+ builtin: AgentConfig[];
11
+ user: AgentConfig[];
12
+ project: AgentConfig[];
13
+ }
14
+
15
+ function parseCost(value: string | undefined): "free" | "cheap" | "expensive" | undefined {
16
+ return value === "free" || value === "cheap" || value === "expensive" ? value : undefined;
17
+ }
18
+
19
+ function parseMemory(value: string | undefined): "user" | "project" | "local" | undefined {
20
+ return value === "user" || value === "project" || value === "local" ? value : undefined;
21
+ }
22
+
23
+ function parseLoadMode(value: string | undefined): "essential" | "lean" | undefined {
24
+ return value === "essential" || value === "lean" ? value : undefined;
25
+ }
26
+
27
+ function parseContextMode(value: string | undefined): "fresh" | "fork" | undefined {
28
+ return value === "fresh" || value === "fork" ? value : undefined;
29
+ }
30
+
31
+ function parseAgentFile(filePath: string, source: ResourceSource): AgentConfig | undefined {
32
+ try {
33
+ const content = fs.readFileSync(filePath, "utf-8");
34
+ const { frontmatter, body } = parseFrontmatter(content);
35
+ const name = frontmatter.name?.trim() || path.basename(filePath, path.extname(filePath));
36
+ const description = frontmatter.description?.trim() || "No description provided.";
37
+ const triggers = parseCsv(frontmatter.triggers ?? frontmatter.trigger);
38
+ const useWhen = parseCsv(frontmatter.useWhen);
39
+ const avoidWhen = parseCsv(frontmatter.avoidWhen);
40
+ const cost = parseCost(frontmatter.cost);
41
+ const category = frontmatter.category?.trim() || undefined;
42
+ return {
43
+ name,
44
+ description,
45
+ source,
46
+ filePath,
47
+ systemPrompt: body.trim(),
48
+ model: frontmatter.model === "false" ? undefined : frontmatter.model || undefined,
49
+ fallbackModels: parseCsv(frontmatter.fallbackModels),
50
+ thinking: frontmatter.thinking === "false" ? undefined : frontmatter.thinking || undefined,
51
+ tools: parseCsv(frontmatter.tools),
52
+ extensions: frontmatter.extensions === "" ? [] : parseCsv(frontmatter.extensions),
53
+ skills: parseCsv(frontmatter.skills ?? frontmatter.skill),
54
+ systemPromptMode: frontmatter.systemPromptMode === "append" ? "append" : "replace",
55
+ inheritProjectContext: frontmatter.inheritProjectContext === "true",
56
+ inheritSkills: frontmatter.inheritSkills === "true",
57
+ memory: parseMemory(frontmatter.memory),
58
+ loadMode: parseLoadMode(frontmatter.loadMode),
59
+ defaultTools: frontmatter.defaultTools !== undefined ? parseCsv(frontmatter.defaultTools) ?? null : undefined,
60
+ contextMode: parseContextMode(frontmatter.contextMode),
61
+ maxTurns: (() => { const n = Number.parseInt(frontmatter.maxTurns, 10); return Number.isFinite(n) && n > 0 ? n : undefined; })(),
62
+ disabled: frontmatter.disabled === "true" || frontmatter.enabled === "false",
63
+ routing: triggers || useWhen || avoidWhen || cost || category ? { triggers, useWhen, avoidWhen, cost, category } : undefined,
64
+ };
65
+ } catch (error) {
66
+ logInternalError("discoverAgents.parseAgentFile", error, `filePath=${filePath}`);
67
+ return undefined;
68
+ }
69
+ }
70
+
71
+ function readAgentDir(dir: string, source: ResourceSource): AgentConfig[] {
72
+ if (!fs.existsSync(dir)) return [];
73
+ return fs.readdirSync(dir)
74
+ .filter((entry) => entry.endsWith(".md") && !entry.endsWith(".team.md") && !entry.endsWith(".workflow.md"))
75
+ .map((entry) => parseAgentFile(path.join(dir, entry), source))
76
+ .filter((agent): agent is AgentConfig => agent !== undefined)
77
+ .sort((a, b) => a.name.localeCompare(b.name));
78
+ }
79
+
80
+ function applyAgentOverrides(agents: AgentConfig[], cwd: string, loadedConfig?: LoadedPiTeamsConfig): AgentConfig[] {
81
+ const loaded = loadedConfig ?? loadConfig(cwd);
82
+ const agentsConfig = loaded.config.agents;
83
+ const overrides = agentsConfig?.overrides ?? {};
84
+ return agents
85
+ .filter((agent) => !(agentsConfig?.disableBuiltins && agent.source === "builtin"))
86
+ .map((agent) => {
87
+ const overrideEntry = Object.entries(overrides).find(([name]) => name.toLowerCase() === agent.name.toLowerCase());
88
+ if (!overrideEntry) return agent;
89
+ const [, override] = overrideEntry;
90
+ return {
91
+ ...agent,
92
+ disabled: override.disabled ?? agent.disabled,
93
+ model: override.model === false ? undefined : override.model ?? agent.model,
94
+ fallbackModels: override.fallbackModels === false ? undefined : override.fallbackModels ?? agent.fallbackModels,
95
+ thinking: override.thinking === false ? undefined : override.thinking ?? agent.thinking,
96
+ tools: override.tools === false ? undefined : override.tools ?? agent.tools,
97
+ skills: override.skills === false ? undefined : override.skills ?? agent.skills,
98
+ override: { source: "config", path: loaded.path },
99
+ };
100
+ });
101
+ }
102
+
103
+ export function discoverAgents(cwd: string): AgentDiscoveryResult {
104
+ const loaded = loadConfig(cwd);
105
+ return {
106
+ builtin: applyAgentOverrides(readAgentDir(path.join(packageRoot(), "agents"), "builtin"), cwd, loaded),
107
+ user: applyAgentOverrides(readAgentDir(path.join(userPiRoot(), "agents"), "user"), cwd, loaded),
108
+ project: applyAgentOverrides(readAgentDir(path.join(projectCrewRoot(cwd), "agents"), "project"), cwd, loaded),
109
+ };
110
+ }
111
+
112
+ export function allAgents(discovery: AgentDiscoveryResult): AgentConfig[] {
113
+ const byName = new Map<string, AgentConfig>();
114
+ // Priority: project > builtin > user for disambiguation.
115
+ // This means a project agent with the same name as a builtin/user agent is shadowed
116
+ // (security: project config cannot override trusted builtins).
117
+ for (const agent of [...discovery.project, ...discovery.builtin, ...discovery.user]) {
118
+ byName.set(agent.name.toLowerCase(), agent);
119
+ }
120
+ return [...byName.values()].filter((agent) => !agent.disabled).sort((a, b) => a.name.localeCompare(b.name));
121
+ }