@cluesmith/codev 3.2.4 → 3.3.1
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/dashboard-dist/assets/index-BZRTEMtH.css +32 -0
- package/dashboard-dist/assets/{index-BZ1x7x1X.js → index-D3XaKpZW.js} +46 -44
- package/dashboard-dist/assets/index-D3XaKpZW.js.map +1 -0
- package/dashboard-dist/index.html +2 -2
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +154 -0
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/cleanup.d.ts.map +1 -1
- package/dist/agent-farm/commands/cleanup.js +16 -0
- package/dist/agent-farm/commands/cleanup.js.map +1 -1
- package/dist/agent-farm/commands/inbox.d.ts +42 -0
- package/dist/agent-farm/commands/inbox.d.ts.map +1 -0
- package/dist/agent-farm/commands/inbox.js +129 -0
- package/dist/agent-farm/commands/inbox.js.map +1 -0
- package/dist/agent-farm/commands/interrupt.d.ts +20 -0
- package/dist/agent-farm/commands/interrupt.d.ts.map +1 -0
- package/dist/agent-farm/commands/interrupt.js +65 -0
- package/dist/agent-farm/commands/interrupt.js.map +1 -0
- package/dist/agent-farm/commands/reset/constants.d.ts +52 -0
- package/dist/agent-farm/commands/reset/constants.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/constants.js +52 -0
- package/dist/agent-farm/commands/reset/constants.js.map +1 -0
- package/dist/agent-farm/commands/reset/context.d.ts +230 -0
- package/dist/agent-farm/commands/reset/context.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/context.js +428 -0
- package/dist/agent-farm/commands/reset/context.js.map +1 -0
- package/dist/agent-farm/commands/reset/index.d.ts +192 -0
- package/dist/agent-farm/commands/reset/index.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/index.js +488 -0
- package/dist/agent-farm/commands/reset/index.js.map +1 -0
- package/dist/agent-farm/commands/reset/receipt.d.ts +97 -0
- package/dist/agent-farm/commands/reset/receipt.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/receipt.js +149 -0
- package/dist/agent-farm/commands/reset/receipt.js.map +1 -0
- package/dist/agent-farm/commands/reset/reorient.d.ts +117 -0
- package/dist/agent-farm/commands/reset/reorient.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/reorient.js +313 -0
- package/dist/agent-farm/commands/reset/reorient.js.map +1 -0
- package/dist/agent-farm/commands/reset.d.ts +34 -0
- package/dist/agent-farm/commands/reset.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset.js +309 -0
- package/dist/agent-farm/commands/reset.js.map +1 -0
- package/dist/agent-farm/commands/send.d.ts.map +1 -1
- package/dist/agent-farm/commands/send.js +49 -8
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.d.ts +105 -6
- package/dist/agent-farm/commands/spawn-worktree.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js +289 -66
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
- package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn.js +13 -1
- package/dist/agent-farm/commands/spawn.js.map +1 -1
- package/dist/agent-farm/commands/status.d.ts.map +1 -1
- package/dist/agent-farm/commands/status.js +80 -8
- package/dist/agent-farm/commands/status.js.map +1 -1
- package/dist/agent-farm/commands/tower.d.ts.map +1 -1
- package/dist/agent-farm/commands/tower.js +13 -0
- package/dist/agent-farm/commands/tower.js.map +1 -1
- package/dist/agent-farm/db/index.d.ts +1 -1
- package/dist/agent-farm/db/index.d.ts.map +1 -1
- package/dist/agent-farm/db/index.js +80 -1
- package/dist/agent-farm/db/index.js.map +1 -1
- package/dist/agent-farm/db/mailbox.d.ts +222 -0
- package/dist/agent-farm/db/mailbox.d.ts.map +1 -0
- package/dist/agent-farm/db/mailbox.js +304 -0
- package/dist/agent-farm/db/mailbox.js.map +1 -0
- package/dist/agent-farm/db/schema.d.ts +1 -1
- package/dist/agent-farm/db/schema.d.ts.map +1 -1
- package/dist/agent-farm/db/schema.js +35 -0
- package/dist/agent-farm/db/schema.js.map +1 -1
- package/dist/agent-farm/db/types.d.ts +45 -0
- package/dist/agent-farm/db/types.d.ts.map +1 -1
- package/dist/agent-farm/db/types.js.map +1 -1
- package/dist/agent-farm/lib/builder-lookup.d.ts +1 -1
- package/dist/agent-farm/lib/builder-lookup.js +2 -2
- package/dist/agent-farm/lib/builder-lookup.js.map +1 -1
- package/dist/agent-farm/lib/reconnect-backoff.d.ts +64 -0
- package/dist/agent-farm/lib/reconnect-backoff.d.ts.map +1 -0
- package/dist/agent-farm/lib/reconnect-backoff.js +57 -0
- package/dist/agent-farm/lib/reconnect-backoff.js.map +1 -0
- package/dist/agent-farm/lib/tower-client.d.ts +16 -6
- package/dist/agent-farm/lib/tower-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tower-client.js +37 -6
- package/dist/agent-farm/lib/tower-client.js.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.d.ts +69 -1
- package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.js +225 -30
- package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
- package/dist/agent-farm/servers/canvas-relay.d.ts +60 -0
- package/dist/agent-farm/servers/canvas-relay.d.ts.map +1 -0
- package/dist/agent-farm/servers/canvas-relay.js +376 -0
- package/dist/agent-farm/servers/canvas-relay.js.map +1 -0
- package/dist/agent-farm/servers/cron-delivery.d.ts +72 -0
- package/dist/agent-farm/servers/cron-delivery.d.ts.map +1 -0
- package/dist/agent-farm/servers/cron-delivery.js +80 -0
- package/dist/agent-farm/servers/cron-delivery.js.map +1 -0
- package/dist/agent-farm/servers/delayed-send.d.ts +85 -0
- package/dist/agent-farm/servers/delayed-send.d.ts.map +1 -0
- package/dist/agent-farm/servers/delayed-send.js +165 -0
- package/dist/agent-farm/servers/delayed-send.js.map +1 -0
- package/dist/agent-farm/servers/gate-profiles.d.ts +67 -0
- package/dist/agent-farm/servers/gate-profiles.d.ts.map +1 -0
- package/dist/agent-farm/servers/gate-profiles.js +113 -0
- package/dist/agent-farm/servers/gate-profiles.js.map +1 -0
- package/dist/agent-farm/servers/mailbox-delivery.d.ts +370 -0
- package/dist/agent-farm/servers/mailbox-delivery.d.ts.map +1 -0
- package/dist/agent-farm/servers/mailbox-delivery.js +617 -0
- package/dist/agent-farm/servers/mailbox-delivery.js.map +1 -0
- package/dist/agent-farm/servers/mailbox-wiring.d.ts +125 -0
- package/dist/agent-farm/servers/mailbox-wiring.d.ts.map +1 -0
- package/dist/agent-farm/servers/mailbox-wiring.js +425 -0
- package/dist/agent-farm/servers/mailbox-wiring.js.map +1 -0
- package/dist/agent-farm/servers/message-write.d.ts +53 -1
- package/dist/agent-farm/servers/message-write.d.ts.map +1 -1
- package/dist/agent-farm/servers/message-write.js +63 -0
- package/dist/agent-farm/servers/message-write.js.map +1 -1
- package/dist/agent-farm/servers/overview.d.ts +19 -0
- package/dist/agent-farm/servers/overview.d.ts.map +1 -1
- package/dist/agent-farm/servers/overview.js +100 -4
- package/dist/agent-farm/servers/overview.js.map +1 -1
- package/dist/agent-farm/servers/render-gate.d.ts +141 -0
- package/dist/agent-farm/servers/render-gate.d.ts.map +1 -0
- package/dist/agent-farm/servers/render-gate.js +251 -0
- package/dist/agent-farm/servers/render-gate.js.map +1 -0
- package/dist/agent-farm/servers/session-submit.d.ts +90 -0
- package/dist/agent-farm/servers/session-submit.d.ts.map +1 -0
- package/dist/agent-farm/servers/session-submit.js +127 -0
- package/dist/agent-farm/servers/session-submit.js.map +1 -0
- package/dist/agent-farm/servers/tower-cron.d.ts +10 -7
- package/dist/agent-farm/servers/tower-cron.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-cron.js +58 -53
- package/dist/agent-farm/servers/tower-cron.js.map +1 -1
- package/dist/agent-farm/servers/tower-instances.d.ts +14 -2
- package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-instances.js +78 -16
- package/dist/agent-farm/servers/tower-instances.js.map +1 -1
- package/dist/agent-farm/servers/tower-messages.d.ts +38 -1
- package/dist/agent-farm/servers/tower-messages.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-messages.js +106 -1
- package/dist/agent-farm/servers/tower-messages.js.map +1 -1
- package/dist/agent-farm/servers/tower-routes.d.ts +16 -4
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-routes.js +826 -145
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +188 -34
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts +23 -2
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.js +134 -127
- package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
- package/dist/agent-farm/servers/tower-tunnel.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-tunnel.js +63 -4
- package/dist/agent-farm/servers/tower-tunnel.js.map +1 -1
- package/dist/agent-farm/servers/tower-types.d.ts +2 -1
- package/dist/agent-farm/servers/tower-types.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-utils.d.ts +64 -1
- package/dist/agent-farm/servers/tower-utils.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-utils.js +168 -1
- package/dist/agent-farm/servers/tower-utils.js.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.d.ts +6 -1
- package/dist/agent-farm/servers/tower-websocket.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.js +95 -57
- package/dist/agent-farm/servers/tower-websocket.js.map +1 -1
- package/dist/agent-farm/servers/write-queue.d.ts +35 -0
- package/dist/agent-farm/servers/write-queue.d.ts.map +1 -0
- package/dist/agent-farm/servers/write-queue.js +56 -0
- package/dist/agent-farm/servers/write-queue.js.map +1 -0
- package/dist/agent-farm/types.d.ts +39 -0
- package/dist/agent-farm/types.d.ts.map +1 -1
- package/dist/agent-farm/utils/agent-names.d.ts +2 -2
- package/dist/agent-farm/utils/agent-names.d.ts.map +1 -1
- package/dist/agent-farm/utils/agent-names.js +3 -3
- package/dist/agent-farm/utils/agent-names.js.map +1 -1
- package/dist/agent-farm/utils/architect-name.d.ts +2 -2
- package/dist/agent-farm/utils/architect-name.d.ts.map +1 -1
- package/dist/agent-farm/utils/architect-name.js +3 -3
- package/dist/agent-farm/utils/architect-name.js.map +1 -1
- package/dist/agent-farm/utils/config.d.ts +13 -0
- package/dist/agent-farm/utils/config.d.ts.map +1 -1
- package/dist/agent-farm/utils/config.js +33 -1
- package/dist/agent-farm/utils/config.js.map +1 -1
- package/dist/agent-farm/utils/harness.d.ts +103 -7
- package/dist/agent-farm/utils/harness.d.ts.map +1 -1
- package/dist/agent-farm/utils/harness.js +126 -19
- package/dist/agent-farm/utils/harness.js.map +1 -1
- package/dist/agent-farm/utils/message-format.d.ts +8 -0
- package/dist/agent-farm/utils/message-format.d.ts.map +1 -1
- package/dist/agent-farm/utils/message-format.js +20 -0
- package/dist/agent-farm/utils/message-format.js.map +1 -1
- package/dist/agent-farm/utils/server-utils.d.ts +80 -4
- package/dist/agent-farm/utils/server-utils.d.ts.map +1 -1
- package/dist/agent-farm/utils/server-utils.js +286 -5
- package/dist/agent-farm/utils/server-utils.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -32
- package/dist/cli.js.map +1 -1
- package/dist/commands/consult/cli-options.d.ts +34 -0
- package/dist/commands/consult/cli-options.d.ts.map +1 -0
- package/dist/commands/consult/cli-options.js +67 -0
- package/dist/commands/consult/cli-options.js.map +1 -0
- package/dist/commands/consult/index.d.ts +56 -2
- package/dist/commands/consult/index.d.ts.map +1 -1
- package/dist/commands/consult/index.js +272 -28
- package/dist/commands/consult/index.js.map +1 -1
- package/dist/commands/consult/metrics.d.ts +42 -0
- package/dist/commands/consult/metrics.d.ts.map +1 -1
- package/dist/commands/consult/metrics.js +129 -9
- package/dist/commands/consult/metrics.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +71 -19
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/porch/checks.d.ts +23 -0
- package/dist/commands/porch/checks.d.ts.map +1 -1
- package/dist/commands/porch/checks.js +60 -0
- package/dist/commands/porch/checks.js.map +1 -1
- package/dist/commands/porch/config.d.ts +20 -0
- package/dist/commands/porch/config.d.ts.map +1 -1
- package/dist/commands/porch/config.js +20 -0
- package/dist/commands/porch/config.js.map +1 -1
- package/dist/commands/porch/index.js +21 -28
- package/dist/commands/porch/index.js.map +1 -1
- package/dist/commands/porch/next.d.ts.map +1 -1
- package/dist/commands/porch/next.js +2 -41
- package/dist/commands/porch/next.js.map +1 -1
- package/dist/lib/config.d.ts +69 -3
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +67 -3
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/consult-lanes.d.ts +149 -0
- package/dist/lib/consult-lanes.d.ts.map +1 -0
- package/dist/lib/consult-lanes.js +360 -0
- package/dist/lib/consult-lanes.js.map +1 -0
- package/dist/lib/forge-contracts.d.ts +9 -0
- package/dist/lib/forge-contracts.d.ts.map +1 -1
- package/dist/lib/forge-contracts.js.map +1 -1
- package/dist/lib/github.d.ts +15 -1
- package/dist/lib/github.d.ts.map +1 -1
- package/dist/lib/github.js +18 -1
- package/dist/lib/github.js.map +1 -1
- package/dist/lib/prompt-behavior-metrics.d.ts +67 -0
- package/dist/lib/prompt-behavior-metrics.d.ts.map +1 -0
- package/dist/lib/prompt-behavior-metrics.js +290 -0
- package/dist/lib/prompt-behavior-metrics.js.map +1 -0
- package/dist/lib/skeleton.d.ts +22 -1
- package/dist/lib/skeleton.d.ts.map +1 -1
- package/dist/lib/skeleton.js +120 -0
- package/dist/lib/skeleton.js.map +1 -1
- package/dist/lib/test-env.d.ts +74 -0
- package/dist/lib/test-env.d.ts.map +1 -0
- package/dist/lib/test-env.js +92 -0
- package/dist/lib/test-env.js.map +1 -0
- package/dist/terminal/attach-replay.d.ts +39 -0
- package/dist/terminal/attach-replay.d.ts.map +1 -0
- package/dist/terminal/attach-replay.js +76 -0
- package/dist/terminal/attach-replay.js.map +1 -0
- package/dist/terminal/pty-manager.d.ts +2 -0
- package/dist/terminal/pty-manager.d.ts.map +1 -1
- package/dist/terminal/pty-manager.js +51 -23
- package/dist/terminal/pty-manager.js.map +1 -1
- package/dist/terminal/pty-session.d.ts +201 -1
- package/dist/terminal/pty-session.d.ts.map +1 -1
- package/dist/terminal/pty-session.js +327 -46
- package/dist/terminal/pty-session.js.map +1 -1
- package/dist/terminal/ring-buffer.d.ts +39 -6
- package/dist/terminal/ring-buffer.d.ts.map +1 -1
- package/dist/terminal/ring-buffer.js +74 -6
- package/dist/terminal/ring-buffer.js.map +1 -1
- package/dist/terminal/session-manager.d.ts +53 -0
- package/dist/terminal/session-manager.d.ts.map +1 -1
- package/dist/terminal/session-manager.js +94 -9
- package/dist/terminal/session-manager.js.map +1 -1
- package/dist/terminal/session-screen.d.ts +116 -0
- package/dist/terminal/session-screen.d.ts.map +1 -0
- package/dist/terminal/session-screen.js +180 -0
- package/dist/terminal/session-screen.js.map +1 -0
- package/dist/terminal/shellper-main.js +2 -1
- package/dist/terminal/shellper-main.js.map +1 -1
- package/dist/terminal/shellper-process.d.ts +1 -1
- package/dist/terminal/shellper-process.d.ts.map +1 -1
- package/dist/terminal/shellper-process.js +17 -8
- package/dist/terminal/shellper-process.js.map +1 -1
- package/dist/terminal/shellper-replay-buffer.d.ts +69 -7
- package/dist/terminal/shellper-replay-buffer.d.ts.map +1 -1
- package/dist/terminal/shellper-replay-buffer.js +167 -31
- package/dist/terminal/shellper-replay-buffer.js.map +1 -1
- package/package.json +13 -8
- package/scripts/forge/gitea/pr-view.sh +4 -1
- package/scripts/forge/github/pr-view.sh +1 -1
- package/scripts/forge/gitlab/pr-view.sh +4 -1
- package/skeleton/.claude/skills/afx/SKILL.md +68 -1
- package/skeleton/.claude/skills/arch-init/SKILL.md +22 -9
- package/skeleton/.claude/skills/arch-save/SKILL.md +183 -0
- package/skeleton/.claude/skills/codev/SKILL.md +31 -0
- package/skeleton/.claude/skills/runnable-worktrees/SKILL.md +119 -0
- package/skeleton/.codex/skills/afx/SKILL.md +68 -1
- package/skeleton/.codex/skills/arch-init/SKILL.md +22 -9
- package/skeleton/.codex/skills/arch-save/SKILL.md +183 -0
- package/skeleton/.codex/skills/codev/SKILL.md +31 -0
- package/skeleton/.codex/skills/runnable-worktrees/SKILL.md +119 -0
- package/skeleton/protocols/air/builder-prompt.md +28 -47
- package/skeleton/protocols/air/consult-types/impl-review.md +17 -34
- package/skeleton/protocols/air/consult-types/pr-review.md +14 -37
- package/skeleton/protocols/air/prompts/implement.md +20 -73
- package/skeleton/protocols/air/prompts/pr.md +22 -54
- package/skeleton/protocols/air/protocol.md +40 -71
- package/skeleton/protocols/aspir/builder-prompt.md +29 -66
- package/skeleton/protocols/aspir/consult-types/impl-review.md +17 -44
- package/skeleton/protocols/aspir/consult-types/phase-review.md +17 -44
- package/skeleton/protocols/aspir/consult-types/plan-review.md +14 -38
- package/skeleton/protocols/aspir/consult-types/pr-review.md +13 -39
- package/skeleton/protocols/aspir/consult-types/spec-review.md +13 -33
- package/skeleton/protocols/aspir/prompts/implement.md +27 -196
- package/skeleton/protocols/aspir/prompts/plan.md +21 -85
- package/skeleton/protocols/aspir/prompts/review.md +29 -228
- package/skeleton/protocols/aspir/prompts/specify.md +25 -111
- package/skeleton/protocols/aspir/protocol.json +10 -0
- package/skeleton/protocols/aspir/protocol.md +36 -82
- package/skeleton/protocols/bugfix/builder-prompt.md +23 -45
- package/skeleton/protocols/bugfix/consult-types/impl-review.md +21 -45
- package/skeleton/protocols/bugfix/consult-types/pr-review.md +18 -52
- package/skeleton/protocols/bugfix/prompts/fix.md +16 -61
- package/skeleton/protocols/bugfix/prompts/investigate.md +18 -62
- package/skeleton/protocols/bugfix/prompts/pr.md +22 -57
- package/skeleton/protocols/bugfix/protocol.md +44 -50
- package/skeleton/protocols/experiment/builder-prompt.md +25 -58
- package/skeleton/protocols/experiment/protocol.md +22 -188
- package/skeleton/protocols/experiment/templates/notes.md +11 -71
- package/skeleton/protocols/maintain/builder-prompt.md +24 -45
- package/skeleton/protocols/maintain/consult-types/impl-review.md +17 -44
- package/skeleton/protocols/maintain/consult-types/pr-review.md +13 -39
- package/skeleton/protocols/maintain/prompts/maintain.md +1 -1
- package/skeleton/protocols/maintain/protocol.md +32 -266
- package/skeleton/protocols/maintain/templates/maintenance-run.md +11 -0
- package/skeleton/protocols/pir/builder-prompt.md +31 -64
- package/skeleton/protocols/pir/consult-types/impl-review.md +17 -50
- package/skeleton/protocols/pir/consult-types/pr-review.md +11 -40
- package/skeleton/protocols/pir/prompts/implement.md +2 -3
- package/skeleton/protocols/pir/prompts/plan.md +1 -4
- package/skeleton/protocols/pir/prompts/review.md +2 -2
- package/skeleton/protocols/pir/protocol.md +54 -177
- package/skeleton/protocols/research/builder-prompt.md +27 -58
- package/skeleton/protocols/research/protocol.md +28 -153
- package/skeleton/protocols/spike/builder-prompt.md +30 -48
- package/skeleton/protocols/spike/protocol.md +24 -107
- package/skeleton/protocols/spike/templates/findings.md +9 -39
- package/skeleton/protocols/spir/builder-prompt.md +33 -62
- package/skeleton/protocols/spir/consult-types/impl-review.md +17 -44
- package/skeleton/protocols/spir/consult-types/phase-review.md +17 -44
- package/skeleton/protocols/spir/consult-types/plan-review.md +14 -38
- package/skeleton/protocols/spir/consult-types/pr-review.md +13 -39
- package/skeleton/protocols/spir/consult-types/spec-review.md +13 -33
- package/skeleton/protocols/spir/prompts/implement.md +26 -195
- package/skeleton/protocols/spir/prompts/plan.md +20 -84
- package/skeleton/protocols/spir/prompts/review.md +28 -227
- package/skeleton/protocols/spir/prompts/specify.md +24 -110
- package/skeleton/protocols/spir/protocol.json +10 -0
- package/skeleton/protocols/spir/protocol.md +84 -633
- package/skeleton/protocols/spir/templates/plan.md +28 -147
- package/skeleton/protocols/spir/templates/review.md +21 -80
- package/skeleton/protocols/spir/templates/spec.md +24 -118
- package/skeleton/resources/commands/agent-farm.md +262 -0
- package/skeleton/resources/commands/consult.md +236 -8
- package/skeleton/resources/commands/overview.md +1 -0
- package/skeleton/roles/architect.md +67 -317
- package/skeleton/roles/builder.md +76 -191
- package/skeleton/templates/AGENTS.md +2 -0
- package/skeleton/templates/CLAUDE.md +2 -0
- package/templates/3d-viewer.html +32 -4
- package/templates/open.html +58 -12
- package/templates/tower.html +65 -9
- package/templates/vendor/three-3MFLoader.js +1478 -0
- package/templates/vendor/three-STLLoader.js +410 -0
- package/templates/vendor/three-TrackballControls.js +828 -0
- package/templates/vendor/three-fflate.module.js +2474 -0
- package/templates/vendor/three.module.js +53044 -0
- package/dashboard-dist/assets/index-BZ1x7x1X.js.map +0 -1
- package/dashboard-dist/assets/index-DB1KBSNE.css +0 -32
- package/dist/agent-farm/servers/send-buffer.d.ts +0 -59
- package/dist/agent-farm/servers/send-buffer.d.ts.map +0 -1
- package/dist/agent-farm/servers/send-buffer.js +0 -116
- package/dist/agent-farm/servers/send-buffer.js.map +0 -1
- package/skeleton/porch/prompts/defend.md +0 -108
- package/skeleton/porch/prompts/diagnose.md +0 -70
- package/skeleton/porch/prompts/evaluate.md +0 -132
- package/skeleton/porch/prompts/fix.md +0 -59
- package/skeleton/porch/prompts/implement.md +0 -88
- package/skeleton/porch/prompts/plan.md +0 -74
- package/skeleton/porch/prompts/pr.md +0 -84
- package/skeleton/porch/prompts/review.md +0 -249
- package/skeleton/porch/prompts/specify.md +0 -53
- package/skeleton/porch/prompts/test.md +0 -63
- package/skeleton/protocols/aspir/templates/plan.md +0 -184
- package/skeleton/protocols/aspir/templates/review.md +0 -120
- package/skeleton/protocols/aspir/templates/spec.md +0 -154
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canvas command relay + live view registry for Tower (spec 1401).
|
|
3
|
+
*
|
|
4
|
+
* Lets any CONTROLLER (a control device, a companion app, a test harness) drive an open
|
|
5
|
+
* artifact-canvas view over Tower's existing channels:
|
|
6
|
+
* - host -> Tower: REST on `/api/canvas/views` (register / heartbeat / unregister).
|
|
7
|
+
* - controller -> Tower: REST POST `/api/canvas/command`.
|
|
8
|
+
* - Tower -> host: SSE `canvas-command` at /api/events, addressed to one resolved view.
|
|
9
|
+
*
|
|
10
|
+
* Why this is not just another verb on `command-relay.ts`: that relay is a fire-and-forget
|
|
11
|
+
* broadcast which answers `{ok:true}` whether or not anything is listening. It structurally
|
|
12
|
+
* cannot say "no canvas is open", and it cannot pick one view among several. Both are hard
|
|
13
|
+
* requirements here, so Tower keeps a registry of live views, resolves exactly ONE target, and
|
|
14
|
+
* reports which one it drove.
|
|
15
|
+
*
|
|
16
|
+
* The registry is deliberately in-memory and lease-based: a view is a live UI surface, not
|
|
17
|
+
* durable state, and a host that dies without unregistering must age out rather than linger as
|
|
18
|
+
* a ghost that silently swallows commands.
|
|
19
|
+
*/
|
|
20
|
+
import * as path from 'node:path';
|
|
21
|
+
import * as fs from 'node:fs';
|
|
22
|
+
import { randomUUID } from 'node:crypto';
|
|
23
|
+
import { parseJsonBody } from '../utils/server-utils.js';
|
|
24
|
+
// Wire names — the canonical contract lives in @cluesmith/codev-types
|
|
25
|
+
// (CANVAS_COMMAND_ROUTE / CANVAS_VIEWS_ROUTE / CANVAS_COMMAND_EVENT) and must match these. They
|
|
26
|
+
// are re-declared locally because codev runs UNBUNDLED from dist/ and codev-types is a
|
|
27
|
+
// compile-time-only (type) dependency with no runtime dist on the codev side, so a runtime value
|
|
28
|
+
// import from it would not resolve. Same reason command-relay.ts re-declares COMMAND_ROUTE.
|
|
29
|
+
export const CANVAS_COMMAND_ROUTE = '/api/canvas/command';
|
|
30
|
+
export const CANVAS_VIEWS_ROUTE = '/api/canvas/views';
|
|
31
|
+
const CANVAS_COMMAND_EVENT = 'canvas-command';
|
|
32
|
+
/** Everything under this prefix belongs to this module. */
|
|
33
|
+
export const CANVAS_ROUTE_PREFIX = '/api/canvas/';
|
|
34
|
+
/** How often a host should heartbeat to keep its lease alive. */
|
|
35
|
+
export const CANVAS_VIEW_HEARTBEAT_MS = 30_000;
|
|
36
|
+
/**
|
|
37
|
+
* How long a view survives without a heartbeat. Three missed beats: long enough to ride out a
|
|
38
|
+
* busy event loop or a paused debugger, short enough that a killed host's ghost view stops
|
|
39
|
+
* absorbing commands quickly.
|
|
40
|
+
*/
|
|
41
|
+
export const CANVAS_VIEW_LEASE_MS = 90_000;
|
|
42
|
+
/**
|
|
43
|
+
* The closed command vocabulary as runtime data, so an unknown command can be rejected. The
|
|
44
|
+
* assertion below fails to compile if `CanvasCommand` gains a member that is missing here, which
|
|
45
|
+
* is what keeps Tower's validation from silently falling behind the contract.
|
|
46
|
+
*/
|
|
47
|
+
const CANVAS_COMMANDS = [
|
|
48
|
+
'block-next',
|
|
49
|
+
'block-prev',
|
|
50
|
+
'comment-next',
|
|
51
|
+
'comment-prev',
|
|
52
|
+
'heading-next',
|
|
53
|
+
'heading-prev',
|
|
54
|
+
'column-forward',
|
|
55
|
+
'column-back',
|
|
56
|
+
'viewport-down',
|
|
57
|
+
'viewport-up',
|
|
58
|
+
'doc-start',
|
|
59
|
+
'doc-end',
|
|
60
|
+
'composer-open',
|
|
61
|
+
'composer-submit',
|
|
62
|
+
'composer-cancel',
|
|
63
|
+
'composer-open-or-submit',
|
|
64
|
+
'reading-mode-toggle',
|
|
65
|
+
];
|
|
66
|
+
/** The commands `count` is valid on. Same drift protection as above. */
|
|
67
|
+
const TRAVERSAL_COMMANDS = [
|
|
68
|
+
'block-next',
|
|
69
|
+
'block-prev',
|
|
70
|
+
'comment-next',
|
|
71
|
+
'comment-prev',
|
|
72
|
+
'heading-next',
|
|
73
|
+
'heading-prev',
|
|
74
|
+
'column-forward',
|
|
75
|
+
'column-back',
|
|
76
|
+
'viewport-down',
|
|
77
|
+
'viewport-up',
|
|
78
|
+
];
|
|
79
|
+
const views = new Map();
|
|
80
|
+
let sequence = 0;
|
|
81
|
+
let deps = null;
|
|
82
|
+
let inited = false;
|
|
83
|
+
/** Wire the module's dependencies. */
|
|
84
|
+
export function initCanvasRelay(d) {
|
|
85
|
+
deps = d;
|
|
86
|
+
inited = true;
|
|
87
|
+
}
|
|
88
|
+
/** Tear down state (used by tests and shutdown). */
|
|
89
|
+
export function shutdownCanvasRelay() {
|
|
90
|
+
views.clear();
|
|
91
|
+
sequence = 0;
|
|
92
|
+
deps = null;
|
|
93
|
+
inited = false;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Resolve a path the same way the file-tab registry does, so the two agree on what "the same
|
|
97
|
+
* file" means: follow symlinks, fall back to resolving the parent when the file itself does not
|
|
98
|
+
* exist, and finally to a plain absolute path.
|
|
99
|
+
*/
|
|
100
|
+
function canonicalPath(raw) {
|
|
101
|
+
try {
|
|
102
|
+
return fs.realpathSync(raw);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
try {
|
|
106
|
+
return path.join(fs.realpathSync(path.dirname(raw)), path.basename(raw));
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return path.resolve(raw);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/** Drop views whose lease has lapsed. Called on every access, so no timer is needed. */
|
|
114
|
+
function sweep(nowMs) {
|
|
115
|
+
for (const [id, view] of views) {
|
|
116
|
+
if (nowMs - view.lastSeenAt > CANVAS_VIEW_LEASE_MS)
|
|
117
|
+
views.delete(id);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Pick the single view a command should go to.
|
|
122
|
+
*
|
|
123
|
+
* Zero matches is the caller's problem to hear about, not something to paper over. More than one
|
|
124
|
+
* match resolves to the most recently active view and NEVER fans out: delivering
|
|
125
|
+
* `composer-submit` to two views of one file would post the comment twice.
|
|
126
|
+
*/
|
|
127
|
+
function resolveTarget(workspace, file, nowMs) {
|
|
128
|
+
sweep(nowMs);
|
|
129
|
+
const ws = canonicalPath(workspace);
|
|
130
|
+
let wanted = null;
|
|
131
|
+
if (file !== undefined)
|
|
132
|
+
wanted = canonicalPath(file);
|
|
133
|
+
const matches = [];
|
|
134
|
+
for (const view of views.values()) {
|
|
135
|
+
if (view.workspace !== ws)
|
|
136
|
+
continue;
|
|
137
|
+
if (wanted !== null && view.file !== wanted)
|
|
138
|
+
continue;
|
|
139
|
+
matches.push(view);
|
|
140
|
+
}
|
|
141
|
+
if (matches.length === 0)
|
|
142
|
+
return null;
|
|
143
|
+
matches.sort((a, b) => {
|
|
144
|
+
if (b.lastActiveAt !== a.lastActiveAt)
|
|
145
|
+
return b.lastActiveAt - a.lastActiveAt;
|
|
146
|
+
return b.sequence - a.sequence;
|
|
147
|
+
});
|
|
148
|
+
return matches[0];
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Single entry point for `/api/canvas/*`, delegated from tower-routes. Lazily initializes from
|
|
152
|
+
* the RouteContext on first hit, then dispatches.
|
|
153
|
+
*/
|
|
154
|
+
export async function handleCanvasRoute(req, res, url, ctx) {
|
|
155
|
+
if (!inited) {
|
|
156
|
+
initCanvasRelay({
|
|
157
|
+
broadcast: (type, body) => ctx.broadcastNotification({ type, title: type, body: JSON.stringify(body) }),
|
|
158
|
+
now: () => Date.now(),
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
if (req.method === 'POST' && url.pathname === CANVAS_COMMAND_ROUTE) {
|
|
162
|
+
return handleCanvasCommand(req, res);
|
|
163
|
+
}
|
|
164
|
+
if (req.method === 'POST' && url.pathname === CANVAS_VIEWS_ROUTE) {
|
|
165
|
+
return handleRegisterView(req, res);
|
|
166
|
+
}
|
|
167
|
+
const viewMatch = url.pathname.match(/^\/api\/canvas\/views\/([^/]+)(\/heartbeat)?$/);
|
|
168
|
+
if (viewMatch) {
|
|
169
|
+
const viewId = decodeURIComponent(viewMatch[1]);
|
|
170
|
+
if (req.method === 'POST' && viewMatch[2])
|
|
171
|
+
return handleHeartbeat(req, res, viewId);
|
|
172
|
+
if (req.method === 'DELETE' && !viewMatch[2])
|
|
173
|
+
return handleUnregisterView(res, viewId);
|
|
174
|
+
}
|
|
175
|
+
sendJson(res, 404, { ok: false, error: 'Unknown canvas route' });
|
|
176
|
+
}
|
|
177
|
+
/** POST /api/canvas/views — a host registers one live canvas view. */
|
|
178
|
+
async function handleRegisterView(req, res) {
|
|
179
|
+
const d = requireDeps();
|
|
180
|
+
let parsed;
|
|
181
|
+
try {
|
|
182
|
+
parsed = await parseJsonBody(req);
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
return sendJson(res, 400, { ok: false, error: 'Invalid JSON' });
|
|
186
|
+
}
|
|
187
|
+
const body = asObject(parsed);
|
|
188
|
+
if (!body)
|
|
189
|
+
return sendJson(res, 400, { ok: false, error: 'Invalid JSON' });
|
|
190
|
+
if (!isNonEmptyString(body.workspace)) {
|
|
191
|
+
return sendJson(res, 400, { ok: false, error: 'Missing workspace' });
|
|
192
|
+
}
|
|
193
|
+
if (!isNonEmptyString(body.file)) {
|
|
194
|
+
return sendJson(res, 400, { ok: false, error: 'Missing file' });
|
|
195
|
+
}
|
|
196
|
+
const nowMs = d.now();
|
|
197
|
+
sweep(nowMs);
|
|
198
|
+
sequence += 1;
|
|
199
|
+
const viewId = `canvas-${randomUUID()}`;
|
|
200
|
+
const file = canonicalPath(body.file);
|
|
201
|
+
// One registration per VIEW, never per file: two panels showing the same document are two
|
|
202
|
+
// views with distinct ids, which is precisely the case the MRU rule exists to disambiguate.
|
|
203
|
+
views.set(viewId, {
|
|
204
|
+
viewId,
|
|
205
|
+
workspace: canonicalPath(body.workspace),
|
|
206
|
+
file,
|
|
207
|
+
lastActiveAt: nowMs,
|
|
208
|
+
lastSeenAt: nowMs,
|
|
209
|
+
sequence,
|
|
210
|
+
});
|
|
211
|
+
const result = { ok: true, viewId, file };
|
|
212
|
+
return sendJson(res, 200, result);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* POST /api/canvas/views/:viewId/heartbeat — keep the lease alive.
|
|
216
|
+
*
|
|
217
|
+
* `focused: true` additionally makes this the most recently active view. Tower stamps both times
|
|
218
|
+
* itself; host clocks are never trusted, so MRU stays deterministic across hosts whose clocks
|
|
219
|
+
* disagree.
|
|
220
|
+
*/
|
|
221
|
+
async function handleHeartbeat(req, res, viewId) {
|
|
222
|
+
const d = requireDeps();
|
|
223
|
+
let parsed;
|
|
224
|
+
try {
|
|
225
|
+
parsed = await parseJsonBody(req);
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
// A bodyless heartbeat is valid and already parses as `{}` ("still here, not necessarily
|
|
229
|
+
// focused"), so reaching here means the body was genuinely malformed. Renewing the lease on
|
|
230
|
+
// a payload we could not read would be extending liveness on the strength of a broken
|
|
231
|
+
// request.
|
|
232
|
+
return sendJson(res, 400, { ok: false, error: 'Invalid JSON' });
|
|
233
|
+
}
|
|
234
|
+
const body = asObject(parsed);
|
|
235
|
+
if (!body)
|
|
236
|
+
return sendJson(res, 400, { ok: false, error: 'Invalid JSON' });
|
|
237
|
+
// `focused` is optional but typed: a non-boolean violates `CanvasViewHeartbeat`. Reject before
|
|
238
|
+
// touching the lease, matching how the command route treats a bad `count` — a payload that does
|
|
239
|
+
// not meet the contract should not buy liveness just because the rest of it parsed.
|
|
240
|
+
if (body.focused !== undefined && typeof body.focused !== 'boolean') {
|
|
241
|
+
return sendJson(res, 400, { ok: false, error: 'focused must be a boolean' });
|
|
242
|
+
}
|
|
243
|
+
const nowMs = d.now();
|
|
244
|
+
sweep(nowMs);
|
|
245
|
+
const view = views.get(viewId);
|
|
246
|
+
// 404 rather than a silent re-create: a host holding an id Tower has forgotten (a restart, an
|
|
247
|
+
// expired lease) must learn that and re-register, or it would heartbeat into the void forever.
|
|
248
|
+
if (!view)
|
|
249
|
+
return sendJson(res, 404, { ok: false, error: 'Unknown view' });
|
|
250
|
+
view.lastSeenAt = nowMs;
|
|
251
|
+
if (body.focused === true)
|
|
252
|
+
view.lastActiveAt = nowMs;
|
|
253
|
+
return sendJson(res, 200, { ok: true });
|
|
254
|
+
}
|
|
255
|
+
/** DELETE /api/canvas/views/:viewId — the host's view is gone. */
|
|
256
|
+
function handleUnregisterView(res, viewId) {
|
|
257
|
+
const existed = views.delete(viewId);
|
|
258
|
+
if (!existed)
|
|
259
|
+
return sendJson(res, 404, { ok: false, error: 'Unknown view' });
|
|
260
|
+
return sendJson(res, 200, { ok: true });
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* POST /api/canvas/command — run one command against the resolved target view.
|
|
264
|
+
*
|
|
265
|
+
* Answers explicitly in every case: `no-canvas` (404) when the selector matches nothing,
|
|
266
|
+
* `invalid-request` (400) when the payload is malformed, and the resolved target on success.
|
|
267
|
+
* Delivery itself rides SSE and is best-effort; what is guaranteed is the ANSWER about targeting.
|
|
268
|
+
*/
|
|
269
|
+
async function handleCanvasCommand(req, res) {
|
|
270
|
+
const d = requireDeps();
|
|
271
|
+
let parsed;
|
|
272
|
+
try {
|
|
273
|
+
parsed = await parseJsonBody(req);
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
return sendJson(res, 400, invalidRequest('Invalid JSON'));
|
|
277
|
+
}
|
|
278
|
+
const raw = asObject(parsed);
|
|
279
|
+
if (!raw)
|
|
280
|
+
return sendJson(res, 400, invalidRequest('Invalid JSON'));
|
|
281
|
+
const invalid = validateCommandRequest(raw);
|
|
282
|
+
if (invalid)
|
|
283
|
+
return sendJson(res, 400, invalidRequest(invalid));
|
|
284
|
+
const workspace = raw.workspace;
|
|
285
|
+
const file = raw.file;
|
|
286
|
+
const command = raw.command;
|
|
287
|
+
const count = raw.count;
|
|
288
|
+
const nowMs = d.now();
|
|
289
|
+
const target = resolveTarget(workspace, file, nowMs);
|
|
290
|
+
if (!target) {
|
|
291
|
+
const noCanvas = {
|
|
292
|
+
ok: false,
|
|
293
|
+
code: 'no-canvas',
|
|
294
|
+
error: 'No canvas view is open for that workspace/file',
|
|
295
|
+
};
|
|
296
|
+
return sendJson(res, 404, noCanvas);
|
|
297
|
+
}
|
|
298
|
+
const event = { viewId: target.viewId, command };
|
|
299
|
+
if (count !== undefined)
|
|
300
|
+
event.count = count;
|
|
301
|
+
d.broadcast(CANVAS_COMMAND_EVENT, event);
|
|
302
|
+
// Driving a view is activity: it keeps that view the MRU target for the follow-up commands a
|
|
303
|
+
// controller is about to send, even though it never took focus in its host.
|
|
304
|
+
//
|
|
305
|
+
// It is deliberately NOT liveness. Delivery is fire-and-forget over SSE and proves nothing
|
|
306
|
+
// about the host still being alive, so refreshing the lease here would mean a ghost view kept
|
|
307
|
+
// renewing itself for as long as a controller kept driving it — exactly when the reviewer most
|
|
308
|
+
// needs to be told there is no canvas. Only a heartbeat, which only a live host can send,
|
|
309
|
+
// extends the lease.
|
|
310
|
+
target.lastActiveAt = nowMs;
|
|
311
|
+
const ok = {
|
|
312
|
+
ok: true,
|
|
313
|
+
target: { viewId: target.viewId, file: target.file },
|
|
314
|
+
};
|
|
315
|
+
return sendJson(res, 200, ok);
|
|
316
|
+
}
|
|
317
|
+
/** Returns an error message when the payload is not a valid command request, else null. */
|
|
318
|
+
function validateCommandRequest(raw) {
|
|
319
|
+
if (!isNonEmptyString(raw.workspace))
|
|
320
|
+
return 'Missing workspace';
|
|
321
|
+
if (raw.file !== undefined && !isNonEmptyString(raw.file))
|
|
322
|
+
return 'Invalid file';
|
|
323
|
+
if (typeof raw.command !== 'string')
|
|
324
|
+
return 'Missing command';
|
|
325
|
+
if (!CANVAS_COMMANDS.includes(raw.command)) {
|
|
326
|
+
return `Unknown command: ${raw.command}`;
|
|
327
|
+
}
|
|
328
|
+
if (raw.count !== undefined) {
|
|
329
|
+
const count = raw.count;
|
|
330
|
+
if (typeof count !== 'number' || !Number.isInteger(count) || count < 1) {
|
|
331
|
+
return 'count must be a positive integer';
|
|
332
|
+
}
|
|
333
|
+
if (!TRAVERSAL_COMMANDS.includes(raw.command)) {
|
|
334
|
+
return `count is not valid for ${raw.command}`;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
/** Every command-route failure carries a wire `code`; this keeps that impossible to forget. */
|
|
340
|
+
function invalidRequest(error) {
|
|
341
|
+
return { ok: false, code: 'invalid-request', error };
|
|
342
|
+
}
|
|
343
|
+
function isNonEmptyString(value) {
|
|
344
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* `parseJsonBody` is typed as returning an object but will happily resolve a literal `null`, a
|
|
348
|
+
* bare array, or a number, since those are all valid JSON. Reading a field off `null` throws,
|
|
349
|
+
* which would escape as a 500 with no wire `code` — the one thing the error contract forbids.
|
|
350
|
+
*/
|
|
351
|
+
function asObject(value) {
|
|
352
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
353
|
+
return null;
|
|
354
|
+
return value;
|
|
355
|
+
}
|
|
356
|
+
/** Access the wired deps, throwing a clear error if init was skipped. */
|
|
357
|
+
function requireDeps() {
|
|
358
|
+
if (!deps)
|
|
359
|
+
throw new Error('Canvas relay not initialized');
|
|
360
|
+
return deps;
|
|
361
|
+
}
|
|
362
|
+
/** Write a JSON response with the given status code. */
|
|
363
|
+
function sendJson(res, status, body) {
|
|
364
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
365
|
+
res.end(JSON.stringify(body));
|
|
366
|
+
}
|
|
367
|
+
/** Live views, for tests and diagnostics. Never part of the wire surface. */
|
|
368
|
+
export function listCanvasViewsForTest() {
|
|
369
|
+
return [...views.values()].map((v) => ({
|
|
370
|
+
viewId: v.viewId,
|
|
371
|
+
workspace: v.workspace,
|
|
372
|
+
file: v.file,
|
|
373
|
+
lastActiveAt: v.lastActiveAt,
|
|
374
|
+
}));
|
|
375
|
+
}
|
|
376
|
+
//# sourceMappingURL=canvas-relay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-relay.js","sourceRoot":"","sources":["../../../src/agent-farm/servers/canvas-relay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron message delivery through the mailbox + gate (Spec 1313, Phase 6).
|
|
3
|
+
*
|
|
4
|
+
* Cron is today the most unguarded message writer: it wrote straight to the PTY with
|
|
5
|
+
* no idle check and logged "delivered" unconditionally. This phase makes it an
|
|
6
|
+
* ordinary mailbox sender — every cron notification is persisted and then delivered
|
|
7
|
+
* through the SAME single gated path (`deliverAgentMailSerialized`) that `handleSend`
|
|
8
|
+
* and the backstop drainer use, so a cron message can never land mid-draft or fuse
|
|
9
|
+
* with a human's half-typed line. There is no force path: a busy/menu/wrapper screen
|
|
10
|
+
* holds the message for the backstop, exactly like any other send.
|
|
11
|
+
*
|
|
12
|
+
* Two cron-specific twists on top of the shared path:
|
|
13
|
+
* - **Supersede key = task name** (Baked Decision 6): a newer run of a task replaces
|
|
14
|
+
* its own older *held* row instead of queueing a backlog. Supersede keys are
|
|
15
|
+
* cron-only in this project — no non-cron send ever supplies one.
|
|
16
|
+
* - **Honest run outcome**: the caller logs the real fate (`delivered` / `held` /
|
|
17
|
+
* `superseded`) rather than an unconditional "delivered".
|
|
18
|
+
*
|
|
19
|
+
* This module holds the registry-free orchestration core behind the Phase-4
|
|
20
|
+
* {@link DeliveryPorts} seam, so it is unit-testable against a real mailbox DB with
|
|
21
|
+
* fake edges (no live Tower). The identity resolution that needs the live routing
|
|
22
|
+
* registry (`resolveTarget` + the architect reverse-map + the dead-session registry
|
|
23
|
+
* fallback) lives in `tower-routes.ts`'s `deliverCronMessage`, which calls this.
|
|
24
|
+
*/
|
|
25
|
+
import type Database from 'better-sqlite3';
|
|
26
|
+
import type { MailboxReason } from '../db/types.js';
|
|
27
|
+
import { type DeliveryPorts } from './mailbox-delivery.js';
|
|
28
|
+
/** The pseudo-agent identity every cron notification is sent as. */
|
|
29
|
+
export declare const CRON_SENDER = "af-cron";
|
|
30
|
+
/** The real fate of one cron run's message (what the run log records). */
|
|
31
|
+
export type CronOutcome = 'delivered' | 'held' | 'superseded' | 'unresolved';
|
|
32
|
+
/** Outcome of routing a cron notification through the mailbox + gate. */
|
|
33
|
+
export interface CronDeliveryResult {
|
|
34
|
+
/**
|
|
35
|
+
* `delivered` — written to a render-verified empty prompt now; `held` — this run's
|
|
36
|
+
* message is held for the backstop (line busy / menu / no profile / no live PTY);
|
|
37
|
+
* `superseded` — held, and it replaced a still-held row from an earlier run of the
|
|
38
|
+
* same task (no backlog); `unresolved` — the target could not be resolved at all
|
|
39
|
+
* (nothing persisted).
|
|
40
|
+
*/
|
|
41
|
+
outcome: CronOutcome;
|
|
42
|
+
/** Why held, when `held`/`superseded`; null when `delivered`/`unresolved`. */
|
|
43
|
+
reason: MailboxReason | null;
|
|
44
|
+
/** The persisted row id (audit); null only when `unresolved`. */
|
|
45
|
+
mailboxId: string | null;
|
|
46
|
+
}
|
|
47
|
+
/** A resolved cron recipient plus the bytes to persist. */
|
|
48
|
+
export interface CronTarget {
|
|
49
|
+
workspacePath: string;
|
|
50
|
+
/** Canonical recipient agent id (a builder id or a specific architect name). */
|
|
51
|
+
toAgent: string;
|
|
52
|
+
/** Last-known PTY hint; null when the recipient has no live terminal. */
|
|
53
|
+
terminalId: string | null;
|
|
54
|
+
/** Raw message body (never logged). */
|
|
55
|
+
body: string;
|
|
56
|
+
/** Exact bytes written to the PTY on delivery. */
|
|
57
|
+
formattedMessage: string;
|
|
58
|
+
/** Per-task coalescing key (Baked Decision 6) — the task name. */
|
|
59
|
+
supersedeKey: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Persist a cron notification (superseding any still-held row from an earlier run of
|
|
63
|
+
* the same task) and attempt one gated delivery, returning the run's real outcome.
|
|
64
|
+
*
|
|
65
|
+
* The corruption-safety is entirely inherited from {@link deliverAgentMailSerialized}:
|
|
66
|
+
* the body is only ever written to a render-verified empty prompt, and the per-agent
|
|
67
|
+
* serializer means a concurrent send can never interleave with this write. A busy or
|
|
68
|
+
* unclassifiable screen simply leaves the row held for the backstop — there is no
|
|
69
|
+
* force path here, by construction.
|
|
70
|
+
*/
|
|
71
|
+
export declare function deliverCronMail(ports: DeliveryPorts, db: Database.Database, target: CronTarget): Promise<CronDeliveryResult>;
|
|
72
|
+
//# sourceMappingURL=cron-delivery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-delivery.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/servers/cron-delivery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAA8B,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEvF,oEAAoE;AACpE,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC,0EAA0E;AAC1E,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,MAAM,GAAG,YAAY,GAAG,YAAY,CAAC;AAE7E,yEAAyE;AACzE,MAAM,WAAW,kBAAkB;IACjC;;;;;;OAMG;IACH,OAAO,EAAE,WAAW,CAAC;IACrB,8EAA8E;IAC9E,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,iEAAiE;IACjE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,2DAA2D;AAC3D,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,gBAAgB,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,aAAa,EACpB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,kBAAkB,CAAC,CAgD7B"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron message delivery through the mailbox + gate (Spec 1313, Phase 6).
|
|
3
|
+
*
|
|
4
|
+
* Cron is today the most unguarded message writer: it wrote straight to the PTY with
|
|
5
|
+
* no idle check and logged "delivered" unconditionally. This phase makes it an
|
|
6
|
+
* ordinary mailbox sender — every cron notification is persisted and then delivered
|
|
7
|
+
* through the SAME single gated path (`deliverAgentMailSerialized`) that `handleSend`
|
|
8
|
+
* and the backstop drainer use, so a cron message can never land mid-draft or fuse
|
|
9
|
+
* with a human's half-typed line. There is no force path: a busy/menu/wrapper screen
|
|
10
|
+
* holds the message for the backstop, exactly like any other send.
|
|
11
|
+
*
|
|
12
|
+
* Two cron-specific twists on top of the shared path:
|
|
13
|
+
* - **Supersede key = task name** (Baked Decision 6): a newer run of a task replaces
|
|
14
|
+
* its own older *held* row instead of queueing a backlog. Supersede keys are
|
|
15
|
+
* cron-only in this project — no non-cron send ever supplies one.
|
|
16
|
+
* - **Honest run outcome**: the caller logs the real fate (`delivered` / `held` /
|
|
17
|
+
* `superseded`) rather than an unconditional "delivered".
|
|
18
|
+
*
|
|
19
|
+
* This module holds the registry-free orchestration core behind the Phase-4
|
|
20
|
+
* {@link DeliveryPorts} seam, so it is unit-testable against a real mailbox DB with
|
|
21
|
+
* fake edges (no live Tower). The identity resolution that needs the live routing
|
|
22
|
+
* registry (`resolveTarget` + the architect reverse-map + the dead-session registry
|
|
23
|
+
* fallback) lives in `tower-routes.ts`'s `deliverCronMessage`, which calls this.
|
|
24
|
+
*/
|
|
25
|
+
import { supersede, getById, countHeldWithKey } from '../db/mailbox.js';
|
|
26
|
+
import { deliverAgentMailSerialized } from './mailbox-delivery.js';
|
|
27
|
+
/** The pseudo-agent identity every cron notification is sent as. */
|
|
28
|
+
export const CRON_SENDER = 'af-cron';
|
|
29
|
+
/**
|
|
30
|
+
* Persist a cron notification (superseding any still-held row from an earlier run of
|
|
31
|
+
* the same task) and attempt one gated delivery, returning the run's real outcome.
|
|
32
|
+
*
|
|
33
|
+
* The corruption-safety is entirely inherited from {@link deliverAgentMailSerialized}:
|
|
34
|
+
* the body is only ever written to a render-verified empty prompt, and the per-agent
|
|
35
|
+
* serializer means a concurrent send can never interleave with this write. A busy or
|
|
36
|
+
* unclassifiable screen simply leaves the row held for the backstop — there is no
|
|
37
|
+
* force path here, by construction.
|
|
38
|
+
*/
|
|
39
|
+
export async function deliverCronMail(ports, db, target) {
|
|
40
|
+
const { workspacePath, toAgent, supersedeKey } = target;
|
|
41
|
+
// Did an earlier run of this task leave a row still held? Read it BEFORE the
|
|
42
|
+
// supersede, with no await between, so the pair is atomic on the synchronous DB
|
|
43
|
+
// handle (see countHeldWithKey). This only informs the log word — the "no backlog"
|
|
44
|
+
// correctness comes from supersede() being atomic regardless.
|
|
45
|
+
const replacedPrior = countHeldWithKey(db, workspacePath, supersedeKey) > 0;
|
|
46
|
+
const row = supersede(db, workspacePath, supersedeKey, {
|
|
47
|
+
workspacePath,
|
|
48
|
+
toAgent,
|
|
49
|
+
terminalId: target.terminalId,
|
|
50
|
+
body: target.body,
|
|
51
|
+
formattedMessage: target.formattedMessage,
|
|
52
|
+
fromAgent: CRON_SENDER,
|
|
53
|
+
fromWorkspace: workspacePath,
|
|
54
|
+
}, ports.now());
|
|
55
|
+
// The held set changed (a new row enqueued, possibly replacing a prior held one) →
|
|
56
|
+
// refresh the indicator count (Spec 1313, Phase 7). A clean delivery below fires it
|
|
57
|
+
// again when the row leaves the set; both are cheap, idempotent refetch triggers.
|
|
58
|
+
ports.onHeldStateChange();
|
|
59
|
+
try {
|
|
60
|
+
await deliverAgentMailSerialized(ports, db, workspacePath, toAgent);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
// A gate/write error leaves the row HELD (markDelivered only runs on a completed
|
|
64
|
+
// write); the backstop drainer retries. Mirrors handleSend — never throws upward.
|
|
65
|
+
ports.log(`[cron] delivery attempt errored for ${toAgent} (row ${row.id.slice(0, 8)}… stays held): ${String(err)}`);
|
|
66
|
+
}
|
|
67
|
+
const stored = getById(db, row.id);
|
|
68
|
+
if (stored?.status === 'delivered') {
|
|
69
|
+
return { outcome: 'delivered', reason: null, mailboxId: row.id };
|
|
70
|
+
}
|
|
71
|
+
// Held. `reason` is set by the delivery pass when it holds; default to `busy` for
|
|
72
|
+
// the rare case where an older row for the same agent delivered first and left ours
|
|
73
|
+
// queued behind it (its Enter makes the line busy for the next pass anyway).
|
|
74
|
+
return {
|
|
75
|
+
outcome: replacedPrior ? 'superseded' : 'held',
|
|
76
|
+
reason: stored?.reason ?? 'busy',
|
|
77
|
+
mailboxId: row.id,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=cron-delivery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-delivery.js","sourceRoot":"","sources":["../../../src/agent-farm/servers/cron-delivery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAExE,OAAO,EAAE,0BAA0B,EAAsB,MAAM,uBAAuB,CAAC;AAEvF,oEAAoE;AACpE,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AAoCrC;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAoB,EACpB,EAAqB,EACrB,MAAkB;IAElB,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAExD,6EAA6E;IAC7E,gFAAgF;IAChF,mFAAmF;IACnF,8DAA8D;IAC9D,MAAM,aAAa,GAAG,gBAAgB,CAAC,EAAE,EAAE,aAAa,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;IAC5E,MAAM,GAAG,GAAG,SAAS,CACnB,EAAE,EACF,aAAa,EACb,YAAY,EACZ;QACE,aAAa;QACb,OAAO;QACP,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,SAAS,EAAE,WAAW;QACtB,aAAa,EAAE,aAAa;KAC7B,EACD,KAAK,CAAC,GAAG,EAAE,CACZ,CAAC;IACF,mFAAmF;IACnF,oFAAoF;IACpF,kFAAkF;IAClF,KAAK,CAAC,iBAAiB,EAAE,CAAC;IAE1B,IAAI,CAAC;QACH,MAAM,0BAA0B,CAAC,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,iFAAiF;QACjF,kFAAkF;QAClF,KAAK,CAAC,GAAG,CAAC,uCAAuC,OAAO,SAAS,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,kBAAkB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACtH,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACnC,IAAI,MAAM,EAAE,MAAM,KAAK,WAAW,EAAE,CAAC;QACnC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;IACnE,CAAC;IACD,kFAAkF;IAClF,oFAAoF;IACpF,6EAA6E;IAC7E,OAAO;QACL,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM;QAC9C,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,MAAM;QAChC,SAAS,EAAE,GAAG,CAAC,EAAE;KAClB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Due-time timer for the delayed `afx send --delay --interrupt` path (Spec 1307,
|
|
3
|
+
* reshaped by Spec 1313 round 3).
|
|
4
|
+
*
|
|
5
|
+
* ## What this module does NOW (and no longer does)
|
|
6
|
+
*
|
|
7
|
+
* The message *body* of every `--delay` send is persisted to the durable mailbox
|
|
8
|
+
* at REQUEST time, with a `not_before` due time, by `handleDelayedSend` in
|
|
9
|
+
* tower-routes.ts — NOT here, and NOT at fire time. The gated backstop drainer
|
|
10
|
+
* delivers that row once `not_before` passes, so a plain `--delay` keeps no timer
|
|
11
|
+
* at all and survives a Tower restart by construction.
|
|
12
|
+
*
|
|
13
|
+
* This module holds a due-time timer used by ONE caller: the delayed-`--interrupt`
|
|
14
|
+
* path. When it fires it writes only the Ctrl+C that ends the current turn — no
|
|
15
|
+
* message body, and it marks nothing `delivered`. The body then lands through the
|
|
16
|
+
* same render gate every send uses, after the ^C ends the turn.
|
|
17
|
+
*
|
|
18
|
+
* ## Why the registry exists at all
|
|
19
|
+
*
|
|
20
|
+
* A bare `setTimeout` would work until Tower shuts down, at which point the
|
|
21
|
+
* process would either hang on a pending timer or exit with a ^C half-scheduled
|
|
22
|
+
* and no record of it. The registry makes shutdown explicit.
|
|
23
|
+
*
|
|
24
|
+
* ## Shutdown drops the ^C nudge, never the message
|
|
25
|
+
*
|
|
26
|
+
* A pre-due `--delay` message is a persisted mailbox row: it survives a restart
|
|
27
|
+
* and delivers when the target's prompt is next clean. Only the in-memory ^C
|
|
28
|
+
* nudge is dropped on shutdown — recoverable (a human re-interrupts if it matters),
|
|
29
|
+
* and matching the documented "only the interrupt semantics gracefully degrade"
|
|
30
|
+
* boundary. This is the CONSCIOUS reversal of Spec 1307's original body-drop-on-
|
|
31
|
+
* restart trade (see review 1313): the render gate now supplies the protection that
|
|
32
|
+
* trade wanted — a post-restart delivery still only lands on a render-verified empty
|
|
33
|
+
* prompt, and a stale pending row is visible and cancellable in `afx inbox`.
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* Upper bound on `--delay`, in seconds.
|
|
37
|
+
*
|
|
38
|
+
* One hour. Not a meaningful workflow limit — it exists so a typo (`--delay
|
|
39
|
+
* 1500` when 15 was meant) cannot park a message far in the future unnoticed.
|
|
40
|
+
* Under Spec 1313 round 3 a parked send IS listable and cancellable via
|
|
41
|
+
* `afx inbox` / `afx inbox dismiss` (it is a durable mailbox row), but the
|
|
42
|
+
* ceiling stays as a cheap guard against the typo case.
|
|
43
|
+
*/
|
|
44
|
+
export declare const MAX_DELAY_SECONDS = 3600;
|
|
45
|
+
/**
|
|
46
|
+
* Validate a delay in seconds, returning null when acceptable or an error
|
|
47
|
+
* string naming the problem.
|
|
48
|
+
*
|
|
49
|
+
* `Number.isInteger` rather than a bare comparison chain: `NaN > 0` and
|
|
50
|
+
* `NaN <= 0` are both false, so a NaN slips through any single comparison
|
|
51
|
+
* written the obvious way and yields a `setTimeout` that fires immediately —
|
|
52
|
+
* silently converting a delayed send into an immediate one. Infinity is
|
|
53
|
+
* rejected for the same class of reason.
|
|
54
|
+
*/
|
|
55
|
+
export declare function validateDelaySeconds(value: unknown): string | null;
|
|
56
|
+
/**
|
|
57
|
+
* Schedule `deliver` to run after `delaySeconds`.
|
|
58
|
+
*
|
|
59
|
+
* The callback is responsible for re-resolving the session and re-deciding how
|
|
60
|
+
* to deliver; this module guarantees only *when* it is invoked, and that it is
|
|
61
|
+
* invoked at most once.
|
|
62
|
+
*/
|
|
63
|
+
export declare function scheduleDelayedSend(delaySeconds: number, terminalId: string,
|
|
64
|
+
/**
|
|
65
|
+
* Invoked when the send comes due. Receives `isStillLive`, which it must
|
|
66
|
+
* re-check at the moment it actually writes (inside the submission lock): a
|
|
67
|
+
* delivery can acquire the lock only AFTER a shutdown that fired while it
|
|
68
|
+
* queued, and the generation check below only guards the moment BEFORE it
|
|
69
|
+
* enters the lock. Return value is ignored.
|
|
70
|
+
*/
|
|
71
|
+
deliver: (isStillLive: () => boolean) => unknown): void;
|
|
72
|
+
/**
|
|
73
|
+
* Cancel every pending delayed send without delivering. Returns the count of
|
|
74
|
+
* still-timing sends dropped, so shutdown can log it rather than losing
|
|
75
|
+
* messages silently.
|
|
76
|
+
*
|
|
77
|
+
* Covers two states: sends still on their timer (cleared here) and sends whose
|
|
78
|
+
* timer has fired but whose delivery has not started — invalidated by bumping
|
|
79
|
+
* `generation`, which the delivery callback re-checks. A delivery already
|
|
80
|
+
* writing when this runs is NOT interrupted; see `generation`'s note.
|
|
81
|
+
*/
|
|
82
|
+
export declare function shutdownDelayedSends(): number;
|
|
83
|
+
/** Number of pending delayed sends. Diagnostics and tests. */
|
|
84
|
+
export declare function pendingDelayedSendCount(): number;
|
|
85
|
+
//# sourceMappingURL=delayed-send.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delayed-send.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/servers/delayed-send.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAwCH;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAWlE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM;AAClB;;;;;;GAMG;AACH,OAAO,EAAE,CAAC,WAAW,EAAE,MAAM,OAAO,KAAK,OAAO,GAC/C,IAAI,CAmCN;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAQ7C;AAED,8DAA8D;AAC9D,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD"}
|