pi-crew 0.9.56 → 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.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +29 -0
- package/README.md +53 -5
- package/dist/index.mjs +5350 -4350
- package/docs/README.md +54 -0
- package/package.json +12 -12
- package/skills/real-test-pi-crew/SKILL.md +93 -3
- package/src/agents/discover-agents.ts +68 -10
- package/src/benchmark/feedback-loop.ts +1 -1
- package/src/config/config.ts +2 -1
- package/src/config/types.ts +12 -0
- package/src/extension/action-suggestions.ts +16 -63
- package/src/extension/async-notifier.ts +3 -3
- package/src/extension/command-completions.ts +2 -2
- package/src/extension/crew-cleanup.ts +3 -3
- package/src/extension/crew-vibes/footer.ts +4 -2
- package/src/extension/cross-extension-rpc.ts +10 -5
- package/src/extension/knowledge-injection.ts +57 -10
- package/src/extension/register.ts +2 -2
- package/src/extension/registration/artifact-cleanup.ts +41 -3
- package/src/extension/registration/commands.ts +4 -4
- package/src/extension/registration/context-builder.ts +10 -10
- package/src/extension/registration/crash-recovery-cache.ts +3 -3
- package/src/extension/registration/foreground-run-controller.ts +1 -1
- package/src/extension/registration/lazy-configurers.ts +2 -2
- package/src/extension/registration/lifecycle-handlers.ts +12 -12
- package/src/extension/registration/lifecycle.ts +2 -2
- package/src/extension/registration/observability.ts +2 -2
- package/src/extension/registration/registration-types.ts +3 -3
- package/src/extension/registration/runtime-cleanup.ts +1 -1
- package/src/extension/registration/subagent-helpers.ts +2 -2
- package/src/extension/registration/subagent-manager-setup.ts +2 -2
- package/src/extension/registration/subagent-tools.ts +21 -16
- package/src/extension/registration/team-tool.ts +108 -17
- package/src/extension/registration/viewers.ts +3 -4
- package/src/extension/registration/wire-cross-extension.ts +7 -7
- package/src/extension/rpc-hmac.ts +3 -2
- package/src/extension/run-bundle-schema.ts +13 -4
- package/src/extension/run-export.ts +2 -2
- package/src/extension/run-index.ts +2 -3
- package/src/extension/run-maintenance.ts +57 -1
- package/src/extension/team-manager-command.ts +3 -1
- package/src/extension/team-tool/anchor.ts +8 -2
- package/src/extension/team-tool/api.ts +117 -39
- package/src/extension/team-tool/cancel.ts +23 -8
- package/src/extension/team-tool/chain-executor.ts +1 -1
- package/src/extension/team-tool/dispatch/automate.ts +17 -2
- package/src/extension/team-tool/dispatch/control.ts +17 -2
- package/src/extension/team-tool/dispatch/manage.ts +34 -2
- package/src/extension/team-tool/dispatch/run.ts +17 -2
- package/src/extension/team-tool/dispatch/status.ts +37 -5
- package/src/extension/team-tool/doctor.ts +2 -2
- package/src/extension/team-tool/explain.ts +1 -1
- package/src/extension/team-tool/goal-wrap.ts +5 -5
- package/src/extension/team-tool/goal.ts +30 -9
- package/src/extension/team-tool/handle-schedule.ts +37 -19
- package/src/extension/team-tool/inspect.ts +21 -5
- package/src/extension/team-tool/lifecycle-actions.ts +53 -10
- package/src/extension/team-tool/parallel-dispatch.ts +14 -5
- package/src/extension/team-tool/param-error.ts +24 -0
- package/src/extension/team-tool/respond.ts +20 -6
- package/src/extension/team-tool/run.ts +27 -17
- package/src/extension/team-tool/status.ts +11 -5
- package/src/extension/team-tool.ts +26 -19
- package/src/hooks/registry.ts +1 -1
- package/src/i18n.ts +22 -0
- package/src/observability/event-bus.ts +1 -1
- package/src/prompt/prompt-runtime.ts +2 -2
- package/src/runtime/README.md +35 -0
- package/src/runtime/agent-control.ts +1 -1
- package/src/runtime/anchor-manager.ts +0 -2
- package/src/runtime/async-runner.ts +1 -1
- package/src/runtime/attention-events.ts +1 -1
- package/src/runtime/auto-summarize.ts +0 -2
- package/src/runtime/background-runner.ts +103 -30
- package/src/runtime/{crew-broker-child.ts → broker/crew-broker-child.ts} +2 -2
- package/src/runtime/{crew-broker-client.ts → broker/crew-broker-client.ts} +4 -7
- package/src/runtime/{crew-broker.ts → broker/crew-broker.ts} +13 -21
- package/src/runtime/chain-runner.ts +50 -5
- package/src/runtime/{child-pi-constants.ts → child-pi/child-pi-constants.ts} +1 -1
- package/src/runtime/{child-pi-kill.ts → child-pi/child-pi-kill.ts} +3 -3
- package/src/runtime/{child-pi-spawn.ts → child-pi/child-pi-spawn.ts} +28 -12
- package/src/runtime/{child-pi-steering.ts → child-pi/child-pi-steering.ts} +1 -1
- package/src/runtime/{child-pi-streams.ts → child-pi/child-pi-streams.ts} +11 -4
- package/src/runtime/{child-pi-transcript.ts → child-pi/child-pi-transcript.ts} +6 -6
- package/src/runtime/{child-pi.ts → child-pi/child-pi.ts} +28 -72
- package/src/runtime/{compact-stages → compaction/compact-stages}/bounded-tail.ts +1 -1
- package/src/runtime/{compact-stages → compaction/compact-stages}/index.ts +2 -2
- package/src/runtime/{compaction-summary.ts → compaction/compaction-summary.ts} +3 -3
- package/src/runtime/{tool-output-pruner.ts → compaction/tool-output-pruner.ts} +1 -1
- package/src/runtime/custom-tools/irc-tool.ts +2 -2
- package/src/runtime/delivery-coordinator.ts +0 -3
- package/src/runtime/diagnostic-export.ts +3 -3
- package/src/runtime/foreground-control.ts +1 -1
- package/src/runtime/foreground-watchdog.ts +1 -1
- package/src/runtime/{adaptive-plan.ts → goal-workflow/adaptive-plan.ts} +8 -8
- package/src/runtime/{dynamic-workflow-context.ts → goal-workflow/dynamic-workflow-context.ts} +16 -16
- package/src/runtime/{dynamic-workflow-runner.ts → goal-workflow/dynamic-workflow-runner.ts} +10 -10
- package/src/runtime/{goal-achievement.ts → goal-workflow/goal-achievement.ts} +3 -3
- package/src/runtime/{goal-evaluator.ts → goal-workflow/goal-evaluator.ts} +8 -8
- package/src/runtime/{goal-loop-runner.ts → goal-workflow/goal-loop-runner.ts} +27 -25
- package/src/runtime/{goal-state-store.ts → goal-workflow/goal-state-store.ts} +8 -8
- package/src/runtime/{plan-templates.ts → goal-workflow/plan-templates.ts} +1 -1
- package/src/runtime/group-join.ts +3 -3
- package/src/runtime/handoff-manager.ts +0 -2
- package/src/runtime/{heartbeat-watcher.ts → heartbeat/heartbeat-watcher.ts} +7 -7
- package/src/runtime/iteration-hooks.ts +1 -1
- package/src/runtime/{live-agent-control.ts → live-session/live-agent-control.ts} +2 -2
- package/src/runtime/{live-agent-manager.ts → live-session/live-agent-manager.ts} +4 -4
- package/src/runtime/{live-session-runtime.ts → live-session/live-session-runtime.ts} +39 -41
- package/src/runtime/manifest-cache.ts +1 -1
- package/src/runtime/{model-fallback.ts → model/model-fallback.ts} +1 -1
- package/src/runtime/{pi-args.ts → model/pi-args.ts} +20 -5
- package/src/runtime/model/provider-extensions.ts +116 -0
- package/src/runtime/{runtime-policy.ts → model/runtime-policy.ts} +2 -2
- package/src/runtime/{runtime-resolver.ts → model/runtime-resolver.ts} +3 -3
- package/src/runtime/{runtime-warmup.ts → model/runtime-warmup.ts} +8 -8
- package/src/runtime/orphan-worker-registry.ts +1 -1
- package/src/runtime/{progress-tracker.ts → output/progress-tracker.ts} +1 -1
- package/src/runtime/{result-extractor.ts → output/result-extractor.ts} +4 -4
- package/src/runtime/{sidechain-output.ts → output/sidechain-output.ts} +2 -2
- package/src/runtime/{stream-preview.ts → output/stream-preview.ts} +1 -1
- package/src/runtime/{streaming-output.ts → output/streaming-output.ts} +2 -2
- package/src/runtime/{tool-progress.ts → output/tool-progress.ts} +1 -1
- package/src/runtime/parent-guard.ts +30 -10
- package/src/runtime/pipeline-runner.ts +2 -2
- package/src/runtime/policy-engine.ts +2 -2
- package/src/runtime/{cancellation.ts → process/cancellation.ts} +1 -1
- package/src/runtime/{post-exit-stdio-guard.ts → process/post-exit-stdio-guard.ts} +1 -1
- package/src/runtime/{process-lifecycle.ts → process/process-lifecycle.ts} +3 -3
- package/src/runtime/{checkpoint.ts → recovery/checkpoint.ts} +4 -4
- package/src/runtime/{crash-recovery.ts → recovery/crash-recovery.ts} +93 -21
- package/src/runtime/{overflow-recovery.ts → recovery/overflow-recovery.ts} +1 -1
- package/src/runtime/{recovery-recipes.ts → recovery/recovery-recipes.ts} +1 -1
- package/src/runtime/{retry-executor.ts → recovery/retry-executor.ts} +2 -2
- package/src/runtime/{retry-runner.ts → recovery/retry-runner.ts} +2 -8
- package/src/runtime/run-tracker.ts +1 -1
- package/src/runtime/run-worker.ts +3 -3
- package/src/runtime/{coalesce-tasks.ts → scheduling/coalesce-tasks.ts} +3 -3
- package/src/runtime/{concurrency.ts → scheduling/concurrency.ts} +1 -1
- package/src/runtime/{parallel-research.ts → scheduling/parallel-research.ts} +4 -2
- package/src/runtime/{run-coalesced-task-group.ts → scheduling/run-coalesced-task-group.ts} +95 -36
- package/src/runtime/{task-graph-scheduler.ts → scheduling/task-graph-scheduler.ts} +1 -1
- package/src/runtime/session-resources.ts +1 -1
- package/src/runtime/settings-store.ts +1 -1
- package/src/runtime/single-agent-compose.ts +1 -0
- package/src/runtime/stale-reconciler.ts +1 -1
- package/src/runtime/subagent-manager.ts +1 -1
- package/src/runtime/supervisor-contact.ts +1 -1
- package/src/runtime/task-output-context.ts +7 -5
- package/src/runtime/task-runner/child-executor.ts +62 -22
- package/src/runtime/task-runner/live-executor.ts +8 -8
- package/src/runtime/task-runner/post-execution.ts +12 -12
- package/src/runtime/task-runner/pre-execution.ts +6 -6
- package/src/runtime/task-runner/progress.ts +1 -1
- package/src/runtime/task-runner/run-projection.ts +1 -1
- package/src/runtime/task-runner/scaffold-executor.ts +1 -1
- package/src/runtime/task-runner/state-helpers.ts +2 -2
- package/src/runtime/task-runner.ts +4 -4
- package/src/runtime/team-runner.ts +380 -139
- package/src/runtime/{completion-guard.ts → verification/completion-guard.ts} +1 -1
- package/src/runtime/{green-contract.ts → verification/green-contract.ts} +1 -1
- package/src/runtime/{post-checks.ts → verification/post-checks.ts} +4 -4
- package/src/runtime/{verification-gates.ts → verification/verification-gates.ts} +5 -5
- package/src/runtime/{verification-integrity.ts → verification/verification-integrity.ts} +1 -1
- package/src/schema/config-schema.ts +1 -0
- package/src/schema/team-tool-schema.ts +133 -177
- package/src/state/README.md +44 -0
- package/src/state/atomic-write.ts +24 -3
- package/src/state/{locks.ts → coordination/locks.ts} +118 -38
- package/src/state/{mailbox.ts → coordination/mailbox.ts} +14 -8
- package/src/state/{schedule.ts → coordination/schedule.ts} +3 -3
- package/src/state/{task-claims.ts → coordination/task-claims.ts} +1 -1
- package/src/state/decision-ledger.ts +1 -1
- package/src/state/{event-log-rotation.ts → event-log/event-log-rotation.ts} +161 -31
- package/src/state/{event-log.ts → event-log/event-log.ts} +38 -26
- package/src/state/{jsonl-writer.ts → event-log/jsonl-writer.ts} +14 -6
- package/src/state/hook-instinct-bridge.ts +2 -2
- package/src/state/{active-run-registry.ts → stores/active-run-registry.ts} +7 -7
- package/src/state/{artifact-store.ts → stores/artifact-store.ts} +62 -4
- package/src/state/{blob-store.ts → stores/blob-store.ts} +3 -3
- package/src/state/{health-store.ts → stores/health-store.ts} +3 -3
- package/src/state/{instinct-store.ts → stores/instinct-store.ts} +3 -3
- package/src/state/{observation-store.ts → stores/observation-store.ts} +2 -2
- package/src/state/{run-cache.ts → stores/run-cache.ts} +4 -4
- package/src/state/{run-graph.ts → stores/run-graph.ts} +4 -4
- package/src/state/{run-metrics.ts → stores/run-metrics.ts} +3 -3
- package/src/state/{state-store.ts → stores/state-store.ts} +236 -17
- package/src/state/types.ts +27 -3
- package/src/ui/component.ts +55 -0
- package/src/ui/crew-select-list.ts +3 -1
- package/src/ui/dashboard-panes/agents-pane.ts +1 -1
- package/src/ui/dwf-phase-display.ts +1 -1
- package/src/ui/heartbeat-aggregator.ts +1 -1
- package/src/ui/keybinding-map.ts +179 -6
- package/src/ui/layout-primitives.ts +9 -5
- package/src/ui/live-conversation-overlay.ts +1 -1
- package/src/ui/live-run-sidebar.ts +1 -1
- package/src/ui/overlay-stack.ts +148 -0
- package/src/ui/overlays/agent-picker-overlay.ts +1 -1
- package/src/ui/overlays/mailbox-compose-overlay.ts +1 -1
- package/src/ui/overlays/mailbox-detail-overlay.ts +2 -2
- package/src/ui/powerbar-publisher.ts +1 -1
- package/src/ui/render-scheduler.ts +1 -1
- package/src/ui/run-action-dispatcher.ts +3 -3
- package/src/ui/run-dashboard.ts +5 -33
- package/src/ui/run-event-bus.ts +3 -3
- package/src/ui/run-snapshot-cache.ts +37 -18
- package/src/ui/settings-overlay.ts +13 -21
- package/src/ui/snapshot-types.ts +1 -1
- package/src/ui/status-colors.ts +0 -2
- package/src/ui/terminal-status.ts +1 -1
- package/src/ui/theme-adapter.ts +33 -13
- package/src/ui/tool-renderers/index.ts +8 -0
- package/src/ui/transcript-viewer.ts +37 -13
- package/src/ui/widget/index.ts +32 -9
- package/src/ui/widget/widget-formatters.ts +62 -4
- package/src/ui/widget/widget-model.ts +2 -2
- package/src/ui/widget/widget-renderer.ts +1 -1
- package/src/utils/conflict-detect.ts +58 -5
- package/src/utils/ndjson.ts +2 -2
- package/src/utils/socket-path.ts +1 -1
- package/src/workflows/workflow-config.ts +1 -1
- package/src/worktree/cleanup.ts +1 -1
- package/src/worktree/worktree-manager.ts +88 -39
- package/workflows/chain.workflow.md +2 -2
- package/index.bundle.ts +0 -25
- package/scripts/bench-check.mjs +0 -96
- package/scripts/bench-cold-start.mjs +0 -216
- package/scripts/build-bundle.mjs +0 -92
- package/scripts/check-all-skills.ts +0 -294
- package/scripts/check-bundle-size.mjs +0 -38
- package/scripts/check-bundle-staleness.mjs +0 -97
- package/scripts/check-conflict-markers.mjs +0 -91
- package/scripts/check-lazy-imports.mjs +0 -28
- package/scripts/dev-runner.mjs +0 -106
- package/scripts/profile-startup.mjs +0 -125
- package/scripts/release-smoke.mjs +0 -74
- package/scripts/run-bench.mjs +0 -47
- package/scripts/run-real-chain.ts +0 -41
- package/scripts/smoke-team-perf.ts +0 -43
- package/scripts/test-issue-29-crash.ts +0 -111
- package/scripts/test-issue-29-e2e.ts +0 -183
- package/scripts/test-issue-29-real-runtime.ts +0 -330
- package/scripts/test-issue-29-real-tasks.ts +0 -387
- package/scripts/test-issue-29-team-tool.ts +0 -105
- package/scripts/test-runner.mjs +0 -84
- package/scripts/verify-flicker-fix.ts +0 -109
- package/scripts/verify-skill.ts +0 -550
- package/scripts/watch-bundle.mjs +0 -259
- package/scripts/watchdog-harness.ts +0 -119
- package/src/adapters/claude-adapter.ts +0 -23
- package/src/adapters/codex-adapter.ts +0 -21
- package/src/adapters/cursor-adapter.ts +0 -17
- package/src/adapters/export-util.ts +0 -143
- package/src/adapters/index.ts +0 -15
- package/src/adapters/registry.ts +0 -18
- package/src/adapters/types.ts +0 -23
- package/src/runtime/code-summary.ts +0 -292
- package/src/runtime/cross-extension-rpc.ts +0 -143
- package/src/runtime/hidden-handoff.ts +0 -407
- package/src/runtime/prose-compressor.ts +0 -162
- package/src/subagents/async-entry.ts +0 -1
- package/src/subagents/index.ts +0 -3
- package/src/subagents/live/control.ts +0 -1
- package/src/subagents/live/manager.ts +0 -1
- package/src/subagents/live/realtime.ts +0 -1
- package/src/subagents/live/session-runtime.ts +0 -1
- package/src/subagents/manager.ts +0 -1
- package/src/subagents/spawn.ts +0 -1
- package/test-integration-check.ts +0 -118
- /package/src/runtime/{broker-issuer.ts → broker/broker-issuer.ts} +0 -0
- /package/src/runtime/{crew-broker-tokens.ts → broker/crew-broker-tokens.ts} +0 -0
- /package/src/runtime/{child-pi-pool.ts → child-pi/child-pi-pool.ts} +0 -0
- /package/src/runtime/{compact-pipeline.ts → compaction/compact-pipeline.ts} +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/ansi-strip-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/blank-collapse-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/deduplicate-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/head-snap-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/tail-capture-stage.ts +0 -0
- /package/src/runtime/{compact-stages → compaction/compact-stages}/truncation-stage.ts +0 -0
- /package/src/runtime/{important-line-classifier.ts → compaction/important-line-classifier.ts} +0 -0
- /package/src/runtime/{heartbeat-gradient.ts → heartbeat/heartbeat-gradient.ts} +0 -0
- /package/src/runtime/{worker-heartbeat.ts → heartbeat/worker-heartbeat.ts} +0 -0
- /package/src/runtime/{worker-startup.ts → heartbeat/worker-startup.ts} +0 -0
- /package/src/runtime/{intercom-bridge.ts → live-session/intercom-bridge.ts} +0 -0
- /package/src/runtime/{live-control-realtime.ts → live-session/live-control-realtime.ts} +0 -0
- /package/src/runtime/{live-extension-bridge.ts → live-session/live-extension-bridge.ts} +0 -0
- /package/src/runtime/{live-irc.ts → live-session/live-irc.ts} +0 -0
- /package/src/runtime/{live-session-health.ts → live-session/live-session-health.ts} +0 -0
- /package/src/runtime/{model-resolver.ts → model/model-resolver.ts} +0 -0
- /package/src/runtime/{model-scope.ts → model/model-scope.ts} +0 -0
- /package/src/runtime/{output-validator.ts → output/output-validator.ts} +0 -0
- /package/src/runtime/{pi-json-output.ts → output/pi-json-output.ts} +0 -0
- /package/src/runtime/{progress-event-coalescer.ts → output/progress-event-coalescer.ts} +0 -0
- /package/src/runtime/{cancellation-token.ts → process/cancellation-token.ts} +0 -0
- /package/src/runtime/{zombie-scanner.ts → process/zombie-scanner.ts} +0 -0
- /package/src/runtime/{crash-classification.ts → recovery/crash-classification.ts} +0 -0
- /package/src/runtime/{batch-barrier.ts → scheduling/batch-barrier.ts} +0 -0
- /package/src/runtime/{global-worker-cap.ts → scheduling/global-worker-cap.ts} +0 -0
- /package/src/runtime/{parallel-utils.ts → scheduling/parallel-utils.ts} +0 -0
- /package/src/runtime/{scheduler.ts → scheduling/scheduler.ts} +0 -0
- /package/src/runtime/{semaphore.ts → scheduling/semaphore.ts} +0 -0
- /package/src/runtime/{task-graph.ts → scheduling/task-graph.ts} +0 -0
- /package/src/runtime/{verification-worktree.ts → verification/verification-worktree.ts} +0 -0
- /package/src/state/{event-reconstructor.ts → event-log/event-reconstructor.ts} +0 -0
- /package/src/state/{worker-atomic-writer.ts → event-log/worker-atomic-writer.ts} +0 -0
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
|
|
20
20
|
import { loadConfig } from "../../config/config.ts";
|
|
21
21
|
import type { GoalWrapWorkflowConfig } from "../../config/types.ts";
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
22
|
+
import { spawnBackgroundTeamRun } from "../../runtime/async-runner.ts";
|
|
23
|
+
import { GoalStore } from "../../runtime/goal-workflow/goal-state-store.ts";
|
|
24
|
+
import { snapshotManifests } from "../../runtime/verification/verification-integrity.ts";
|
|
24
25
|
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
25
26
|
import { atomicWriteJson } from "../../state/atomic-write.ts";
|
|
26
|
-
import { appendEvent } from "../../state/event-log.ts";
|
|
27
|
-
import { createRunPaths, saveRunManifestAsync } from "../../state/state-store.ts";
|
|
27
|
+
import { appendEvent } from "../../state/event-log/event-log.ts";
|
|
28
|
+
import { createRunPaths, saveRunManifestAsync } from "../../state/stores/state-store.ts";
|
|
28
29
|
import type { GoalLoopState, TeamRunManifest } from "../../state/types.ts";
|
|
29
|
-
import { spawnBackgroundTeamRun } from "../../subagents/async-entry.ts";
|
|
30
30
|
import { logInternalError } from "../../utils/internal-error.ts";
|
|
31
31
|
import type { WorkflowConfig } from "../../workflows/workflow-config.ts";
|
|
32
32
|
import { result, type TeamContext } from "./context.ts";
|
|
@@ -14,16 +14,17 @@
|
|
|
14
14
|
* §0c C11 (control path: cooperative flag + handleCancel(currentRunId) via abortOwned).
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
17
|
+
import { spawnBackgroundTeamRun } from "../../runtime/async-runner.ts";
|
|
18
|
+
import { GoalStore } from "../../runtime/goal-workflow/goal-state-store.ts";
|
|
19
|
+
import { snapshotManifests } from "../../runtime/verification/verification-integrity.ts";
|
|
19
20
|
import { isWorkspaceBusy } from "../../runtime/workspace-lock.ts";
|
|
20
21
|
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
21
|
-
import { appendEvent } from "../../state/event-log.ts";
|
|
22
|
-
import { createRunPaths, saveRunManifestAsync } from "../../state/state-store.ts";
|
|
22
|
+
import { appendEvent } from "../../state/event-log/event-log.ts";
|
|
23
|
+
import { createRunPaths, saveRunManifestAsync } from "../../state/stores/state-store.ts";
|
|
23
24
|
import type { GoalLoopState, GoalLoopStatus, TeamRunManifest } from "../../state/types.ts";
|
|
24
|
-
import { spawnBackgroundTeamRun } from "../../subagents/async-entry.ts";
|
|
25
25
|
import { logInternalError } from "../../utils/internal-error.ts";
|
|
26
26
|
import { result, type TeamContext } from "./context.ts";
|
|
27
|
+
import { paramRequired } from "./param-error.ts";
|
|
27
28
|
|
|
28
29
|
const MAX_GOAL_OBJECTIVE_CHARS = 4000;
|
|
29
30
|
|
|
@@ -296,7 +297,12 @@ function assertGoalOwnership(goal: GoalLoopState, ctx: TeamContext, action: stri
|
|
|
296
297
|
function handleStateFlip(input: GoalSubActionInput, nextState: GoalLoopStatus, label: string): ReturnType<typeof result> {
|
|
297
298
|
const { params, ctx, store } = input;
|
|
298
299
|
const goalId = params.config?.goalId as string | undefined;
|
|
299
|
-
if (!goalId)
|
|
300
|
+
if (!goalId)
|
|
301
|
+
return result(
|
|
302
|
+
paramRequired(label, "config.goalId", "{ action: 'goal', config: { goalId: '...' } }"),
|
|
303
|
+
{ action: "goal", status: "error" },
|
|
304
|
+
true,
|
|
305
|
+
);
|
|
300
306
|
const existing = store.load(goalId);
|
|
301
307
|
if (!existing) return result(`Goal '${goalId}' not found.`, { action: "goal", status: "error" }, true);
|
|
302
308
|
if (params.force !== true) {
|
|
@@ -325,7 +331,12 @@ function handleStateFlip(input: GoalSubActionInput, nextState: GoalLoopStatus, l
|
|
|
325
331
|
async function handleStop(input: GoalSubActionInput): Promise<ReturnType<typeof result>> {
|
|
326
332
|
const { params, ctx, store } = input;
|
|
327
333
|
const goalId = params.config?.goalId as string | undefined;
|
|
328
|
-
if (!goalId)
|
|
334
|
+
if (!goalId)
|
|
335
|
+
return result(
|
|
336
|
+
paramRequired("stop", "config.goalId", "{ action: 'goal', config: { subAction: 'stop', goalId: '...' } }"),
|
|
337
|
+
{ action: "goal", status: "error" },
|
|
338
|
+
true,
|
|
339
|
+
);
|
|
329
340
|
const eventsPath = createRunPaths(ctx.cwd, goalId).eventsPath;
|
|
330
341
|
const before = store.load(goalId);
|
|
331
342
|
if (!before) return result(`Goal '${goalId}' not found.`, { action: "goal", status: "error" }, true);
|
|
@@ -386,7 +397,12 @@ async function handleStop(input: GoalSubActionInput): Promise<ReturnType<typeof
|
|
|
386
397
|
async function handleResume(input: GoalSubActionInput): Promise<ReturnType<typeof result>> {
|
|
387
398
|
const { params, ctx, store } = input;
|
|
388
399
|
const goalId = params.config?.goalId as string | undefined;
|
|
389
|
-
if (!goalId)
|
|
400
|
+
if (!goalId)
|
|
401
|
+
return result(
|
|
402
|
+
paramRequired("resume", "config.goalId", "{ action: 'goal', config: { subAction: 'resume', goalId: '...' } }"),
|
|
403
|
+
{ action: "goal", status: "error" },
|
|
404
|
+
true,
|
|
405
|
+
);
|
|
390
406
|
const existing = store.load(goalId);
|
|
391
407
|
if (!existing) return result(`Goal '${goalId}' not found.`, { action: "goal", status: "error" }, true);
|
|
392
408
|
if (params.force !== true) {
|
|
@@ -510,7 +526,12 @@ export async function handleGoal(params: TeamToolParamsValue, ctx: TeamContext):
|
|
|
510
526
|
// Fix P1-3 + round-5 P2: remove the goal file. But refuse if the loop is still
|
|
511
527
|
// running (would leave a zombie background process). Require stop first.
|
|
512
528
|
const clearGoalId = params.config?.goalId as string | undefined;
|
|
513
|
-
if (!clearGoalId)
|
|
529
|
+
if (!clearGoalId)
|
|
530
|
+
return result(
|
|
531
|
+
paramRequired("clear", "config.goalId", "{ action: 'goal', config: { subAction: 'clear', goalId: '...' } }"),
|
|
532
|
+
{ action: "goal", status: "error" },
|
|
533
|
+
true,
|
|
534
|
+
);
|
|
514
535
|
const existing = store.load(clearGoalId);
|
|
515
536
|
if (!existing) return result(`Goal '${clearGoalId}' not found (already cleared?).`, { action: "goal", status: "error" }, true);
|
|
516
537
|
if (params.force !== true) {
|
|
@@ -1,28 +1,39 @@
|
|
|
1
1
|
import * as crypto from "node:crypto";
|
|
2
|
-
import { humanizeSchedule, nextRunTime, parseSchedule } from "../../runtime/scheduler.ts";
|
|
2
|
+
import { humanizeSchedule, nextRunTime, parseSchedule } from "../../runtime/scheduling/scheduler.ts";
|
|
3
3
|
import { type CrewSettings, updateCrewSettings } from "../../runtime/settings-store.ts";
|
|
4
4
|
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
5
5
|
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
6
6
|
import { result, type TeamContext } from "./context.ts";
|
|
7
|
+
import { paramRequired } from "./param-error.ts";
|
|
7
8
|
|
|
8
|
-
//
|
|
9
|
-
|
|
9
|
+
// Module-scoped scheduler reference — one per extension load (EXT-9).
|
|
10
|
+
// Previously this lived on `globalThis[Symbol.for("pi-crew:scheduler")]`, which
|
|
11
|
+
// was fragile (cross-realm, no lifecycle, peer extensions could overwrite it).
|
|
10
12
|
type SchedulerRef = {
|
|
11
|
-
add(job: import("../../runtime/scheduler.ts").ScheduledJob): void;
|
|
12
|
-
list(): import("../../runtime/scheduler.ts").ScheduledJob[];
|
|
13
|
+
add(job: import("../../runtime/scheduling/scheduler.ts").ScheduledJob): void;
|
|
14
|
+
list(): import("../../runtime/scheduling/scheduler.ts").ScheduledJob[];
|
|
13
15
|
remove(id: string): boolean;
|
|
14
16
|
update(
|
|
15
17
|
id: string,
|
|
16
|
-
patch: Partial<import("../../runtime/scheduler.ts").ScheduledJob>,
|
|
17
|
-
): import("../../runtime/scheduler.ts").ScheduledJob | undefined;
|
|
18
|
+
patch: Partial<import("../../runtime/scheduling/scheduler.ts").ScheduledJob>,
|
|
19
|
+
): import("../../runtime/scheduling/scheduler.ts").ScheduledJob | undefined;
|
|
18
20
|
};
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
// Module-scoped scheduler instance — one per extension load (EXT-9).
|
|
23
|
+
let crewSchedulerInstance: SchedulerRef | undefined;
|
|
24
|
+
|
|
25
|
+
/** @internal — exported for lifecycle tests. */
|
|
26
|
+
export function getCrewScheduler(): SchedulerRef | undefined {
|
|
27
|
+
return crewSchedulerInstance;
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
export function registerCrewScheduler(scheduler: SchedulerRef): void {
|
|
25
|
-
|
|
31
|
+
crewSchedulerInstance = scheduler;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Remove the scheduler singleton. Call during session cleanup. */
|
|
35
|
+
export function unregisterCrewScheduler(): void {
|
|
36
|
+
crewSchedulerInstance = undefined;
|
|
26
37
|
}
|
|
27
38
|
|
|
28
39
|
interface ScheduleParams {
|
|
@@ -35,9 +46,9 @@ interface ScheduleParams {
|
|
|
35
46
|
}
|
|
36
47
|
|
|
37
48
|
function buildScheduleSpec(params: ScheduleParams): {
|
|
38
|
-
spec: import("../../runtime/scheduler.ts").ScheduleSpec;
|
|
49
|
+
spec: import("../../runtime/scheduling/scheduler.ts").ScheduleSpec;
|
|
39
50
|
schedule: string;
|
|
40
|
-
scheduleType: import("../../runtime/scheduler.ts").ScheduleType;
|
|
51
|
+
scheduleType: import("../../runtime/scheduling/scheduler.ts").ScheduleType;
|
|
41
52
|
intervalMs?: number;
|
|
42
53
|
} {
|
|
43
54
|
// Priority: cron > interval > once
|
|
@@ -100,7 +111,12 @@ export function handleSchedule(params: TeamToolParamsValue, ctx: TeamContext): P
|
|
|
100
111
|
|
|
101
112
|
const team = params.team ?? "default";
|
|
102
113
|
const goal = params.goal ?? params.task ?? "";
|
|
103
|
-
if (!goal)
|
|
114
|
+
if (!goal)
|
|
115
|
+
return result(
|
|
116
|
+
paramRequired("schedule", "goal or task", "{ action: 'schedule', goal: '...', cron: '0 9 * * *' }"),
|
|
117
|
+
{ action: "schedule", status: "error" },
|
|
118
|
+
true,
|
|
119
|
+
);
|
|
104
120
|
|
|
105
121
|
let specResult: ReturnType<typeof buildScheduleSpec>;
|
|
106
122
|
try {
|
|
@@ -121,7 +137,7 @@ export function handleSchedule(params: TeamToolParamsValue, ctx: TeamContext): P
|
|
|
121
137
|
if ("error" in next) return result(next.error, { action: "schedule", status: "error" }, true);
|
|
122
138
|
|
|
123
139
|
// Build the ScheduledJob
|
|
124
|
-
const job: import("../../runtime/scheduler.ts").ScheduledJob = {
|
|
140
|
+
const job: import("../../runtime/scheduling/scheduler.ts").ScheduledJob = {
|
|
125
141
|
id: crypto.randomUUID(),
|
|
126
142
|
name: `${team}: ${goal.slice(0, 60)}`,
|
|
127
143
|
description: `Scheduled run for team '${team}'`,
|
|
@@ -190,11 +206,13 @@ export function handleSchedule(params: TeamToolParamsValue, ctx: TeamContext): P
|
|
|
190
206
|
);
|
|
191
207
|
}
|
|
192
208
|
|
|
193
|
-
function scheduledJobsOf(settings: CrewSettings): import("../../runtime/scheduler.ts").ScheduledJob[] {
|
|
194
|
-
return Array.isArray(settings.scheduledJobs)
|
|
209
|
+
function scheduledJobsOf(settings: CrewSettings): import("../../runtime/scheduling/scheduler.ts").ScheduledJob[] {
|
|
210
|
+
return Array.isArray(settings.scheduledJobs)
|
|
211
|
+
? (settings.scheduledJobs as import("../../runtime/scheduling/scheduler.ts").ScheduledJob[])
|
|
212
|
+
: [];
|
|
195
213
|
}
|
|
196
214
|
|
|
197
|
-
function persistScheduledJob(cwd: string, job: import("../../runtime/scheduler.ts").ScheduledJob): void {
|
|
215
|
+
function persistScheduledJob(cwd: string, job: import("../../runtime/scheduling/scheduler.ts").ScheduledJob): void {
|
|
198
216
|
try {
|
|
199
217
|
updateCrewSettings(cwd, (settings) => ({
|
|
200
218
|
...settings,
|
|
@@ -206,7 +224,7 @@ function persistScheduledJob(cwd: string, job: import("../../runtime/scheduler.t
|
|
|
206
224
|
}
|
|
207
225
|
|
|
208
226
|
/** Update an existing scheduled job in persistent settings. */
|
|
209
|
-
export function persistScheduledJobUpdate(cwd: string, job: import("../../runtime/scheduler.ts").ScheduledJob): void {
|
|
227
|
+
export function persistScheduledJobUpdate(cwd: string, job: import("../../runtime/scheduling/scheduler.ts").ScheduledJob): void {
|
|
210
228
|
try {
|
|
211
229
|
updateCrewSettings(cwd, (settings) => ({
|
|
212
230
|
...settings,
|
|
@@ -309,7 +327,7 @@ export function handleUpdateScheduled(params: TeamToolParamsValue, ctx: TeamCont
|
|
|
309
327
|
return result("Scheduler not running.", { action: "schedule", status: "error" }, true);
|
|
310
328
|
}
|
|
311
329
|
|
|
312
|
-
const patch: Partial<import("../../runtime/scheduler.ts").ScheduledJob> = {};
|
|
330
|
+
const patch: Partial<import("../../runtime/scheduling/scheduler.ts").ScheduledJob> = {};
|
|
313
331
|
if (subAction === "disable") patch.enabled = false;
|
|
314
332
|
if (subAction === "enable") patch.enabled = true;
|
|
315
333
|
// For generic "update", allow patch of cron / interval / goal.
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
2
|
-
import { readEvents } from "../../state/event-log.ts";
|
|
3
|
-
import { loadRunManifestById } from "../../state/state-store.ts";
|
|
2
|
+
import { readEvents } from "../../state/event-log/event-log.ts";
|
|
3
|
+
import { loadRunManifestById } from "../../state/stores/state-store.ts";
|
|
4
4
|
import { aggregateUsage, formatCostReport, formatUsage } from "../../state/usage.ts";
|
|
5
5
|
import { locateRunCwd } from "../team-tool.ts";
|
|
6
6
|
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
7
7
|
import { result, type TeamContext } from "./context.ts";
|
|
8
8
|
import { formatFailurePatterns } from "./failure-patterns.ts";
|
|
9
|
+
import { paramRequired } from "./param-error.ts";
|
|
9
10
|
import { RUN_NOT_FOUND_HINT } from "./run-not-found.ts";
|
|
10
11
|
|
|
11
12
|
export function handleEvents(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
12
|
-
if (!params.runId)
|
|
13
|
+
if (!params.runId)
|
|
14
|
+
return result(
|
|
15
|
+
paramRequired("events", "runId", "{ action: 'events', runId: 'team_...' }"),
|
|
16
|
+
{ action: "events", status: "error" },
|
|
17
|
+
true,
|
|
18
|
+
);
|
|
13
19
|
const runCwd = locateRunCwd(params.runId, ctx.cwd);
|
|
14
20
|
if (!runCwd) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "events", status: "error" }, true);
|
|
15
21
|
const loaded = loadRunManifestById(runCwd, params.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
@@ -33,7 +39,12 @@ export function handleEvents(params: TeamToolParamsValue, ctx: TeamContext): PiT
|
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
export function handleArtifacts(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
36
|
-
if (!params.runId)
|
|
42
|
+
if (!params.runId)
|
|
43
|
+
return result(
|
|
44
|
+
paramRequired("artifacts", "runId", "{ action: 'artifacts', runId: 'team_...' }"),
|
|
45
|
+
{ action: "artifacts", status: "error" },
|
|
46
|
+
true,
|
|
47
|
+
);
|
|
37
48
|
const runCwd = locateRunCwd(params.runId, ctx.cwd);
|
|
38
49
|
if (!runCwd) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "artifacts", status: "error" }, true);
|
|
39
50
|
const loaded = loadRunManifestById(runCwd, params.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
@@ -56,7 +67,12 @@ export function handleArtifacts(params: TeamToolParamsValue, ctx: TeamContext):
|
|
|
56
67
|
}
|
|
57
68
|
|
|
58
69
|
export function handleSummary(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
59
|
-
if (!params.runId)
|
|
70
|
+
if (!params.runId)
|
|
71
|
+
return result(
|
|
72
|
+
paramRequired("summary", "runId", "{ action: 'summary', runId: 'team_...' }"),
|
|
73
|
+
{ action: "summary", status: "error" },
|
|
74
|
+
true,
|
|
75
|
+
);
|
|
60
76
|
const runCwd = locateRunCwd(params.runId, ctx.cwd);
|
|
61
77
|
if (!runCwd) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "summary", status: "error" }, true);
|
|
62
78
|
const loaded = loadRunManifestById(runCwd, params.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
@@ -2,11 +2,11 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { removeGuidance } from "../../config/markers.ts";
|
|
4
4
|
import { appendHookEvent, executeHook } from "../../hooks/registry.ts";
|
|
5
|
-
import { killProcessPid } from "../../runtime/child-pi.ts";
|
|
6
|
-
import { terminateLiveAgentsForRun } from "../../runtime/live-agent-manager.ts";
|
|
5
|
+
import { killProcessPid } from "../../runtime/child-pi/child-pi.ts";
|
|
6
|
+
import { terminateLiveAgentsForRun } from "../../runtime/live-session/live-agent-manager.ts";
|
|
7
7
|
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
8
|
-
import { appendEvent } from "../../state/event-log.ts";
|
|
9
|
-
import { loadRunManifestById } from "../../state/state-store.ts";
|
|
8
|
+
import { appendEvent } from "../../state/event-log/event-log.ts";
|
|
9
|
+
import { loadRunManifestById } from "../../state/stores/state-store.ts";
|
|
10
10
|
import { logInternalError } from "../../utils/internal-error.ts";
|
|
11
11
|
import { projectCrewRoot, userCrewRoot, userPiRoot } from "../../utils/paths.ts";
|
|
12
12
|
import { resolveRealContainedPath } from "../../utils/safe-paths.ts";
|
|
@@ -18,10 +18,16 @@ import { pruneFinishedRuns } from "../run-maintenance.ts";
|
|
|
18
18
|
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
19
19
|
import { configRecord, result, type TeamContext } from "./context.ts";
|
|
20
20
|
import { enforceDestructiveIntent, intentFromConfig } from "./intent-policy.ts";
|
|
21
|
+
import { paramRequired } from "./param-error.ts";
|
|
21
22
|
import { RUN_NOT_FOUND_HINT } from "./run-not-found.ts";
|
|
22
23
|
|
|
23
24
|
export function handleWorktrees(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
24
|
-
if (!params.runId)
|
|
25
|
+
if (!params.runId)
|
|
26
|
+
return result(
|
|
27
|
+
paramRequired("worktrees", "runId", "{ action: 'worktrees', runId: 'team_...' }"),
|
|
28
|
+
{ action: "worktrees", status: "error" },
|
|
29
|
+
true,
|
|
30
|
+
);
|
|
25
31
|
const loaded = loadRunManifestById(ctx.cwd, params.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
26
32
|
if (!loaded) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "worktrees", status: "error" }, true);
|
|
27
33
|
const withWorktrees = loaded.tasks.filter((task) => task.worktree);
|
|
@@ -59,7 +65,16 @@ export function handleImports(_params: TeamToolParamsValue, ctx: TeamContext): P
|
|
|
59
65
|
export function handleImport(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
60
66
|
const cfg = configRecord(params.config);
|
|
61
67
|
const bundlePath = typeof cfg.path === "string" ? cfg.path : typeof cfg.bundlePath === "string" ? cfg.bundlePath : undefined;
|
|
62
|
-
if (!bundlePath)
|
|
68
|
+
if (!bundlePath)
|
|
69
|
+
return result(
|
|
70
|
+
paramRequired(
|
|
71
|
+
"import",
|
|
72
|
+
"config.path pointing at run-export.json",
|
|
73
|
+
"{ action: 'import', config: { path: '/path/to/run-export.json' } }",
|
|
74
|
+
),
|
|
75
|
+
{ action: "import", status: "error" },
|
|
76
|
+
true,
|
|
77
|
+
);
|
|
63
78
|
const scope = cfg.scope === "user" ? "user" : "project";
|
|
64
79
|
try {
|
|
65
80
|
const imported = importRunBundle(ctx.cwd, bundlePath, scope);
|
|
@@ -74,7 +89,12 @@ export function handleImport(params: TeamToolParamsValue, ctx: TeamContext): PiT
|
|
|
74
89
|
}
|
|
75
90
|
|
|
76
91
|
export async function handleExport(params: TeamToolParamsValue, ctx: TeamContext): Promise<PiTeamsToolResult> {
|
|
77
|
-
if (!params.runId)
|
|
92
|
+
if (!params.runId)
|
|
93
|
+
return result(
|
|
94
|
+
paramRequired("export", "runId", "{ action: 'export', runId: 'team_...' }"),
|
|
95
|
+
{ action: "export", status: "error" },
|
|
96
|
+
true,
|
|
97
|
+
);
|
|
78
98
|
const loaded = loadRunManifestById(ctx.cwd, params.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
79
99
|
if (!loaded) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "export", status: "error" }, true);
|
|
80
100
|
|
|
@@ -126,7 +146,12 @@ export async function handleExport(params: TeamToolParamsValue, ctx: TeamContext
|
|
|
126
146
|
export async function handlePrune(params: TeamToolParamsValue, ctx: TeamContext): Promise<PiTeamsToolResult> {
|
|
127
147
|
const intentError = enforceDestructiveIntent("prune", params, ctx.config);
|
|
128
148
|
if (intentError) return intentError;
|
|
129
|
-
if (!params.confirm)
|
|
149
|
+
if (!params.confirm)
|
|
150
|
+
return result(
|
|
151
|
+
paramRequired("prune", "confirm: true", "{ action: 'prune', confirm: true }"),
|
|
152
|
+
{ action: "prune", status: "error" },
|
|
153
|
+
true,
|
|
154
|
+
);
|
|
130
155
|
const keep = params.keep ?? 20;
|
|
131
156
|
if (keep < 0 || !Number.isInteger(keep)) return result("keep must be an integer >= 0.", { action: "prune", status: "error" }, true);
|
|
132
157
|
const intent = intentFromConfig(params.config);
|
|
@@ -164,8 +189,18 @@ export async function handlePrune(params: TeamToolParamsValue, ctx: TeamContext)
|
|
|
164
189
|
export async function handleForget(params: TeamToolParamsValue, ctx: TeamContext): Promise<PiTeamsToolResult> {
|
|
165
190
|
const intentError = enforceDestructiveIntent("forget", params, ctx.config);
|
|
166
191
|
if (intentError) return intentError;
|
|
167
|
-
if (!params.runId)
|
|
168
|
-
|
|
192
|
+
if (!params.runId)
|
|
193
|
+
return result(
|
|
194
|
+
paramRequired("forget", "runId", "{ action: 'forget', runId: 'team_...', confirm: true }"),
|
|
195
|
+
{ action: "forget", status: "error" },
|
|
196
|
+
true,
|
|
197
|
+
);
|
|
198
|
+
if (!params.confirm)
|
|
199
|
+
return result(
|
|
200
|
+
paramRequired("forget", "confirm: true", "{ action: 'forget', runId: 'team_...', confirm: true }"),
|
|
201
|
+
{ action: "forget", status: "error" },
|
|
202
|
+
true,
|
|
203
|
+
);
|
|
169
204
|
const loaded = loadRunManifestById(ctx.cwd, params.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
170
205
|
if (!loaded) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "forget", status: "error" }, true);
|
|
171
206
|
|
|
@@ -269,6 +304,14 @@ export async function handleCleanup(params: TeamToolParamsValue, ctx: TeamContex
|
|
|
269
304
|
// can stay focused on their own logic.
|
|
270
305
|
const intentError = enforceDestructiveIntent("cleanup", params, ctx.config);
|
|
271
306
|
if (intentError) return intentError;
|
|
307
|
+
// SEC-5: self-enforce confirm:true (defense-in-depth), matching handlePrune/handleForget.
|
|
308
|
+
// dryRun:true is a non-destructive preview and is always allowed.
|
|
309
|
+
if (params.confirm !== true && params.dryRun !== true)
|
|
310
|
+
return result(
|
|
311
|
+
paramRequired("cleanup", "confirm: true", "{ action: 'cleanup', confirm: true }"),
|
|
312
|
+
{ action: "cleanup", status: "error" },
|
|
313
|
+
true,
|
|
314
|
+
);
|
|
272
315
|
// Three cleanup modes:
|
|
273
316
|
// 1. WITH runId → per-run worktree cleanup (existing behavior).
|
|
274
317
|
// 2. WITHOUT runId, scope=project (default) → PROJECT-LEVEL uninstall:
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { discoverAgents } from "../../agents/discover-agents.ts";
|
|
10
10
|
import { loadConfig } from "../../config/config.ts";
|
|
11
|
-
import {
|
|
11
|
+
import { spawnBackgroundTeamRun } from "../../runtime/async-runner.ts";
|
|
12
|
+
import { resolveCrewRuntime } from "../../runtime/model/runtime-resolver.ts";
|
|
12
13
|
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
13
|
-
import { appendEvent } from "../../state/event-log.ts";
|
|
14
|
-
import { createRunManifest } from "../../state/state-store.ts";
|
|
15
|
-
import { spawnBackgroundTeamRun } from "../../subagents/async-entry.ts";
|
|
14
|
+
import { appendEvent } from "../../state/event-log/event-log.ts";
|
|
15
|
+
import { createRunManifest } from "../../state/stores/state-store.ts";
|
|
16
16
|
import { discoverTeams } from "../../teams/discover-teams.ts";
|
|
17
17
|
import type { TeamConfig } from "../../teams/team-config.ts";
|
|
18
18
|
import { discoverWorkflows } from "../../workflows/discover-workflows.ts";
|
|
@@ -20,6 +20,7 @@ import type { WorkflowConfig } from "../../workflows/workflow-config.ts";
|
|
|
20
20
|
import { resolveCwdOverride } from "../registration/team-tool.ts";
|
|
21
21
|
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
22
22
|
import { result, type TeamContext } from "./context.ts";
|
|
23
|
+
import { paramRequired } from "./param-error.ts";
|
|
23
24
|
|
|
24
25
|
const MAX_CONCURRENCY = 8;
|
|
25
26
|
const DEFAULT_CONCURRENCY = 4;
|
|
@@ -29,7 +30,15 @@ const DEFAULT_AGENT = "explorer";
|
|
|
29
30
|
export async function handleParallel(params: TeamToolParamsValue, ctx: TeamContext): Promise<PiTeamsToolResult> {
|
|
30
31
|
const tasksParam = params.config?.tasks;
|
|
31
32
|
if (!Array.isArray(tasksParam) || tasksParam.length === 0) {
|
|
32
|
-
return result(
|
|
33
|
+
return result(
|
|
34
|
+
paramRequired(
|
|
35
|
+
"parallel",
|
|
36
|
+
"config.tasks: [{goal, agent?}]",
|
|
37
|
+
"{ action: 'parallel', config: { tasks: [{ goal: '...', agent: 'explorer' }] } }",
|
|
38
|
+
),
|
|
39
|
+
{ action: "parallel", status: "error" },
|
|
40
|
+
true,
|
|
41
|
+
);
|
|
33
42
|
}
|
|
34
43
|
|
|
35
44
|
const concurrency = Math.min(Math.max(1, Math.floor((params.config?.concurrency as number) ?? DEFAULT_CONCURRENCY)), MAX_CONCURRENCY);
|
|
@@ -112,3 +112,27 @@ export function formatTeamToolParamError(schema: TSchema, params: unknown): stri
|
|
|
112
112
|
"as an array/object instead of a single string; params nested instead of flat.",
|
|
113
113
|
].join("\n");
|
|
114
114
|
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Build a runtime handler error string for a MISSING REQUIRED FIELD, including
|
|
118
|
+
* a concrete example shape so the calling agent (LLM) can self-correct instead
|
|
119
|
+
* of looping on the same malformed call.
|
|
120
|
+
*
|
|
121
|
+
* The schema-validation path (`formatTeamToolParamError` above) already
|
|
122
|
+
* provides rich examples, but runtime handler errors used to return a plain
|
|
123
|
+
* `"X requires Y."` with NO example — giving LLMs worse guidance for the MORE
|
|
124
|
+
* COMMON failure (valid action, missing field). This helper closes that
|
|
125
|
+
* two-tier error-quality gap (AUDIT-2026-07-30 EXT-2).
|
|
126
|
+
*
|
|
127
|
+
* @param action The team-tool action (e.g. "status", "cancel").
|
|
128
|
+
* @param field The required field/fields (e.g. "runId", "goal or task").
|
|
129
|
+
* @param example Optional concrete example shape,
|
|
130
|
+
* e.g. `{ action: 'status', runId: 'team_...' }`.
|
|
131
|
+
* @returns An error string like
|
|
132
|
+
* `"Status requires runId. Example: { action: 'status', runId: 'team_...' }"`.
|
|
133
|
+
*/
|
|
134
|
+
export function paramRequired(action: string, field: string, example?: string): string {
|
|
135
|
+
const subject = action.charAt(0).toUpperCase() + action.slice(1);
|
|
136
|
+
const base = `${subject} requires ${field}.`;
|
|
137
|
+
return example ? `${base} Example: ${example}` : base;
|
|
138
|
+
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { readCrewAgents, recordFromTask, saveCrewAgents } from "../../runtime/crew-agent-records.ts";
|
|
2
2
|
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { loadRunManifestById, saveRunTasks, updateRunStatus } from "../../state/state-store.ts";
|
|
3
|
+
import { withRunLockSync } from "../../state/coordination/locks.ts";
|
|
4
|
+
import { appendMailboxMessage, updateMailboxMessageReply } from "../../state/coordination/mailbox.ts";
|
|
5
|
+
import { appendEvent } from "../../state/event-log/event-log.ts";
|
|
6
|
+
import { loadRunManifestById, saveRunTasks, updateRunStatus } from "../../state/stores/state-store.ts";
|
|
7
7
|
import { logInternalError } from "../../utils/internal-error.ts";
|
|
8
8
|
import { locateRunCwd } from "../team-tool.ts";
|
|
9
9
|
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
10
10
|
import { result, type TeamContext } from "./context.ts";
|
|
11
|
+
import { paramRequired } from "./param-error.ts";
|
|
11
12
|
import { RUN_NOT_FOUND_HINT } from "./run-not-found.ts";
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -16,9 +17,22 @@ import { RUN_NOT_FOUND_HINT } from "./run-not-found.ts";
|
|
|
16
17
|
* mailbox and the task is re-queued for durable scheduler resume.
|
|
17
18
|
*/
|
|
18
19
|
export function handleRespond(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
19
|
-
if (!params.runId)
|
|
20
|
+
if (!params.runId)
|
|
21
|
+
return result(
|
|
22
|
+
paramRequired("respond", "runId", "{ action: 'respond', runId: 'team_...', message: '...' }"),
|
|
23
|
+
{ action: "respond", status: "error" },
|
|
24
|
+
true,
|
|
25
|
+
);
|
|
20
26
|
if (!params.message && !params.taskId)
|
|
21
|
-
return result(
|
|
27
|
+
return result(
|
|
28
|
+
paramRequired(
|
|
29
|
+
"respond",
|
|
30
|
+
"taskId and/or message",
|
|
31
|
+
"{ action: 'respond', runId: 'team_...', taskId: '01_agent', message: '...' }",
|
|
32
|
+
),
|
|
33
|
+
{ action: "respond", status: "error" },
|
|
34
|
+
true,
|
|
35
|
+
);
|
|
22
36
|
|
|
23
37
|
const runCwd = locateRunCwd(params.runId, ctx.cwd);
|
|
24
38
|
if (!runCwd) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "respond", status: "error" }, true);
|
|
@@ -4,10 +4,10 @@ import { sanitizeTaskText } from "../../runtime/task-packet.ts";
|
|
|
4
4
|
// Heavy runtime — lazy-loaded to avoid 1.4s import cost at extension registration.
|
|
5
5
|
import type { executeTeamRun as ExecuteTeamRunFn } from "../../runtime/team-runner.ts";
|
|
6
6
|
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
7
|
-
import { registerActiveRun, unregisterActiveRun } from "../../state/active-run-registry.ts";
|
|
8
|
-
import { writeArtifact } from "../../state/artifact-store.ts";
|
|
9
7
|
import { atomicWriteJson } from "../../state/atomic-write.ts";
|
|
10
|
-
import {
|
|
8
|
+
import { registerActiveRun, unregisterActiveRun } from "../../state/stores/active-run-registry.ts";
|
|
9
|
+
import { writeArtifact } from "../../state/stores/artifact-store.ts";
|
|
10
|
+
import { createRunManifest, loadRunManifestById, updateRunStatus } from "../../state/stores/state-store.ts";
|
|
11
11
|
import { allTeams, discoverTeams } from "../../teams/discover-teams.ts";
|
|
12
12
|
import { allWorkflows, discoverWorkflows } from "../../workflows/discover-workflows.ts";
|
|
13
13
|
import { assertCleanLeaderAsync, findGitRootAsync } from "../../worktree/worktree-manager.ts";
|
|
@@ -18,6 +18,7 @@ const _typeCheck: typeof ExecuteTeamRunFn = null as never as typeof ExecuteTeamR
|
|
|
18
18
|
import { errorMessage } from "../../utils/guards.ts";
|
|
19
19
|
import { logInternalError } from "../../utils/internal-error.ts";
|
|
20
20
|
import { resolveRealContainedPath } from "../../utils/safe-paths.ts";
|
|
21
|
+
import { paramRequired } from "./param-error.ts";
|
|
21
22
|
|
|
22
23
|
let _cachedExecuteTeamRun: typeof ExecuteTeamRunFn | undefined;
|
|
23
24
|
async function executeTeamRun(...args: Parameters<typeof ExecuteTeamRunFn>): Promise<Awaited<ReturnType<typeof ExecuteTeamRunFn>>> {
|
|
@@ -29,11 +30,11 @@ async function executeTeamRun(...args: Parameters<typeof ExecuteTeamRunFn>): Pro
|
|
|
29
30
|
return _cachedExecuteTeamRun(...args);
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import
|
|
33
|
+
import { spawnBackgroundTeamRun } from "../../runtime/async-runner.ts";
|
|
34
|
+
import { resolveCrewRuntime, runtimeResolutionState } from "../../runtime/model/runtime-resolver.ts";
|
|
35
|
+
import { appendEventAsync, readEvents } from "../../state/event-log/event-log.ts";
|
|
36
|
+
import type { RunMetrics } from "../../state/stores/run-metrics.ts";
|
|
35
37
|
import type { RuntimeResolutionState, TeamRunManifest, TeamTaskState } from "../../state/types.ts";
|
|
36
|
-
import { spawnBackgroundTeamRun } from "../../subagents/async-entry.ts";
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* Module-scoped latch for the crew-init dynamic import.
|
|
@@ -72,10 +73,11 @@ function loadCrewInit(): Promise<typeof import("../../state/crew-init.ts")> {
|
|
|
72
73
|
|
|
73
74
|
import * as fs from "node:fs";
|
|
74
75
|
import * as path from "node:path";
|
|
76
|
+
import { t } from "../../i18n.ts";
|
|
75
77
|
import { hasAsyncStartMarker } from "../../runtime/async-marker.ts";
|
|
76
78
|
import { checkProcessLiveness, isActiveRunStatus } from "../../runtime/process-status.ts";
|
|
77
79
|
import { waitForRun } from "../../runtime/run-tracker.ts";
|
|
78
|
-
import { collectRunMetrics } from "../../state/run-metrics.ts";
|
|
80
|
+
import { collectRunMetrics } from "../../state/stores/run-metrics.ts";
|
|
79
81
|
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
80
82
|
import { effectiveRunConfig } from "./config-patch.ts";
|
|
81
83
|
import { buildParentContext, result, type TeamContext } from "./context.ts";
|
|
@@ -256,7 +258,7 @@ function formatRunResult(manifest: TeamRunManifest, options: FormatRunResultOpti
|
|
|
256
258
|
? "Experimental live-session worker execution was enabled."
|
|
257
259
|
: "Safe scaffold mode: child Pi workers were not launched because runtime.mode=scaffold or executeWorkers=false was configured.";
|
|
258
260
|
const text = [
|
|
259
|
-
|
|
261
|
+
t("team.run.created", { runId: manifest.runId }),
|
|
260
262
|
`Team: ${team}`,
|
|
261
263
|
`Workflow: ${workflow}`,
|
|
262
264
|
`Status: ${manifest.status}`,
|
|
@@ -285,7 +287,10 @@ function formatRunResult(manifest: TeamRunManifest, options: FormatRunResultOpti
|
|
|
285
287
|
}
|
|
286
288
|
|
|
287
289
|
// mode === "waited" — detailed per-task summary.
|
|
288
|
-
const lines: string[] = [
|
|
290
|
+
const lines: string[] = [
|
|
291
|
+
t("team.run.completed", { status: manifest.status, runId: manifest.runId, team }),
|
|
292
|
+
`Goal: ${goal.slice(0, 100)}`,
|
|
293
|
+
];
|
|
289
294
|
if (metrics) {
|
|
290
295
|
lines.push("");
|
|
291
296
|
lines.push(
|
|
@@ -346,10 +351,10 @@ function formatRunResult(manifest: TeamRunManifest, options: FormatRunResultOpti
|
|
|
346
351
|
|
|
347
352
|
if (failedCount === 0) {
|
|
348
353
|
lines.push("");
|
|
349
|
-
lines.push("
|
|
354
|
+
lines.push(t("team.run.allCompleted"));
|
|
350
355
|
} else {
|
|
351
356
|
lines.push("");
|
|
352
|
-
lines.push(
|
|
357
|
+
lines.push(t("team.run.tasksFailed", { count: failedCount, ids: failedIds.join(", ") }));
|
|
353
358
|
}
|
|
354
359
|
} else {
|
|
355
360
|
lines.push(
|
|
@@ -385,7 +390,12 @@ export async function handleRun(params: TeamToolParamsValue, ctx: TeamContext):
|
|
|
385
390
|
return handleChainRun(params, ctx, handleRun);
|
|
386
391
|
}
|
|
387
392
|
const goal = params.goal ?? params.task;
|
|
388
|
-
if (!goal)
|
|
393
|
+
if (!goal)
|
|
394
|
+
return result(
|
|
395
|
+
paramRequired("run", "goal or task", "{ action: 'run', goal: '<what to achieve>' }"),
|
|
396
|
+
{ action: "run", status: "error" },
|
|
397
|
+
true,
|
|
398
|
+
);
|
|
389
399
|
const intentPrefix = goal.length > 60 ? `${goal.slice(0, 57)}...` : goal;
|
|
390
400
|
|
|
391
401
|
// P0: Ensure .crew directory structure exists before creating any manifests.
|
|
@@ -494,7 +504,7 @@ export async function handleRun(params: TeamToolParamsValue, ctx: TeamContext):
|
|
|
494
504
|
if (analysisParam.error) return result(analysisParam.error, { action: "run", status: "error" }, true);
|
|
495
505
|
|
|
496
506
|
// LAZY: dodge the jiti ESM/CJS interop TDZ race on the static `import { expandParallelResearchWorkflow }` above (issue #28, RFC 17). At call time the module body has fully evaluated, so the dynamic import returns a live binding. Multi-line form breaks scripts/check-lazy-imports.mjs (which does `lines[lineNum - 2]`), so keep destructuring + await import on one line.
|
|
497
|
-
const { expandParallelResearchWorkflow: expandParallelResearch } = await import("../../runtime/parallel-research.ts");
|
|
507
|
+
const { expandParallelResearchWorkflow: expandParallelResearch } = await import("../../runtime/scheduling/parallel-research.ts");
|
|
498
508
|
const workflow = directAgent ? baseWorkflow : expandParallelResearch(baseWorkflow, resolvedCtx.cwd);
|
|
499
509
|
const isDynamicWorkflow =
|
|
500
510
|
!directAgent && (workflow as import("../../workflows/workflow-config.ts").WorkflowConfig).runtime === "dynamic";
|
|
@@ -623,8 +633,8 @@ export async function handleRun(params: TeamToolParamsValue, ctx: TeamContext):
|
|
|
623
633
|
console.warn(
|
|
624
634
|
`[pi-crew SECURITY] Dynamic workflow '${workflow.name}' executes as trusted Node.js code with full process/require/import access; run only reviewed .dwf.ts files.`,
|
|
625
635
|
);
|
|
626
|
-
// LAZY: defer dynamic import of ../../runtime/dynamic-workflow-runner.ts to its call site.
|
|
627
|
-
const { runDynamicWorkflow } = await import("../../runtime/dynamic-workflow-runner.ts");
|
|
636
|
+
// LAZY: defer dynamic import of ../../runtime/goal-workflow/dynamic-workflow-runner.ts to its call site.
|
|
637
|
+
const { runDynamicWorkflow } = await import("../../runtime/goal-workflow/dynamic-workflow-runner.ts");
|
|
628
638
|
// Re-synthesize a dynamic-team (§0c C9) for role resolution.
|
|
629
639
|
const dwfTeam: import("../../teams/team-config.ts").TeamConfig = {
|
|
630
640
|
name: `dwf-${manifest.runId.slice(-12)}`,
|
|
@@ -643,7 +653,7 @@ export async function handleRun(params: TeamToolParamsValue, ctx: TeamContext):
|
|
|
643
653
|
// CORE-8: unified deadline — resolve params > config > 1h default.
|
|
644
654
|
const dwfDeadline = resolveRunDeadline(ctx, params);
|
|
645
655
|
try {
|
|
646
|
-
let dwfResult: import("../../runtime/dynamic-workflow-runner.ts").RunDynamicWorkflowResult | undefined;
|
|
656
|
+
let dwfResult: import("../../runtime/goal-workflow/dynamic-workflow-runner.ts").RunDynamicWorkflowResult | undefined;
|
|
647
657
|
try {
|
|
648
658
|
dwfResult = await runDynamicWorkflow({
|
|
649
659
|
manifest: dwfManifest,
|