pi-crew 0.9.55 → 0.9.57

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 (309) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +58 -0
  3. package/README.md +53 -5
  4. package/dist/index.mjs +5666 -4370
  5. package/docs/README.md +54 -0
  6. package/package.json +12 -13
  7. package/skills/real-test-pi-crew/SKILL.md +93 -3
  8. package/src/agents/discover-agents.ts +68 -10
  9. package/src/benchmark/feedback-loop.ts +1 -1
  10. package/src/config/config.ts +2 -1
  11. package/src/config/types.ts +12 -0
  12. package/src/extension/action-suggestions.ts +16 -63
  13. package/src/extension/async-notifier.ts +3 -3
  14. package/src/extension/command-completions.ts +2 -2
  15. package/src/extension/crew-cleanup.ts +3 -3
  16. package/src/extension/crew-vibes/footer.ts +4 -2
  17. package/src/extension/cross-extension-rpc.ts +10 -5
  18. package/src/extension/knowledge-injection.ts +57 -10
  19. package/src/extension/register.ts +2 -2
  20. package/src/extension/registration/artifact-cleanup.ts +41 -3
  21. package/src/extension/registration/commands.ts +4 -4
  22. package/src/extension/registration/context-builder.ts +10 -10
  23. package/src/extension/registration/crash-recovery-cache.ts +3 -3
  24. package/src/extension/registration/foreground-run-controller.ts +1 -1
  25. package/src/extension/registration/lazy-configurers.ts +2 -2
  26. package/src/extension/registration/lifecycle-handlers.ts +12 -12
  27. package/src/extension/registration/lifecycle.ts +2 -2
  28. package/src/extension/registration/observability.ts +2 -2
  29. package/src/extension/registration/registration-types.ts +3 -3
  30. package/src/extension/registration/runtime-cleanup.ts +1 -1
  31. package/src/extension/registration/subagent-helpers.ts +2 -2
  32. package/src/extension/registration/subagent-manager-setup.ts +2 -2
  33. package/src/extension/registration/subagent-tools.ts +21 -16
  34. package/src/extension/registration/team-tool.ts +109 -17
  35. package/src/extension/registration/viewers.ts +3 -4
  36. package/src/extension/registration/wire-cross-extension.ts +7 -7
  37. package/src/extension/rpc-hmac.ts +3 -2
  38. package/src/extension/run-bundle-schema.ts +13 -4
  39. package/src/extension/run-export.ts +2 -2
  40. package/src/extension/run-index.ts +2 -3
  41. package/src/extension/run-maintenance.ts +57 -1
  42. package/src/extension/team-manager-command.ts +3 -1
  43. package/src/extension/team-tool/anchor.ts +8 -2
  44. package/src/extension/team-tool/api.ts +117 -39
  45. package/src/extension/team-tool/cancel.ts +23 -8
  46. package/src/extension/team-tool/chain-executor.ts +1 -1
  47. package/src/extension/team-tool/dispatch/automate.ts +17 -2
  48. package/src/extension/team-tool/dispatch/control.ts +17 -2
  49. package/src/extension/team-tool/dispatch/manage.ts +34 -2
  50. package/src/extension/team-tool/dispatch/run.ts +17 -2
  51. package/src/extension/team-tool/dispatch/status.ts +37 -5
  52. package/src/extension/team-tool/doctor.ts +2 -2
  53. package/src/extension/team-tool/explain.ts +1 -1
  54. package/src/extension/team-tool/goal-wrap.ts +5 -5
  55. package/src/extension/team-tool/goal.ts +30 -9
  56. package/src/extension/team-tool/handle-schedule.ts +37 -19
  57. package/src/extension/team-tool/inspect.ts +21 -5
  58. package/src/extension/team-tool/lifecycle-actions.ts +53 -10
  59. package/src/extension/team-tool/parallel-dispatch.ts +14 -5
  60. package/src/extension/team-tool/param-error.ts +138 -0
  61. package/src/extension/team-tool/respond.ts +20 -6
  62. package/src/extension/team-tool/run.ts +27 -17
  63. package/src/extension/team-tool/status.ts +17 -6
  64. package/src/extension/team-tool.ts +26 -19
  65. package/src/hooks/registry.ts +1 -1
  66. package/src/i18n.ts +22 -0
  67. package/src/observability/event-bus.ts +1 -1
  68. package/src/prompt/prompt-runtime.ts +2 -2
  69. package/src/runtime/README.md +35 -0
  70. package/src/runtime/agent-control.ts +1 -1
  71. package/src/runtime/anchor-manager.ts +0 -2
  72. package/src/runtime/async-runner.ts +1 -1
  73. package/src/runtime/attention-events.ts +3 -2
  74. package/src/runtime/auto-summarize.ts +0 -2
  75. package/src/runtime/background-runner.ts +103 -30
  76. package/src/runtime/{crew-broker-child.ts → broker/crew-broker-child.ts} +2 -2
  77. package/src/runtime/{crew-broker-client.ts → broker/crew-broker-client.ts} +4 -7
  78. package/src/runtime/{crew-broker.ts → broker/crew-broker.ts} +13 -21
  79. package/src/runtime/chain-runner.ts +50 -5
  80. package/src/runtime/{child-pi-constants.ts → child-pi/child-pi-constants.ts} +1 -1
  81. package/src/runtime/{child-pi-kill.ts → child-pi/child-pi-kill.ts} +3 -3
  82. package/src/runtime/{child-pi-spawn.ts → child-pi/child-pi-spawn.ts} +28 -12
  83. package/src/runtime/{child-pi-steering.ts → child-pi/child-pi-steering.ts} +1 -1
  84. package/src/runtime/{child-pi-streams.ts → child-pi/child-pi-streams.ts} +23 -4
  85. package/src/runtime/{child-pi-transcript.ts → child-pi/child-pi-transcript.ts} +6 -6
  86. package/src/runtime/{child-pi.ts → child-pi/child-pi.ts} +47 -78
  87. package/src/runtime/compaction/compact-stages/bounded-tail.ts +84 -0
  88. package/src/runtime/{compact-stages → compaction/compact-stages}/index.ts +2 -2
  89. package/src/runtime/{compaction-summary.ts → compaction/compaction-summary.ts} +3 -3
  90. package/src/runtime/{tool-output-pruner.ts → compaction/tool-output-pruner.ts} +1 -1
  91. package/src/runtime/crew-agent-records.ts +48 -2
  92. package/src/runtime/custom-tools/irc-tool.ts +2 -2
  93. package/src/runtime/delivery-coordinator.ts +0 -3
  94. package/src/runtime/diagnostic-export.ts +5 -4
  95. package/src/runtime/foreground-control.ts +1 -1
  96. package/src/runtime/foreground-watchdog.ts +1 -1
  97. package/src/runtime/{adaptive-plan.ts → goal-workflow/adaptive-plan.ts} +8 -8
  98. package/src/runtime/{dynamic-workflow-context.ts → goal-workflow/dynamic-workflow-context.ts} +16 -16
  99. package/src/runtime/{dynamic-workflow-runner.ts → goal-workflow/dynamic-workflow-runner.ts} +10 -10
  100. package/src/runtime/{goal-achievement.ts → goal-workflow/goal-achievement.ts} +3 -3
  101. package/src/runtime/{goal-evaluator.ts → goal-workflow/goal-evaluator.ts} +8 -8
  102. package/src/runtime/{goal-loop-runner.ts → goal-workflow/goal-loop-runner.ts} +27 -25
  103. package/src/runtime/{goal-state-store.ts → goal-workflow/goal-state-store.ts} +8 -8
  104. package/src/runtime/{plan-templates.ts → goal-workflow/plan-templates.ts} +1 -1
  105. package/src/runtime/group-join.ts +3 -3
  106. package/src/runtime/handoff-manager.ts +0 -2
  107. package/src/runtime/{heartbeat-watcher.ts → heartbeat/heartbeat-watcher.ts} +7 -7
  108. package/src/runtime/iteration-hooks.ts +1 -1
  109. package/src/runtime/{live-agent-control.ts → live-session/live-agent-control.ts} +2 -2
  110. package/src/runtime/{live-agent-manager.ts → live-session/live-agent-manager.ts} +4 -4
  111. package/src/runtime/{live-session-runtime.ts → live-session/live-session-runtime.ts} +39 -41
  112. package/src/runtime/manifest-cache.ts +6 -2
  113. package/src/runtime/{model-fallback.ts → model/model-fallback.ts} +1 -1
  114. package/src/runtime/{pi-args.ts → model/pi-args.ts} +20 -5
  115. package/src/runtime/model/provider-extensions.ts +116 -0
  116. package/src/runtime/{runtime-policy.ts → model/runtime-policy.ts} +2 -2
  117. package/src/runtime/{runtime-resolver.ts → model/runtime-resolver.ts} +3 -3
  118. package/src/runtime/{runtime-warmup.ts → model/runtime-warmup.ts} +8 -8
  119. package/src/runtime/orphan-worker-registry.ts +1 -1
  120. package/src/runtime/{progress-tracker.ts → output/progress-tracker.ts} +1 -1
  121. package/src/runtime/{result-extractor.ts → output/result-extractor.ts} +4 -4
  122. package/src/runtime/{sidechain-output.ts → output/sidechain-output.ts} +2 -2
  123. package/src/runtime/{stream-preview.ts → output/stream-preview.ts} +1 -1
  124. package/src/runtime/{streaming-output.ts → output/streaming-output.ts} +2 -2
  125. package/src/runtime/{tool-progress.ts → output/tool-progress.ts} +1 -1
  126. package/src/runtime/parent-guard.ts +30 -10
  127. package/src/runtime/pipeline-runner.ts +2 -2
  128. package/src/runtime/policy-engine.ts +2 -2
  129. package/src/runtime/{cancellation.ts → process/cancellation.ts} +1 -1
  130. package/src/runtime/{post-exit-stdio-guard.ts → process/post-exit-stdio-guard.ts} +1 -1
  131. package/src/runtime/{process-lifecycle.ts → process/process-lifecycle.ts} +3 -3
  132. package/src/runtime/{checkpoint.ts → recovery/checkpoint.ts} +4 -4
  133. package/src/runtime/{crash-recovery.ts → recovery/crash-recovery.ts} +93 -21
  134. package/src/runtime/{overflow-recovery.ts → recovery/overflow-recovery.ts} +1 -1
  135. package/src/runtime/{recovery-recipes.ts → recovery/recovery-recipes.ts} +1 -1
  136. package/src/runtime/{retry-executor.ts → recovery/retry-executor.ts} +2 -2
  137. package/src/runtime/{retry-runner.ts → recovery/retry-runner.ts} +2 -8
  138. package/src/runtime/run-tracker.ts +1 -1
  139. package/src/runtime/run-worker.ts +3 -3
  140. package/src/runtime/{coalesce-tasks.ts → scheduling/coalesce-tasks.ts} +3 -3
  141. package/src/runtime/{concurrency.ts → scheduling/concurrency.ts} +9 -3
  142. package/src/runtime/{parallel-research.ts → scheduling/parallel-research.ts} +4 -2
  143. package/src/runtime/{run-coalesced-task-group.ts → scheduling/run-coalesced-task-group.ts} +95 -36
  144. package/src/runtime/{semaphore.ts → scheduling/semaphore.ts} +4 -1
  145. package/src/runtime/{task-graph-scheduler.ts → scheduling/task-graph-scheduler.ts} +1 -1
  146. package/src/runtime/session-resources.ts +1 -1
  147. package/src/runtime/settings-store.ts +1 -1
  148. package/src/runtime/single-agent-compose.ts +1 -0
  149. package/src/runtime/stale-reconciler.ts +1 -1
  150. package/src/runtime/subagent-manager.ts +1 -1
  151. package/src/runtime/supervisor-contact.ts +28 -13
  152. package/src/runtime/task-output-context.ts +7 -5
  153. package/src/runtime/task-runner/child-executor.ts +67 -31
  154. package/src/runtime/task-runner/live-executor.ts +8 -8
  155. package/src/runtime/task-runner/post-execution.ts +12 -12
  156. package/src/runtime/task-runner/pre-execution.ts +6 -6
  157. package/src/runtime/task-runner/progress.ts +1 -1
  158. package/src/runtime/task-runner/run-projection.ts +1 -1
  159. package/src/runtime/task-runner/scaffold-executor.ts +1 -1
  160. package/src/runtime/task-runner/state-helpers.ts +2 -2
  161. package/src/runtime/task-runner.ts +4 -4
  162. package/src/runtime/team-runner.ts +441 -175
  163. package/src/runtime/{completion-guard.ts → verification/completion-guard.ts} +1 -1
  164. package/src/runtime/{green-contract.ts → verification/green-contract.ts} +1 -1
  165. package/src/runtime/{post-checks.ts → verification/post-checks.ts} +4 -4
  166. package/src/runtime/{verification-gates.ts → verification/verification-gates.ts} +5 -5
  167. package/src/runtime/{verification-integrity.ts → verification/verification-integrity.ts} +1 -1
  168. package/src/schema/config-schema.ts +1 -0
  169. package/src/schema/team-tool-schema.ts +149 -185
  170. package/src/state/README.md +44 -0
  171. package/src/state/atomic-write.ts +24 -3
  172. package/src/state/{locks.ts → coordination/locks.ts} +118 -38
  173. package/src/state/{mailbox.ts → coordination/mailbox.ts} +14 -8
  174. package/src/state/{schedule.ts → coordination/schedule.ts} +3 -3
  175. package/src/state/{task-claims.ts → coordination/task-claims.ts} +1 -1
  176. package/src/state/decision-ledger.ts +1 -1
  177. package/src/state/{event-log-rotation.ts → event-log/event-log-rotation.ts} +189 -31
  178. package/src/state/{event-log.ts → event-log/event-log.ts} +77 -39
  179. package/src/state/{jsonl-writer.ts → event-log/jsonl-writer.ts} +14 -6
  180. package/src/state/hook-instinct-bridge.ts +2 -2
  181. package/src/state/{active-run-registry.ts → stores/active-run-registry.ts} +7 -7
  182. package/src/state/{artifact-store.ts → stores/artifact-store.ts} +62 -4
  183. package/src/state/{blob-store.ts → stores/blob-store.ts} +3 -3
  184. package/src/state/{health-store.ts → stores/health-store.ts} +3 -3
  185. package/src/state/{instinct-store.ts → stores/instinct-store.ts} +3 -3
  186. package/src/state/{observation-store.ts → stores/observation-store.ts} +2 -2
  187. package/src/state/{run-cache.ts → stores/run-cache.ts} +4 -4
  188. package/src/state/{run-graph.ts → stores/run-graph.ts} +4 -4
  189. package/src/state/{run-metrics.ts → stores/run-metrics.ts} +3 -3
  190. package/src/state/{state-store.ts → stores/state-store.ts} +254 -21
  191. package/src/state/types.ts +27 -3
  192. package/src/ui/component.ts +55 -0
  193. package/src/ui/crew-select-list.ts +3 -1
  194. package/src/ui/dashboard-panes/agents-pane.ts +1 -1
  195. package/src/ui/dwf-phase-display.ts +1 -1
  196. package/src/ui/heartbeat-aggregator.ts +1 -1
  197. package/src/ui/keybinding-map.ts +179 -6
  198. package/src/ui/layout-primitives.ts +9 -5
  199. package/src/ui/live-conversation-overlay.ts +1 -1
  200. package/src/ui/live-run-sidebar.ts +1 -1
  201. package/src/ui/overlay-stack.ts +148 -0
  202. package/src/ui/overlays/agent-picker-overlay.ts +1 -1
  203. package/src/ui/overlays/mailbox-compose-overlay.ts +1 -1
  204. package/src/ui/overlays/mailbox-detail-overlay.ts +2 -2
  205. package/src/ui/powerbar-publisher.ts +1 -1
  206. package/src/ui/render-scheduler.ts +1 -1
  207. package/src/ui/run-action-dispatcher.ts +3 -3
  208. package/src/ui/run-dashboard.ts +5 -33
  209. package/src/ui/run-event-bus.ts +3 -3
  210. package/src/ui/run-snapshot-cache.ts +37 -18
  211. package/src/ui/settings-overlay.ts +13 -21
  212. package/src/ui/snapshot-types.ts +1 -1
  213. package/src/ui/status-colors.ts +0 -2
  214. package/src/ui/terminal-status.ts +1 -1
  215. package/src/ui/theme-adapter.ts +33 -13
  216. package/src/ui/tool-renderers/index.ts +8 -0
  217. package/src/ui/transcript-viewer.ts +37 -13
  218. package/src/ui/widget/index.ts +32 -9
  219. package/src/ui/widget/widget-formatters.ts +62 -4
  220. package/src/ui/widget/widget-model.ts +2 -2
  221. package/src/ui/widget/widget-renderer.ts +1 -1
  222. package/src/utils/conflict-detect.ts +58 -5
  223. package/src/utils/ndjson.ts +2 -2
  224. package/src/utils/redaction.ts +39 -0
  225. package/src/utils/socket-path.ts +1 -1
  226. package/src/workflows/workflow-config.ts +1 -1
  227. package/src/worktree/cleanup.ts +1 -1
  228. package/src/worktree/worktree-manager.ts +111 -47
  229. package/workflows/chain.workflow.md +2 -2
  230. package/dist/build-meta.json +0 -16807
  231. package/index.bundle.ts +0 -25
  232. package/scripts/bench-check.mjs +0 -96
  233. package/scripts/bench-cold-start.mjs +0 -216
  234. package/scripts/build-bundle.mjs +0 -92
  235. package/scripts/check-all-skills.ts +0 -294
  236. package/scripts/check-bundle-size.mjs +0 -38
  237. package/scripts/check-bundle-staleness.mjs +0 -97
  238. package/scripts/check-conflict-markers.mjs +0 -91
  239. package/scripts/check-lazy-imports.mjs +0 -28
  240. package/scripts/dev-runner.mjs +0 -106
  241. package/scripts/profile-startup.mjs +0 -125
  242. package/scripts/release-smoke.mjs +0 -74
  243. package/scripts/run-bench.mjs +0 -47
  244. package/scripts/run-real-chain.ts +0 -41
  245. package/scripts/test-issue-29-crash.ts +0 -111
  246. package/scripts/test-issue-29-e2e.ts +0 -183
  247. package/scripts/test-issue-29-real-runtime.ts +0 -330
  248. package/scripts/test-issue-29-real-tasks.ts +0 -387
  249. package/scripts/test-issue-29-team-tool.ts +0 -105
  250. package/scripts/test-runner.mjs +0 -84
  251. package/scripts/verify-flicker-fix.ts +0 -109
  252. package/scripts/verify-skill.ts +0 -550
  253. package/scripts/watch-bundle.mjs +0 -259
  254. package/scripts/watchdog-harness.ts +0 -119
  255. package/src/adapters/claude-adapter.ts +0 -23
  256. package/src/adapters/codex-adapter.ts +0 -21
  257. package/src/adapters/cursor-adapter.ts +0 -17
  258. package/src/adapters/export-util.ts +0 -143
  259. package/src/adapters/index.ts +0 -15
  260. package/src/adapters/registry.ts +0 -18
  261. package/src/adapters/types.ts +0 -23
  262. package/src/runtime/code-summary.ts +0 -292
  263. package/src/runtime/cross-extension-rpc.ts +0 -143
  264. package/src/runtime/hidden-handoff.ts +0 -407
  265. package/src/runtime/prose-compressor.ts +0 -162
  266. package/src/subagents/async-entry.ts +0 -1
  267. package/src/subagents/index.ts +0 -3
  268. package/src/subagents/live/control.ts +0 -1
  269. package/src/subagents/live/manager.ts +0 -1
  270. package/src/subagents/live/realtime.ts +0 -1
  271. package/src/subagents/live/session-runtime.ts +0 -1
  272. package/src/subagents/manager.ts +0 -1
  273. package/src/subagents/spawn.ts +0 -1
  274. package/test-integration-check.ts +0 -118
  275. /package/src/runtime/{broker-issuer.ts → broker/broker-issuer.ts} +0 -0
  276. /package/src/runtime/{crew-broker-tokens.ts → broker/crew-broker-tokens.ts} +0 -0
  277. /package/src/runtime/{child-pi-pool.ts → child-pi/child-pi-pool.ts} +0 -0
  278. /package/src/runtime/{compact-pipeline.ts → compaction/compact-pipeline.ts} +0 -0
  279. /package/src/runtime/{compact-stages → compaction/compact-stages}/ansi-strip-stage.ts +0 -0
  280. /package/src/runtime/{compact-stages → compaction/compact-stages}/blank-collapse-stage.ts +0 -0
  281. /package/src/runtime/{compact-stages → compaction/compact-stages}/deduplicate-stage.ts +0 -0
  282. /package/src/runtime/{compact-stages → compaction/compact-stages}/head-snap-stage.ts +0 -0
  283. /package/src/runtime/{compact-stages → compaction/compact-stages}/tail-capture-stage.ts +0 -0
  284. /package/src/runtime/{compact-stages → compaction/compact-stages}/truncation-stage.ts +0 -0
  285. /package/src/runtime/{important-line-classifier.ts → compaction/important-line-classifier.ts} +0 -0
  286. /package/src/runtime/{heartbeat-gradient.ts → heartbeat/heartbeat-gradient.ts} +0 -0
  287. /package/src/runtime/{worker-heartbeat.ts → heartbeat/worker-heartbeat.ts} +0 -0
  288. /package/src/runtime/{worker-startup.ts → heartbeat/worker-startup.ts} +0 -0
  289. /package/src/runtime/{intercom-bridge.ts → live-session/intercom-bridge.ts} +0 -0
  290. /package/src/runtime/{live-control-realtime.ts → live-session/live-control-realtime.ts} +0 -0
  291. /package/src/runtime/{live-extension-bridge.ts → live-session/live-extension-bridge.ts} +0 -0
  292. /package/src/runtime/{live-irc.ts → live-session/live-irc.ts} +0 -0
  293. /package/src/runtime/{live-session-health.ts → live-session/live-session-health.ts} +0 -0
  294. /package/src/runtime/{model-resolver.ts → model/model-resolver.ts} +0 -0
  295. /package/src/runtime/{model-scope.ts → model/model-scope.ts} +0 -0
  296. /package/src/runtime/{output-validator.ts → output/output-validator.ts} +0 -0
  297. /package/src/runtime/{pi-json-output.ts → output/pi-json-output.ts} +0 -0
  298. /package/src/runtime/{progress-event-coalescer.ts → output/progress-event-coalescer.ts} +0 -0
  299. /package/src/runtime/{cancellation-token.ts → process/cancellation-token.ts} +0 -0
  300. /package/src/runtime/{zombie-scanner.ts → process/zombie-scanner.ts} +0 -0
  301. /package/src/runtime/{crash-classification.ts → recovery/crash-classification.ts} +0 -0
  302. /package/src/runtime/{batch-barrier.ts → scheduling/batch-barrier.ts} +0 -0
  303. /package/src/runtime/{global-worker-cap.ts → scheduling/global-worker-cap.ts} +0 -0
  304. /package/src/runtime/{parallel-utils.ts → scheduling/parallel-utils.ts} +0 -0
  305. /package/src/runtime/{scheduler.ts → scheduling/scheduler.ts} +0 -0
  306. /package/src/runtime/{task-graph.ts → scheduling/task-graph.ts} +0 -0
  307. /package/src/runtime/{verification-worktree.ts → verification/verification-worktree.ts} +0 -0
  308. /package/src/state/{event-reconstructor.ts → event-log/event-reconstructor.ts} +0 -0
  309. /package/src/state/{worker-atomic-writer.ts → event-log/worker-atomic-writer.ts} +0 -0
@@ -1,292 +0,0 @@
1
- /**
2
- * Structural code summary — regex-based summarizer that elides function bodies,
3
- * long arrays, block comments, and import groups, keeping signatures.
4
- * Pure TypeScript fallback (no tree-sitter / Rust native dependency).
5
- */
6
-
7
- // ── Public types ──
8
-
9
- export interface SummarySegment {
10
- kind: "kept" | "elided";
11
- startLine: number;
12
- endLine: number;
13
- /** Verbatim text for kept segments; absent for elided */
14
- text?: string;
15
- }
16
-
17
- export interface SummaryResult {
18
- language: string | null;
19
- totalLines: number;
20
- elided: boolean;
21
- segments: SummarySegment[];
22
- rendered: string;
23
- }
24
-
25
- export interface SummaryOptions {
26
- minBodyLines?: number; // default 4
27
- minCommentLines?: number; // default 6
28
- }
29
-
30
- // ── Language detection ──
31
-
32
- const EXT_MAP: ReadonlyMap<string, string> = new Map([
33
- [".ts", "typescript"],
34
- [".tsx", "typescript"],
35
- [".js", "javascript"],
36
- [".jsx", "javascript"],
37
- [".mjs", "javascript"],
38
- [".cjs", "javascript"],
39
- [".py", "python"],
40
- [".rs", "rust"],
41
- ]);
42
-
43
- export function detectLanguage(filePath: string): string | null {
44
- const dot = filePath.lastIndexOf(".");
45
- if (dot === -1) return null;
46
- return EXT_MAP.get(filePath.slice(dot).toLowerCase()) ?? null;
47
- }
48
-
49
- // ── Internal range helpers ──
50
-
51
- interface Range {
52
- start: number;
53
- end: number;
54
- }
55
-
56
- function mergeRanges(ranges: Range[]): Range[] {
57
- if (ranges.length === 0) return [];
58
- const sorted = [...ranges].sort((a, b) => a.start - b.start || a.end - b.end);
59
- const merged: Range[] = [sorted[0]];
60
- for (let i = 1; i < sorted.length; i++) {
61
- const last = merged[merged.length - 1];
62
- if (sorted[i].start <= last.end + 1) last.end = Math.max(last.end, sorted[i].end);
63
- else merged.push({ ...sorted[i] });
64
- }
65
- return merged;
66
- }
67
-
68
- // ── Brace-based elision (TS/JS/Rust) ──
69
- // NOTE: This is a regex heuristic, not a parser. Braces inside string literals,
70
- // template strings, regex, and comments are counted, which can produce incorrect
71
- // elision for edge cases like `const s = "{...}"` or `${expr}`. Acceptable for
72
- // summaries; do not use for correctness-sensitive parsing.
73
-
74
- function findBraceRanges(lines: string[], openPattern: RegExp, minBody: number): Range[] {
75
- const ranges: Range[] = [];
76
- for (let i = 0; i < lines.length; i++) {
77
- if (!openPattern.test(lines[i])) continue;
78
- let depth = 0;
79
- let foundOpen = false;
80
- const start = i;
81
- for (let j = i; j < lines.length; j++) {
82
- for (const ch of lines[j]) {
83
- if (ch === "{") {
84
- depth++;
85
- foundOpen = true;
86
- } else if (ch === "}") {
87
- depth--;
88
- }
89
- }
90
- if (foundOpen && depth <= 0) {
91
- if (j - start - 1 >= minBody) ranges.push({ start: start + 1, end: j - 1 });
92
- break;
93
- }
94
- }
95
- }
96
- return ranges;
97
- }
98
-
99
- // ── TypeScript / JavaScript ──
100
-
101
- const TS_FN_SIG =
102
- /^\s*(export\s+)?(async\s+)?function\s|^\s*(export\s+)?(static\s+|get\s+|set\s+|private\s+|public\s+|protected\s+|readonly\s+)*\*?\s*\w+\s*[(<]/;
103
- const TS_CLASS_SIG = /^\s*(export\s+)?(default\s+)?(abstract\s+)?class\s/;
104
- const TS_STRUCT_SIG = /^\s*(export\s+)?(default\s+)?(const|let|var)\s+\w+\s*=\s*(\[[\s]*$|\{[\s]*$)/;
105
-
106
- function tsRanges(lines: string[], minBody: number): Range[] {
107
- return [
108
- ...findBraceRanges(lines, TS_FN_SIG, minBody),
109
- ...findBraceRanges(lines, TS_CLASS_SIG, minBody),
110
- ...findBraceRanges(lines, TS_STRUCT_SIG, minBody),
111
- ];
112
- }
113
-
114
- // ── Block comments ──
115
-
116
- function blockCommentRanges(lines: string[], minComment: number): Range[] {
117
- const ranges: Range[] = [];
118
- let i = 0;
119
- while (i < lines.length) {
120
- const idx = lines[i].indexOf("/*");
121
- if (idx === -1 || lines[i].includes("*/", idx + 2)) {
122
- i++;
123
- continue;
124
- }
125
- const openLine = i;
126
- let j = i + 1;
127
- while (j < lines.length && !lines[j].includes("*/")) j++;
128
- if (j < lines.length && j - openLine - 1 >= minComment) ranges.push({ start: openLine + 1, end: j - 1 });
129
- i = j + 1;
130
- }
131
- return ranges;
132
- }
133
-
134
- // ── Import groups ──
135
-
136
- const IMPORT_RE = /^\s*import\s/;
137
- const PY_IMPORT_RE = /^\s*(import\s|from\s+\S+\s+import\s)/;
138
-
139
- function importGroupRanges(lines: string[], pattern: RegExp): Range[] {
140
- const groups: Array<{ start: number; end: number }> = [];
141
- let gs = -1,
142
- last = -1;
143
- for (let i = 0; i < lines.length; i++) {
144
- if (pattern.test(lines[i])) {
145
- if (gs === -1) gs = i;
146
- last = i;
147
- } else if (gs !== -1 && i > last) {
148
- groups.push({ start: gs, end: last });
149
- gs = -1;
150
- last = -1;
151
- }
152
- }
153
- if (gs !== -1) groups.push({ start: gs, end: last });
154
- const ranges: Range[] = [];
155
- for (const g of groups) {
156
- if (g.end - g.start >= 2) ranges.push({ start: g.start + 1, end: g.end - 1 });
157
- }
158
- return ranges;
159
- }
160
-
161
- // ── Python ──
162
-
163
- function pythonRanges(lines: string[], minBody: number): Range[] {
164
- const ranges: Range[] = [];
165
- for (let i = 0; i < lines.length; i++) {
166
- const m = /^(\s*)(async\s+)?def\s/.exec(lines[i]) || /^(\s*)class\s/.exec(lines[i]);
167
- if (!m) continue;
168
- const base = m[1].length;
169
- let bs = -1,
170
- be = -1;
171
- for (let j = i + 1; j < lines.length; j++) {
172
- if (lines[j].trim() === "") continue;
173
- const indent = lines[j].length - lines[j].trimStart().length;
174
- if (indent <= base) break;
175
- if (bs === -1) bs = j;
176
- be = j;
177
- }
178
- if (bs !== -1 && be - bs + 1 >= minBody) ranges.push({ start: bs, end: be });
179
- }
180
- ranges.push(...importGroupRanges(lines, PY_IMPORT_RE));
181
- return ranges;
182
- }
183
-
184
- // ── Rust ──
185
-
186
- const RS_FN_SIG = /^\s*(pub\s+)?(async\s+)?(unsafe\s+)?fn\s/;
187
- const RS_STRUCT_SIG = /^\s*(pub\s+)?struct\s+\w+.*\{$/;
188
- const RS_ENUM_SIG = /^\s*(pub\s+)?enum\s+\w+.*\{$/;
189
- const RS_MOD_SIG = /^\s*(pub\s+)?mod\s+\w+.*\{$/;
190
-
191
- function rustRanges(lines: string[], minBody: number): Range[] {
192
- return [
193
- ...findBraceRanges(lines, RS_FN_SIG, minBody),
194
- ...findBraceRanges(lines, RS_STRUCT_SIG, minBody),
195
- ...findBraceRanges(lines, RS_ENUM_SIG, minBody),
196
- ...findBraceRanges(lines, RS_MOD_SIG, minBody),
197
- ];
198
- }
199
-
200
- // ── Main entry ──
201
-
202
- function fullResult(language: string | null, totalLines: number, code: string): SummaryResult {
203
- return {
204
- language,
205
- totalLines,
206
- elided: false,
207
- segments: [{ kind: "kept", startLine: 1, endLine: totalLines, text: code }],
208
- rendered: code,
209
- };
210
- }
211
-
212
- export function summarizeCode(code: string, language: string | null, options?: SummaryOptions): SummaryResult {
213
- const minBody = options?.minBodyLines ?? 4;
214
- const minComment = options?.minCommentLines ?? 6;
215
-
216
- if (!code || code.trim() === "") {
217
- return {
218
- language,
219
- totalLines: 0,
220
- elided: false,
221
- segments: [],
222
- rendered: "",
223
- };
224
- }
225
-
226
- const lines = code.split("\n");
227
- const totalLines = lines.length;
228
-
229
- if (!language) return fullResult(null, totalLines, code);
230
-
231
- const rawRanges: Range[] = [];
232
- switch (language) {
233
- case "typescript":
234
- case "javascript":
235
- rawRanges.push(...tsRanges(lines, minBody), ...blockCommentRanges(lines, minComment), ...importGroupRanges(lines, IMPORT_RE));
236
- break;
237
- case "python":
238
- rawRanges.push(...pythonRanges(lines, minBody));
239
- break;
240
- case "rust":
241
- rawRanges.push(...rustRanges(lines, minBody), ...blockCommentRanges(lines, minComment));
242
- break;
243
- default:
244
- return fullResult(language, totalLines, code);
245
- }
246
-
247
- const ranges = mergeRanges(rawRanges);
248
- if (ranges.length === 0) return fullResult(language, totalLines, code);
249
-
250
- // Build segments
251
- const segments: SummarySegment[] = [];
252
- let cursor = 0;
253
- for (const r of ranges) {
254
- if (cursor < r.start) {
255
- segments.push({
256
- kind: "kept",
257
- startLine: cursor + 1,
258
- endLine: r.start,
259
- text: lines.slice(cursor, r.start).join("\n"),
260
- });
261
- }
262
- segments.push({
263
- kind: "elided",
264
- startLine: r.start + 1,
265
- endLine: r.end + 1,
266
- });
267
- cursor = r.end + 1;
268
- }
269
- if (cursor < totalLines) {
270
- segments.push({
271
- kind: "kept",
272
- startLine: cursor + 1,
273
- endLine: totalLines,
274
- text: lines.slice(cursor).join("\n"),
275
- });
276
- }
277
-
278
- // Render
279
- const parts: string[] = [];
280
- for (const seg of segments) {
281
- if (seg.kind === "kept") parts.push(seg.text ?? "");
282
- else parts.push(` ... ${seg.endLine - seg.startLine + 1} lines elided ...`);
283
- }
284
-
285
- return {
286
- language,
287
- totalLines,
288
- elided: true,
289
- segments,
290
- rendered: parts.join("\n"),
291
- };
292
- }
@@ -1,143 +0,0 @@
1
- import * as crypto from "node:crypto";
2
- import { extractSignaturePayload, isHmacEnabled, verifyRpcSignature } from "../extension/rpc-hmac.ts";
3
-
4
- export interface EventBus {
5
- on(event: string, handler: (data: unknown) => void): () => void;
6
- emit(event: string, data: unknown): void;
7
- }
8
-
9
- export type RpcReply<T = void> = { success: true; data?: T } | { success: false; error: string };
10
-
11
- export const PROTOCOL_VERSION = 1;
12
-
13
- // H-2 fix (code-review 2026-06-23): the old authorization relied on a
14
- // self-declared `source === "pi-crew"` field, which any co-installed
15
- // extension on the shared event bus can spoof. We now also require an
16
- // unguessable per-process token. Only in-process pi-crew code can obtain it
17
- // via getCrewRpcToken(); a cross-extension attacker cannot forge a UUID it
18
- // has never seen. (A full fix still needs event-bus-level origin signing, but
19
- // this closes the trivial spoof.)
20
- let CREW_RPC_TOKEN: string | undefined;
21
- /** @internal Per-process token that legitimate in-process RPC callers must include. */
22
- export function getCrewRpcToken(): string {
23
- if (!CREW_RPC_TOKEN) CREW_RPC_TOKEN = crypto.randomUUID();
24
- return CREW_RPC_TOKEN;
25
- }
26
-
27
- export interface RpcDeps {
28
- events: EventBus;
29
- getCtx: () => unknown | undefined;
30
- spawn: (type: string, prompt: string, options?: Record<string, unknown>) => string;
31
- abort: (agentId: string) => boolean;
32
- }
33
-
34
- export interface RpcHandle {
35
- unsubPing: () => void;
36
- unsubSpawn: () => void;
37
- unsubStop: () => void;
38
- }
39
-
40
- function handleRpc<P extends { requestId: string }>(
41
- events: EventBus,
42
- channel: string,
43
- fn: (params: P) => unknown | Promise<unknown>,
44
- ): () => void {
45
- return events.on(channel, async (raw: unknown) => {
46
- const params = raw as P;
47
- // SECURITY: Validate requestId format to prevent channel injection.
48
- if (!/^[a-zA-Z0-9_-]+$/.test(params.requestId)) {
49
- throw new Error("Security: invalid requestId format");
50
- }
51
- // SECURITY: HMAC signature verification (when enabled).
52
- if (isHmacEnabled()) {
53
- const sigPayload = extractSignaturePayload(params);
54
- if (!sigPayload) {
55
- throw new Error("[pi-crew HMAC] Missing HMAC signature in RPC request.");
56
- }
57
- // Strip HMAC fields before verification (HMAC was signed over original params)
58
- const originalParams = { ...params };
59
- delete (originalParams as Record<string, unknown>).hmacVersion;
60
- delete (originalParams as Record<string, unknown>).hmacOrigin;
61
- delete (originalParams as Record<string, unknown>).hmacTimestamp;
62
- delete (originalParams as Record<string, unknown>).hmacChannel;
63
- delete (originalParams as Record<string, unknown>).hmacNonce;
64
- delete (originalParams as Record<string, unknown>).hmacSignature;
65
- const verification = verifyRpcSignature(sigPayload, originalParams);
66
- if (!verification.valid) {
67
- throw new Error(`[pi-crew HMAC] ${verification.reason}`);
68
- }
69
- }
70
- try {
71
- const data = await fn(params);
72
- const reply: { success: true; data?: unknown } = { success: true };
73
- if (data !== undefined) reply.data = data;
74
- events.emit(`${channel}:reply:${params.requestId}`, reply);
75
- } catch (err: unknown) {
76
- events.emit(`${channel}:reply:${params.requestId}`, {
77
- success: false,
78
- error: err instanceof Error ? err.message : String(err),
79
- });
80
- }
81
- });
82
- }
83
-
84
- export function registerCrewRpcHandlers(deps: RpcDeps): RpcHandle {
85
- const { events, getCtx, spawn, abort } = deps;
86
-
87
- const unsubPing = handleRpc(events, "crew:rpc:ping", () => {
88
- return { version: PROTOCOL_VERSION };
89
- });
90
-
91
- // SECURITY TRUST BOUNDARY: crew:rpc:spawn and crew:rpc:stop are privileged
92
- // operations that create or terminate child processes. Any subscriber on
93
- // the shared event bus can emit these events. In a multi-extension
94
- // environment, this means a malicious extension could spawn/stop agents.
95
- // Mitigations: HMAC origin signing (see rpc-hmac.ts) + per-process token
96
- // (H-2) + legacy `source` identifier.
97
- const CREW_RPC_SOURCE = "pi-crew";
98
- const EXPECTED_TOKEN = getCrewRpcToken();
99
-
100
- function validateRpcSource(params: { requestId: string; source?: string; token?: string }): boolean {
101
- if (params.token !== EXPECTED_TOKEN) {
102
- console.warn(
103
- `[pi-crew SECURITY] RPC invocation rejected: missing/invalid token (source=${params.source ?? "(none)"}). ` +
104
- `Privileged RPC requires the in-process token. Request may be from an untrusted extension.`,
105
- );
106
- return false;
107
- }
108
- if (!params.source || params.source !== CREW_RPC_SOURCE) {
109
- console.warn(
110
- `[pi-crew SECURITY] RPC invocation from unexpected source: ${params.source ?? "(none)"}. ` +
111
- `Expected '${CREW_RPC_SOURCE}'. Request may be from an untrusted extension.`,
112
- );
113
- return false;
114
- }
115
- return true;
116
- }
117
-
118
- const unsubSpawn = handleRpc<{
119
- requestId: string;
120
- type: string;
121
- prompt: string;
122
- options?: Record<string, unknown>;
123
- source?: string;
124
- token?: string;
125
- }>(events, "crew:rpc:spawn", (params) => {
126
- if (!validateRpcSource(params)) throw new Error("Unauthorized: RPC spawn requires valid token and source='pi-crew'");
127
- const ctx = getCtx();
128
- if (!ctx) throw new Error("No active session");
129
- return { id: spawn(params.type, params.prompt, params.options ?? {}) };
130
- });
131
-
132
- const unsubStop = handleRpc<{
133
- requestId: string;
134
- agentId: string;
135
- source?: string;
136
- token?: string;
137
- }>(events, "crew:rpc:stop", (params) => {
138
- if (!validateRpcSource(params)) throw new Error("Unauthorized: RPC stop requires valid token and source='pi-crew'");
139
- if (!abort(params.agentId)) throw new Error("Agent not found");
140
- });
141
-
142
- return { unsubPing, unsubSpawn, unsubStop };
143
- }