pi-crew 0.9.55 → 0.9.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +58 -0
- package/README.md +53 -5
- package/dist/index.mjs +5666 -4370
- package/docs/README.md +54 -0
- package/package.json +12 -13
- 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 +109 -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 +138 -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 +17 -6
- 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 +3 -2
- 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} +23 -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} +47 -78
- package/src/runtime/compaction/compact-stages/bounded-tail.ts +84 -0
- 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/crew-agent-records.ts +48 -2
- package/src/runtime/custom-tools/irc-tool.ts +2 -2
- package/src/runtime/delivery-coordinator.ts +0 -3
- package/src/runtime/diagnostic-export.ts +5 -4
- 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 +6 -2
- 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} +9 -3
- 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/{semaphore.ts → scheduling/semaphore.ts} +4 -1
- 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 +28 -13
- package/src/runtime/task-output-context.ts +7 -5
- package/src/runtime/task-runner/child-executor.ts +67 -31
- 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 +441 -175
- 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 +149 -185
- 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} +189 -31
- package/src/state/{event-log.ts → event-log/event-log.ts} +77 -39
- 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} +254 -21
- 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/redaction.ts +39 -0
- 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 +111 -47
- package/workflows/chain.workflow.md +2 -2
- package/dist/build-meta.json +0 -16807
- 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/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/{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
package/scripts/watch-bundle.mjs
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Auto-rebuild bundle watcher — dev-loop ergonomics for v0.9.17+.
|
|
4
|
-
*
|
|
5
|
-
* Watches `src/`, `index.bundle.ts` for changes and rebuilds
|
|
6
|
-
* `dist/index.mjs` after a 300ms debounce. Solves the "edit src/foo.ts,
|
|
7
|
-
* forget to rebuild, run stale bundle" race that motivated check:
|
|
8
|
-
* bundle-staleness as a CI gate.
|
|
9
|
-
*
|
|
10
|
-
* Usage:
|
|
11
|
-
* node scripts/watch-bundle.mjs # default: watch src/ + index.bundle.ts
|
|
12
|
-
* node scripts/watch-bundle.mjs --once # build once and exit (CI prep)
|
|
13
|
-
* node scripts/watch-bundle.mjs --debounce 500 # custom debounce ms
|
|
14
|
-
*
|
|
15
|
-
* Why native fs.watch (not chokidar):
|
|
16
|
-
* - Adds zero deps (chokidar would add ~50 transitive deps)
|
|
17
|
-
* - Node 22 + Linux/macOS support recursive watching (fs.watch recursive)
|
|
18
|
-
*
|
|
19
|
-
* Why not in-process (bundled into build:bundle):
|
|
20
|
-
* - Watch is a separate dev concern; doesn't belong in the build script
|
|
21
|
-
* - Keeps the build script one-shot (CI-friendly, deterministic)
|
|
22
|
-
*/
|
|
23
|
-
import { spawn } from "node:child_process";
|
|
24
|
-
import { existsSync, statSync } from "node:fs";
|
|
25
|
-
import { readdir, watch } from "node:fs/promises";
|
|
26
|
-
import { fileURLToPath } from "node:url";
|
|
27
|
-
import path from "node:path";
|
|
28
|
-
|
|
29
|
-
const args = process.argv.slice(2);
|
|
30
|
-
let onceMode = false;
|
|
31
|
-
let debounceMs = 300;
|
|
32
|
-
for (let i = 0; i < args.length; i += 1) {
|
|
33
|
-
if (args[i] === "--once") {
|
|
34
|
-
onceMode = true;
|
|
35
|
-
} else if (args[i] === "--debounce" && args[i + 1]) {
|
|
36
|
-
debounceMs = Number(args[i + 1]);
|
|
37
|
-
i += 1;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
42
|
-
const root = path.resolve(here, "..");
|
|
43
|
-
|
|
44
|
-
const WATCH_PATHS = ["src", "index.bundle.ts"];
|
|
45
|
-
const EXTENSIONS_TO_WATCH = new Set([".ts", ".mts", ".cts", ".js", ".mjs"]);
|
|
46
|
-
const IGNORE_DIRS = new Set(["node_modules", "dist", ".git"]);
|
|
47
|
-
|
|
48
|
-
let pending = null;
|
|
49
|
-
let lastBuildReason = null;
|
|
50
|
-
|
|
51
|
-
function scheduleRebuild(reason, file) {
|
|
52
|
-
lastBuildReason = `${reason} ${path.relative(root, file ?? "")}`;
|
|
53
|
-
if (pending) clearTimeout(pending);
|
|
54
|
-
pending = setTimeout(() => {
|
|
55
|
-
pending = null;
|
|
56
|
-
runBuild().catch((err) => console.error("[watch-bundle] build crashed:", err));
|
|
57
|
-
}, debounceMs);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function runBuild() {
|
|
61
|
-
return new Promise((resolve, reject) => {
|
|
62
|
-
const startMs = Date.now();
|
|
63
|
-
const child = spawn(process.execPath, [path.join(root, "scripts/build-bundle.mjs")], {
|
|
64
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
65
|
-
cwd: root,
|
|
66
|
-
env: { ...process.env, FORCE_COLOR: "0" },
|
|
67
|
-
});
|
|
68
|
-
let stderr = "";
|
|
69
|
-
child.stdout.on("data", (chunk) => {
|
|
70
|
-
const text = String(chunk);
|
|
71
|
-
if (text.includes("[build-bundle] dist/index.mjs")) {
|
|
72
|
-
process.stdout.write(`[watch-bundle] ${text}`);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
child.stderr.on("data", (chunk) => {
|
|
76
|
-
stderr += String(chunk);
|
|
77
|
-
process.stderr.write(`[watch-bundle] ${chunk}`);
|
|
78
|
-
});
|
|
79
|
-
child.on("exit", (code) => {
|
|
80
|
-
const ms = Date.now() - startMs;
|
|
81
|
-
if (code === 0) {
|
|
82
|
-
console.log(`[watch-bundle] ok in ${ms}ms (${lastBuildReason ?? "initial"})`);
|
|
83
|
-
resolve();
|
|
84
|
-
} else {
|
|
85
|
-
reject(new Error(`build exited with code ${code}: ${stderr.trim().split("\n").slice(-3).join(" / ")}`));
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
child.on("error", reject);
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async function listFiles(dir) {
|
|
93
|
-
const out = [];
|
|
94
|
-
let entries;
|
|
95
|
-
try {
|
|
96
|
-
entries = await readdir(dir, { withFileTypes: true });
|
|
97
|
-
} catch {
|
|
98
|
-
return out;
|
|
99
|
-
}
|
|
100
|
-
for (const entry of entries) {
|
|
101
|
-
const full = path.join(dir, entry.name);
|
|
102
|
-
if (entry.isDirectory()) {
|
|
103
|
-
if (IGNORE_DIRS.has(entry.name)) continue;
|
|
104
|
-
out.push(...(await listFiles(full)));
|
|
105
|
-
} else if (entry.isFile()) {
|
|
106
|
-
const ext = path.extname(entry.name).toLowerCase();
|
|
107
|
-
if (EXTENSIONS_TO_WATCH.has(ext)) out.push(full);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return out;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async function watchDir(dir) {
|
|
114
|
-
// Linux inotify (used by fs.watch {recursive: true} on modern Node)
|
|
115
|
-
// sometimes misses events on deep trees. Walk the tree once and
|
|
116
|
-
// spawn a per-directory watcher for robustness. Cost: O(2N) FDs
|
|
117
|
-
// where N = number of source dirs (~5 for a typical pi-crew tree).
|
|
118
|
-
// Each watcher is independent and yields events as its dir changes.
|
|
119
|
-
const watcherJobs = [];
|
|
120
|
-
try {
|
|
121
|
-
// Watch the dir itself (catches direct children changes)
|
|
122
|
-
const rootWatcher = await watch(dir, { persistent: true });
|
|
123
|
-
watcherJobs.push(
|
|
124
|
-
(async () => {
|
|
125
|
-
for await (const e of rootWatcher) {
|
|
126
|
-
if (e.filename) handleEvent(dir, e.filename);
|
|
127
|
-
}
|
|
128
|
-
})(),
|
|
129
|
-
);
|
|
130
|
-
} catch (err) {
|
|
131
|
-
console.warn(`[watch-bundle] cannot watch ${dir}:`, err?.code ?? err?.message ?? err);
|
|
132
|
-
}
|
|
133
|
-
// Recurse into subdirectories (skip ignored) — each gets its own watcher
|
|
134
|
-
try {
|
|
135
|
-
const entries = await readdir(dir, { withFileTypes: true });
|
|
136
|
-
for (const entry of entries) {
|
|
137
|
-
if (!entry.isDirectory()) continue;
|
|
138
|
-
if (IGNORE_DIRS.has(entry.name)) continue;
|
|
139
|
-
const sub = path.join(dir, entry.name);
|
|
140
|
-
watcherJobs.push(
|
|
141
|
-
(async () => {
|
|
142
|
-
try {
|
|
143
|
-
const subWatcher = await watch(sub, { persistent: true });
|
|
144
|
-
for await (const e of subWatcher) {
|
|
145
|
-
if (e.filename) handleEvent(sub, e.filename);
|
|
146
|
-
}
|
|
147
|
-
} catch (err) {
|
|
148
|
-
console.warn(
|
|
149
|
-
`[watch-bundle] cannot watch ${sub}:`,
|
|
150
|
-
err?.code ?? err?.message ?? err,
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
})(),
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
} catch {
|
|
157
|
-
// ignore readdir errors
|
|
158
|
-
}
|
|
159
|
-
// Block until any watcher completes (they shouldn't, they're persistent)
|
|
160
|
-
await Promise.race(watcherJobs);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function handleEvent(watchedDir, filename) {
|
|
164
|
-
const fullPath = path.resolve(watchedDir, filename);
|
|
165
|
-
const ext = path.extname(fullPath).toLowerCase();
|
|
166
|
-
if (!EXTENSIONS_TO_WATCH.has(ext)) return;
|
|
167
|
-
if (fullPath.includes(`${path.sep}dist${path.sep}`)) return;
|
|
168
|
-
scheduleRebuild("change", fullPath);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async function watchFile(file) {
|
|
172
|
-
if (!existsSync(file)) return;
|
|
173
|
-
const dir = path.dirname(file);
|
|
174
|
-
const watcher = watch(dir, { persistent: true });
|
|
175
|
-
for await (const event of watcher) {
|
|
176
|
-
if (!event.filename) continue;
|
|
177
|
-
const changed = path.resolve(dir, event.filename);
|
|
178
|
-
if (changed === file) scheduleRebuild("change", changed);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
async function main() {
|
|
183
|
-
const watchables = WATCH_PATHS.map((p) => path.join(root, p)).filter((p) => {
|
|
184
|
-
try {
|
|
185
|
-
return existsSync(p);
|
|
186
|
-
} catch {
|
|
187
|
-
return false;
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
if (watchables.length === 0) {
|
|
191
|
-
console.error("[watch-bundle] no watchable paths found (run from repo root)");
|
|
192
|
-
process.exit(1);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
console.log("[watch-bundle] initial build...");
|
|
196
|
-
let initialOk = true;
|
|
197
|
-
try {
|
|
198
|
-
await runBuild();
|
|
199
|
-
} catch (err) {
|
|
200
|
-
console.error("[watch-bundle] initial build failed:", err.message);
|
|
201
|
-
initialOk = false;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (onceMode) {
|
|
205
|
-
process.exit(initialOk ? 0 : 2);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (!initialOk) {
|
|
209
|
-
console.warn("[watch-bundle] initial build failed; watching anyway");
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
let seedCount = 0;
|
|
213
|
-
for (const p of watchables) {
|
|
214
|
-
try {
|
|
215
|
-
const stat = statSync(p);
|
|
216
|
-
if (stat.isDirectory()) {
|
|
217
|
-
seedCount += (await listFiles(p)).length;
|
|
218
|
-
} else if (stat.isFile()) {
|
|
219
|
-
seedCount += 1;
|
|
220
|
-
}
|
|
221
|
-
} catch {
|
|
222
|
-
// skip
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
console.log(`[watch-bundle] seeded with ${seedCount} source files`);
|
|
226
|
-
|
|
227
|
-
const watchJobs = [];
|
|
228
|
-
for (const p of watchables) {
|
|
229
|
-
try {
|
|
230
|
-
const stat = statSync(p);
|
|
231
|
-
watchJobs.push(stat.isDirectory() ? watchDir(p) : watchFile(p));
|
|
232
|
-
} catch (err) {
|
|
233
|
-
console.warn(`[watch-bundle] cannot watch ${p}:`, err?.code ?? err?.message ?? err);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
console.log(`[watch-bundle] watching ${watchables.length} paths; debounce=${debounceMs}ms; Ctrl+C to stop`);
|
|
238
|
-
|
|
239
|
-
let shutting = false;
|
|
240
|
-
const stop = () => {
|
|
241
|
-
if (shutting) return;
|
|
242
|
-
shutting = true;
|
|
243
|
-
console.log("\n[watch-bundle] shutting down...");
|
|
244
|
-
if (pending) {
|
|
245
|
-
clearTimeout(pending);
|
|
246
|
-
pending = null;
|
|
247
|
-
}
|
|
248
|
-
setTimeout(() => process.exit(0), 200);
|
|
249
|
-
};
|
|
250
|
-
process.on("SIGINT", stop);
|
|
251
|
-
process.on("SIGTERM", stop);
|
|
252
|
-
|
|
253
|
-
await Promise.race(watchJobs);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
main().catch((err) => {
|
|
257
|
-
console.error("[watch-bundle] fatal:", err);
|
|
258
|
-
process.exit(1);
|
|
259
|
-
});
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Watchdog harness — a minimal script that mimics the background-runner's
|
|
3
|
-
* watchdog + keepAlive mechanism WITHOUT needing a real team/run manifest.
|
|
4
|
-
*
|
|
5
|
-
* This is used by test/integration/background-runner-watchdog-e2e.test.ts to
|
|
6
|
-
* verify the watchdog fires and force-exits a hung process.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* node --experimental-strip-types scripts/watchdog-harness.ts
|
|
10
|
-
*
|
|
11
|
-
* Env vars:
|
|
12
|
-
* PI_CREW_MAX_RUN_MS — watchdog timeout (ms). Default: 2h.
|
|
13
|
-
* PI_CREW_PARENT_PID — parent guard PID. If parent dies, exit 124.
|
|
14
|
-
* PI_CREW_HARD_KILL_GRACE_MS — grace period before force-exit. Default: 15000.
|
|
15
|
-
*
|
|
16
|
-
* The script:
|
|
17
|
-
* 1. Starts the parent guard (self-terminates if parent dies)
|
|
18
|
-
* 2. Starts a keepAlive interval (prevents event-loop exit)
|
|
19
|
-
* 3. Starts a watchdog timer (fires after MAX_RUN_MS, schedules force-exit)
|
|
20
|
-
* 4. NEVER resolves — simulating a hung team run
|
|
21
|
-
*
|
|
22
|
-
* Expected behaviour: process exits via watchdog force-exit within
|
|
23
|
-
* PI_CREW_MAX_RUN_MS + PI_CREW_HARD_KILL_GRACE_MS milliseconds.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
// ─── Config (from env — mirrors background-runner.ts) ─────────────────────────
|
|
27
|
-
const MAX_BACKGROUND_RUN_MS = (() => {
|
|
28
|
-
const env = Number.parseInt(process.env.PI_CREW_MAX_RUN_MS ?? "", 10);
|
|
29
|
-
return Number.isFinite(env) && env > 0 ? env : 2 * 60 * 60 * 1000; // 2h default
|
|
30
|
-
})();
|
|
31
|
-
|
|
32
|
-
const HARD_KILL_GRACE_MS = Number.parseInt(process.env.PI_CREW_HARD_KILL_GRACE_MS ?? "", 10) || 15_000;
|
|
33
|
-
|
|
34
|
-
// ─── Global error handlers (mirror background-runner.ts patterns) ─────────────
|
|
35
|
-
// These prevent unhandled exceptions/rejections from crashing the process
|
|
36
|
-
// before the watchdog can fire. The harness deliberately hangs, so these are
|
|
37
|
-
// the only way to keep the process alive long enough for the watchdog to trigger.
|
|
38
|
-
process.on("uncaughtException", (err) => {
|
|
39
|
-
console.error(`[watchdog-harness] uncaughtException: ${err.message}`);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
process.on("unhandledRejection", (reason) => {
|
|
43
|
-
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
44
|
-
console.error(`[watchdog-harness] unhandledRejection: ${msg}`);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
// ─── Parent Guard ──────────────────────────────────────────────────────────────
|
|
48
|
-
const parentPid = Number(process.env.PI_CREW_PARENT_PID);
|
|
49
|
-
if (parentPid > 0) {
|
|
50
|
-
const POLL_INTERVAL_MS = 500;
|
|
51
|
-
|
|
52
|
-
function isPidAlive(pid: number): boolean {
|
|
53
|
-
try {
|
|
54
|
-
process.kill(pid, 0);
|
|
55
|
-
return true;
|
|
56
|
-
} catch {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const guard = setInterval(() => {
|
|
62
|
-
// Wrap in try/catch: if isPidAlive throws unexpectedly (e.g. EPERM on
|
|
63
|
-
// some platforms), we don't want the interval itself to crash and prevent
|
|
64
|
-
// the watchdog from ever firing.
|
|
65
|
-
try {
|
|
66
|
-
if (!isPidAlive(parentPid)) {
|
|
67
|
-
clearInterval(guard);
|
|
68
|
-
process.exit(124); // 124 = "parent died" exit code
|
|
69
|
-
}
|
|
70
|
-
} catch (err) {
|
|
71
|
-
// Unexpected error in parent guard — log and continue polling.
|
|
72
|
-
console.error(`[watchdog-harness] parent-guard error: ${err}`);
|
|
73
|
-
}
|
|
74
|
-
}, POLL_INTERVAL_MS);
|
|
75
|
-
// NOTE: intentionally NOT unref'd — must keep event loop alive while parent is alive.
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// ─── KeepAlive (same interval as background-runner.ts) ─────────────────────────
|
|
79
|
-
const keepAlive = setInterval(() => {}, 5000);
|
|
80
|
-
// NOTE: intentionally NOT unref'd — must hold the event loop open while the
|
|
81
|
-
// process is alive. The event loop MUST stay alive so the forceExit setTimeout
|
|
82
|
-
// below can fire. If keepAlive is cleared too early, the event loop drains
|
|
83
|
-
// and all pending setTimeouts are silently cancelled before they fire.
|
|
84
|
-
|
|
85
|
-
// ─── Watchdog ─────────────────────────────────────────────────────────────────
|
|
86
|
-
// Track whether abort+force-exit has already been triggered (prevents double-fire).
|
|
87
|
-
let watchdogFired = false;
|
|
88
|
-
|
|
89
|
-
const watchdogTimer = setTimeout(() => {
|
|
90
|
-
if (watchdogFired) return;
|
|
91
|
-
watchdogFired = true;
|
|
92
|
-
|
|
93
|
-
console.error(
|
|
94
|
-
`[watchdog-harness] WATCHDOG: run exceeded ${MAX_BACKGROUND_RUN_MS}ms — scheduling force-exit in ${HARD_KILL_GRACE_MS}ms (zombie prevention)`,
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
// Hard-exit safety net: if the abort does not propagate within grace period,
|
|
98
|
-
// force-kill so the process cannot linger. Matches background-runner.ts logic.
|
|
99
|
-
// NOTE: keepAlive is NOT cleared here — it keeps the event loop alive so
|
|
100
|
-
// the forceExit setTimeout below can fire. If keepAlive is cleared, the
|
|
101
|
-
// event loop drains and forceExit is silently cancelled (observed: process
|
|
102
|
-
// exits via module-level finally/runCleanup with the last exit code instead).
|
|
103
|
-
const forceExit = setTimeout(() => {
|
|
104
|
-
// Clear keepAlive only at the very end, right before force-exit.
|
|
105
|
-
clearInterval(keepAlive);
|
|
106
|
-
clearTimeout(watchdogTimer);
|
|
107
|
-
process.exit(1);
|
|
108
|
-
}, HARD_KILL_GRACE_MS);
|
|
109
|
-
// NOTE: intentionally NOT unref'd — this timer MUST fire to force-exit.
|
|
110
|
-
}, MAX_BACKGROUND_RUN_MS);
|
|
111
|
-
|
|
112
|
-
// ─── Hung run simulation ──────────────────────────────────────────────────────
|
|
113
|
-
// NEVER resolve this promise — simulates a team run that hangs forever.
|
|
114
|
-
// The watchdog setTimeout above fires and force-exits the process first.
|
|
115
|
-
await new Promise<void>((resolve) => {
|
|
116
|
-
// Intentionally never resolved. The unhandledRejection handler above keeps
|
|
117
|
-
// the process alive until the watchdog fires and calls process.exit().
|
|
118
|
-
void resolve;
|
|
119
|
-
});
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { ExportAdapter, ExportContent } from "./types.ts";
|
|
2
|
-
|
|
3
|
-
export const claudeAdapter: ExportAdapter = {
|
|
4
|
-
toolId: "claude",
|
|
5
|
-
toolName: "Claude Code",
|
|
6
|
-
fileExtension: ".md",
|
|
7
|
-
|
|
8
|
-
getFilePath(content: ExportContent): string {
|
|
9
|
-
return `.claude/commands/pi-crew/${content.id}.md`;
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
formatFile(content: ExportContent): string {
|
|
13
|
-
const tagLines = content.tags.length > 0 ? ["tags:", ...content.tags.map((tag) => ` - ${JSON.stringify(tag)}`)] : [];
|
|
14
|
-
const frontmatter = [
|
|
15
|
-
"---",
|
|
16
|
-
`description: ${JSON.stringify(content.description)}`,
|
|
17
|
-
`category: ${JSON.stringify(content.category)}`,
|
|
18
|
-
...tagLines,
|
|
19
|
-
"---",
|
|
20
|
-
].join("\n");
|
|
21
|
-
return `${frontmatter}\n\n# ${content.name}\n\n${content.body}\n`;
|
|
22
|
-
},
|
|
23
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { ExportAdapter, ExportContent } from "./types.ts";
|
|
2
|
-
|
|
3
|
-
export const codexAdapter: ExportAdapter = {
|
|
4
|
-
toolId: "codex",
|
|
5
|
-
toolName: "Codex",
|
|
6
|
-
fileExtension: ".md",
|
|
7
|
-
|
|
8
|
-
getFilePath(_content: ExportContent): string {
|
|
9
|
-
return "AGENTS.md";
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
formatFile(content: ExportContent): string {
|
|
13
|
-
const tags = content.tags.length > 0 ? ` (${content.tags.join(", ")})` : "";
|
|
14
|
-
return [
|
|
15
|
-
`## ${content.name}${tags}\n`,
|
|
16
|
-
`**Source:** ${content.source.type}/${content.source.name} `,
|
|
17
|
-
`**Category:** ${content.category}\n`,
|
|
18
|
-
content.body,
|
|
19
|
-
].join("\n");
|
|
20
|
-
},
|
|
21
|
-
};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { ExportAdapter, ExportContent } from "./types.ts";
|
|
2
|
-
|
|
3
|
-
export const cursorAdapter: ExportAdapter = {
|
|
4
|
-
toolId: "cursor",
|
|
5
|
-
toolName: "Cursor",
|
|
6
|
-
fileExtension: ".md",
|
|
7
|
-
|
|
8
|
-
getFilePath(content: ExportContent): string {
|
|
9
|
-
return `.cursor/rules/pi-crew-${content.id}.md`;
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
formatFile(content: ExportContent): string {
|
|
13
|
-
const header = `# ${content.name}\n\n> ${content.description}`;
|
|
14
|
-
const tags = content.tags.length > 0 ? `\n\n**Tags:** ${content.tags.join(", ")}` : "";
|
|
15
|
-
return `${header}${tags}\n\n${content.body}\n`;
|
|
16
|
-
},
|
|
17
|
-
};
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import type { AgentConfig } from "../agents/agent-config.ts";
|
|
2
|
-
import type { SkillDescriptor } from "../skills/discover-skills.ts";
|
|
3
|
-
import type { TeamConfig } from "../teams/team-config.ts";
|
|
4
|
-
import { resolveRealContainedPath } from "../utils/safe-paths.ts";
|
|
5
|
-
import type { WorkflowConfig } from "../workflows/workflow-config.ts";
|
|
6
|
-
import { adapterRegistry } from "./registry.ts";
|
|
7
|
-
import type { ExportContent } from "./types.ts";
|
|
8
|
-
|
|
9
|
-
function slugify(value: string): string {
|
|
10
|
-
return value
|
|
11
|
-
.toLowerCase()
|
|
12
|
-
.replace(/[^a-z0-9]+/g, "-")
|
|
13
|
-
.replace(/^-+|-+$/g, "");
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function agentToExportContent(agent: AgentConfig): ExportContent {
|
|
17
|
-
const category = agent.routing?.category ?? "agent";
|
|
18
|
-
const tags = agent.routing?.triggers ?? [];
|
|
19
|
-
return {
|
|
20
|
-
id: slugify(agent.name),
|
|
21
|
-
name: agent.name,
|
|
22
|
-
description: agent.description,
|
|
23
|
-
category,
|
|
24
|
-
tags,
|
|
25
|
-
body: agent.systemPrompt,
|
|
26
|
-
source: { type: "agent", name: agent.name },
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function teamToExportContent(team: TeamConfig): ExportContent {
|
|
31
|
-
const category = team.routing?.category ?? "team";
|
|
32
|
-
const tags = team.routing?.triggers ?? [];
|
|
33
|
-
const rolesDesc = team.roles.map((role) => `- **${role.name}**: ${role.description ?? role.agent}`).join("\n");
|
|
34
|
-
const body = `${team.description}\n\n### Roles\n${rolesDesc}`;
|
|
35
|
-
return {
|
|
36
|
-
id: slugify(team.name),
|
|
37
|
-
name: team.name,
|
|
38
|
-
description: team.description,
|
|
39
|
-
category,
|
|
40
|
-
tags,
|
|
41
|
-
body,
|
|
42
|
-
source: { type: "team", name: team.name },
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function workflowToExportContent(workflow: WorkflowConfig): ExportContent {
|
|
47
|
-
const stepsDesc = workflow.steps.map((step) => `- **${step.id}** (${step.role}): ${step.task}`).join("\n");
|
|
48
|
-
const body = `${workflow.description}\n\n### Steps\n${stepsDesc}`;
|
|
49
|
-
return {
|
|
50
|
-
id: slugify(workflow.name),
|
|
51
|
-
name: workflow.name,
|
|
52
|
-
description: workflow.description,
|
|
53
|
-
category: "workflow",
|
|
54
|
-
tags: [],
|
|
55
|
-
body,
|
|
56
|
-
source: { type: "workflow", name: workflow.name },
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function skillToExportContent(skill: SkillDescriptor): ExportContent {
|
|
61
|
-
return {
|
|
62
|
-
id: slugify(skill.name),
|
|
63
|
-
name: skill.name,
|
|
64
|
-
description: skill.description || `Skill: ${skill.name}`,
|
|
65
|
-
category: "skill",
|
|
66
|
-
tags: [],
|
|
67
|
-
body: `Skill loaded from ${skill.source}: ${skill.path}`,
|
|
68
|
-
source: { type: "skill", name: skill.name },
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export type ExportableResource =
|
|
73
|
-
| { kind: "agent"; config: AgentConfig }
|
|
74
|
-
| { kind: "team"; config: TeamConfig }
|
|
75
|
-
| { kind: "workflow"; config: WorkflowConfig }
|
|
76
|
-
| { kind: "skill"; config: SkillDescriptor };
|
|
77
|
-
|
|
78
|
-
export function resourcesToExportContent(resources: ExportableResource[]): ExportContent[] {
|
|
79
|
-
const results: ExportContent[] = [];
|
|
80
|
-
for (const resource of resources) {
|
|
81
|
-
switch (resource.kind) {
|
|
82
|
-
case "agent":
|
|
83
|
-
results.push(agentToExportContent(resource.config));
|
|
84
|
-
break;
|
|
85
|
-
case "team":
|
|
86
|
-
results.push(teamToExportContent(resource.config));
|
|
87
|
-
break;
|
|
88
|
-
case "workflow":
|
|
89
|
-
results.push(workflowToExportContent(resource.config));
|
|
90
|
-
break;
|
|
91
|
-
case "skill":
|
|
92
|
-
results.push(skillToExportContent(resource.config));
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return results;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export interface ToolExportResult {
|
|
100
|
-
toolId: string;
|
|
101
|
-
files: Array<{ path: string; content: string }>;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export function generateToolExport(toolId: string, resources: ExportableResource[], projectRoot?: string): ToolExportResult {
|
|
105
|
-
const adapter = adapterRegistry.get(toolId);
|
|
106
|
-
if (!adapter) {
|
|
107
|
-
throw new Error(
|
|
108
|
-
`Unknown export adapter: ${toolId}. Available: ${adapterRegistry
|
|
109
|
-
.getAll()
|
|
110
|
-
.map((a) => a.toolId)
|
|
111
|
-
.join(", ")}`,
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
const contents = resourcesToExportContent(resources);
|
|
115
|
-
const files = contents.map((content): { path: string; content: string } => {
|
|
116
|
-
const filePath = adapter.getFilePath(content);
|
|
117
|
-
// Validate path containment when a project root is provided
|
|
118
|
-
if (projectRoot) {
|
|
119
|
-
try {
|
|
120
|
-
resolveRealContainedPath(projectRoot, filePath);
|
|
121
|
-
} catch (e) {
|
|
122
|
-
throw new Error(
|
|
123
|
-
`Export path '${filePath}' escapes project root '${projectRoot}': ${e instanceof Error ? e.message : String(e)}`,
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
return {
|
|
128
|
-
path: filePath,
|
|
129
|
-
content: adapter.formatFile(content),
|
|
130
|
-
};
|
|
131
|
-
});
|
|
132
|
-
// Merge duplicate file paths (e.g., codex adapter maps everything to AGENTS.md)
|
|
133
|
-
const merged = new Map<string, string>();
|
|
134
|
-
for (const f of files) {
|
|
135
|
-
const existing = merged.get(f.path);
|
|
136
|
-
merged.set(f.path, existing ? `${existing}\n\n${f.content}` : f.content);
|
|
137
|
-
}
|
|
138
|
-
const mergedFiles = [...merged.entries()].map(([p, content]) => ({
|
|
139
|
-
path: p,
|
|
140
|
-
content,
|
|
141
|
-
}));
|
|
142
|
-
return { toolId, files: mergedFiles };
|
|
143
|
-
}
|
package/src/adapters/index.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export { claudeAdapter } from "./claude-adapter.ts";
|
|
2
|
-
export { codexAdapter } from "./codex-adapter.ts";
|
|
3
|
-
export { cursorAdapter } from "./cursor-adapter.ts";
|
|
4
|
-
export { generateToolExport, resourcesToExportContent } from "./export-util.ts";
|
|
5
|
-
export { adapterRegistry, createAdapterRegistry } from "./registry.ts";
|
|
6
|
-
export type { AdapterRegistry, ExportAdapter, ExportContent } from "./types.ts";
|
|
7
|
-
|
|
8
|
-
import { claudeAdapter } from "./claude-adapter.ts";
|
|
9
|
-
import { codexAdapter } from "./codex-adapter.ts";
|
|
10
|
-
import { cursorAdapter } from "./cursor-adapter.ts";
|
|
11
|
-
import { adapterRegistry } from "./registry.ts";
|
|
12
|
-
|
|
13
|
-
adapterRegistry.register(claudeAdapter);
|
|
14
|
-
adapterRegistry.register(cursorAdapter);
|
|
15
|
-
adapterRegistry.register(codexAdapter);
|
package/src/adapters/registry.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { AdapterRegistry, ExportAdapter } from "./types.ts";
|
|
2
|
-
|
|
3
|
-
export function createAdapterRegistry(): AdapterRegistry {
|
|
4
|
-
const adapters = new Map<string, ExportAdapter>();
|
|
5
|
-
return {
|
|
6
|
-
get(toolId: string): ExportAdapter | undefined {
|
|
7
|
-
return adapters.get(toolId);
|
|
8
|
-
},
|
|
9
|
-
getAll(): ExportAdapter[] {
|
|
10
|
-
return [...adapters.values()];
|
|
11
|
-
},
|
|
12
|
-
register(adapter: ExportAdapter): void {
|
|
13
|
-
adapters.set(adapter.toolId, adapter);
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const adapterRegistry: AdapterRegistry = createAdapterRegistry();
|
package/src/adapters/types.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export interface ExportContent {
|
|
2
|
-
id: string;
|
|
3
|
-
name: string;
|
|
4
|
-
description: string;
|
|
5
|
-
category: string;
|
|
6
|
-
tags: string[];
|
|
7
|
-
body: string;
|
|
8
|
-
source: { type: "agent" | "team" | "workflow" | "skill"; name: string };
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface ExportAdapter {
|
|
12
|
-
readonly toolId: string;
|
|
13
|
-
readonly toolName: string;
|
|
14
|
-
readonly fileExtension: string;
|
|
15
|
-
getFilePath(content: ExportContent): string;
|
|
16
|
-
formatFile(content: ExportContent): string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface AdapterRegistry {
|
|
20
|
-
get(toolId: string): ExportAdapter | undefined;
|
|
21
|
-
getAll(): ExportAdapter[];
|
|
22
|
-
register(adapter: ExportAdapter): void;
|
|
23
|
-
}
|