pi-crew 0.9.16 → 0.9.17
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.
- package/CHANGELOG.md +81 -0
- package/README.md +19 -0
- package/dist/build-meta.json +21790 -0
- package/dist/index.mjs +83070 -0
- package/dist/index.mjs.map +7 -0
- package/docs/A +358 -0
- package/docs/M-A +357 -0
- package/docs/REVIEW-FINDINGS-2026-06 +357 -0
- package/docs/Y +357 -0
- package/docs/a +357 -0
- package/docs/aA +358 -0
- package/docs/archive/README.md +91 -0
- package/docs/patterns/command-agent-skill.md +1 -1
- package/docs/skills/REFERENCE.md +0 -17
- package/docs//303/242mmaAAA/303/242 +357 -0
- package/index.bundle.ts +25 -0
- package/index.ts +95 -4
- package/package.json +15 -4
- package/skills/iterative-audit/SKILL.md +0 -1
- package/skills/widget-rendering/SKILL.md +17 -0
- package/src/adapters/claude-adapter.ts +1 -3
- package/src/adapters/export-util.ts +16 -16
- package/src/adapters/index.ts +5 -5
- package/src/agents/agent-config.ts +20 -14
- package/src/agents/agent-serializer.ts +1 -1
- package/src/agents/discover-agents.ts +83 -39
- package/src/benchmark/benchmark-runner.ts +51 -51
- package/src/benchmark/feedback-loop.ts +1 -1
- package/src/config/config.ts +166 -590
- package/src/config/defaults.ts +28 -2
- package/src/config/drift-detector.ts +11 -14
- package/src/config/markers.ts +201 -203
- package/src/config/resilient-parser.ts +14 -6
- package/src/config/role-tools.ts +3 -3
- package/src/config/suggestions.ts +5 -12
- package/src/config/types.ts +9 -25
- package/src/errors.ts +151 -157
- package/src/extension/action-suggestions.ts +54 -9
- package/src/extension/async-notifier.ts +43 -13
- package/src/extension/autonomous-policy.ts +77 -37
- package/src/extension/command-completions.ts +9 -8
- package/src/extension/context-status-injection.ts +14 -12
- package/src/extension/crew-autocomplete.ts +8 -16
- package/src/extension/crew-cleanup.ts +2 -1
- package/src/extension/crew-shortcuts.ts +9 -6
- package/src/extension/cross-extension-rpc.ts +136 -42
- package/src/extension/help.ts +1 -1
- package/src/extension/import-index.ts +10 -5
- package/src/extension/knowledge-injection.ts +88 -15
- package/src/extension/management.ts +89 -349
- package/src/extension/message-renderers.ts +3 -4
- package/src/extension/notification-router.ts +22 -5
- package/src/extension/notification-sink.ts +6 -3
- package/src/extension/pi-api.ts +17 -8
- package/src/extension/plan-orchestrate.ts +8 -27
- package/src/extension/project-init.ts +21 -6
- package/src/extension/register.ts +329 -975
- package/src/extension/registration/artifact-cleanup.ts +9 -4
- package/src/extension/registration/command-utils.ts +5 -1
- package/src/extension/registration/commands.ts +806 -314
- package/src/extension/registration/compaction-guard.ts +15 -15
- package/src/extension/registration/lifecycle.ts +259 -0
- package/src/extension/registration/observability.ts +293 -0
- package/src/extension/registration/subagent-helpers.ts +29 -7
- package/src/extension/registration/subagent-tools.ts +253 -44
- package/src/extension/registration/team-tool.ts +19 -84
- package/src/extension/registration/ui.ts +168 -0
- package/src/extension/registration/viewers.ts +64 -24
- package/src/extension/result-watcher.ts +18 -7
- package/src/extension/run-bundle-schema.ts +21 -6
- package/src/extension/run-export.ts +15 -6
- package/src/extension/run-import.ts +64 -29
- package/src/extension/run-index.ts +28 -9
- package/src/extension/run-maintenance.ts +32 -12
- package/src/extension/session-summary.ts +1 -1
- package/src/extension/team-manager-command.ts +64 -7
- package/src/extension/team-onboard.ts +151 -150
- package/src/extension/team-recommendation.ts +121 -21
- package/src/extension/team-tool/anchor.ts +31 -64
- package/src/extension/team-tool/api.ts +929 -141
- package/src/extension/team-tool/auto-summarize.ts +14 -26
- package/src/extension/team-tool/cache-control.ts +1 -5
- package/src/extension/team-tool/cancel.ts +138 -38
- package/src/extension/team-tool/chain-dispatch.ts +5 -13
- package/src/extension/team-tool/chain-executor.ts +29 -51
- package/src/extension/team-tool/config-patch.ts +1 -1
- package/src/extension/team-tool/context.ts +40 -20
- package/src/extension/team-tool/destructive-gate.ts +10 -5
- package/src/extension/team-tool/doctor.ts +170 -51
- package/src/extension/team-tool/explain.ts +228 -214
- package/src/extension/team-tool/failure-patterns.ts +3 -9
- package/src/extension/team-tool/goal-wrap.ts +71 -29
- package/src/extension/team-tool/goal.ts +185 -35
- package/src/extension/team-tool/handle-schedule.ts +34 -15
- package/src/extension/team-tool/handle-settings.ts +94 -56
- package/src/extension/team-tool/health-monitor.ts +27 -108
- package/src/extension/team-tool/inspect.ts +42 -9
- package/src/extension/team-tool/intent-policy.ts +4 -1
- package/src/extension/team-tool/lifecycle-actions.ts +244 -48
- package/src/extension/team-tool/orchestrate.ts +7 -18
- package/src/extension/team-tool/parallel-dispatch.ts +51 -29
- package/src/extension/team-tool/plan.ts +29 -5
- package/src/extension/team-tool/respond.ts +49 -16
- package/src/extension/team-tool/run-not-found.ts +3 -8
- package/src/extension/team-tool/run.ts +80 -317
- package/src/extension/team-tool/status.ts +135 -43
- package/src/extension/team-tool/workflow-manage.ts +92 -25
- package/src/extension/team-tool-types.ts +8 -1
- package/src/extension/team-tool.ts +142 -551
- package/src/extension/validate-resources.ts +39 -8
- package/src/hooks/registry.ts +66 -17
- package/src/hooks/types.ts +1 -1
- package/src/i18n.ts +25 -11
- package/src/observability/correlation.ts +17 -3
- package/src/observability/event-bus.ts +51 -56
- package/src/observability/event-to-metric.ts +117 -15
- package/src/observability/exporters/otlp-exporter.ts +56 -17
- package/src/observability/exporters/prometheus-exporter.ts +1 -1
- package/src/observability/metric-registry.ts +16 -4
- package/src/observability/metric-retention.ts +8 -2
- package/src/observability/metric-sink.ts +11 -3
- package/src/observability/metrics-primitives.ts +42 -9
- package/src/plugins/plugin-define.ts +2 -2
- package/src/plugins/plugin-registry.ts +25 -25
- package/src/plugins/plugins/index.ts +1 -1
- package/src/plugins/plugins/nextjs.ts +16 -16
- package/src/plugins/plugins/vite.ts +7 -11
- package/src/plugins/plugins/vitest.ts +6 -11
- package/src/runtime/adaptive-plan.ts +225 -40
- package/src/runtime/agent-control.ts +58 -15
- package/src/runtime/agent-memory.ts +15 -9
- package/src/runtime/agent-observability.ts +10 -2
- package/src/runtime/anchor-manager.ts +27 -25
- package/src/runtime/async-marker.ts +7 -1
- package/src/runtime/async-runner.ts +27 -23
- package/src/runtime/auto-summarize.ts +7 -13
- package/src/runtime/background-runner.ts +189 -251
- package/src/runtime/batch-barrier.ts +18 -16
- package/src/runtime/cancellation-token.ts +16 -6
- package/src/runtime/cancellation.ts +46 -8
- package/src/runtime/capability-inventory.ts +6 -4
- package/src/runtime/chain-parser.ts +44 -11
- package/src/runtime/chain-runner.ts +63 -69
- package/src/runtime/checkpoint.ts +12 -56
- package/src/runtime/child-pi.ts +343 -78
- package/src/runtime/coalesce-tasks.ts +268 -0
- package/src/runtime/code-summary.ts +71 -26
- package/src/runtime/compact-stages/index.ts +15 -5
- package/src/runtime/compact-stages/tail-capture-stage.ts +7 -2
- package/src/runtime/compact-stages/truncation-stage.ts +4 -1
- package/src/runtime/compaction-summary.ts +17 -10
- package/src/runtime/completion-guard.ts +33 -16
- package/src/runtime/crash-classification.ts +28 -7
- package/src/runtime/crash-recovery.ts +177 -37
- package/src/runtime/crew-agent-records.ts +145 -47
- package/src/runtime/crew-hooks.ts +9 -24
- package/src/runtime/cross-extension-rpc.ts +25 -23
- package/src/runtime/custom-tools/irc-tool.ts +43 -15
- package/src/runtime/custom-tools/submit-result-tool.ts +16 -5
- package/src/runtime/delivery-coordinator.ts +34 -7
- package/src/runtime/delta-conflict.ts +9 -21
- package/src/runtime/deterministic-ast.ts +1 -1
- package/src/runtime/diagnostic-export.ts +53 -20
- package/src/runtime/direct-run.ts +12 -2
- package/src/runtime/dwf-state-store.ts +1 -1
- package/src/runtime/dynamic-workflow-context.ts +186 -58
- package/src/runtime/dynamic-workflow-runner.ts +42 -20
- package/src/runtime/effectiveness.ts +16 -8
- package/src/runtime/errors/crew-errors.ts +7 -11
- package/src/runtime/event-stream-bridge.ts +9 -3
- package/src/runtime/foreground-control.ts +54 -14
- package/src/runtime/foreground-watchdog.ts +9 -6
- package/src/runtime/goal-achievement.ts +27 -10
- package/src/runtime/goal-evaluator.ts +54 -19
- package/src/runtime/goal-loop-runner.ts +280 -99
- package/src/runtime/goal-state-store.ts +27 -17
- package/src/runtime/green-contract.ts +11 -2
- package/src/runtime/group-join.ts +64 -31
- package/src/runtime/handoff-manager.ts +37 -42
- package/src/runtime/heartbeat-gradient.ts +10 -2
- package/src/runtime/heartbeat-watcher.ts +32 -6
- package/src/runtime/hidden-handoff.ts +12 -30
- package/src/runtime/important-line-classifier.ts +12 -2
- package/src/runtime/iteration-hooks.ts +25 -15
- package/src/runtime/live-agent-control.ts +55 -7
- package/src/runtime/live-agent-manager.ts +130 -27
- package/src/runtime/live-control-realtime.ts +23 -3
- package/src/runtime/live-irc.ts +4 -1
- package/src/runtime/live-session-health.ts +12 -4
- package/src/runtime/live-session-runtime.ts +379 -117
- package/src/runtime/manifest-cache.ts +28 -12
- package/src/runtime/mcp-proxy.ts +8 -16
- package/src/runtime/metric-parser.ts +1 -5
- package/src/runtime/model-fallback.ts +55 -18
- package/src/runtime/model-resolver.ts +2 -6
- package/src/runtime/model-scope.ts +19 -3
- package/src/runtime/notebook-helpers.ts +60 -62
- package/src/runtime/orphan-worker-registry.ts +37 -26
- package/src/runtime/output-validator.ts +18 -3
- package/src/runtime/overflow-recovery.ts +5 -4
- package/src/runtime/parallel-research.ts +29 -5
- package/src/runtime/parallel-utils.ts +9 -11
- package/src/runtime/path-overlap.ts +150 -0
- package/src/runtime/peer-dep.ts +12 -17
- package/src/runtime/per-write-validator.ts +1 -3
- package/src/runtime/phase-tracker.ts +342 -330
- package/src/runtime/pi-args.ts +26 -8
- package/src/runtime/pi-json-output.ts +1 -1
- package/src/runtime/pi-spawn.ts +30 -19
- package/src/runtime/pipeline-runner.ts +56 -55
- package/src/runtime/plan-templates.ts +5 -6
- package/src/runtime/policy-engine.ts +43 -7
- package/src/runtime/post-checks.ts +12 -4
- package/src/runtime/post-exit-stdio-guard.ts +2 -2
- package/src/runtime/process-lifecycle.ts +20 -10
- package/src/runtime/process-status.ts +16 -5
- package/src/runtime/progress-event-coalescer.ts +2 -1
- package/src/runtime/progress-tracker.ts +103 -103
- package/src/runtime/prose-compressor.ts +9 -11
- package/src/runtime/recovery-recipes.ts +118 -24
- package/src/runtime/replace.ts +25 -10
- package/src/runtime/resilient-edit.ts +10 -25
- package/src/runtime/result-extractor.ts +1 -2
- package/src/runtime/retry-executor.ts +20 -4
- package/src/runtime/retry-runner.ts +26 -50
- package/src/runtime/role-permission.ts +6 -1
- package/src/runtime/run-coalesced-task-group.ts +256 -0
- package/src/runtime/run-drift.ts +14 -15
- package/src/runtime/run-tracker.ts +6 -28
- package/src/runtime/runtime-policy.ts +1 -6
- package/src/runtime/runtime-resolver.ts +80 -15
- package/src/runtime/scheduler.ts +47 -18
- package/src/runtime/semaphore.ts +5 -7
- package/src/runtime/sensitive-paths.ts +2 -1
- package/src/runtime/session-usage.ts +1 -1
- package/src/runtime/settings-store.ts +16 -12
- package/src/runtime/sidechain-output.ts +6 -2
- package/src/runtime/single-agent-compose.ts +1 -4
- package/src/runtime/skill-effectiveness.ts +29 -97
- package/src/runtime/skill-instructions.ts +40 -83
- package/src/runtime/stale-reconciler.ts +73 -197
- package/src/runtime/stream-preview.ts +1 -1
- package/src/runtime/streaming-output.ts +1 -1
- package/src/runtime/subagent-manager.ts +44 -169
- package/src/runtime/subprocess-tool-registry.ts +4 -1
- package/src/runtime/supervisor-contact.ts +10 -5
- package/src/runtime/task-display.ts +19 -5
- package/src/runtime/task-graph-scheduler.ts +95 -21
- package/src/runtime/task-graph.ts +5 -11
- package/src/runtime/task-health.ts +54 -47
- package/src/runtime/task-id.ts +11 -18
- package/src/runtime/task-output-context.ts +265 -81
- package/src/runtime/task-packet.ts +12 -20
- package/src/runtime/task-quality.ts +6 -14
- package/src/runtime/task-runner/context-retrieval.ts +4 -13
- package/src/runtime/task-runner/live-executor.ts +114 -36
- package/src/runtime/task-runner/output-splitter.ts +152 -0
- package/src/runtime/task-runner/progress.ts +50 -12
- package/src/runtime/task-runner/prompt-builder.ts +31 -7
- package/src/runtime/task-runner/prompt-pipeline.ts +31 -7
- package/src/runtime/task-runner/result-utils.ts +3 -1
- package/src/runtime/task-runner/retrieval-orchestrator.ts +310 -0
- package/src/runtime/task-runner/run-projection.ts +27 -8
- package/src/runtime/task-runner/state-helpers.ts +29 -8
- package/src/runtime/task-runner/tail-read.ts +2 -6
- package/src/runtime/task-runner.ts +180 -326
- package/src/runtime/team-runner-artifacts.ts +13 -0
- package/src/runtime/team-runner.ts +456 -974
- package/src/runtime/tool-output-pruner.ts +6 -9
- package/src/runtime/tool-progress.ts +11 -21
- package/src/runtime/verification-gates.ts +33 -24
- package/src/runtime/verification-integrity.ts +1 -4
- package/src/runtime/verification-worktree.ts +62 -12
- package/src/runtime/worker-heartbeat.ts +5 -1
- package/src/runtime/worker-startup.ts +29 -5
- package/src/runtime/workflow-state.ts +17 -9
- package/src/runtime/workspace-lock.ts +30 -35
- package/src/runtime/workspace-tree.ts +20 -32
- package/src/runtime/yield-handler.ts +43 -9
- package/src/runtime/zombie-scanner.ts +5 -4
- package/src/schema/config-schema.ts +266 -172
- package/src/schema/team-tool-schema.ts +29 -74
- package/src/schema/validation-types.ts +25 -17
- package/src/skills/discover-skills.ts +35 -10
- package/src/skills/skill-templates.ts +109 -27
- package/src/skills/validate.ts +26 -8
- package/src/state/active-run-registry.ts +87 -28
- package/src/state/artifact-store.ts +9 -5
- package/src/state/atomic-write-v2.ts +85 -63
- package/src/state/atomic-write.ts +105 -26
- package/src/state/blob-store.ts +47 -20
- package/src/state/contracts.ts +20 -5
- package/src/state/crew-init.ts +5 -22
- package/src/state/decision-ledger.ts +19 -73
- package/src/state/event-log-rotation.ts +41 -15
- package/src/state/event-log.ts +168 -53
- package/src/state/event-reconstructor.ts +11 -1
- package/src/state/gitignore-manager.ts +2 -8
- package/src/state/health-store.ts +57 -57
- package/src/state/hook-instinct-bridge.ts +1 -1
- package/src/state/hook-integrations.ts +1 -1
- package/src/state/instinct-store.ts +17 -5
- package/src/state/jsonl-writer.ts +1 -1
- package/src/state/locks.ts +23 -9
- package/src/state/mailbox.ts +151 -28
- package/src/state/observation-store.ts +20 -14
- package/src/state/run-cache.ts +142 -135
- package/src/state/run-graph.ts +6 -15
- package/src/state/run-metrics.ts +5 -18
- package/src/state/schedule.ts +15 -9
- package/src/state/state-store.ts +129 -45
- package/src/state/task-claims.ts +12 -2
- package/src/state/tiered-eval.ts +52 -43
- package/src/state/types-eval.ts +2 -2
- package/src/state/types.ts +24 -20
- package/src/state/usage.ts +20 -4
- package/src/state/worker-atomic-writer.ts +6 -3
- package/src/subagents/index.ts +2 -2
- package/src/teams/discover-teams.ts +21 -6
- package/src/tools/safe-bash-extension.ts +5 -6
- package/src/tools/safe-bash.ts +10 -11
- package/src/types/new-api-types.ts +6 -10
- package/src/ui/agent-management-overlay.ts +52 -40
- package/src/ui/card-colors.ts +13 -4
- package/src/ui/crew-footer.ts +8 -7
- package/src/ui/crew-select-list.ts +1 -1
- package/src/ui/dashboard-panes/agents-pane.ts +41 -25
- package/src/ui/dashboard-panes/cancellation-pane.ts +1 -1
- package/src/ui/dashboard-panes/capability-pane.ts +32 -15
- package/src/ui/dashboard-panes/health-pane.ts +2 -1
- package/src/ui/dashboard-panes/metrics-pane.ts +4 -1
- package/src/ui/dashboard-panes/progress-pane.ts +12 -9
- package/src/ui/heartbeat-aggregator.ts +15 -4
- package/src/ui/keybinding-map.ts +40 -7
- package/src/ui/live-conversation-overlay.ts +36 -20
- package/src/ui/live-duration.ts +1 -4
- package/src/ui/live-run-sidebar.ts +88 -25
- package/src/ui/loaders.ts +2 -8
- package/src/ui/mascot.ts +20 -36
- package/src/ui/overlays/agent-picker-overlay.ts +11 -3
- package/src/ui/overlays/confirm-overlay.ts +4 -2
- package/src/ui/overlays/help-overlay.ts +25 -14
- package/src/ui/overlays/mailbox-compose-overlay.ts +48 -11
- package/src/ui/overlays/mailbox-compose-preview.ts +20 -5
- package/src/ui/overlays/mailbox-detail-overlay.ts +27 -6
- package/src/ui/pi-ui-compat.ts +7 -7
- package/src/ui/powerbar-publisher.ts +120 -42
- package/src/ui/render-diff.ts +10 -3
- package/src/ui/render-scheduler.ts +12 -4
- package/src/ui/run-action-dispatcher.ts +81 -18
- package/src/ui/run-dashboard.ts +172 -76
- package/src/ui/run-event-bus.ts +59 -37
- package/src/ui/run-snapshot-cache.ts +276 -86
- package/src/ui/settings-overlay.ts +361 -74
- package/src/ui/status-colors.ts +12 -1
- package/src/ui/syntax-highlight.ts +1 -1
- package/src/ui/theme-adapter.ts +16 -14
- package/src/ui/theme-discovery.ts +13 -2
- package/src/ui/tool-progress-formatter.ts +7 -7
- package/src/ui/tool-render.ts +128 -56
- package/src/ui/tool-renderers/brief-mode.ts +45 -27
- package/src/ui/tool-renderers/index.ts +109 -43
- package/src/ui/transcript-cache.ts +32 -6
- package/src/ui/transcript-entries.ts +25 -23
- package/src/ui/transcript-viewer.ts +78 -29
- package/src/ui/widget/index.ts +99 -40
- package/src/ui/widget/widget-formatters.ts +13 -6
- package/src/ui/widget/widget-model.ts +19 -8
- package/src/ui/widget/widget-renderer.ts +23 -13
- package/src/ui/widget/widget-types.ts +1 -1
- package/src/utils/bm25-search.ts +199 -199
- package/src/utils/conflict-detect.ts +22 -21
- package/src/utils/env-filter.ts +14 -7
- package/src/utils/file-coalescer.ts +5 -1
- package/src/utils/fingerprint.ts +3 -6
- package/src/utils/frontmatter.ts +3 -1
- package/src/utils/fs-watch.ts +2 -6
- package/src/utils/gh-protocol.ts +119 -44
- package/src/utils/git.ts +13 -15
- package/src/utils/guards.ts +2 -5
- package/src/utils/ids.ts +9 -2
- package/src/utils/incremental-reader.ts +14 -3
- package/src/utils/internal-error.ts +2 -1
- package/src/utils/names.ts +12 -3
- package/src/utils/paths.ts +49 -5
- package/src/utils/project-detector.ts +2 -2
- package/src/utils/redaction.ts +29 -19
- package/src/utils/resolve-shell.ts +9 -7
- package/src/utils/run-watcher-registry.ts +19 -31
- package/src/utils/safe-paths.ts +45 -24
- package/src/utils/scan-cache.ts +9 -2
- package/src/utils/session-utils.ts +2 -4
- package/src/utils/sleep.ts +12 -5
- package/src/utils/sse-parser.ts +5 -17
- package/src/utils/visual.ts +52 -32
- package/src/workflows/discover-workflows.ts +41 -109
- package/src/workflows/intermediate-store.ts +5 -21
- package/src/workflows/preflight-validator.ts +6 -33
- package/src/workflows/topology-analyzer.ts +5 -21
- package/src/workflows/workflow-config.ts +7 -6
- package/src/worktree/branch-freshness.ts +66 -8
- package/src/worktree/cleanup.ts +130 -20
- package/src/worktree/worktree-manager.ts +212 -69
- package/skills/artifact-analysis-loop/SKILL.md +0 -303
- package/skills/detection-pipeline-design/SKILL.md +0 -286
- package/skills/hunting-investigation-loop/SKILL.md +0 -402
- package/skills/incident-playbook-construction/SKILL.md +0 -384
- package/skills/security-review/SKILL.md +0 -561
- package/skills/threat-hypothesis-framework/SKILL.md +0 -176
- package/skills/ui-render-performance/SKILL.md +0 -58
- /package/docs/{followup-review-round3-2026-05-12.md → archive/followup-review-round3-2026-05-12.md} +0 -0
- /package/docs/{followup-review-round4-2026-05-13.md → archive/followup-review-round4-2026-05-13.md} +0 -0
- /package/docs/{pi-crew-bugs.md → archive/pi-crew-bugs.md} +0 -0
- /package/docs/{pi-crew-test-final.md → archive/pi-crew-test-final.md} +0 -0
- /package/docs/{pi-crew-test-results.md → archive/pi-crew-test-results.md} +0 -0
- /package/docs/{pi-crew-test-round2.md → archive/pi-crew-test-round2.md} +0 -0
- /package/docs/{pi-crew-test-round4.md → archive/pi-crew-test-round4.md} +0 -0
- /package/docs/{pi-crew-test-round5.md → archive/pi-crew-test-round5.md} +0 -0
- /package/docs/{pi-crew-test-round6.md → archive/pi-crew-test-round6.md} +0 -0
- /package/docs/{pi-crew-v0.5.10-audit-fix-plan.md → archive/pi-crew-v0.5.10-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.11-audit-fix-plan.md → archive/pi-crew-v0.5.11-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.12-audit-fix-plan.md → archive/pi-crew-v0.5.12-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.13-audit-fix-plan.md → archive/pi-crew-v0.5.13-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.14-audit-fix-plan.md → archive/pi-crew-v0.5.14-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.16-audit-fix-plan.md → archive/pi-crew-v0.5.16-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.17-audit-fix-plan.md → archive/pi-crew-v0.5.17-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.5-audit-fix-plan.md → archive/pi-crew-v0.5.5-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.9-audit-fix-plan.md → archive/pi-crew-v0.5.9-audit-fix-plan.md} +0 -0
- /package/docs/{pi-mono-opportunities.md → archive/pi-mono-opportunities.md} +0 -0
- /package/docs/{pi-mono-review.md → archive/pi-mono-review.md} +0 -0
- /package/docs/{pi-subagent4-comparison.md → archive/pi-subagent4-comparison.md} +0 -0
- /package/docs/{pi-subagents3-deep-analysis.md → archive/pi-subagents3-deep-analysis.md} +0 -0
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import * as crypto from "node:crypto";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import type {
|
|
5
|
-
AgentConfig,
|
|
6
|
-
ResourceSource,
|
|
7
|
-
RoutingMetadata,
|
|
8
|
-
} from "../agents/agent-config.ts";
|
|
4
|
+
import type { AgentConfig, ResourceSource, RoutingMetadata } from "../agents/agent-config.ts";
|
|
9
5
|
import { serializeAgent } from "../agents/agent-serializer.ts";
|
|
10
6
|
import { discoverAgents } from "../agents/discover-agents.ts";
|
|
11
7
|
import type { PiTeamsConfig } from "../config/config.ts";
|
|
@@ -13,21 +9,10 @@ import type { TeamToolParamsValue } from "../schema/team-tool-schema.ts";
|
|
|
13
9
|
import { allTeams, discoverTeams } from "../teams/discover-teams.ts";
|
|
14
10
|
import type { TeamConfig, TeamRole } from "../teams/team-config.ts";
|
|
15
11
|
import { serializeTeam } from "../teams/team-serializer.ts";
|
|
16
|
-
import {
|
|
17
|
-
hasOwn,
|
|
18
|
-
parseConfigObject,
|
|
19
|
-
requireString,
|
|
20
|
-
sanitizeName,
|
|
21
|
-
} from "../utils/names.ts";
|
|
12
|
+
import { hasOwn, parseConfigObject, requireString, sanitizeName } from "../utils/names.ts";
|
|
22
13
|
import { projectCrewRoot, userPiRoot } from "../utils/paths.ts";
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
discoverWorkflows,
|
|
26
|
-
} from "../workflows/discover-workflows.ts";
|
|
27
|
-
import type {
|
|
28
|
-
WorkflowConfig,
|
|
29
|
-
WorkflowStep,
|
|
30
|
-
} from "../workflows/workflow-config.ts";
|
|
14
|
+
import { allWorkflows, discoverWorkflows } from "../workflows/discover-workflows.ts";
|
|
15
|
+
import type { WorkflowConfig, WorkflowStep } from "../workflows/workflow-config.ts";
|
|
31
16
|
import { serializeWorkflow } from "../workflows/workflow-serializer.ts";
|
|
32
17
|
import { enforceDestructiveIntent } from "./team-tool/intent-policy.ts";
|
|
33
18
|
import type { TeamToolDetails } from "./team-tool-types.ts";
|
|
@@ -42,19 +27,11 @@ type MutableSource = "user" | "project";
|
|
|
42
27
|
|
|
43
28
|
type MutableResource = AgentConfig | TeamConfig | WorkflowConfig;
|
|
44
29
|
|
|
45
|
-
function result(
|
|
46
|
-
text: string,
|
|
47
|
-
status: TeamToolDetails["status"] = "ok",
|
|
48
|
-
isError = false,
|
|
49
|
-
): PiTeamsToolResult {
|
|
30
|
+
function result(text: string, status: TeamToolDetails["status"] = "ok", isError = false): PiTeamsToolResult {
|
|
50
31
|
return toolResult(text, { action: "management", status }, isError);
|
|
51
32
|
}
|
|
52
33
|
|
|
53
|
-
function scopeDir(
|
|
54
|
-
ctx: ManagementContext,
|
|
55
|
-
resource: "agent" | "team" | "workflow",
|
|
56
|
-
scope: MutableSource,
|
|
57
|
-
): string {
|
|
34
|
+
function scopeDir(ctx: ManagementContext, resource: "agent" | "team" | "workflow", scope: MutableSource): string {
|
|
58
35
|
const base = scope === "user" ? userPiRoot() : projectCrewRoot(ctx.cwd);
|
|
59
36
|
if (resource === "agent") return path.join(base, "agents");
|
|
60
37
|
if (resource === "team") return path.join(base, "teams");
|
|
@@ -77,16 +54,8 @@ function backupFile(filePath: string): string {
|
|
|
77
54
|
return backupPath;
|
|
78
55
|
}
|
|
79
56
|
|
|
80
|
-
function targetPath(
|
|
81
|
-
ctx
|
|
82
|
-
resource: "agent" | "team" | "workflow",
|
|
83
|
-
scope: MutableSource,
|
|
84
|
-
name: string,
|
|
85
|
-
): string {
|
|
86
|
-
return path.join(
|
|
87
|
-
scopeDir(ctx, resource, scope),
|
|
88
|
-
`${name}${extensionFor(resource)}`,
|
|
89
|
-
);
|
|
57
|
+
function targetPath(ctx: ManagementContext, resource: "agent" | "team" | "workflow", scope: MutableSource, name: string): string {
|
|
58
|
+
return path.join(scopeDir(ctx, resource, scope), `${name}${extensionFor(resource)}`);
|
|
90
59
|
}
|
|
91
60
|
|
|
92
61
|
function parseStringArray(value: unknown): string[] | undefined {
|
|
@@ -96,58 +65,31 @@ function parseStringArray(value: unknown): string[] | undefined {
|
|
|
96
65
|
.map((entry) => entry.trim())
|
|
97
66
|
.filter(Boolean);
|
|
98
67
|
if (Array.isArray(value))
|
|
99
|
-
return value
|
|
100
|
-
.filter(
|
|
101
|
-
(entry): entry is string =>
|
|
102
|
-
typeof entry === "string" && entry.trim().length > 0,
|
|
103
|
-
)
|
|
104
|
-
.map((entry) => entry.trim());
|
|
68
|
+
return value.filter((entry): entry is string => typeof entry === "string" && entry.trim().length > 0).map((entry) => entry.trim());
|
|
105
69
|
return undefined;
|
|
106
70
|
}
|
|
107
71
|
|
|
108
|
-
function parseRouting(
|
|
109
|
-
value: Record<string, unknown>,
|
|
110
|
-
fallback?: RoutingMetadata,
|
|
111
|
-
): RoutingMetadata | undefined {
|
|
72
|
+
function parseRouting(value: Record<string, unknown>, fallback?: RoutingMetadata): RoutingMetadata | undefined {
|
|
112
73
|
const routing = {
|
|
113
|
-
triggers: hasOwn(value, "triggers")
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
? parseStringArray(value.useWhen)
|
|
118
|
-
: fallback?.useWhen,
|
|
119
|
-
avoidWhen: hasOwn(value, "avoidWhen")
|
|
120
|
-
? parseStringArray(value.avoidWhen)
|
|
121
|
-
: fallback?.avoidWhen,
|
|
122
|
-
cost:
|
|
123
|
-
value.cost === "free" ||
|
|
124
|
-
value.cost === "cheap" ||
|
|
125
|
-
value.cost === "expensive"
|
|
126
|
-
? value.cost
|
|
127
|
-
: fallback?.cost,
|
|
74
|
+
triggers: hasOwn(value, "triggers") ? parseStringArray(value.triggers) : fallback?.triggers,
|
|
75
|
+
useWhen: hasOwn(value, "useWhen") ? parseStringArray(value.useWhen) : fallback?.useWhen,
|
|
76
|
+
avoidWhen: hasOwn(value, "avoidWhen") ? parseStringArray(value.avoidWhen) : fallback?.avoidWhen,
|
|
77
|
+
cost: value.cost === "free" || value.cost === "cheap" || value.cost === "expensive" ? value.cost : fallback?.cost,
|
|
128
78
|
category: hasOwn(value, "category")
|
|
129
79
|
? typeof value.category === "string" && value.category.trim()
|
|
130
80
|
? value.category.trim()
|
|
131
81
|
: undefined
|
|
132
82
|
: fallback?.category,
|
|
133
83
|
};
|
|
134
|
-
return routing.triggers ||
|
|
135
|
-
routing.useWhen ||
|
|
136
|
-
routing.avoidWhen ||
|
|
137
|
-
routing.cost ||
|
|
138
|
-
routing.category
|
|
139
|
-
? routing
|
|
140
|
-
: undefined;
|
|
84
|
+
return routing.triggers || routing.useWhen || routing.avoidWhen || routing.cost || routing.category ? routing : undefined;
|
|
141
85
|
}
|
|
142
86
|
|
|
143
87
|
function parseRoles(value: unknown): { roles?: TeamRole[]; error?: string } {
|
|
144
|
-
if (!Array.isArray(value) || value.length === 0)
|
|
145
|
-
return { error: "config.roles must be a non-empty array." };
|
|
88
|
+
if (!Array.isArray(value) || value.length === 0) return { error: "config.roles must be a non-empty array." };
|
|
146
89
|
const roles: TeamRole[] = [];
|
|
147
90
|
for (let i = 0; i < value.length; i++) {
|
|
148
91
|
const item = value[i];
|
|
149
|
-
if (!item || typeof item !== "object" || Array.isArray(item))
|
|
150
|
-
return { error: `config.roles[${i}] must be an object.` };
|
|
92
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return { error: `config.roles[${i}] must be an object.` };
|
|
151
93
|
const obj = item as Record<string, unknown>;
|
|
152
94
|
const name = requireString(obj.name, `config.roles[${i}].name`);
|
|
153
95
|
if (name.error) return { error: name.error };
|
|
@@ -156,15 +98,10 @@ function parseRoles(value: unknown): { roles?: TeamRole[]; error?: string } {
|
|
|
156
98
|
roles.push({
|
|
157
99
|
name: sanitizeName(name.value!),
|
|
158
100
|
agent: sanitizeName(agent.value!),
|
|
159
|
-
description:
|
|
160
|
-
typeof obj.description === "string"
|
|
161
|
-
? obj.description.trim()
|
|
162
|
-
: undefined,
|
|
101
|
+
description: typeof obj.description === "string" ? obj.description.trim() : undefined,
|
|
163
102
|
model: typeof obj.model === "string" ? obj.model.trim() : undefined,
|
|
164
103
|
maxConcurrency:
|
|
165
|
-
typeof obj.maxConcurrency === "number" &&
|
|
166
|
-
Number.isInteger(obj.maxConcurrency) &&
|
|
167
|
-
obj.maxConcurrency > 0
|
|
104
|
+
typeof obj.maxConcurrency === "number" && Number.isInteger(obj.maxConcurrency) && obj.maxConcurrency > 0
|
|
168
105
|
? obj.maxConcurrency
|
|
169
106
|
: undefined,
|
|
170
107
|
});
|
|
@@ -176,13 +113,11 @@ function parseSteps(value: unknown): {
|
|
|
176
113
|
steps?: WorkflowStep[];
|
|
177
114
|
error?: string;
|
|
178
115
|
} {
|
|
179
|
-
if (!Array.isArray(value) || value.length === 0)
|
|
180
|
-
return { error: "config.steps must be a non-empty array." };
|
|
116
|
+
if (!Array.isArray(value) || value.length === 0) return { error: "config.steps must be a non-empty array." };
|
|
181
117
|
const steps: WorkflowStep[] = [];
|
|
182
118
|
for (let i = 0; i < value.length; i++) {
|
|
183
119
|
const item = value[i];
|
|
184
|
-
if (!item || typeof item !== "object" || Array.isArray(item))
|
|
185
|
-
return { error: `config.steps[${i}] must be an object.` };
|
|
120
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return { error: `config.steps[${i}] must be an object.` };
|
|
186
121
|
const obj = item as Record<string, unknown>;
|
|
187
122
|
const id = requireString(obj.id, `config.steps[${i}].id`);
|
|
188
123
|
if (id.error) return { error: id.error };
|
|
@@ -205,23 +140,13 @@ function parseSteps(value: unknown): {
|
|
|
205
140
|
role: sanitizeName(role.value!),
|
|
206
141
|
task,
|
|
207
142
|
dependsOn: parseStringArray(obj.dependsOn),
|
|
208
|
-
parallelGroup:
|
|
209
|
-
|
|
210
|
-
? obj.parallelGroup.trim()
|
|
211
|
-
: undefined,
|
|
212
|
-
output:
|
|
213
|
-
obj.output === false
|
|
214
|
-
? false
|
|
215
|
-
: typeof obj.output === "string"
|
|
216
|
-
? obj.output.trim()
|
|
217
|
-
: undefined,
|
|
143
|
+
parallelGroup: typeof obj.parallelGroup === "string" ? obj.parallelGroup.trim() : undefined,
|
|
144
|
+
output: obj.output === false ? false : typeof obj.output === "string" ? obj.output.trim() : undefined,
|
|
218
145
|
reads: obj.reads === false ? false : parseStringArray(obj.reads),
|
|
219
146
|
model: typeof obj.model === "string" ? obj.model.trim() : undefined,
|
|
220
147
|
skills: obj.skills === false ? false : parseStringArray(obj.skills),
|
|
221
|
-
progress:
|
|
222
|
-
|
|
223
|
-
worktree:
|
|
224
|
-
typeof obj.worktree === "boolean" ? obj.worktree : undefined,
|
|
148
|
+
progress: typeof obj.progress === "boolean" ? obj.progress : undefined,
|
|
149
|
+
worktree: typeof obj.worktree === "boolean" ? obj.worktree : undefined,
|
|
225
150
|
verify: typeof obj.verify === "boolean" ? obj.verify : undefined,
|
|
226
151
|
});
|
|
227
152
|
}
|
|
@@ -229,75 +154,49 @@ function parseSteps(value: unknown): {
|
|
|
229
154
|
}
|
|
230
155
|
|
|
231
156
|
function parseWorkflowMaxConcurrency(value: unknown): number | undefined {
|
|
232
|
-
if (typeof value !== "number" || !Number.isInteger(value) || value < 1)
|
|
233
|
-
return undefined;
|
|
157
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 1) return undefined;
|
|
234
158
|
return value;
|
|
235
159
|
}
|
|
236
160
|
|
|
237
|
-
function findResource(
|
|
238
|
-
ctx: ManagementContext,
|
|
239
|
-
resource: "agent" | "team" | "workflow",
|
|
240
|
-
name: string,
|
|
241
|
-
scope?: string,
|
|
242
|
-
): MutableResource[] {
|
|
161
|
+
function findResource(ctx: ManagementContext, resource: "agent" | "team" | "workflow", name: string, scope?: string): MutableResource[] {
|
|
243
162
|
const normalized = sanitizeName(name);
|
|
244
163
|
const sourceMatches = (item: { name: string; source: ResourceSource }) =>
|
|
245
|
-
(scope === "user" || scope === "project"
|
|
246
|
-
? item.source === scope
|
|
247
|
-
: item.source !== "builtin") && item.name === normalized;
|
|
164
|
+
(scope === "user" || scope === "project" ? item.source === scope : item.source !== "builtin") && item.name === normalized;
|
|
248
165
|
// Search in the correct scope array directly to avoid allAgents shadowing issue.
|
|
249
166
|
if (resource === "agent") {
|
|
250
167
|
const discovery = discoverAgents(ctx.cwd);
|
|
251
168
|
const pool =
|
|
252
|
-
scope === "user"
|
|
253
|
-
? discovery.user
|
|
254
|
-
: scope === "project"
|
|
255
|
-
? discovery.project
|
|
256
|
-
: [...discovery.builtin, ...discovery.user];
|
|
169
|
+
scope === "user" ? discovery.user : scope === "project" ? discovery.project : [...discovery.builtin, ...discovery.user];
|
|
257
170
|
return pool.filter(sourceMatches);
|
|
258
171
|
}
|
|
259
172
|
if (resource === "team") {
|
|
260
173
|
const discovery = discoverTeams(ctx.cwd);
|
|
261
174
|
const pool =
|
|
262
|
-
scope === "user"
|
|
263
|
-
? discovery.user
|
|
264
|
-
: scope === "project"
|
|
265
|
-
? discovery.project
|
|
266
|
-
: [...discovery.builtin, ...discovery.user];
|
|
175
|
+
scope === "user" ? discovery.user : scope === "project" ? discovery.project : [...discovery.builtin, ...discovery.user];
|
|
267
176
|
return pool.filter(sourceMatches);
|
|
268
177
|
}
|
|
269
178
|
{
|
|
270
179
|
const discovery = discoverWorkflows(ctx.cwd);
|
|
271
180
|
const pool =
|
|
272
|
-
scope === "user"
|
|
273
|
-
? discovery.user
|
|
274
|
-
: scope === "project"
|
|
275
|
-
? discovery.project
|
|
276
|
-
: [...discovery.builtin, ...discovery.user];
|
|
181
|
+
scope === "user" ? discovery.user : scope === "project" ? discovery.project : [...discovery.builtin, ...discovery.user];
|
|
277
182
|
return pool.filter(sourceMatches);
|
|
278
183
|
}
|
|
279
184
|
}
|
|
280
185
|
|
|
281
186
|
// Note: only checks agent→team references and defaultWorkflow. Does not detect
|
|
282
187
|
// workflow-step→agent/team references or team name in workflow metadata.
|
|
283
|
-
function findReferences(
|
|
284
|
-
ctx: ManagementContext,
|
|
285
|
-
resource: "agent" | "team" | "workflow",
|
|
286
|
-
name: string,
|
|
287
|
-
): string[] {
|
|
188
|
+
function findReferences(ctx: ManagementContext, resource: "agent" | "team" | "workflow", name: string): string[] {
|
|
288
189
|
const refs: string[] = [];
|
|
289
190
|
if (resource === "agent") {
|
|
290
191
|
for (const team of allTeams(discoverTeams(ctx.cwd))) {
|
|
291
192
|
for (const role of team.roles) {
|
|
292
|
-
if (role.agent === name)
|
|
293
|
-
refs.push(`team '${team.name}' role '${role.name}'`);
|
|
193
|
+
if (role.agent === name) refs.push(`team '${team.name}' role '${role.name}'`);
|
|
294
194
|
}
|
|
295
195
|
}
|
|
296
196
|
}
|
|
297
197
|
if (resource === "workflow") {
|
|
298
198
|
for (const team of allTeams(discoverTeams(ctx.cwd))) {
|
|
299
|
-
if (team.defaultWorkflow === name)
|
|
300
|
-
refs.push(`team '${team.name}' defaultWorkflow`);
|
|
199
|
+
if (team.defaultWorkflow === name) refs.push(`team '${team.name}' defaultWorkflow`);
|
|
301
200
|
}
|
|
302
201
|
}
|
|
303
202
|
return refs;
|
|
@@ -332,18 +231,12 @@ function updateReferencesForRename(
|
|
|
332
231
|
if (oldName === newName) return [];
|
|
333
232
|
if (resource !== "agent" && resource !== "workflow") return [];
|
|
334
233
|
const changed: string[] = [];
|
|
335
|
-
for (const team of allTeams(discoverTeams(ctx.cwd)).filter(
|
|
336
|
-
(candidate) => candidate.source === scope,
|
|
337
|
-
)) {
|
|
234
|
+
for (const team of allTeams(discoverTeams(ctx.cwd)).filter((candidate) => candidate.source === scope)) {
|
|
338
235
|
let updated = false;
|
|
339
236
|
let nextTeam = team;
|
|
340
237
|
if (resource === "agent") {
|
|
341
|
-
const roles = team.roles.map((role) =>
|
|
342
|
-
|
|
343
|
-
);
|
|
344
|
-
updated = roles.some(
|
|
345
|
-
(role, index) => role.agent !== team.roles[index]!.agent,
|
|
346
|
-
);
|
|
238
|
+
const roles = team.roles.map((role) => (role.agent === oldName ? { ...role, agent: newName } : role));
|
|
239
|
+
updated = roles.some((role, index) => role.agent !== team.roles[index]!.agent);
|
|
347
240
|
nextTeam = { ...team, roles };
|
|
348
241
|
}
|
|
349
242
|
if (resource === "workflow" && team.defaultWorkflow === oldName) {
|
|
@@ -359,9 +252,7 @@ function updateReferencesForRename(
|
|
|
359
252
|
}
|
|
360
253
|
// L12 fix: also update workflow step role references when renaming agents.
|
|
361
254
|
// Workflow files use `role:` to reference agent roles, not agent names.
|
|
362
|
-
for (const workflow of allWorkflows(discoverWorkflows(ctx.cwd)).filter(
|
|
363
|
-
(w) => w.source === scope,
|
|
364
|
-
)) {
|
|
255
|
+
for (const workflow of allWorkflows(discoverWorkflows(ctx.cwd)).filter((w) => w.source === scope)) {
|
|
365
256
|
let updated = false;
|
|
366
257
|
const newSteps = workflow.steps.map((step) => {
|
|
367
258
|
if (step.role === oldName) {
|
|
@@ -374,28 +265,16 @@ function updateReferencesForRename(
|
|
|
374
265
|
changed.push(workflow.filePath);
|
|
375
266
|
if (!dryRun) {
|
|
376
267
|
backupFile(workflow.filePath);
|
|
377
|
-
fs.writeFileSync(
|
|
378
|
-
workflow.filePath,
|
|
379
|
-
serializeWorkflow({ ...workflow, steps: newSteps }),
|
|
380
|
-
"utf-8",
|
|
381
|
-
);
|
|
268
|
+
fs.writeFileSync(workflow.filePath, serializeWorkflow({ ...workflow, steps: newSteps }), "utf-8");
|
|
382
269
|
}
|
|
383
270
|
}
|
|
384
271
|
// L12 fix: update agent references in test fixtures.
|
|
385
|
-
const testDir =
|
|
386
|
-
scope === "user"
|
|
387
|
-
? path.join(projectCrewRoot(ctx.cwd), "test")
|
|
388
|
-
: path.join(ctx.cwd, "test", "fixtures");
|
|
272
|
+
const testDir = scope === "user" ? path.join(projectCrewRoot(ctx.cwd), "test") : path.join(ctx.cwd, "test", "fixtures");
|
|
389
273
|
if (fs.existsSync(testDir)) {
|
|
390
274
|
for (const fixture of walkTsFiles(testDir)) {
|
|
391
275
|
const content = fs.readFileSync(fixture, "utf-8");
|
|
392
276
|
if (!content.includes(oldName)) continue;
|
|
393
|
-
const agentPattern = new RegExp(
|
|
394
|
-
"([\"'\\`]agent[=\"':\\s]*)" +
|
|
395
|
-
escapeRegex(oldName) +
|
|
396
|
-
"([\"'\\`]|\\s)",
|
|
397
|
-
"g",
|
|
398
|
-
);
|
|
277
|
+
const agentPattern = new RegExp("([\"'\\`]agent[=\"':\\s]*)" + escapeRegex(oldName) + "([\"'\\`]|\\s)", "g");
|
|
399
278
|
const newContent = content.replace(agentPattern, `$1${newName}$2`);
|
|
400
279
|
if (newContent !== content) {
|
|
401
280
|
changed.push(fixture);
|
|
@@ -408,80 +287,42 @@ function updateReferencesForRename(
|
|
|
408
287
|
return changed;
|
|
409
288
|
}
|
|
410
289
|
|
|
411
|
-
function resolveMutable(
|
|
412
|
-
ctx: ManagementContext,
|
|
413
|
-
params: TeamToolParamsValue,
|
|
414
|
-
): { resource?: MutableResource; error?: PiTeamsToolResult } {
|
|
290
|
+
function resolveMutable(ctx: ManagementContext, params: TeamToolParamsValue): { resource?: MutableResource; error?: PiTeamsToolResult } {
|
|
415
291
|
if (!params.resource)
|
|
416
292
|
return {
|
|
417
|
-
error: result(
|
|
418
|
-
"resource is required for update/delete.",
|
|
419
|
-
"error",
|
|
420
|
-
true,
|
|
421
|
-
),
|
|
293
|
+
error: result("resource is required for update/delete.", "error", true),
|
|
422
294
|
};
|
|
423
|
-
const name =
|
|
424
|
-
params.resource === "agent"
|
|
425
|
-
? params.agent
|
|
426
|
-
: params.resource === "team"
|
|
427
|
-
? params.team
|
|
428
|
-
: params.workflow;
|
|
295
|
+
const name = params.resource === "agent" ? params.agent : params.resource === "team" ? params.team : params.workflow;
|
|
429
296
|
if (!name)
|
|
430
297
|
return {
|
|
431
|
-
error: result(
|
|
432
|
-
`${params.resource} name is required.`,
|
|
433
|
-
"error",
|
|
434
|
-
true,
|
|
435
|
-
),
|
|
298
|
+
error: result(`${params.resource} name is required.`, "error", true),
|
|
436
299
|
};
|
|
437
300
|
const matches = findResource(ctx, params.resource, name, params.scope);
|
|
438
301
|
if (matches.length === 0)
|
|
439
302
|
return {
|
|
440
|
-
error: result(
|
|
441
|
-
`${params.resource} '${name}' not found in mutable user/project scopes.`,
|
|
442
|
-
"error",
|
|
443
|
-
true,
|
|
444
|
-
),
|
|
303
|
+
error: result(`${params.resource} '${name}' not found in mutable user/project scopes.`, "error", true),
|
|
445
304
|
};
|
|
446
305
|
if (matches.length > 1)
|
|
447
306
|
return {
|
|
448
|
-
error: result(
|
|
449
|
-
`${params.resource} '${name}' exists in multiple scopes. Specify scope: 'user' or 'project'.`,
|
|
450
|
-
"error",
|
|
451
|
-
true,
|
|
452
|
-
),
|
|
307
|
+
error: result(`${params.resource} '${name}' exists in multiple scopes. Specify scope: 'user' or 'project'.`, "error", true),
|
|
453
308
|
};
|
|
454
309
|
return { resource: matches[0] };
|
|
455
310
|
}
|
|
456
311
|
|
|
457
|
-
export function handleCreate(
|
|
458
|
-
params
|
|
459
|
-
ctx: ManagementContext,
|
|
460
|
-
): PiTeamsToolResult {
|
|
461
|
-
if (!params.resource)
|
|
462
|
-
return result("resource is required for create.", "error", true);
|
|
312
|
+
export function handleCreate(params: TeamToolParamsValue, ctx: ManagementContext): PiTeamsToolResult {
|
|
313
|
+
if (!params.resource) return result("resource is required for create.", "error", true);
|
|
463
314
|
const parsed = parseConfigObject(params.config);
|
|
464
315
|
if (parsed.error) return result(parsed.error, "error", true);
|
|
465
316
|
const cfg = parsed.value!;
|
|
466
317
|
const nameValue = requireString(cfg.name, "config.name");
|
|
467
318
|
if (nameValue.error) return result(nameValue.error, "error", true);
|
|
468
|
-
const descriptionValue = requireString(
|
|
469
|
-
|
|
470
|
-
"config.description",
|
|
471
|
-
);
|
|
472
|
-
if (descriptionValue.error)
|
|
473
|
-
return result(descriptionValue.error, "error", true);
|
|
319
|
+
const descriptionValue = requireString(cfg.description, "config.description");
|
|
320
|
+
if (descriptionValue.error) return result(descriptionValue.error, "error", true);
|
|
474
321
|
const name = sanitizeName(nameValue.value!);
|
|
475
|
-
if (!name)
|
|
476
|
-
return result(
|
|
477
|
-
"config.name is invalid after sanitization.",
|
|
478
|
-
"error",
|
|
479
|
-
true,
|
|
480
|
-
);
|
|
322
|
+
if (!name) return result("config.name is invalid after sanitization.", "error", true);
|
|
481
323
|
const scope = cfg.scope === "project" ? "project" : "user";
|
|
482
324
|
const filePath = targetPath(ctx, params.resource, scope, name);
|
|
483
|
-
if (fs.existsSync(filePath))
|
|
484
|
-
return result(`File already exists: ${filePath}`, "error", true);
|
|
325
|
+
if (fs.existsSync(filePath)) return result(`File already exists: ${filePath}`, "error", true);
|
|
485
326
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
486
327
|
|
|
487
328
|
let content: string;
|
|
@@ -491,19 +332,14 @@ export function handleCreate(
|
|
|
491
332
|
description: descriptionValue.value!,
|
|
492
333
|
source: scope,
|
|
493
334
|
filePath,
|
|
494
|
-
systemPrompt:
|
|
495
|
-
typeof cfg.systemPrompt === "string" ? cfg.systemPrompt : "",
|
|
335
|
+
systemPrompt: typeof cfg.systemPrompt === "string" ? cfg.systemPrompt : "",
|
|
496
336
|
model: typeof cfg.model === "string" ? cfg.model : undefined,
|
|
497
337
|
fallbackModels: parseStringArray(cfg.fallbackModels),
|
|
498
|
-
thinking:
|
|
499
|
-
typeof cfg.thinking === "string" ? cfg.thinking : undefined,
|
|
338
|
+
thinking: typeof cfg.thinking === "string" ? cfg.thinking : undefined,
|
|
500
339
|
tools: parseStringArray(cfg.tools),
|
|
501
|
-
extensions: hasOwn(cfg, "extensions")
|
|
502
|
-
? (parseStringArray(cfg.extensions) ?? [])
|
|
503
|
-
: undefined,
|
|
340
|
+
extensions: hasOwn(cfg, "extensions") ? (parseStringArray(cfg.extensions) ?? []) : undefined,
|
|
504
341
|
skills: parseStringArray(cfg.skills),
|
|
505
|
-
systemPromptMode:
|
|
506
|
-
cfg.systemPromptMode === "append" ? "append" : "replace",
|
|
342
|
+
systemPromptMode: cfg.systemPromptMode === "append" ? "append" : "replace",
|
|
507
343
|
inheritProjectContext: cfg.inheritProjectContext === true,
|
|
508
344
|
inheritSkills: cfg.inheritSkills === true,
|
|
509
345
|
routing: parseRouting(cfg),
|
|
@@ -518,16 +354,10 @@ export function handleCreate(
|
|
|
518
354
|
source: scope,
|
|
519
355
|
filePath,
|
|
520
356
|
roles: parsedRoles.roles!,
|
|
521
|
-
defaultWorkflow:
|
|
522
|
-
|
|
523
|
-
? sanitizeName(cfg.defaultWorkflow)
|
|
524
|
-
: undefined,
|
|
525
|
-
workspaceMode:
|
|
526
|
-
cfg.workspaceMode === "worktree" ? "worktree" : "single",
|
|
357
|
+
defaultWorkflow: typeof cfg.defaultWorkflow === "string" ? sanitizeName(cfg.defaultWorkflow) : undefined,
|
|
358
|
+
workspaceMode: cfg.workspaceMode === "worktree" ? "worktree" : "single",
|
|
527
359
|
maxConcurrency:
|
|
528
|
-
typeof cfg.maxConcurrency === "number" &&
|
|
529
|
-
Number.isInteger(cfg.maxConcurrency) &&
|
|
530
|
-
cfg.maxConcurrency > 0
|
|
360
|
+
typeof cfg.maxConcurrency === "number" && Number.isInteger(cfg.maxConcurrency) && cfg.maxConcurrency > 0
|
|
531
361
|
? cfg.maxConcurrency
|
|
532
362
|
: undefined,
|
|
533
363
|
routing: parseRouting(cfg),
|
|
@@ -545,10 +375,7 @@ export function handleCreate(
|
|
|
545
375
|
});
|
|
546
376
|
}
|
|
547
377
|
|
|
548
|
-
if (params.dryRun)
|
|
549
|
-
return result(
|
|
550
|
-
`[dry-run] Would create ${params.resource} '${name}' at ${filePath}:\n\n${content}`,
|
|
551
|
-
);
|
|
378
|
+
if (params.dryRun) return result(`[dry-run] Would create ${params.resource} '${name}' at ${filePath}:\n\n${content}`);
|
|
552
379
|
try {
|
|
553
380
|
fs.writeFileSync(filePath, content, "utf-8");
|
|
554
381
|
} catch (writeError) {
|
|
@@ -561,29 +388,18 @@ export function handleCreate(
|
|
|
561
388
|
return result(`Created ${params.resource} '${name}' at ${filePath}.`);
|
|
562
389
|
}
|
|
563
390
|
|
|
564
|
-
export function handleUpdate(
|
|
565
|
-
params: TeamToolParamsValue,
|
|
566
|
-
ctx: ManagementContext,
|
|
567
|
-
): PiTeamsToolResult {
|
|
391
|
+
export function handleUpdate(params: TeamToolParamsValue, ctx: ManagementContext): PiTeamsToolResult {
|
|
568
392
|
const resolved = resolveMutable(ctx, params);
|
|
569
393
|
if (resolved.error) return resolved.error;
|
|
570
394
|
const parsed = parseConfigObject(params.config);
|
|
571
395
|
if (parsed.error) return result(parsed.error, "error", true);
|
|
572
396
|
const cfg = parsed.value!;
|
|
573
397
|
const current = resolved.resource!;
|
|
574
|
-
const nextName = hasOwn(cfg, "name")
|
|
575
|
-
|
|
576
|
-
: current.name;
|
|
577
|
-
if (!nextName)
|
|
578
|
-
return result(
|
|
579
|
-
"config.name is invalid after sanitization.",
|
|
580
|
-
"error",
|
|
581
|
-
true,
|
|
582
|
-
);
|
|
398
|
+
const nextName = hasOwn(cfg, "name") ? sanitizeName(String(cfg.name ?? "")) : current.name;
|
|
399
|
+
if (!nextName) return result("config.name is invalid after sanitization.", "error", true);
|
|
583
400
|
const source = current.source === "project" ? "project" : "user";
|
|
584
401
|
const nextPath = targetPath(ctx, params.resource!, source, nextName);
|
|
585
|
-
if (nextPath !== current.filePath && fs.existsSync(nextPath))
|
|
586
|
-
return result(`Target file already exists: ${nextPath}`, "error", true);
|
|
402
|
+
if (nextPath !== current.filePath && fs.existsSync(nextPath)) return result(`Target file already exists: ${nextPath}`, "error", true);
|
|
587
403
|
|
|
588
404
|
let content: string;
|
|
589
405
|
if (params.resource === "agent") {
|
|
@@ -592,50 +408,22 @@ export function handleUpdate(
|
|
|
592
408
|
...agent,
|
|
593
409
|
name: nextName,
|
|
594
410
|
filePath: nextPath,
|
|
595
|
-
description:
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
systemPrompt:
|
|
600
|
-
typeof cfg.systemPrompt === "string"
|
|
601
|
-
? cfg.systemPrompt
|
|
602
|
-
: agent.systemPrompt,
|
|
603
|
-
model: hasOwn(cfg, "model")
|
|
604
|
-
? typeof cfg.model === "string" && cfg.model.trim()
|
|
605
|
-
? cfg.model.trim()
|
|
606
|
-
: undefined
|
|
607
|
-
: agent.model,
|
|
608
|
-
fallbackModels: hasOwn(cfg, "fallbackModels")
|
|
609
|
-
? parseStringArray(cfg.fallbackModels)
|
|
610
|
-
: agent.fallbackModels,
|
|
411
|
+
description: typeof cfg.description === "string" && cfg.description.trim() ? cfg.description.trim() : agent.description,
|
|
412
|
+
systemPrompt: typeof cfg.systemPrompt === "string" ? cfg.systemPrompt : agent.systemPrompt,
|
|
413
|
+
model: hasOwn(cfg, "model") ? (typeof cfg.model === "string" && cfg.model.trim() ? cfg.model.trim() : undefined) : agent.model,
|
|
414
|
+
fallbackModels: hasOwn(cfg, "fallbackModels") ? parseStringArray(cfg.fallbackModels) : agent.fallbackModels,
|
|
611
415
|
thinking: hasOwn(cfg, "thinking")
|
|
612
416
|
? typeof cfg.thinking === "string" && cfg.thinking.trim()
|
|
613
417
|
? cfg.thinking.trim()
|
|
614
418
|
: undefined
|
|
615
419
|
: agent.thinking,
|
|
616
|
-
tools: hasOwn(cfg, "tools")
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
extensions: hasOwn(cfg, "extensions")
|
|
620
|
-
? (parseStringArray(cfg.extensions) ?? [])
|
|
621
|
-
: agent.extensions,
|
|
622
|
-
skills: hasOwn(cfg, "skills")
|
|
623
|
-
? parseStringArray(cfg.skills)
|
|
624
|
-
: agent.skills,
|
|
420
|
+
tools: hasOwn(cfg, "tools") ? parseStringArray(cfg.tools) : agent.tools,
|
|
421
|
+
extensions: hasOwn(cfg, "extensions") ? (parseStringArray(cfg.extensions) ?? []) : agent.extensions,
|
|
422
|
+
skills: hasOwn(cfg, "skills") ? parseStringArray(cfg.skills) : agent.skills,
|
|
625
423
|
systemPromptMode:
|
|
626
|
-
cfg.systemPromptMode === "append"
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
? "replace"
|
|
630
|
-
: agent.systemPromptMode,
|
|
631
|
-
inheritProjectContext:
|
|
632
|
-
typeof cfg.inheritProjectContext === "boolean"
|
|
633
|
-
? cfg.inheritProjectContext
|
|
634
|
-
: agent.inheritProjectContext,
|
|
635
|
-
inheritSkills:
|
|
636
|
-
typeof cfg.inheritSkills === "boolean"
|
|
637
|
-
? cfg.inheritSkills
|
|
638
|
-
: agent.inheritSkills,
|
|
424
|
+
cfg.systemPromptMode === "append" ? "append" : cfg.systemPromptMode === "replace" ? "replace" : agent.systemPromptMode,
|
|
425
|
+
inheritProjectContext: typeof cfg.inheritProjectContext === "boolean" ? cfg.inheritProjectContext : agent.inheritProjectContext,
|
|
426
|
+
inheritSkills: typeof cfg.inheritSkills === "boolean" ? cfg.inheritSkills : agent.inheritSkills,
|
|
639
427
|
routing: parseRouting(cfg, agent.routing),
|
|
640
428
|
});
|
|
641
429
|
} else if (params.resource === "team") {
|
|
@@ -643,34 +431,23 @@ export function handleUpdate(
|
|
|
643
431
|
let roles = team.roles;
|
|
644
432
|
if (hasOwn(cfg, "roles")) {
|
|
645
433
|
const parsedRoles = parseRoles(cfg.roles);
|
|
646
|
-
if (parsedRoles.error)
|
|
647
|
-
return result(parsedRoles.error, "error", true);
|
|
434
|
+
if (parsedRoles.error) return result(parsedRoles.error, "error", true);
|
|
648
435
|
roles = parsedRoles.roles!;
|
|
649
436
|
}
|
|
650
437
|
content = serializeTeam({
|
|
651
438
|
...team,
|
|
652
439
|
name: nextName,
|
|
653
440
|
filePath: nextPath,
|
|
654
|
-
description:
|
|
655
|
-
typeof cfg.description === "string" && cfg.description.trim()
|
|
656
|
-
? cfg.description.trim()
|
|
657
|
-
: team.description,
|
|
441
|
+
description: typeof cfg.description === "string" && cfg.description.trim() ? cfg.description.trim() : team.description,
|
|
658
442
|
roles,
|
|
659
443
|
defaultWorkflow: hasOwn(cfg, "defaultWorkflow")
|
|
660
444
|
? typeof cfg.defaultWorkflow === "string"
|
|
661
445
|
? sanitizeName(cfg.defaultWorkflow)
|
|
662
446
|
: undefined
|
|
663
447
|
: team.defaultWorkflow,
|
|
664
|
-
workspaceMode:
|
|
665
|
-
cfg.workspaceMode === "worktree"
|
|
666
|
-
? "worktree"
|
|
667
|
-
: cfg.workspaceMode === "single"
|
|
668
|
-
? "single"
|
|
669
|
-
: team.workspaceMode,
|
|
448
|
+
workspaceMode: cfg.workspaceMode === "worktree" ? "worktree" : cfg.workspaceMode === "single" ? "single" : team.workspaceMode,
|
|
670
449
|
maxConcurrency:
|
|
671
|
-
typeof cfg.maxConcurrency === "number" &&
|
|
672
|
-
Number.isInteger(cfg.maxConcurrency) &&
|
|
673
|
-
cfg.maxConcurrency > 0
|
|
450
|
+
typeof cfg.maxConcurrency === "number" && Number.isInteger(cfg.maxConcurrency) && cfg.maxConcurrency > 0
|
|
674
451
|
? cfg.maxConcurrency
|
|
675
452
|
: team.maxConcurrency,
|
|
676
453
|
routing: parseRouting(cfg, team.routing),
|
|
@@ -680,34 +457,21 @@ export function handleUpdate(
|
|
|
680
457
|
let steps = workflow.steps;
|
|
681
458
|
if (hasOwn(cfg, "steps")) {
|
|
682
459
|
const parsedSteps = parseSteps(cfg.steps);
|
|
683
|
-
if (parsedSteps.error)
|
|
684
|
-
return result(parsedSteps.error, "error", true);
|
|
460
|
+
if (parsedSteps.error) return result(parsedSteps.error, "error", true);
|
|
685
461
|
steps = parsedSteps.steps!;
|
|
686
462
|
}
|
|
687
463
|
content = serializeWorkflow({
|
|
688
464
|
...workflow,
|
|
689
465
|
name: nextName,
|
|
690
466
|
filePath: nextPath,
|
|
691
|
-
description:
|
|
692
|
-
|
|
693
|
-
? cfg.description.trim()
|
|
694
|
-
: workflow.description,
|
|
695
|
-
maxConcurrency: hasOwn(cfg, "maxConcurrency")
|
|
696
|
-
? parseWorkflowMaxConcurrency(cfg.maxConcurrency)
|
|
697
|
-
: workflow.maxConcurrency,
|
|
467
|
+
description: typeof cfg.description === "string" && cfg.description.trim() ? cfg.description.trim() : workflow.description,
|
|
468
|
+
maxConcurrency: hasOwn(cfg, "maxConcurrency") ? parseWorkflowMaxConcurrency(cfg.maxConcurrency) : workflow.maxConcurrency,
|
|
698
469
|
steps,
|
|
699
470
|
});
|
|
700
471
|
}
|
|
701
472
|
|
|
702
473
|
const referenceUpdates = params.updateReferences
|
|
703
|
-
? updateReferencesForRename(
|
|
704
|
-
ctx,
|
|
705
|
-
params.resource!,
|
|
706
|
-
current.name,
|
|
707
|
-
nextName,
|
|
708
|
-
source,
|
|
709
|
-
true,
|
|
710
|
-
)
|
|
474
|
+
? updateReferencesForRename(ctx, params.resource!, current.name, nextName, source, true)
|
|
711
475
|
: [];
|
|
712
476
|
if (params.dryRun) {
|
|
713
477
|
return result(
|
|
@@ -716,13 +480,7 @@ export function handleUpdate(
|
|
|
716
480
|
"",
|
|
717
481
|
content,
|
|
718
482
|
...(referenceUpdates.length
|
|
719
|
-
? [
|
|
720
|
-
"",
|
|
721
|
-
"Would update references in:",
|
|
722
|
-
...referenceUpdates.map(
|
|
723
|
-
(filePath) => `- ${filePath}`,
|
|
724
|
-
),
|
|
725
|
-
]
|
|
483
|
+
? ["", "Would update references in:", ...referenceUpdates.map((filePath) => `- ${filePath}`)]
|
|
726
484
|
: []),
|
|
727
485
|
].join("\n"),
|
|
728
486
|
);
|
|
@@ -750,36 +508,20 @@ export function handleUpdate(
|
|
|
750
508
|
);
|
|
751
509
|
}
|
|
752
510
|
const updatedRefs = params.updateReferences
|
|
753
|
-
? updateReferencesForRename(
|
|
754
|
-
ctx,
|
|
755
|
-
params.resource!,
|
|
756
|
-
current.name,
|
|
757
|
-
nextName,
|
|
758
|
-
source,
|
|
759
|
-
false,
|
|
760
|
-
)
|
|
511
|
+
? updateReferencesForRename(ctx, params.resource!, current.name, nextName, source, false)
|
|
761
512
|
: [];
|
|
762
513
|
return result(
|
|
763
514
|
[
|
|
764
515
|
`Updated ${params.resource} at ${nextPath}. Backup: ${backupPath}.`,
|
|
765
|
-
...(updatedRefs.length
|
|
766
|
-
? [
|
|
767
|
-
"Updated references:",
|
|
768
|
-
...updatedRefs.map((filePath) => `- ${filePath}`),
|
|
769
|
-
]
|
|
770
|
-
: []),
|
|
516
|
+
...(updatedRefs.length ? ["Updated references:", ...updatedRefs.map((filePath) => `- ${filePath}`)] : []),
|
|
771
517
|
].join("\n"),
|
|
772
518
|
);
|
|
773
519
|
}
|
|
774
520
|
|
|
775
|
-
export function handleDelete(
|
|
776
|
-
params: TeamToolParamsValue,
|
|
777
|
-
ctx: ManagementContext,
|
|
778
|
-
): PiTeamsToolResult {
|
|
521
|
+
export function handleDelete(params: TeamToolParamsValue, ctx: ManagementContext): PiTeamsToolResult {
|
|
779
522
|
const intentError = enforceDestructiveIntent("delete", params, ctx.config);
|
|
780
523
|
if (intentError) return intentError;
|
|
781
|
-
if (!params.confirm)
|
|
782
|
-
return result("delete requires confirm: true.", "error", true);
|
|
524
|
+
if (!params.confirm) return result("delete requires confirm: true.", "error", true);
|
|
783
525
|
const resolved = resolveMutable(ctx, params);
|
|
784
526
|
if (resolved.error) return resolved.error;
|
|
785
527
|
const refs = findReferences(ctx, params.resource!, resolved.resource!.name);
|
|
@@ -804,7 +546,5 @@ export function handleDelete(
|
|
|
804
546
|
true,
|
|
805
547
|
);
|
|
806
548
|
}
|
|
807
|
-
return result(
|
|
808
|
-
`Deleted ${params.resource} at ${resolved.resource!.filePath}. Backup: ${backupPath}.`,
|
|
809
|
-
);
|
|
549
|
+
return result(`Deleted ${params.resource} at ${resolved.resource!.filePath}. Backup: ${backupPath}.`);
|
|
810
550
|
}
|