pi-crew 0.1.46 → 0.1.49

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 (253) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/agents/analyst.md +11 -11
  3. package/agents/critic.md +11 -11
  4. package/agents/executor.md +11 -11
  5. package/agents/explorer.md +11 -11
  6. package/agents/planner.md +11 -11
  7. package/agents/reviewer.md +11 -11
  8. package/agents/security-reviewer.md +11 -11
  9. package/agents/test-engineer.md +11 -11
  10. package/agents/verifier.md +11 -11
  11. package/agents/writer.md +11 -11
  12. package/docs/next-upgrade-roadmap.md +117 -42
  13. package/docs/refactor-tasks-phase3.md +394 -394
  14. package/docs/refactor-tasks-phase4.md +564 -564
  15. package/docs/refactor-tasks-phase5.md +402 -402
  16. package/docs/refactor-tasks-phase6.md +662 -662
  17. package/docs/research/AGENT-EXECUTION-ARCHITECTURE.md +261 -0
  18. package/docs/research/AGENT-LIFECYCLE-COMPARISON.md +111 -0
  19. package/docs/research/AUDIT_OH_MY_PI.md +261 -0
  20. package/docs/research/AUDIT_PI_CREW.md +457 -0
  21. package/docs/research/CAVEMAN-DEEP-RESEARCH.md +281 -0
  22. package/docs/research/COMPARISON_OH_MY_PI_VS_PI_CREW.md +264 -0
  23. package/docs/research/DEEP-RESEARCH-PI-POWERBAR.md +343 -0
  24. package/docs/research/DEEP_RESEARCH_SUBAGENT_ARCHITECTURE.md +480 -0
  25. package/docs/research/GAP_CLOSURE_IMPLEMENTATION_PLAN.md +354 -0
  26. package/docs/research/IMPLEMENTATION_PLAN.md +385 -0
  27. package/docs/research/LIVE-SESSION-PRODUCTION-READY-PLAN.md +502 -0
  28. package/docs/research/OH-MY-PI-DEEP-RESEARCH-v14.7.6.md +266 -0
  29. package/docs/research/REMAINING-GAPS-PLAN.md +363 -0
  30. package/docs/research/SESSION-SUMMARY-2026-05-08.md +146 -0
  31. package/docs/research/UI-RESPONSIVENESS-AUDIT.md +173 -0
  32. package/docs/research-awesome-agent-skills-distillation.md +100 -100
  33. package/docs/research-extension-examples.md +297 -297
  34. package/docs/research-extension-system.md +324 -324
  35. package/docs/research-oh-my-pi-distillation.md +56 -9
  36. package/docs/research-optimization-plan.md +548 -548
  37. package/docs/research-phase10-distillation.md +198 -198
  38. package/docs/research-phase11-distillation.md +201 -201
  39. package/docs/research-pi-coding-agent.md +357 -357
  40. package/docs/research-source-pi-crew-reference.md +174 -174
  41. package/docs/runtime-flow.md +148 -148
  42. package/docs/source-runtime-refactor-map.md +107 -107
  43. package/index.ts +6 -6
  44. package/package.json +99 -98
  45. package/schema.json +8 -0
  46. package/skills/async-worker-recovery/SKILL.md +42 -42
  47. package/skills/context-artifact-hygiene/SKILL.md +52 -52
  48. package/skills/delegation-patterns/SKILL.md +54 -54
  49. package/skills/mailbox-interactive/SKILL.md +40 -40
  50. package/skills/model-routing-context/SKILL.md +39 -39
  51. package/skills/multi-perspective-review/SKILL.md +58 -58
  52. package/skills/observability-reliability/SKILL.md +41 -41
  53. package/skills/orchestration/SKILL.md +157 -0
  54. package/skills/ownership-session-security/SKILL.md +41 -41
  55. package/skills/pi-extension-lifecycle/SKILL.md +39 -39
  56. package/skills/requirements-to-task-packet/SKILL.md +63 -63
  57. package/skills/resource-discovery-config/SKILL.md +41 -41
  58. package/skills/runtime-state-reader/SKILL.md +44 -44
  59. package/skills/secure-agent-orchestration-review/SKILL.md +45 -45
  60. package/skills/state-mutation-locking/SKILL.md +42 -42
  61. package/skills/systematic-debugging/SKILL.md +67 -67
  62. package/skills/ui-render-performance/SKILL.md +39 -39
  63. package/skills/verification-before-done/SKILL.md +57 -57
  64. package/skills/worktree-isolation/SKILL.md +39 -39
  65. package/src/agents/agent-config.ts +6 -0
  66. package/src/agents/agent-search.ts +98 -0
  67. package/src/agents/agent-serializer.ts +4 -0
  68. package/src/agents/discover-agents.ts +17 -4
  69. package/src/config/config.ts +24 -0
  70. package/src/config/defaults.ts +11 -0
  71. package/src/extension/autonomous-policy.ts +26 -33
  72. package/src/extension/cross-extension-rpc.ts +82 -82
  73. package/src/extension/help.ts +1 -0
  74. package/src/extension/management.ts +5 -0
  75. package/src/extension/register.ts +58 -13
  76. package/src/extension/registration/commands.ts +33 -1
  77. package/src/extension/registration/compaction-guard.ts +125 -125
  78. package/src/extension/registration/team-tool.ts +6 -4
  79. package/src/extension/run-bundle-schema.ts +89 -89
  80. package/src/extension/run-index.ts +24 -18
  81. package/src/extension/run-maintenance.ts +68 -62
  82. package/src/extension/team-tool/api.ts +23 -2
  83. package/src/extension/team-tool/cancel.ts +86 -11
  84. package/src/extension/team-tool/context.ts +3 -0
  85. package/src/extension/team-tool/handle-settings.ts +188 -188
  86. package/src/extension/team-tool/inspect.ts +41 -41
  87. package/src/extension/team-tool/intent-policy.ts +42 -0
  88. package/src/extension/team-tool/lifecycle-actions.ts +47 -18
  89. package/src/extension/team-tool/parallel-dispatch.ts +156 -0
  90. package/src/extension/team-tool/plan.ts +19 -19
  91. package/src/extension/team-tool/respond.ts +10 -2
  92. package/src/extension/team-tool/run.ts +3 -2
  93. package/src/extension/team-tool/status.ts +1 -1
  94. package/src/extension/team-tool-types.ts +1 -0
  95. package/src/extension/team-tool.ts +13 -3
  96. package/src/hooks/registry.ts +61 -0
  97. package/src/hooks/types.ts +41 -0
  98. package/src/i18n.ts +184 -184
  99. package/src/observability/exporters/otlp-exporter.ts +77 -77
  100. package/src/prompt/prompt-runtime.ts +72 -72
  101. package/src/runtime/agent-control.ts +108 -2
  102. package/src/runtime/agent-memory.ts +72 -72
  103. package/src/runtime/agent-observability.ts +114 -114
  104. package/src/runtime/async-marker.ts +26 -26
  105. package/src/runtime/async-runner.ts +3 -1
  106. package/src/runtime/attention-events.ts +28 -28
  107. package/src/runtime/background-runner.ts +19 -0
  108. package/src/runtime/cancellation-token.ts +89 -0
  109. package/src/runtime/cancellation.ts +61 -51
  110. package/src/runtime/capability-inventory.ts +116 -0
  111. package/src/runtime/child-pi.ts +2 -1
  112. package/src/runtime/code-summary.ts +247 -0
  113. package/src/runtime/completion-guard.ts +190 -190
  114. package/src/runtime/crash-recovery.ts +181 -0
  115. package/src/runtime/crew-agent-records.ts +35 -7
  116. package/src/runtime/crew-agent-runtime.ts +1 -0
  117. package/src/runtime/custom-tools/irc-tool.ts +201 -0
  118. package/src/runtime/custom-tools/submit-result-tool.ts +90 -0
  119. package/src/runtime/delivery-coordinator.ts +3 -1
  120. package/src/runtime/direct-run.ts +35 -35
  121. package/src/runtime/effectiveness.ts +81 -76
  122. package/src/runtime/event-stream-bridge.ts +90 -0
  123. package/src/runtime/foreground-control.ts +82 -82
  124. package/src/runtime/green-contract.ts +46 -46
  125. package/src/runtime/group-join.ts +106 -106
  126. package/src/runtime/heartbeat-gradient.ts +28 -28
  127. package/src/runtime/heartbeat-watcher.ts +124 -124
  128. package/src/runtime/live-agent-control.ts +88 -88
  129. package/src/runtime/live-agent-manager.ts +78 -2
  130. package/src/runtime/live-control-realtime.ts +36 -36
  131. package/src/runtime/live-extension-bridge.ts +150 -0
  132. package/src/runtime/live-irc.ts +92 -0
  133. package/src/runtime/live-session-health.ts +100 -0
  134. package/src/runtime/live-session-runtime.ts +297 -7
  135. package/src/runtime/mcp-proxy.ts +113 -0
  136. package/src/runtime/notebook-helpers.ts +90 -0
  137. package/src/runtime/orphan-sentinel.ts +7 -0
  138. package/src/runtime/output-validator.ts +187 -0
  139. package/src/runtime/parallel-research.ts +44 -44
  140. package/src/runtime/parallel-utils.ts +57 -0
  141. package/src/runtime/parent-guard.ts +80 -0
  142. package/src/runtime/pi-json-output.ts +111 -111
  143. package/src/runtime/policy-engine.ts +79 -79
  144. package/src/runtime/progress-event-coalescer.ts +43 -43
  145. package/src/runtime/prose-compressor.ts +164 -0
  146. package/src/runtime/recovery-recipes.ts +74 -74
  147. package/src/runtime/result-extractor.ts +121 -0
  148. package/src/runtime/role-permission.ts +39 -39
  149. package/src/runtime/runtime-resolver.ts +1 -4
  150. package/src/runtime/semaphore.ts +131 -0
  151. package/src/runtime/sensitive-paths.ts +92 -0
  152. package/src/runtime/session-resources.ts +25 -25
  153. package/src/runtime/session-snapshot.ts +59 -59
  154. package/src/runtime/session-usage.ts +79 -79
  155. package/src/runtime/sidechain-output.ts +29 -29
  156. package/src/runtime/stream-preview.ts +177 -0
  157. package/src/runtime/subagent-manager.ts +3 -2
  158. package/src/runtime/subprocess-tool-registry.ts +67 -0
  159. package/src/runtime/supervisor-contact.ts +59 -59
  160. package/src/runtime/task-display.ts +38 -38
  161. package/src/runtime/task-output-context.ts +59 -9
  162. package/src/runtime/task-runner/capabilities.ts +78 -78
  163. package/src/runtime/task-runner/live-executor.ts +2 -0
  164. package/src/runtime/task-runner/progress.ts +119 -119
  165. package/src/runtime/task-runner/prompt-builder.ts +70 -8
  166. package/src/runtime/task-runner/prompt-pipeline.ts +64 -64
  167. package/src/runtime/task-runner/result-utils.ts +14 -14
  168. package/src/runtime/task-runner/run-projection.ts +104 -0
  169. package/src/runtime/task-runner/state-helpers.ts +22 -22
  170. package/src/runtime/task-runner.ts +75 -4
  171. package/src/runtime/team-runner.ts +60 -8
  172. package/src/runtime/worker-heartbeat.ts +21 -21
  173. package/src/runtime/worker-startup.ts +57 -57
  174. package/src/runtime/workspace-tree.ts +298 -0
  175. package/src/runtime/yield-handler.ts +189 -0
  176. package/src/schema/config-schema.ts +6 -0
  177. package/src/schema/team-tool-schema.ts +11 -1
  178. package/src/skills/discover-skills.ts +67 -0
  179. package/src/state/active-run-registry.ts +4 -2
  180. package/src/state/artifact-store.ts +4 -1
  181. package/src/state/atomic-write.ts +50 -1
  182. package/src/state/blob-store.ts +117 -0
  183. package/src/state/contracts.ts +1 -0
  184. package/src/state/event-log-rotation.ts +158 -0
  185. package/src/state/event-log.ts +52 -2
  186. package/src/state/mailbox.ts +87 -7
  187. package/src/state/state-store.ts +24 -4
  188. package/src/state/task-claims.ts +44 -44
  189. package/src/state/types.ts +20 -0
  190. package/src/state/usage.ts +29 -29
  191. package/src/subagents/async-entry.ts +1 -1
  192. package/src/subagents/index.ts +3 -3
  193. package/src/subagents/live/control.ts +1 -1
  194. package/src/subagents/live/manager.ts +1 -1
  195. package/src/subagents/live/realtime.ts +1 -1
  196. package/src/subagents/live/session-runtime.ts +1 -1
  197. package/src/subagents/manager.ts +1 -1
  198. package/src/subagents/spawn.ts +1 -1
  199. package/src/teams/team-serializer.ts +38 -38
  200. package/src/types/diff.d.ts +18 -18
  201. package/src/ui/agent-management-overlay.ts +144 -0
  202. package/src/ui/crew-footer.ts +101 -101
  203. package/src/ui/crew-select-list.ts +111 -111
  204. package/src/ui/crew-widget.ts +11 -2
  205. package/src/ui/dashboard-panes/cancellation-pane.ts +43 -0
  206. package/src/ui/dashboard-panes/capability-pane.ts +60 -0
  207. package/src/ui/dashboard-panes/mailbox-pane.ts +35 -11
  208. package/src/ui/dashboard-panes/metrics-pane.ts +34 -34
  209. package/src/ui/dynamic-border.ts +25 -25
  210. package/src/ui/layout-primitives.ts +106 -106
  211. package/src/ui/live-run-sidebar.ts +4 -0
  212. package/src/ui/loaders.ts +158 -158
  213. package/src/ui/powerbar-publisher.ts +77 -15
  214. package/src/ui/render-coalescer.ts +51 -0
  215. package/src/ui/render-diff.ts +119 -119
  216. package/src/ui/render-scheduler.ts +143 -143
  217. package/src/ui/run-dashboard.ts +4 -0
  218. package/src/ui/run-event-bus.ts +209 -0
  219. package/src/ui/run-snapshot-cache.ts +68 -16
  220. package/src/ui/snapshot-types.ts +8 -0
  221. package/src/ui/spinner.ts +17 -17
  222. package/src/ui/status-colors.ts +58 -58
  223. package/src/ui/syntax-highlight.ts +116 -116
  224. package/src/ui/transcript-entries.ts +258 -0
  225. package/src/utils/atomic-write.ts +33 -33
  226. package/src/utils/completion-dedupe.ts +63 -63
  227. package/src/utils/frontmatter.ts +68 -68
  228. package/src/utils/git.ts +262 -262
  229. package/src/utils/ids.ts +17 -12
  230. package/src/utils/incremental-reader.ts +104 -0
  231. package/src/utils/names.ts +27 -27
  232. package/src/utils/redaction.ts +44 -44
  233. package/src/utils/safe-paths.ts +47 -47
  234. package/src/utils/scan-cache.ts +137 -0
  235. package/src/utils/sleep.ts +32 -32
  236. package/src/utils/sse-parser.ts +134 -0
  237. package/src/utils/task-name-generator.ts +337 -0
  238. package/src/utils/visual.ts +33 -2
  239. package/src/workflows/validate-workflow.ts +40 -40
  240. package/src/worktree/branch-freshness.ts +45 -45
  241. package/src/worktree/cleanup.ts +2 -1
  242. package/teams/default.team.md +12 -12
  243. package/teams/fast-fix.team.md +11 -11
  244. package/teams/implementation.team.md +18 -18
  245. package/teams/parallel-research.team.md +14 -14
  246. package/teams/research.team.md +11 -11
  247. package/teams/review.team.md +12 -12
  248. package/workflows/default.workflow.md +29 -29
  249. package/workflows/fast-fix.workflow.md +22 -22
  250. package/workflows/implementation.workflow.md +38 -38
  251. package/workflows/parallel-research.workflow.md +46 -46
  252. package/workflows/research.workflow.md +22 -22
  253. package/workflows/review.workflow.md +30 -30
@@ -1,297 +1,297 @@
1
- # Research: Extension Examples & Patterns
2
-
3
- > Ngày: 2026-04-29 | Read-only research | Source: `source/pi-mono/packages/coding-agent/examples/extensions/`
4
-
5
- ## 1. Example Catalog (86 files, 60+ extensions)
6
-
7
- ### 1.1 Sorted by relevance to pi-crew
8
-
9
- | Priority | Example | Relevance |
10
- |---|---|---|
11
- | ⭐⭐⭐ | `subagent/` | Most similar to pi-crew: child Pi spawning, parallel, chain |
12
- | ⭐⭐⭐ | `custom-compaction.ts` | Hook compaction — useful for preserving run state |
13
- | ⭐⭐⭐ | `event-bus.ts` | Cross-extension communication pattern |
14
- | ⭐⭐⭐ | `plan-mode/` | State persistence, dynamic tools, widget management |
15
- | ⭐⭐⭐ | `structured-output.ts` | `terminate: true` — save LLM turns |
16
- | ⭐⭐ | `handoff.ts` | Context transfer to new session |
17
- | ⭐⭐ | `dynamic-tools.ts` | Register tools at runtime |
18
- | ⭐⭐ | `permission-gate.ts` | Gate dangerous operations |
19
- | ⭐⭐ | `trigger-compact.ts` | Proactive compaction monitoring |
20
- | ⭐⭐ | `send-user-message.ts` | sendUserMessage pattern |
21
- | ⭐ | `dirty-repo-guard.ts` | Guard against uncommitted changes |
22
- | ⭐ | `model-status.ts` | Model status in footer |
23
- | ⭐ | `confirm-destructive.ts` | Confirm destructive operations |
24
-
25
- ## 2. Deep Analysis of Key Examples
26
-
27
- ### 2.1 subagent/ — The Reference Implementation
28
-
29
- **Files:**
30
- - `index.ts` (~530 dòng): Main tool with execute + render
31
- - `agents.ts` (~130 dòng): Agent discovery (user/project scope)
32
-
33
- **Architecture:**
34
- ```
35
- subagent tool
36
- ├── Single: runSingleAgent() → spawn pi --mode json -p
37
- ├── Parallel: mapWithConcurrencyLimit(tasks, 4, runSingleAgent)
38
- └── Chain: sequential loop with {previous} placeholder
39
- ```
40
-
41
- **Key patterns:**
42
- - Agent discovery: `discoverAgents(cwd, scope)` — scans `.md` files with YAML frontmatter
43
- - Child process: `getPiInvocation()` detects current runtime (node/bun/pi binary)
44
- - Streaming: `onUpdate` callback for partial results during execution
45
- - Render: `renderCall()` + `renderResult()` with collapsed/expanded views
46
- - Abort: AbortSignal propagated to child process
47
-
48
- **What pi-crew does better:**
49
- - Durable state (manifest, tasks, events) instead of in-memory only
50
- - Team/workflow abstraction instead of flat agent list
51
- - Task graph with DAG dependencies instead of linear chain
52
- - Async background runner with PID tracking
53
- - Policy engine for limits/retry/escalation
54
- - Mailbox for inter-task communication
55
- - Worktree isolation per task
56
-
57
- **What pi-crew could adopt from this:**
58
- - `terminate: true` on final results (not used in example either, but available)
59
- - `renderCall/Result` custom rendering patterns
60
- - `mapWithConcurrencyLimit` pattern (pi-crew already has similar)
61
-
62
- ### 2.2 custom-compaction.ts — Custom Compaction
63
-
64
- **Pattern:**
65
- ```typescript
66
- pi.on("session_before_compact", async (event, ctx) => {
67
- // 1. Get preparation data
68
- const { messagesToSummarize, turnPrefixMessages, tokensBefore, firstKeptEntryId } = event.preparation;
69
-
70
- // 2. Use different model for summarization (cheaper)
71
- const model = ctx.modelRegistry.find("google", "gemini-2.5-flash");
72
-
73
- // 3. Custom prompt
74
- const summary = await complete(model, { messages: [...] }, { apiKey, signal });
75
-
76
- // 4. Return custom compaction result
77
- return {
78
- compaction: { summary, firstKeptEntryId, tokensBefore }
79
- };
80
- });
81
- ```
82
-
83
- **Relevance to pi-crew:**
84
- - Can use cheap model to summarize completed tasks
85
- - Can protect foreground runs from being compacted mid-execution
86
- - Can store structured artifact index in compaction `details`
87
-
88
- ### 2.3 event-bus.ts — Cross-Extension Communication
89
-
90
- **Pattern:**
91
- ```typescript
92
- // Extension A: emit events
93
- pi.events.emit("my:notification", { message: "hello", from: "ext-a" });
94
-
95
- // Extension B: listen
96
- pi.events.on("my:notification", (data) => {
97
- currentCtx?.ui.notify(`Event from ${data.from}: ${data.message}`);
98
- });
99
- ```
100
-
101
- **Relevance to pi-crew:**
102
- - Already used for internal events (`subagent.stuck-blocked`)
103
- - Could publish structured events for other extensions to consume:
104
- - `pi-crew:run:completed`
105
- - `pi-crew:subagent:completed`
106
- - `pi-crew:run:failed`
107
-
108
- ### 2.4 plan-mode/ — State Persistence + Dynamic Tools
109
-
110
- **Key patterns:**
111
-
112
- State persistence:
113
- ```typescript
114
- // Save
115
- pi.appendEntry("plan-mode", { enabled, todos, executing });
116
-
117
- // Restore on session_start
118
- const entries = ctx.sessionManager.getEntries();
119
- const state = entries
120
- .filter(e => e.type === "custom" && e.customType === "plan-mode")
121
- .pop()?.data;
122
- ```
123
-
124
- Dynamic tools:
125
- ```typescript
126
- // Switch between tool sets
127
- if (planModeEnabled) {
128
- pi.setActiveTools(["read", "bash", "grep", "find", "ls"]);
129
- } else {
130
- pi.setActiveTools(["read", "bash", "edit", "write"]);
131
- }
132
- ```
133
-
134
- Tool call gate:
135
- ```typescript
136
- pi.on("tool_call", async (event) => {
137
- if (planModeEnabled && event.toolName === "bash") {
138
- if (!isSafeCommand(event.input.command)) {
139
- return { block: true, reason: "..." };
140
- }
141
- }
142
- });
143
- ```
144
-
145
- **Relevance to pi-crew:**
146
- - `pi.appendEntry` pattern for cross-session run awareness
147
- - `pi.setActiveTools` could be used to restrict tools during team runs
148
- - `tool_call` gate for destructive team actions
149
-
150
- ### 2.5 structured-output.ts — terminate: true
151
-
152
- **Pattern:**
153
- ```typescript
154
- async execute(_toolCallId, params) {
155
- return {
156
- content: [{ type: "text", text: "Done" }],
157
- details: { headline, summary, actionItems },
158
- terminate: true, // ← No follow-up LLM turn needed
159
- };
160
- }
161
- ```
162
-
163
- **Relevance to pi-crew:**
164
- - `Agent` tool results could use `terminate: true` when background run queued
165
- - `get_subagent_result` could terminate when result is final
166
- - `team` tool status/list/recommend actions could terminate
167
-
168
- ### 2.6 handoff.ts — Context Transfer to New Session
169
-
170
- **Pattern:**
171
- ```typescript
172
- // 1. Extract conversation context
173
- const messages = ctx.sessionManager.getBranch()
174
- .filter(e => e.type === "message")
175
- .map(e => e.message);
176
-
177
- // 2. Generate focused prompt
178
- const prompt = await complete(model, { systemPrompt, messages }, { apiKey });
179
-
180
- // 3. Create new session with pre-filled editor
181
- await ctx.newSession({
182
- parentSession: currentSessionFile,
183
- withSession: async (replacementCtx) => {
184
- replacementCtx.ui.setEditorText(prompt);
185
- },
186
- });
187
- ```
188
-
189
- **Relevance to pi-crew:**
190
- - When a task in a team run needs isolated context, could handoff to new session
191
- - Parent session tracking via `parentSession`
192
-
193
- ### 2.7 permission-gate.ts — Dangerous Operation Gate
194
-
195
- **Pattern:**
196
- ```typescript
197
- pi.on("tool_call", async (event, ctx) => {
198
- if (event.toolName !== "bash") return;
199
- if (isDangerousPattern(event.input.command)) {
200
- const choice = await ctx.ui.select("Allow?", ["Yes", "No"]);
201
- if (choice !== "Yes") {
202
- return { block: true, reason: "Blocked by user" };
203
- }
204
- }
205
- });
206
- ```
207
-
208
- **Relevance to pi-crew:**
209
- - Gate destructive team actions (delete, forget, prune)
210
- - Only allow with explicit `confirm: true` parameter
211
-
212
- ### 2.8 trigger-compact.ts — Proactive Compaction
213
-
214
- **Pattern:**
215
- ```typescript
216
- pi.on("turn_end", (_event, ctx) => {
217
- const usage = ctx.getContextUsage();
218
- if (usage?.tokens && usage.tokens > THRESHOLD) {
219
- ctx.compact({ customInstructions: "..." });
220
- }
221
- });
222
- ```
223
-
224
- **Relevance to pi-crew:**
225
- - Monitor context during long team runs
226
- - Auto-compact before hitting overflow errors
227
- - Use compact's callback to track state
228
-
229
- ## 3. Pattern Summary
230
-
231
- ### 3.1 Patterns pi-crew already implements well
232
-
233
- | Pattern | pi-crew implementation |
234
- |---|---|
235
- | Child Pi spawning | `SubagentManager` + `spawn.ts` with full process management |
236
- | Parallel execution | `mapConcurrent` in team runner |
237
- | State persistence | Durable file-based (manifest, tasks, events, artifacts) |
238
- | Widget rendering | `CrewWidget`, `LiveRunSidebar`, `Powerbar` |
239
- | Lifecycle hooks | `session_start`, `session_before_switch`, `session_shutdown` |
240
- | Config merge | `loadConfig` with user/project priority |
241
- | Abort propagation | `AbortController` trees in foreground runs |
242
-
243
- ### 3.2 Patterns pi-crew could adopt
244
-
245
- | Pattern | Current status | Recommendation |
246
- |---|---|---|
247
- | `terminate: true` | ❌ Not used | Add to Agent/get_subagent_result |
248
- | `session_before_compact` hook | ❌ Not hooked | Cancel compact during foreground runs |
249
- | Custom compaction model | ❌ Not used | Use Haiku/Gemini Flash for task summaries |
250
- | `pi.events` publish | ⚠️ Internal only | Add public structured events |
251
- | `pi.appendEntry` | ❌ Not used | Cross-session run references |
252
- | `tool_call` permission gate | ❌ Not gated | Gate destructive team actions |
253
- | Config-driven tool registration | ❌ Always all | Register tools per config |
254
- | Working indicator | ❌ Widget only | Use `ctx.ui.setWorkingIndicator` |
255
- | Session name auto-set | ❌ Manual only | Auto-name from team run context |
256
- | `ctx.compact()` proactive | ❌ No monitoring | Monitor + auto-compact at threshold |
257
-
258
- ## 4. Example: Complete Tool with terminate + render
259
-
260
- This shows a hypothetical optimized pi-crew Agent tool:
261
-
262
- ```typescript
263
- // OPTIMIZED Agent tool pattern
264
- const AgentTool = defineTool({
265
- name: "Agent",
266
- label: "Agent",
267
- description: "Launch a real pi-crew subagent...",
268
- parameters: Type.Object({
269
- prompt: Type.String(),
270
- description: Type.String(),
271
- subagent_type: Type.String(),
272
- run_in_background: Type.Optional(Type.Boolean()),
273
- }),
274
- async execute(_id, params, signal, _onUpdate, ctx) {
275
- // ... spawn subagent ...
276
- if (params.run_in_background) {
277
- return {
278
- content: [{ type: "text", text: `Agent queued. ID: ${record.id}` }],
279
- details: { agentId: record.id, status: "queued" },
280
- terminate: true, // ← No need for LLM follow-up
281
- };
282
- }
283
- await record.promise;
284
- const output = readResult(record);
285
- return {
286
- content: [{ type: "text", text: output }],
287
- details: { agentId: record.id, status: record.status },
288
- terminate: true, // ← Final result, save LLM turn
289
- };
290
- },
291
- renderResult(result, { expanded }, theme) {
292
- // Custom rendering with colored status icons
293
- // Collapsed/expanded views
294
- // Usage stats display
295
- },
296
- });
297
- ```
1
+ # Research: Extension Examples & Patterns
2
+
3
+ > Ngày: 2026-04-29 | Read-only research | Source: `source/pi-mono/packages/coding-agent/examples/extensions/`
4
+
5
+ ## 1. Example Catalog (86 files, 60+ extensions)
6
+
7
+ ### 1.1 Sorted by relevance to pi-crew
8
+
9
+ | Priority | Example | Relevance |
10
+ |---|---|---|
11
+ | ⭐⭐⭐ | `subagent/` | Most similar to pi-crew: child Pi spawning, parallel, chain |
12
+ | ⭐⭐⭐ | `custom-compaction.ts` | Hook compaction — useful for preserving run state |
13
+ | ⭐⭐⭐ | `event-bus.ts` | Cross-extension communication pattern |
14
+ | ⭐⭐⭐ | `plan-mode/` | State persistence, dynamic tools, widget management |
15
+ | ⭐⭐⭐ | `structured-output.ts` | `terminate: true` — save LLM turns |
16
+ | ⭐⭐ | `handoff.ts` | Context transfer to new session |
17
+ | ⭐⭐ | `dynamic-tools.ts` | Register tools at runtime |
18
+ | ⭐⭐ | `permission-gate.ts` | Gate dangerous operations |
19
+ | ⭐⭐ | `trigger-compact.ts` | Proactive compaction monitoring |
20
+ | ⭐⭐ | `send-user-message.ts` | sendUserMessage pattern |
21
+ | ⭐ | `dirty-repo-guard.ts` | Guard against uncommitted changes |
22
+ | ⭐ | `model-status.ts` | Model status in footer |
23
+ | ⭐ | `confirm-destructive.ts` | Confirm destructive operations |
24
+
25
+ ## 2. Deep Analysis of Key Examples
26
+
27
+ ### 2.1 subagent/ — The Reference Implementation
28
+
29
+ **Files:**
30
+ - `index.ts` (~530 dòng): Main tool with execute + render
31
+ - `agents.ts` (~130 dòng): Agent discovery (user/project scope)
32
+
33
+ **Architecture:**
34
+ ```
35
+ subagent tool
36
+ ├── Single: runSingleAgent() → spawn pi --mode json -p
37
+ ├── Parallel: mapWithConcurrencyLimit(tasks, 4, runSingleAgent)
38
+ └── Chain: sequential loop with {previous} placeholder
39
+ ```
40
+
41
+ **Key patterns:**
42
+ - Agent discovery: `discoverAgents(cwd, scope)` — scans `.md` files with YAML frontmatter
43
+ - Child process: `getPiInvocation()` detects current runtime (node/bun/pi binary)
44
+ - Streaming: `onUpdate` callback for partial results during execution
45
+ - Render: `renderCall()` + `renderResult()` with collapsed/expanded views
46
+ - Abort: AbortSignal propagated to child process
47
+
48
+ **What pi-crew does better:**
49
+ - Durable state (manifest, tasks, events) instead of in-memory only
50
+ - Team/workflow abstraction instead of flat agent list
51
+ - Task graph with DAG dependencies instead of linear chain
52
+ - Async background runner with PID tracking
53
+ - Policy engine for limits/retry/escalation
54
+ - Mailbox for inter-task communication
55
+ - Worktree isolation per task
56
+
57
+ **What pi-crew could adopt from this:**
58
+ - `terminate: true` on final results (not used in example either, but available)
59
+ - `renderCall/Result` custom rendering patterns
60
+ - `mapWithConcurrencyLimit` pattern (pi-crew already has similar)
61
+
62
+ ### 2.2 custom-compaction.ts — Custom Compaction
63
+
64
+ **Pattern:**
65
+ ```typescript
66
+ pi.on("session_before_compact", async (event, ctx) => {
67
+ // 1. Get preparation data
68
+ const { messagesToSummarize, turnPrefixMessages, tokensBefore, firstKeptEntryId } = event.preparation;
69
+
70
+ // 2. Use different model for summarization (cheaper)
71
+ const model = ctx.modelRegistry.find("google", "gemini-2.5-flash");
72
+
73
+ // 3. Custom prompt
74
+ const summary = await complete(model, { messages: [...] }, { apiKey, signal });
75
+
76
+ // 4. Return custom compaction result
77
+ return {
78
+ compaction: { summary, firstKeptEntryId, tokensBefore }
79
+ };
80
+ });
81
+ ```
82
+
83
+ **Relevance to pi-crew:**
84
+ - Can use cheap model to summarize completed tasks
85
+ - Can protect foreground runs from being compacted mid-execution
86
+ - Can store structured artifact index in compaction `details`
87
+
88
+ ### 2.3 event-bus.ts — Cross-Extension Communication
89
+
90
+ **Pattern:**
91
+ ```typescript
92
+ // Extension A: emit events
93
+ pi.events.emit("my:notification", { message: "hello", from: "ext-a" });
94
+
95
+ // Extension B: listen
96
+ pi.events.on("my:notification", (data) => {
97
+ currentCtx?.ui.notify(`Event from ${data.from}: ${data.message}`);
98
+ });
99
+ ```
100
+
101
+ **Relevance to pi-crew:**
102
+ - Already used for internal events (`subagent.stuck-blocked`)
103
+ - Could publish structured events for other extensions to consume:
104
+ - `pi-crew:run:completed`
105
+ - `pi-crew:subagent:completed`
106
+ - `pi-crew:run:failed`
107
+
108
+ ### 2.4 plan-mode/ — State Persistence + Dynamic Tools
109
+
110
+ **Key patterns:**
111
+
112
+ State persistence:
113
+ ```typescript
114
+ // Save
115
+ pi.appendEntry("plan-mode", { enabled, todos, executing });
116
+
117
+ // Restore on session_start
118
+ const entries = ctx.sessionManager.getEntries();
119
+ const state = entries
120
+ .filter(e => e.type === "custom" && e.customType === "plan-mode")
121
+ .pop()?.data;
122
+ ```
123
+
124
+ Dynamic tools:
125
+ ```typescript
126
+ // Switch between tool sets
127
+ if (planModeEnabled) {
128
+ pi.setActiveTools(["read", "bash", "grep", "find", "ls"]);
129
+ } else {
130
+ pi.setActiveTools(["read", "bash", "edit", "write"]);
131
+ }
132
+ ```
133
+
134
+ Tool call gate:
135
+ ```typescript
136
+ pi.on("tool_call", async (event) => {
137
+ if (planModeEnabled && event.toolName === "bash") {
138
+ if (!isSafeCommand(event.input.command)) {
139
+ return { block: true, reason: "..." };
140
+ }
141
+ }
142
+ });
143
+ ```
144
+
145
+ **Relevance to pi-crew:**
146
+ - `pi.appendEntry` pattern for cross-session run awareness
147
+ - `pi.setActiveTools` could be used to restrict tools during team runs
148
+ - `tool_call` gate for destructive team actions
149
+
150
+ ### 2.5 structured-output.ts — terminate: true
151
+
152
+ **Pattern:**
153
+ ```typescript
154
+ async execute(_toolCallId, params) {
155
+ return {
156
+ content: [{ type: "text", text: "Done" }],
157
+ details: { headline, summary, actionItems },
158
+ terminate: true, // ← No follow-up LLM turn needed
159
+ };
160
+ }
161
+ ```
162
+
163
+ **Relevance to pi-crew:**
164
+ - `Agent` tool results could use `terminate: true` when background run queued
165
+ - `get_subagent_result` could terminate when result is final
166
+ - `team` tool status/list/recommend actions could terminate
167
+
168
+ ### 2.6 handoff.ts — Context Transfer to New Session
169
+
170
+ **Pattern:**
171
+ ```typescript
172
+ // 1. Extract conversation context
173
+ const messages = ctx.sessionManager.getBranch()
174
+ .filter(e => e.type === "message")
175
+ .map(e => e.message);
176
+
177
+ // 2. Generate focused prompt
178
+ const prompt = await complete(model, { systemPrompt, messages }, { apiKey });
179
+
180
+ // 3. Create new session with pre-filled editor
181
+ await ctx.newSession({
182
+ parentSession: currentSessionFile,
183
+ withSession: async (replacementCtx) => {
184
+ replacementCtx.ui.setEditorText(prompt);
185
+ },
186
+ });
187
+ ```
188
+
189
+ **Relevance to pi-crew:**
190
+ - When a task in a team run needs isolated context, could handoff to new session
191
+ - Parent session tracking via `parentSession`
192
+
193
+ ### 2.7 permission-gate.ts — Dangerous Operation Gate
194
+
195
+ **Pattern:**
196
+ ```typescript
197
+ pi.on("tool_call", async (event, ctx) => {
198
+ if (event.toolName !== "bash") return;
199
+ if (isDangerousPattern(event.input.command)) {
200
+ const choice = await ctx.ui.select("Allow?", ["Yes", "No"]);
201
+ if (choice !== "Yes") {
202
+ return { block: true, reason: "Blocked by user" };
203
+ }
204
+ }
205
+ });
206
+ ```
207
+
208
+ **Relevance to pi-crew:**
209
+ - Gate destructive team actions (delete, forget, prune)
210
+ - Only allow with explicit `confirm: true` parameter
211
+
212
+ ### 2.8 trigger-compact.ts — Proactive Compaction
213
+
214
+ **Pattern:**
215
+ ```typescript
216
+ pi.on("turn_end", (_event, ctx) => {
217
+ const usage = ctx.getContextUsage();
218
+ if (usage?.tokens && usage.tokens > THRESHOLD) {
219
+ ctx.compact({ customInstructions: "..." });
220
+ }
221
+ });
222
+ ```
223
+
224
+ **Relevance to pi-crew:**
225
+ - Monitor context during long team runs
226
+ - Auto-compact before hitting overflow errors
227
+ - Use compact's callback to track state
228
+
229
+ ## 3. Pattern Summary
230
+
231
+ ### 3.1 Patterns pi-crew already implements well
232
+
233
+ | Pattern | pi-crew implementation |
234
+ |---|---|
235
+ | Child Pi spawning | `SubagentManager` + `spawn.ts` with full process management |
236
+ | Parallel execution | `mapConcurrent` in team runner |
237
+ | State persistence | Durable file-based (manifest, tasks, events, artifacts) |
238
+ | Widget rendering | `CrewWidget`, `LiveRunSidebar`, `Powerbar` |
239
+ | Lifecycle hooks | `session_start`, `session_before_switch`, `session_shutdown` |
240
+ | Config merge | `loadConfig` with user/project priority |
241
+ | Abort propagation | `AbortController` trees in foreground runs |
242
+
243
+ ### 3.2 Patterns pi-crew could adopt
244
+
245
+ | Pattern | Current status | Recommendation |
246
+ |---|---|---|
247
+ | `terminate: true` | ❌ Not used | Add to Agent/get_subagent_result |
248
+ | `session_before_compact` hook | ❌ Not hooked | Cancel compact during foreground runs |
249
+ | Custom compaction model | ❌ Not used | Use Haiku/Gemini Flash for task summaries |
250
+ | `pi.events` publish | ⚠️ Internal only | Add public structured events |
251
+ | `pi.appendEntry` | ❌ Not used | Cross-session run references |
252
+ | `tool_call` permission gate | ❌ Not gated | Gate destructive team actions |
253
+ | Config-driven tool registration | ❌ Always all | Register tools per config |
254
+ | Working indicator | ❌ Widget only | Use `ctx.ui.setWorkingIndicator` |
255
+ | Session name auto-set | ❌ Manual only | Auto-name from team run context |
256
+ | `ctx.compact()` proactive | ❌ No monitoring | Monitor + auto-compact at threshold |
257
+
258
+ ## 4. Example: Complete Tool with terminate + render
259
+
260
+ This shows a hypothetical optimized pi-crew Agent tool:
261
+
262
+ ```typescript
263
+ // OPTIMIZED Agent tool pattern
264
+ const AgentTool = defineTool({
265
+ name: "Agent",
266
+ label: "Agent",
267
+ description: "Launch a real pi-crew subagent...",
268
+ parameters: Type.Object({
269
+ prompt: Type.String(),
270
+ description: Type.String(),
271
+ subagent_type: Type.String(),
272
+ run_in_background: Type.Optional(Type.Boolean()),
273
+ }),
274
+ async execute(_id, params, signal, _onUpdate, ctx) {
275
+ // ... spawn subagent ...
276
+ if (params.run_in_background) {
277
+ return {
278
+ content: [{ type: "text", text: `Agent queued. ID: ${record.id}` }],
279
+ details: { agentId: record.id, status: "queued" },
280
+ terminate: true, // ← No need for LLM follow-up
281
+ };
282
+ }
283
+ await record.promise;
284
+ const output = readResult(record);
285
+ return {
286
+ content: [{ type: "text", text: output }],
287
+ details: { agentId: record.id, status: record.status },
288
+ terminate: true, // ← Final result, save LLM turn
289
+ };
290
+ },
291
+ renderResult(result, { expanded }, theme) {
292
+ // Custom rendering with colored status icons
293
+ // Collapsed/expanded views
294
+ // Usage stats display
295
+ },
296
+ });
297
+ ```