pi-crew 0.1.51 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/CHANGELOG.md +56 -1
  2. package/README.md +176 -781
  3. package/agents/analyst.md +11 -11
  4. package/agents/critic.md +11 -11
  5. package/agents/executor.md +11 -11
  6. package/agents/explorer.md +11 -11
  7. package/agents/planner.md +11 -11
  8. package/agents/reviewer.md +11 -11
  9. package/agents/security-reviewer.md +11 -11
  10. package/agents/test-engineer.md +11 -11
  11. package/agents/verifier.md +70 -11
  12. package/agents/writer.md +11 -11
  13. package/docs/actions-reference.md +595 -0
  14. package/docs/commands-reference.md +347 -0
  15. package/docs/runtime-flow.md +148 -148
  16. package/index.ts +6 -6
  17. package/package.json +99 -99
  18. package/skills/async-worker-recovery/SKILL.md +42 -42
  19. package/skills/context-artifact-hygiene/SKILL.md +52 -52
  20. package/skills/delegation-patterns/SKILL.md +54 -54
  21. package/skills/mailbox-interactive/SKILL.md +40 -40
  22. package/skills/model-routing-context/SKILL.md +39 -39
  23. package/skills/multi-perspective-review/SKILL.md +58 -58
  24. package/skills/observability-reliability/SKILL.md +41 -41
  25. package/skills/orchestration/SKILL.md +157 -157
  26. package/skills/ownership-session-security/SKILL.md +41 -41
  27. package/skills/pi-extension-lifecycle/SKILL.md +39 -39
  28. package/skills/requirements-to-task-packet/SKILL.md +63 -63
  29. package/skills/resource-discovery-config/SKILL.md +41 -41
  30. package/skills/runtime-state-reader/SKILL.md +44 -44
  31. package/skills/secure-agent-orchestration-review/SKILL.md +45 -45
  32. package/skills/state-mutation-locking/SKILL.md +42 -42
  33. package/skills/systematic-debugging/SKILL.md +67 -67
  34. package/skills/ui-render-performance/SKILL.md +39 -39
  35. package/skills/verification-before-done/SKILL.md +57 -57
  36. package/skills/worktree-isolation/SKILL.md +39 -39
  37. package/src/adapters/claude-adapter.ts +25 -0
  38. package/src/adapters/codex-adapter.ts +21 -0
  39. package/src/adapters/cursor-adapter.ts +17 -0
  40. package/src/adapters/export-util.ts +137 -0
  41. package/src/adapters/index.ts +15 -0
  42. package/src/adapters/registry.ts +18 -0
  43. package/src/adapters/types.ts +23 -0
  44. package/src/agents/agent-config.ts +2 -0
  45. package/src/agents/agent-search.ts +98 -98
  46. package/src/agents/discover-agents.ts +2 -1
  47. package/src/config/config.ts +13 -1
  48. package/src/config/drift-detector.ts +211 -0
  49. package/src/config/markers.ts +327 -0
  50. package/src/config/resilient-parser.ts +108 -0
  51. package/src/config/suggestions.ts +74 -0
  52. package/src/extension/cross-extension-rpc.ts +103 -94
  53. package/src/extension/project-init.ts +21 -1
  54. package/src/extension/register.ts +45 -14
  55. package/src/extension/registration/commands.ts +77 -8
  56. package/src/extension/registration/subagent-tools.ts +10 -1
  57. package/src/extension/registration/team-tool.ts +10 -1
  58. package/src/extension/registration/viewers.ts +48 -34
  59. package/src/extension/run-bundle-schema.ts +89 -89
  60. package/src/extension/run-import.ts +25 -1
  61. package/src/extension/run-index.ts +5 -1
  62. package/src/extension/run-maintenance.ts +142 -68
  63. package/src/extension/team-manager-command.ts +10 -1
  64. package/src/extension/team-tool/doctor.ts +28 -3
  65. package/src/extension/team-tool/handle-settings.ts +195 -188
  66. package/src/extension/team-tool/inspect.ts +41 -41
  67. package/src/extension/team-tool/intent-policy.ts +42 -42
  68. package/src/extension/team-tool/lifecycle-actions.ts +27 -8
  69. package/src/extension/team-tool/plan.ts +19 -19
  70. package/src/extension/team-tool/run.ts +12 -1
  71. package/src/extension/team-tool.ts +11 -1
  72. package/src/i18n.ts +184 -184
  73. package/src/observability/exporters/otlp-exporter.ts +92 -77
  74. package/src/prompt/prompt-runtime.ts +72 -72
  75. package/src/runtime/agent-memory.ts +72 -72
  76. package/src/runtime/agent-observability.ts +114 -114
  77. package/src/runtime/async-marker.ts +26 -26
  78. package/src/runtime/attention-events.ts +28 -28
  79. package/src/runtime/auto-resume.ts +100 -0
  80. package/src/runtime/background-runner.ts +11 -1
  81. package/src/runtime/cancellation-token.ts +89 -89
  82. package/src/runtime/cancellation.ts +61 -61
  83. package/src/runtime/capability-inventory.ts +116 -116
  84. package/src/runtime/child-pi.ts +7 -2
  85. package/src/runtime/compaction-summary.ts +271 -0
  86. package/src/runtime/completion-guard.ts +190 -190
  87. package/src/runtime/crash-recovery.ts +33 -0
  88. package/src/runtime/delta-conflict.ts +360 -0
  89. package/src/runtime/direct-run.ts +35 -35
  90. package/src/runtime/foreground-control.ts +82 -82
  91. package/src/runtime/green-contract.ts +46 -46
  92. package/src/runtime/group-join.ts +106 -106
  93. package/src/runtime/heartbeat-gradient.ts +28 -28
  94. package/src/runtime/heartbeat-watcher.ts +124 -124
  95. package/src/runtime/iteration-hooks.ts +262 -0
  96. package/src/runtime/live-agent-control.ts +88 -88
  97. package/src/runtime/live-control-realtime.ts +36 -36
  98. package/src/runtime/live-extension-bridge.ts +150 -150
  99. package/src/runtime/live-irc.ts +92 -92
  100. package/src/runtime/live-session-health.ts +100 -100
  101. package/src/runtime/loop-gates.ts +129 -0
  102. package/src/runtime/metric-parser.ts +40 -0
  103. package/src/runtime/notebook-helpers.ts +90 -90
  104. package/src/runtime/orphan-sentinel.ts +7 -7
  105. package/src/runtime/parallel-research.ts +44 -44
  106. package/src/runtime/phase-progress.ts +217 -0
  107. package/src/runtime/pi-args.ts +38 -11
  108. package/src/runtime/pi-json-output.ts +111 -111
  109. package/src/runtime/pi-spawn.ts +57 -7
  110. package/src/runtime/policy-engine.ts +79 -79
  111. package/src/runtime/post-checks.ts +122 -0
  112. package/src/runtime/progress-event-coalescer.ts +43 -43
  113. package/src/runtime/prose-compressor.ts +164 -164
  114. package/src/runtime/recovery-recipes.ts +74 -74
  115. package/src/runtime/result-extractor.ts +121 -121
  116. package/src/runtime/role-permission.ts +39 -39
  117. package/src/runtime/sensitive-paths.ts +2 -2
  118. package/src/runtime/session-resources.ts +25 -25
  119. package/src/runtime/session-snapshot.ts +59 -59
  120. package/src/runtime/session-usage.ts +79 -79
  121. package/src/runtime/sidechain-output.ts +29 -29
  122. package/src/runtime/stream-preview.ts +177 -177
  123. package/src/runtime/supervisor-contact.ts +59 -59
  124. package/src/runtime/task-display.ts +38 -38
  125. package/src/runtime/task-graph.ts +207 -0
  126. package/src/runtime/task-quality.ts +207 -0
  127. package/src/runtime/task-runner/capabilities.ts +78 -78
  128. package/src/runtime/task-runner/live-executor.ts +7 -1
  129. package/src/runtime/task-runner/progress.ts +119 -119
  130. package/src/runtime/task-runner/prompt-pipeline.ts +64 -64
  131. package/src/runtime/task-runner/result-utils.ts +14 -14
  132. package/src/runtime/task-runner/run-projection.ts +103 -103
  133. package/src/runtime/task-runner/state-helpers.ts +22 -22
  134. package/src/runtime/team-runner.ts +117 -7
  135. package/src/runtime/worker-heartbeat.ts +21 -21
  136. package/src/runtime/worker-startup.ts +57 -57
  137. package/src/runtime/workflow-state.ts +187 -0
  138. package/src/runtime/workspace-tree.ts +298 -298
  139. package/src/schema/config-schema.ts +11 -0
  140. package/src/schema/validation-types.ts +148 -0
  141. package/src/skills/skill-templates.ts +374 -0
  142. package/src/state/active-run-registry.ts +35 -11
  143. package/src/state/atomic-write.ts +33 -26
  144. package/src/state/contracts.ts +1 -0
  145. package/src/state/event-reconstructor.ts +217 -0
  146. package/src/state/locks.ts +2 -13
  147. package/src/state/mailbox.ts +4 -3
  148. package/src/state/state-store.ts +32 -14
  149. package/src/state/task-claims.ts +44 -44
  150. package/src/state/types.ts +9 -0
  151. package/src/state/usage.ts +29 -29
  152. package/src/subagents/async-entry.ts +1 -1
  153. package/src/subagents/index.ts +3 -3
  154. package/src/subagents/live/control.ts +1 -1
  155. package/src/subagents/live/manager.ts +1 -1
  156. package/src/subagents/live/realtime.ts +1 -1
  157. package/src/subagents/live/session-runtime.ts +1 -1
  158. package/src/subagents/manager.ts +1 -1
  159. package/src/subagents/spawn.ts +1 -1
  160. package/src/teams/team-serializer.ts +38 -38
  161. package/src/types/diff.d.ts +18 -18
  162. package/src/ui/crew-footer.ts +101 -101
  163. package/src/ui/crew-select-list.ts +111 -111
  164. package/src/ui/crew-widget.ts +5 -2
  165. package/src/ui/dashboard-panes/cancellation-pane.ts +42 -42
  166. package/src/ui/dashboard-panes/capability-pane.ts +59 -59
  167. package/src/ui/dashboard-panes/mailbox-pane.ts +35 -35
  168. package/src/ui/dashboard-panes/metrics-pane.ts +34 -34
  169. package/src/ui/dashboard-panes/progress-pane.ts +11 -0
  170. package/src/ui/dynamic-border.ts +25 -25
  171. package/src/ui/layout-primitives.ts +106 -106
  172. package/src/ui/loaders.ts +158 -158
  173. package/src/ui/render-coalescer.ts +51 -51
  174. package/src/ui/render-diff.ts +119 -119
  175. package/src/ui/render-scheduler.ts +143 -143
  176. package/src/ui/run-action-dispatcher.ts +10 -1
  177. package/src/ui/spinner.ts +17 -17
  178. package/src/ui/status-colors.ts +58 -58
  179. package/src/ui/syntax-highlight.ts +116 -116
  180. package/src/ui/transcript-entries.ts +258 -258
  181. package/src/utils/completion-dedupe.ts +63 -63
  182. package/src/utils/frontmatter.ts +68 -68
  183. package/src/utils/git.ts +262 -262
  184. package/src/utils/ids.ts +17 -17
  185. package/src/utils/incremental-reader.ts +104 -104
  186. package/src/utils/names.ts +27 -27
  187. package/src/utils/redaction.ts +44 -44
  188. package/src/utils/safe-paths.ts +47 -47
  189. package/src/utils/scan-cache.ts +136 -136
  190. package/src/utils/sleep.ts +40 -26
  191. package/src/utils/task-name-generator.ts +337 -337
  192. package/src/workflows/validate-workflow.ts +40 -40
  193. package/src/worktree/branch-freshness.ts +45 -45
  194. package/teams/default.team.md +12 -12
  195. package/teams/fast-fix.team.md +11 -11
  196. package/teams/implementation.team.md +18 -18
  197. package/teams/parallel-research.team.md +14 -14
  198. package/teams/research.team.md +11 -11
  199. package/teams/review.team.md +12 -12
  200. package/workflows/default.workflow.md +30 -29
  201. package/workflows/fast-fix.workflow.md +23 -22
  202. package/workflows/implementation.workflow.md +43 -43
  203. package/workflows/parallel-research.workflow.md +46 -46
  204. package/workflows/research.workflow.md +22 -22
  205. package/workflows/review.workflow.md +30 -30
  206. package/docs/refactor-tasks-phase3.md +0 -394
  207. package/docs/refactor-tasks-phase4.md +0 -564
  208. package/docs/refactor-tasks-phase5.md +0 -402
  209. package/docs/refactor-tasks-phase6.md +0 -662
  210. package/docs/refactor-tasks.md +0 -1484
  211. package/docs/research/AGENT-EXECUTION-ARCHITECTURE.md +0 -261
  212. package/docs/research/AGENT-LIFECYCLE-COMPARISON.md +0 -111
  213. package/docs/research/AUDIT_OH_MY_PI.md +0 -261
  214. package/docs/research/AUDIT_PI_CREW.md +0 -457
  215. package/docs/research/CAVEMAN-DEEP-RESEARCH.md +0 -281
  216. package/docs/research/COMPARISON_OH_MY_PI_VS_PI_CREW.md +0 -264
  217. package/docs/research/DEEP-RESEARCH-PI-POWERBAR.md +0 -343
  218. package/docs/research/DEEP_RESEARCH_SUBAGENT_ARCHITECTURE.md +0 -480
  219. package/docs/research/GAP_CLOSURE_IMPLEMENTATION_PLAN.md +0 -354
  220. package/docs/research/IMPLEMENTATION_PLAN.md +0 -385
  221. package/docs/research/LIVE-SESSION-PRODUCTION-READY-PLAN.md +0 -502
  222. package/docs/research/OH-MY-PI-DEEP-RESEARCH-v14.7.6.md +0 -266
  223. package/docs/research/REMAINING-GAPS-PLAN.md +0 -363
  224. package/docs/research/SESSION-SUMMARY-2026-05-08.md +0 -146
  225. package/docs/research/UI-RESPONSIVENESS-AUDIT.md +0 -173
  226. package/docs/research-awesome-agent-skills-distillation.md +0 -100
  227. package/docs/research-extension-examples.md +0 -297
  228. package/docs/research-extension-system.md +0 -324
  229. package/docs/research-oh-my-pi-distillation.md +0 -369
  230. package/docs/research-optimization-plan.md +0 -548
  231. package/docs/research-phase10-distillation.md +0 -199
  232. package/docs/research-phase11-distillation.md +0 -201
  233. package/docs/research-phase8-operator-experience-plan.md +0 -819
  234. package/docs/research-phase9-observability-reliability-plan.md +0 -1190
  235. package/docs/research-pi-coding-agent.md +0 -357
  236. package/docs/research-source-pi-crew-reference.md +0 -174
  237. package/docs/research-ui-optimization-plan.md +0 -480
  238. package/docs/source-runtime-refactor-map.md +0 -107
  239. package/src/utils/atomic-write.ts +0 -33
@@ -1,297 +0,0 @@
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,324 +0,0 @@
1
- # Research: Pi Extension System Deep Dive
2
-
3
- > Ngày: 2026-04-29 | Read-only research | Source: `source/pi-mono/packages/coding-agent/src/core/extensions/`
4
-
5
- ## 1. Extension System Architecture
6
-
7
- Pi extension system là plugin framework cho coding agent. Extensions được viết bằng TypeScript,
8
- load qua jiti (JIT compiler), và có thể hook vào mọi phase của agent lifecycle.
9
-
10
- ```
11
- ┌─────────────────────────────────────────────────────────────┐
12
- │ ExtensionAPI ("pi.*") │
13
- │ Event sub: pi.on(event, handler) │
14
- │ Tools: pi.registerTool(def) │
15
- │ Commands: pi.registerCommand(name, opts) │
16
- │ Shortcuts: pi.registerShortcut(key, opts) │
17
- │ Flags: pi.registerFlag(name, opts) │
18
- │ Messages: pi.sendMessage() / pi.sendUserMessage() │
19
- │ State: pi.appendEntry(customType, data) │
20
- │ Provider: pi.registerProvider(name, config) │
21
- │ Event bus: pi.events.emit/on() │
22
- │ Model: pi.setModel() / getThinkingLevel() │
23
- │ Tools mgmt: pi.getActiveTools() / setActiveTools() │
24
- ├─────────────────────────────────────────────────────────────┤
25
- │ ExtensionFactory │
26
- │ (pi: ExtensionAPI) => void | Promise<void> │
27
- ├─────────────────────────────────────────────────────────────┤
28
- │ loader.ts ──► jiti → TypeScript module loading │
29
- │ runner.ts ──► ExtensionRunner → lifecycle + event emit │
30
- │ types.ts ───► 1545 dòng type definitions │
31
- └─────────────────────────────────────────────────────────────┘
32
- ```
33
-
34
- ## 2. Extension Loading Flow
35
-
36
- ```
37
- discoverAndLoadExtensions(cwd, agentDir, extensionPaths)
38
- ├── Scan directories:
39
- │ ├── ~/.pi/agent/extensions/**/index.ts (user-global)
40
- │ ├── .pi/extensions/**/index.ts (project-local)
41
- │ └── CLI --extension paths (explicit)
42
- ├── Create ExtensionRuntime (shared state + action stubs)
43
- ├── For each extension file:
44
- │ ├── jiti.import(path) # Load TS module
45
- │ ├── Call default export: factory(pi) # Register handlers/tools/commands
46
- │ └── Collect into Extension object
47
- └── Return LoadExtensionsResult
48
-
49
- ExtensionRunner.initialize(session, context, actions)
50
- ├── Bind real action implementations to runtime
51
- ├── Process queued provider registrations
52
- └── Emit session_start event
53
- ```
54
-
55
- ### 2.1 Discovery priority
56
-
57
- Project-local > user-global. Extensions cùng tên: project override user.
58
-
59
- ### 2.2 Runtime replacement (reload)
60
-
61
- Khi `/reload` hoặc session switch:
62
- 1. `emitSessionShutdownEvent("reload")`
63
- 2. Invalidate old ExtensionRuntime (throws if stale extension tries to act)
64
- 3. Re-discover + re-load tất cả extensions
65
- 4. Re-initialize ExtensionRunner
66
-
67
- ## 3. Full Event Lifecycle
68
-
69
- ### 3.1 Event model (23 event types)
70
-
71
- **Session events** — session-level lifecycle:
72
- ```
73
- session_start ← Khi session được tạo/load/reload
74
- resources_discover ← Extension có thể inject thêm paths
75
- session_before_switch ← Trước khi switch session (có thể cancel)
76
- session_before_fork ← Trước khi fork session (có thể cancel)
77
- session_before_compact ← Trước khi compaction (có thể cancel hoặc custom)
78
- session_compact ← Sau khi compaction hoàn tất
79
- session_before_tree ← Trước khi navigate tree (có thể cancel)
80
- session_tree ← Sau khi navigate tree
81
- session_shutdown ← Khi session bị hủy (quit/reload/new/resume/fork)
82
- ```
83
-
84
- **Agent events** — per-prompt:
85
- ```
86
- input ← Khi user input received (có thể transform/block)
87
- before_agent_start ← Trước khi agent loop chạy (inject custom message / swap system prompt)
88
- context ← Transform messages trước khi gửi LLM
89
- before_provider_request ← Thay đổi payload trước khi gửi provider
90
- after_provider_response ← Quan sát response status/headers
91
- agent_start ← Agent loop bắt đầu
92
- agent_end ← Agent loop kết thúc
93
- ```
94
-
95
- **Turn events** — per-turn:
96
- ```
97
- turn_start ← Bắt đầu turn mới
98
- turn_end ← Kết thúc turn (có message + tool results)
99
- ```
100
-
101
- **Message events** — per-message:
102
- ```
103
- message_start ← Message bắt đầu (user/assistant/toolResult)
104
- message_update ← Streaming token-by-token update
105
- message_end ← Message hoàn tất
106
- ```
107
-
108
- **Tool events** — per-tool:
109
- ```
110
- tool_call ← Trước khi tool execute (có thể block/mutate args)
111
- tool_execution_start ← Tool bắt đầu chạy
112
- tool_execution_update ← Partial/streaming result
113
- tool_execution_end ← Tool hoàn tất
114
- tool_result ← Sau khi tool execute (có thể modify result)
115
- ```
116
-
117
- **Other:**
118
- ```
119
- model_select ← Khi model được chọn/thay đổi
120
- user_bash ← Khi user dùng ! prefix cho bash
121
- ```
122
-
123
- ### 3.2 Event result contracts
124
-
125
- Mỗi event có thể return result để ảnh hưởng đến behavior:
126
-
127
- | Event | Result type | Effect |
128
- |---|---|---|
129
- | `input` | `{ action: "continue" \| "transform" \| "handled" }` | Transform/block input |
130
- | `before_agent_start` | `{ message?, systemPrompt? }` | Inject custom message, swap system prompt |
131
- | `context` | `{ messages? }` | Replace context messages |
132
- | `before_provider_request` | `any` | Replace payload |
133
- | `tool_call` | `{ block?, reason? }` | Block tool execution |
134
- | `tool_result` | `{ content?, details?, isError? }` | Modify result |
135
- | `user_bash` | `{ operations?, result? }` | Custom bash execution |
136
- | `session_before_*` | `{ cancel? }` | Cancel session operation |
137
- | `session_before_compact` | `{ cancel?, compaction? }` | Cancel or custom compact |
138
- | `session_before_tree` | `{ cancel?, summary?, customInstructions? }` | Cancel or custom summary |
139
- | `resources_discover` | `{ skillPaths?, promptPaths?, themePaths? }` | Inject resource paths |
140
-
141
- ## 4. Context Objects Available to Extensions
142
-
143
- ### 4.1 ExtensionContext (`ctx.*`) — có sẵn trong mọi event handler
144
-
145
- ```typescript
146
- interface ExtensionContext {
147
- ui: ExtensionUIContext; // UI methods (select, confirm, notify, widgets...)
148
- hasUI: boolean; // false in print/RPC mode
149
- cwd: string; // Current working directory
150
- sessionManager: ReadonlySessionManager; // Session access (read-only)
151
- modelRegistry: ModelRegistry; // Auth + model discovery
152
- model: Model<any> | undefined; // Current model
153
- isIdle(): boolean; // Check if agent is streaming
154
- signal: AbortSignal | undefined;// Current abort signal
155
- abort(): void; // Abort current operation
156
- hasPendingMessages(): boolean; // Check message queue
157
- shutdown(): void; // Graceful shutdown
158
- getContextUsage(): ContextUsage | undefined; // Token usage
159
- compact(options?): void; // Trigger compaction
160
- getSystemPrompt(): string; // Current system prompt
161
- }
162
- ```
163
-
164
- ### 4.2 ExtensionCommandContext — extends Context, chỉ trong command handler
165
-
166
- ```typescript
167
- interface ExtensionCommandContext extends ExtensionContext {
168
- waitForIdle(): Promise<void>; // Wait for agent to finish
169
- newSession(options?): Promise<{cancelled}>;
170
- fork(entryId, options?): Promise<{cancelled}>;
171
- navigateTree(targetId, options?): Promise<{cancelled}>;
172
- switchSession(sessionPath, options?): Promise<{cancelled}>;
173
- reload(): Promise<void>;
174
- }
175
- ```
176
-
177
- ### 4.3 ReplacedSessionContext — sau khi switch/new session
178
-
179
- ```typescript
180
- interface ReplacedSessionContext extends ExtensionCommandContext {
181
- sendMessage(message, options?): Promise<void>;
182
- sendUserMessage(content, options?): Promise<void>;
183
- }
184
- ```
185
-
186
- ### 4.4 ExtensionUIContext (`ctx.ui.*`) — chỉ khi `hasUI=true`
187
-
188
- ```typescript
189
- interface ExtensionUIContext {
190
- select(title, options, opts?): Promise<string | undefined>;
191
- confirm(title, message, opts?): Promise<boolean>;
192
- input(title, placeholder?, opts?): Promise<string | undefined>;
193
- notify(message, type?): void;
194
- custom<T>(factory, options?): Promise<T>; // Custom overlay component
195
- setWidget(key, content, options?): void; // Widget above/below editor
196
- setFooter(factory): void; // Custom footer
197
- setHeader(factory): void; // Custom header
198
- setEditorComponent(factory): void; // Custom editor
199
- setStatus(key, text): void; // Status bar
200
- setTitle(title): void; // Terminal title
201
- setWorkingMessage(message?): void; // Working loader text
202
- setWorkingVisible(visible): void; // Show/hide loader
203
- setWorkingIndicator(options?): void; // Custom loader animation
204
- setHiddenThinkingLabel(label?): void; // Thinking block label
205
- onTerminalInput(handler): () => void; // Raw terminal input
206
- getToolsExpanded(): boolean;
207
- setToolsExpanded(expanded): void;
208
- theme: Theme;
209
- getAllThemes(): {name, path}[];
210
- getTheme(name): Theme | undefined;
211
- setTheme(theme): {success, error?};
212
- }
213
- ```
214
-
215
- ## 5. ToolDefinition Contract
216
-
217
- ```typescript
218
- interface ToolDefinition<TParams extends TSchema, TDetails = unknown, TState = any> {
219
- name: string; // Unique tool name
220
- label: string; // Human-readable for UI
221
- description: string; // For LLM
222
- parameters: TParams; // TypeBox schema
223
- promptSnippet?: string; // 1-line for system prompt "Available tools"
224
- promptGuidelines?: string[]; // Bullets for system prompt "Guidelines"
225
- renderShell?: "default" | "self"; // Who renders the outer frame
226
- executionMode?: "sequential" | "parallel"; // Concurrency control
227
- prepareArguments?: (args: unknown) => Static<TParams>;
228
-
229
- // Core execution
230
- execute(
231
- toolCallId: string,
232
- params: Static<TParams>,
233
- signal: AbortSignal | undefined,
234
- onUpdate: AgentToolUpdateCallback<TDetails> | undefined,
235
- ctx: ExtensionContext,
236
- ): Promise<AgentToolResult<TDetails>>;
237
-
238
- // Rendering (optional)
239
- renderCall?(args, theme, context): Component; // Custom call display
240
- renderResult?(result, options, theme, context): Component; // Custom result display
241
- }
242
- ```
243
-
244
- ### 5.1 `terminate: true` pattern
245
-
246
- Tool có thể set `terminate: true` trong result để kết thúc turn ngay sau tool call,
247
- tiết kiệm 1 follow-up LLM turn:
248
-
249
- ```typescript
250
- return {
251
- content: [{ type: "text", text: "Done" }],
252
- details: { ... },
253
- terminate: true, // ← Kết thúc turn, không cần LLM follow-up
254
- };
255
- ```
256
-
257
- ## 6. Provider Registration
258
-
259
- Extension có thể đăng ký provider tùy chỉnh:
260
-
261
- ```typescript
262
- pi.registerProvider("my-provider", {
263
- baseUrl: "https://api.example.com",
264
- apiKey: "PROVIDER_API_KEY",
265
- api: "anthropic-messages",
266
- models: [{
267
- id: "my-model",
268
- name: "My Model",
269
- reasoning: false,
270
- input: ["text", "image"],
271
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
272
- contextWindow: 200000,
273
- maxTokens: 16384,
274
- }],
275
- // Optional OAuth:
276
- oauth: {
277
- name: "My Provider (SSO)",
278
- async login(callbacks) { ... },
279
- async refreshToken(credentials) { ... },
280
- getApiKey(credentials) { return credentials.access; },
281
- },
282
- });
283
- ```
284
-
285
- Hiệu lực ngay lập tức sau `session_start` (không cần `/reload`).
286
-
287
- ## 7. API Comparison: ExtensionAPI vs ExtensionContext
288
-
289
- | Capability | `pi.*` (ExtensionAPI) | `ctx.*` (ExtensionContext) |
290
- |---|---|---|
291
- | Subscribe events | ✅ `pi.on(...)` | ❌ |
292
- | Register tools | ✅ `pi.registerTool()` | ❌ |
293
- | Register commands | ✅ `pi.registerCommand()` | ❌ |
294
- | Register shortcuts | ✅ `pi.registerShortcut()` | ❌ |
295
- | Register flags | ✅ `pi.registerFlag()` | ❌ |
296
- | Register providers | ✅ `pi.registerProvider()` | ❌ |
297
- | Send messages | ✅ `pi.sendMessage()` | ❌ |
298
- | Send user messages | ✅ `pi.sendUserMessage()` | ❌ |
299
- | Append entries | ✅ `pi.appendEntry()` | ❌ |
300
- | Session name | ✅ `pi.setSessionName()` / `getSessionName()` | ❌ |
301
- | Event bus | ✅ `pi.events` | ❌ |
302
- | Get/set active tools | ✅ `pi.getActiveTools()` / `setActiveTools()` | ❌ |
303
- | Get model | ❌ (register-time only) | ✅ `ctx.model` |
304
- | Check idle | ❌ | ✅ `ctx.isIdle()` |
305
- | Abort | ❌ | ✅ `ctx.abort()` |
306
- | Trigger compaction | ❌ | ✅ `ctx.compact()` |
307
- | Context usage | ❌ | ✅ `ctx.getContextUsage()` |
308
- | System prompt | ❌ | ✅ `ctx.getSystemPrompt()` |
309
- | Session manager | ❌ | ✅ `ctx.sessionManager` |
310
- | UI interaction | ❌ | ✅ `ctx.ui` |
311
- | Session control | ❌ | ✅ `ctx.newSession()` / `fork()` (command ctx) |
312
-
313
- **Rule of thumb:**
314
- - `pi.*`: Registration-time API (trong factory function, `session_start`)
315
- - `ctx.*`: Runtime API (trong event handlers, command handlers)
316
-
317
- ## 8. Key Design Decisions
318
-
319
- 1. **No sandbox** — Extensions run in same Node.js process, full system access
320
- 2. **jiti loader** — TypeScript extensions compiled JIT, no build step
321
- 3. **Virtual modules** — For Bun compiled binary, built-in dependencies bundled
322
- 4. **Throwing stubs** — Runtime actions start as stubs, real implementations bound by runner
323
- 5. **Stale detection** — After reload, old extension instances throw on any API call
324
- 6. **Event bus** — Separate from extension events, for cross-extension communication