@cluesmith/codev 2.0.0-rc.7 → 2.0.0-rc.70
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/bin/af.js +2 -2
- package/bin/consult.js +1 -1
- package/bin/porch.js +6 -35
- package/dashboard/dist/assets/index-C7FtNK6Y.css +32 -0
- package/dashboard/dist/assets/index-CDAINZKT.js +131 -0
- package/dashboard/dist/assets/index-CDAINZKT.js.map +1 -0
- package/dashboard/dist/index.html +14 -0
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +173 -118
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/architect.d.ts +3 -3
- package/dist/agent-farm/commands/architect.d.ts.map +1 -1
- package/dist/agent-farm/commands/architect.js +20 -147
- package/dist/agent-farm/commands/architect.js.map +1 -1
- package/dist/agent-farm/commands/attach.d.ts +13 -0
- package/dist/agent-farm/commands/attach.d.ts.map +1 -0
- package/dist/agent-farm/commands/attach.js +144 -0
- package/dist/agent-farm/commands/attach.js.map +1 -0
- package/dist/agent-farm/commands/cleanup.d.ts.map +1 -1
- package/dist/agent-farm/commands/cleanup.js +35 -19
- package/dist/agent-farm/commands/cleanup.js.map +1 -1
- package/dist/agent-farm/commands/consult.d.ts +3 -4
- package/dist/agent-farm/commands/consult.d.ts.map +1 -1
- package/dist/agent-farm/commands/consult.js +27 -37
- package/dist/agent-farm/commands/consult.js.map +1 -1
- package/dist/agent-farm/commands/index.d.ts +2 -2
- package/dist/agent-farm/commands/index.d.ts.map +1 -1
- package/dist/agent-farm/commands/index.js +2 -2
- package/dist/agent-farm/commands/index.js.map +1 -1
- package/dist/agent-farm/commands/open.d.ts +4 -2
- package/dist/agent-farm/commands/open.d.ts.map +1 -1
- package/dist/agent-farm/commands/open.js +33 -83
- package/dist/agent-farm/commands/open.js.map +1 -1
- package/dist/agent-farm/commands/send.d.ts +1 -1
- package/dist/agent-farm/commands/send.d.ts.map +1 -1
- package/dist/agent-farm/commands/send.js +60 -79
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/shell.d.ts +15 -0
- package/dist/agent-farm/commands/shell.d.ts.map +1 -0
- package/dist/agent-farm/commands/shell.js +50 -0
- package/dist/agent-farm/commands/shell.js.map +1 -0
- package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn.js +597 -281
- package/dist/agent-farm/commands/spawn.js.map +1 -1
- package/dist/agent-farm/commands/start.d.ts +10 -20
- package/dist/agent-farm/commands/start.d.ts.map +1 -1
- package/dist/agent-farm/commands/start.js +45 -491
- package/dist/agent-farm/commands/start.js.map +1 -1
- package/dist/agent-farm/commands/status.d.ts +2 -0
- package/dist/agent-farm/commands/status.d.ts.map +1 -1
- package/dist/agent-farm/commands/status.js +75 -24
- package/dist/agent-farm/commands/status.js.map +1 -1
- package/dist/agent-farm/commands/stop.d.ts +6 -0
- package/dist/agent-farm/commands/stop.d.ts.map +1 -1
- package/dist/agent-farm/commands/stop.js +49 -109
- package/dist/agent-farm/commands/stop.js.map +1 -1
- package/dist/agent-farm/commands/tower-cloud.d.ts +48 -0
- package/dist/agent-farm/commands/tower-cloud.d.ts.map +1 -0
- package/dist/agent-farm/commands/tower-cloud.js +334 -0
- package/dist/agent-farm/commands/tower-cloud.js.map +1 -0
- package/dist/agent-farm/commands/tower.d.ts +9 -0
- package/dist/agent-farm/commands/tower.d.ts.map +1 -1
- package/dist/agent-farm/commands/tower.js +59 -19
- package/dist/agent-farm/commands/tower.js.map +1 -1
- package/dist/agent-farm/db/index.d.ts +6 -2
- package/dist/agent-farm/db/index.d.ts.map +1 -1
- package/dist/agent-farm/db/index.js +246 -18
- package/dist/agent-farm/db/index.js.map +1 -1
- package/dist/agent-farm/db/migrate.d.ts +0 -4
- package/dist/agent-farm/db/migrate.d.ts.map +1 -1
- package/dist/agent-farm/db/migrate.js +6 -55
- package/dist/agent-farm/db/migrate.js.map +1 -1
- package/dist/agent-farm/db/schema.d.ts +3 -3
- package/dist/agent-farm/db/schema.d.ts.map +1 -1
- package/dist/agent-farm/db/schema.js +25 -19
- package/dist/agent-farm/db/schema.js.map +1 -1
- package/dist/agent-farm/db/types.d.ts +3 -13
- package/dist/agent-farm/db/types.d.ts.map +1 -1
- package/dist/agent-farm/db/types.js +3 -11
- package/dist/agent-farm/db/types.js.map +1 -1
- package/dist/agent-farm/hq-connector.d.ts +2 -6
- package/dist/agent-farm/hq-connector.d.ts.map +1 -1
- package/dist/agent-farm/hq-connector.js +2 -17
- package/dist/agent-farm/hq-connector.js.map +1 -1
- package/dist/agent-farm/lib/cloud-config.d.ts +59 -0
- package/dist/agent-farm/lib/cloud-config.d.ts.map +1 -0
- package/dist/agent-farm/lib/cloud-config.js +143 -0
- package/dist/agent-farm/lib/cloud-config.js.map +1 -0
- package/dist/agent-farm/lib/tower-client.d.ts +163 -0
- package/dist/agent-farm/lib/tower-client.d.ts.map +1 -0
- package/dist/agent-farm/lib/tower-client.js +233 -0
- package/dist/agent-farm/lib/tower-client.js.map +1 -0
- package/dist/agent-farm/lib/tunnel-client.d.ts +117 -0
- package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -0
- package/dist/agent-farm/lib/tunnel-client.js +504 -0
- package/dist/agent-farm/lib/tunnel-client.js.map +1 -0
- package/dist/agent-farm/servers/tower-server.js +2650 -185
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/state.d.ts +6 -12
- package/dist/agent-farm/state.d.ts.map +1 -1
- package/dist/agent-farm/state.js +34 -49
- package/dist/agent-farm/state.js.map +1 -1
- package/dist/agent-farm/types.d.ts +49 -26
- package/dist/agent-farm/types.d.ts.map +1 -1
- package/dist/agent-farm/utils/config.d.ts +0 -5
- package/dist/agent-farm/utils/config.d.ts.map +1 -1
- package/dist/agent-farm/utils/config.js +12 -44
- package/dist/agent-farm/utils/config.js.map +1 -1
- package/dist/agent-farm/utils/deps.d.ts.map +1 -1
- package/dist/agent-farm/utils/deps.js +0 -32
- package/dist/agent-farm/utils/deps.js.map +1 -1
- package/dist/agent-farm/utils/file-tabs.d.ts +27 -0
- package/dist/agent-farm/utils/file-tabs.d.ts.map +1 -0
- package/dist/agent-farm/utils/file-tabs.js +46 -0
- package/dist/agent-farm/utils/file-tabs.js.map +1 -0
- package/dist/agent-farm/utils/gate-status.d.ts +16 -0
- package/dist/agent-farm/utils/gate-status.d.ts.map +1 -0
- package/dist/agent-farm/utils/gate-status.js +79 -0
- package/dist/agent-farm/utils/gate-status.js.map +1 -0
- package/dist/agent-farm/utils/gate-watcher.d.ts +38 -0
- package/dist/agent-farm/utils/gate-watcher.d.ts.map +1 -0
- package/dist/agent-farm/utils/gate-watcher.js +122 -0
- package/dist/agent-farm/utils/gate-watcher.js.map +1 -0
- package/dist/agent-farm/utils/index.d.ts +0 -1
- package/dist/agent-farm/utils/index.d.ts.map +1 -1
- package/dist/agent-farm/utils/index.js +0 -1
- package/dist/agent-farm/utils/index.js.map +1 -1
- package/dist/agent-farm/utils/notifications.d.ts +30 -0
- package/dist/agent-farm/utils/notifications.d.ts.map +1 -0
- package/dist/agent-farm/utils/notifications.js +121 -0
- package/dist/agent-farm/utils/notifications.js.map +1 -0
- package/dist/agent-farm/utils/server-utils.d.ts +5 -5
- package/dist/agent-farm/utils/server-utils.d.ts.map +1 -1
- package/dist/agent-farm/utils/server-utils.js +5 -16
- package/dist/agent-farm/utils/server-utils.js.map +1 -1
- package/dist/agent-farm/utils/session.d.ts +32 -0
- package/dist/agent-farm/utils/session.d.ts.map +1 -0
- package/dist/agent-farm/utils/session.js +57 -0
- package/dist/agent-farm/utils/session.js.map +1 -0
- package/dist/agent-farm/utils/shell.d.ts +9 -22
- package/dist/agent-farm/utils/shell.d.ts.map +1 -1
- package/dist/agent-farm/utils/shell.js +34 -34
- package/dist/agent-farm/utils/shell.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +11 -54
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt.d.ts.map +1 -1
- package/dist/commands/adopt.js +49 -4
- package/dist/commands/adopt.js.map +1 -1
- package/dist/commands/consult/index.d.ts +13 -2
- package/dist/commands/consult/index.d.ts.map +1 -1
- package/dist/commands/consult/index.js +245 -29
- package/dist/commands/consult/index.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +96 -79
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +41 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/porch/build-counter.d.ts +5 -0
- package/dist/commands/porch/build-counter.d.ts.map +1 -0
- package/dist/commands/porch/build-counter.js +5 -0
- package/dist/commands/porch/build-counter.js.map +1 -0
- package/dist/commands/porch/checks.d.ts +17 -29
- package/dist/commands/porch/checks.d.ts.map +1 -1
- package/dist/commands/porch/checks.js +96 -144
- package/dist/commands/porch/checks.js.map +1 -1
- package/dist/commands/porch/index.d.ts +25 -43
- package/dist/commands/porch/index.d.ts.map +1 -1
- package/dist/commands/porch/index.js +463 -1116
- package/dist/commands/porch/index.js.map +1 -1
- package/dist/commands/porch/next.d.ts +22 -0
- package/dist/commands/porch/next.d.ts.map +1 -0
- package/dist/commands/porch/next.js +571 -0
- package/dist/commands/porch/next.js.map +1 -0
- package/dist/commands/porch/plan.d.ts +70 -0
- package/dist/commands/porch/plan.d.ts.map +1 -0
- package/dist/commands/porch/plan.js +190 -0
- package/dist/commands/porch/plan.js.map +1 -0
- package/dist/commands/porch/prompts.d.ts +19 -0
- package/dist/commands/porch/prompts.d.ts.map +1 -0
- package/dist/commands/porch/prompts.js +277 -0
- package/dist/commands/porch/prompts.js.map +1 -0
- package/dist/commands/porch/protocol.d.ts +59 -0
- package/dist/commands/porch/protocol.d.ts.map +1 -0
- package/dist/commands/porch/protocol.js +294 -0
- package/dist/commands/porch/protocol.js.map +1 -0
- package/dist/commands/porch/state.d.ts +36 -107
- package/dist/commands/porch/state.d.ts.map +1 -1
- package/dist/commands/porch/state.js +120 -699
- package/dist/commands/porch/state.js.map +1 -1
- package/dist/commands/porch/types.d.ts +99 -164
- package/dist/commands/porch/types.d.ts.map +1 -1
- package/dist/commands/porch/types.js +2 -1
- package/dist/commands/porch/types.js.map +1 -1
- package/dist/commands/porch/verdict.d.ts +31 -0
- package/dist/commands/porch/verdict.d.ts.map +1 -0
- package/dist/commands/porch/verdict.js +59 -0
- package/dist/commands/porch/verdict.js.map +1 -0
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +31 -0
- package/dist/commands/update.js.map +1 -1
- package/dist/lib/scaffold.d.ts +37 -0
- package/dist/lib/scaffold.d.ts.map +1 -1
- package/dist/lib/scaffold.js +114 -0
- package/dist/lib/scaffold.js.map +1 -1
- package/dist/terminal/index.d.ts +8 -0
- package/dist/terminal/index.d.ts.map +1 -0
- package/dist/terminal/index.js +5 -0
- package/dist/terminal/index.js.map +1 -0
- package/dist/terminal/pty-manager.d.ts +69 -0
- package/dist/terminal/pty-manager.d.ts.map +1 -0
- package/dist/terminal/pty-manager.js +377 -0
- package/dist/terminal/pty-manager.js.map +1 -0
- package/dist/terminal/pty-session.d.ts +104 -0
- package/dist/terminal/pty-session.d.ts.map +1 -0
- package/dist/terminal/pty-session.js +327 -0
- package/dist/terminal/pty-session.js.map +1 -0
- package/dist/terminal/ring-buffer.d.ts +34 -0
- package/dist/terminal/ring-buffer.d.ts.map +1 -0
- package/dist/terminal/ring-buffer.js +94 -0
- package/dist/terminal/ring-buffer.js.map +1 -0
- package/dist/terminal/session-manager.d.ts +115 -0
- package/dist/terminal/session-manager.d.ts.map +1 -0
- package/dist/terminal/session-manager.js +582 -0
- package/dist/terminal/session-manager.js.map +1 -0
- package/dist/terminal/shepherd-client.d.ts +58 -0
- package/dist/terminal/shepherd-client.d.ts.map +1 -0
- package/dist/terminal/shepherd-client.js +212 -0
- package/dist/terminal/shepherd-client.js.map +1 -0
- package/dist/terminal/shepherd-main.d.ts +19 -0
- package/dist/terminal/shepherd-main.d.ts.map +1 -0
- package/dist/terminal/shepherd-main.js +153 -0
- package/dist/terminal/shepherd-main.js.map +1 -0
- package/dist/terminal/shepherd-process.d.ts +75 -0
- package/dist/terminal/shepherd-process.d.ts.map +1 -0
- package/dist/terminal/shepherd-process.js +279 -0
- package/dist/terminal/shepherd-process.js.map +1 -0
- package/dist/terminal/shepherd-protocol.d.ts +115 -0
- package/dist/terminal/shepherd-protocol.d.ts.map +1 -0
- package/dist/terminal/shepherd-protocol.js +214 -0
- package/dist/terminal/shepherd-protocol.js.map +1 -0
- package/dist/terminal/shepherd-replay-buffer.d.ts +38 -0
- package/dist/terminal/shepherd-replay-buffer.d.ts.map +1 -0
- package/dist/terminal/shepherd-replay-buffer.js +94 -0
- package/dist/terminal/shepherd-replay-buffer.js.map +1 -0
- package/dist/terminal/ws-protocol.d.ts +27 -0
- package/dist/terminal/ws-protocol.d.ts.map +1 -0
- package/dist/terminal/ws-protocol.js +44 -0
- package/dist/terminal/ws-protocol.js.map +1 -0
- package/package.json +19 -5
- package/skeleton/.claude/skills/af/SKILL.md +89 -0
- package/skeleton/.claude/skills/codev/SKILL.md +41 -0
- package/skeleton/.claude/skills/consult/SKILL.md +81 -0
- package/skeleton/.claude/skills/generate-image/SKILL.md +56 -0
- package/skeleton/DEPENDENCIES.md +4 -62
- package/skeleton/builders.md +1 -1
- package/skeleton/consult-types/impl-review.md +18 -9
- package/skeleton/consult-types/integration-review.md +1 -1
- package/skeleton/consult-types/plan-review.md +1 -1
- package/skeleton/consult-types/pr-ready.md +1 -1
- package/skeleton/consult-types/spec-review.md +1 -1
- package/skeleton/porch/prompts/defend.md +1 -1
- package/skeleton/porch/prompts/evaluate.md +2 -2
- package/skeleton/porch/prompts/implement.md +1 -1
- package/skeleton/porch/prompts/plan.md +1 -1
- package/skeleton/porch/prompts/review.md +4 -4
- package/skeleton/porch/prompts/specify.md +1 -1
- package/skeleton/porch/prompts/understand.md +2 -2
- package/skeleton/protocol-schema.json +282 -0
- package/skeleton/protocols/bugfix/builder-prompt.md +54 -0
- package/skeleton/protocols/bugfix/prompts/fix.md +77 -0
- package/skeleton/protocols/bugfix/prompts/investigate.md +77 -0
- package/skeleton/protocols/bugfix/prompts/pr.md +84 -0
- package/skeleton/protocols/bugfix/protocol.json +20 -33
- package/skeleton/protocols/experiment/builder-prompt.md +52 -0
- package/skeleton/protocols/experiment/protocol.json +101 -0
- package/skeleton/protocols/experiment/protocol.md +3 -3
- package/skeleton/protocols/experiment/templates/notes.md +1 -1
- package/skeleton/protocols/maintain/builder-prompt.md +46 -0
- package/skeleton/protocols/maintain/prompts/audit.md +111 -0
- package/skeleton/protocols/maintain/prompts/clean.md +91 -0
- package/skeleton/protocols/maintain/prompts/sync.md +113 -0
- package/skeleton/protocols/maintain/prompts/verify.md +110 -0
- package/skeleton/protocols/maintain/protocol.json +141 -0
- package/skeleton/protocols/maintain/protocol.md +17 -11
- package/skeleton/protocols/protocol-schema.json +54 -1
- package/skeleton/protocols/spir/builder-prompt.md +59 -0
- package/skeleton/protocols/spir/prompts/implement.md +208 -0
- package/skeleton/protocols/{spider → spir}/prompts/plan.md +6 -70
- package/skeleton/protocols/{spider → spir}/prompts/review.md +20 -39
- package/skeleton/protocols/{spider → spir}/prompts/specify.md +33 -61
- package/skeleton/protocols/spir/protocol.json +156 -0
- package/skeleton/protocols/{spider → spir}/protocol.md +35 -21
- package/skeleton/protocols/{spider → spir}/templates/plan.md +14 -0
- package/skeleton/protocols/spir/templates/review.md +89 -0
- package/skeleton/protocols/tick/builder-prompt.md +56 -0
- package/skeleton/protocols/tick/protocol.json +7 -2
- package/skeleton/protocols/tick/protocol.md +18 -18
- package/skeleton/protocols/tick/templates/review.md +1 -1
- package/skeleton/resources/commands/agent-farm.md +63 -46
- package/skeleton/resources/commands/codev.md +0 -2
- package/skeleton/resources/commands/overview.md +7 -17
- package/skeleton/resources/workflow-reference.md +4 -4
- package/skeleton/roles/architect.md +152 -315
- package/skeleton/roles/builder.md +110 -218
- package/skeleton/roles/consultant.md +6 -6
- package/skeleton/templates/AGENTS.md +2 -2
- package/skeleton/templates/CLAUDE.md +2 -2
- package/skeleton/templates/cheatsheet.md +7 -5
- package/skeleton/templates/projectlist.md +1 -1
- package/templates/dashboard/index.html +17 -43
- package/templates/dashboard/js/dialogs.js +7 -7
- package/templates/dashboard/js/files.js +2 -2
- package/templates/dashboard/js/main.js +4 -4
- package/templates/dashboard/js/projects.js +3 -3
- package/templates/dashboard/js/tabs.js +1 -1
- package/templates/dashboard/js/utils.js +22 -87
- package/templates/open.html +26 -0
- package/templates/tower.html +642 -36
- package/dist/agent-farm/commands/kickoff.d.ts +0 -20
- package/dist/agent-farm/commands/kickoff.d.ts.map +0 -1
- package/dist/agent-farm/commands/kickoff.js +0 -337
- package/dist/agent-farm/commands/kickoff.js.map +0 -1
- package/dist/agent-farm/commands/rename.d.ts +0 -13
- package/dist/agent-farm/commands/rename.d.ts.map +0 -1
- package/dist/agent-farm/commands/rename.js +0 -33
- package/dist/agent-farm/commands/rename.js.map +0 -1
- package/dist/agent-farm/commands/tutorial.d.ts +0 -10
- package/dist/agent-farm/commands/tutorial.d.ts.map +0 -1
- package/dist/agent-farm/commands/tutorial.js +0 -49
- package/dist/agent-farm/commands/tutorial.js.map +0 -1
- package/dist/agent-farm/commands/util.d.ts +0 -15
- package/dist/agent-farm/commands/util.d.ts.map +0 -1
- package/dist/agent-farm/commands/util.js +0 -108
- package/dist/agent-farm/commands/util.js.map +0 -1
- package/dist/agent-farm/servers/dashboard-server.d.ts +0 -7
- package/dist/agent-farm/servers/dashboard-server.d.ts.map +0 -1
- package/dist/agent-farm/servers/dashboard-server.js +0 -1872
- package/dist/agent-farm/servers/dashboard-server.js.map +0 -1
- package/dist/agent-farm/servers/open-server.d.ts +0 -7
- package/dist/agent-farm/servers/open-server.d.ts.map +0 -1
- package/dist/agent-farm/servers/open-server.js +0 -315
- package/dist/agent-farm/servers/open-server.js.map +0 -1
- package/dist/agent-farm/tutorial/index.d.ts +0 -8
- package/dist/agent-farm/tutorial/index.d.ts.map +0 -1
- package/dist/agent-farm/tutorial/index.js +0 -8
- package/dist/agent-farm/tutorial/index.js.map +0 -1
- package/dist/agent-farm/tutorial/prompts.d.ts +0 -57
- package/dist/agent-farm/tutorial/prompts.d.ts.map +0 -1
- package/dist/agent-farm/tutorial/prompts.js +0 -147
- package/dist/agent-farm/tutorial/prompts.js.map +0 -1
- package/dist/agent-farm/tutorial/runner.d.ts +0 -52
- package/dist/agent-farm/tutorial/runner.d.ts.map +0 -1
- package/dist/agent-farm/tutorial/runner.js +0 -204
- package/dist/agent-farm/tutorial/runner.js.map +0 -1
- package/dist/agent-farm/tutorial/state.d.ts +0 -26
- package/dist/agent-farm/tutorial/state.d.ts.map +0 -1
- package/dist/agent-farm/tutorial/state.js +0 -89
- package/dist/agent-farm/tutorial/state.js.map +0 -1
- package/dist/agent-farm/tutorial/steps/first-spec.d.ts +0 -7
- package/dist/agent-farm/tutorial/steps/first-spec.d.ts.map +0 -1
- package/dist/agent-farm/tutorial/steps/first-spec.js +0 -136
- package/dist/agent-farm/tutorial/steps/first-spec.js.map +0 -1
- package/dist/agent-farm/tutorial/steps/implementation.d.ts +0 -7
- package/dist/agent-farm/tutorial/steps/implementation.d.ts.map +0 -1
- package/dist/agent-farm/tutorial/steps/implementation.js +0 -76
- package/dist/agent-farm/tutorial/steps/implementation.js.map +0 -1
- package/dist/agent-farm/tutorial/steps/index.d.ts +0 -10
- package/dist/agent-farm/tutorial/steps/index.d.ts.map +0 -1
- package/dist/agent-farm/tutorial/steps/index.js +0 -10
- package/dist/agent-farm/tutorial/steps/index.js.map +0 -1
- package/dist/agent-farm/tutorial/steps/planning.d.ts +0 -7
- package/dist/agent-farm/tutorial/steps/planning.d.ts.map +0 -1
- package/dist/agent-farm/tutorial/steps/planning.js +0 -143
- package/dist/agent-farm/tutorial/steps/planning.js.map +0 -1
- package/dist/agent-farm/tutorial/steps/review.d.ts +0 -7
- package/dist/agent-farm/tutorial/steps/review.d.ts.map +0 -1
- package/dist/agent-farm/tutorial/steps/review.js +0 -78
- package/dist/agent-farm/tutorial/steps/review.js.map +0 -1
- package/dist/agent-farm/tutorial/steps/setup.d.ts +0 -7
- package/dist/agent-farm/tutorial/steps/setup.d.ts.map +0 -1
- package/dist/agent-farm/tutorial/steps/setup.js +0 -126
- package/dist/agent-farm/tutorial/steps/setup.js.map +0 -1
- package/dist/agent-farm/tutorial/steps/welcome.d.ts +0 -7
- package/dist/agent-farm/tutorial/steps/welcome.d.ts.map +0 -1
- package/dist/agent-farm/tutorial/steps/welcome.js +0 -50
- package/dist/agent-farm/tutorial/steps/welcome.js.map +0 -1
- package/dist/agent-farm/utils/orphan-handler.d.ts +0 -27
- package/dist/agent-farm/utils/orphan-handler.d.ts.map +0 -1
- package/dist/agent-farm/utils/orphan-handler.js +0 -149
- package/dist/agent-farm/utils/orphan-handler.js.map +0 -1
- package/dist/agent-farm/utils/port-registry.d.ts +0 -58
- package/dist/agent-farm/utils/port-registry.d.ts.map +0 -1
- package/dist/agent-farm/utils/port-registry.js +0 -166
- package/dist/agent-farm/utils/port-registry.js.map +0 -1
- package/dist/agent-farm/utils/terminal-ports.d.ts +0 -18
- package/dist/agent-farm/utils/terminal-ports.d.ts.map +0 -1
- package/dist/agent-farm/utils/terminal-ports.js +0 -35
- package/dist/agent-farm/utils/terminal-ports.js.map +0 -1
- package/dist/commands/pcheck/cache.d.ts +0 -48
- package/dist/commands/pcheck/cache.d.ts.map +0 -1
- package/dist/commands/pcheck/cache.js +0 -170
- package/dist/commands/pcheck/cache.js.map +0 -1
- package/dist/commands/pcheck/evaluator.d.ts +0 -15
- package/dist/commands/pcheck/evaluator.d.ts.map +0 -1
- package/dist/commands/pcheck/evaluator.js +0 -246
- package/dist/commands/pcheck/evaluator.js.map +0 -1
- package/dist/commands/pcheck/index.d.ts +0 -12
- package/dist/commands/pcheck/index.d.ts.map +0 -1
- package/dist/commands/pcheck/index.js +0 -249
- package/dist/commands/pcheck/index.js.map +0 -1
- package/dist/commands/pcheck/parser.d.ts +0 -39
- package/dist/commands/pcheck/parser.d.ts.map +0 -1
- package/dist/commands/pcheck/parser.js +0 -155
- package/dist/commands/pcheck/parser.js.map +0 -1
- package/dist/commands/pcheck/types.d.ts +0 -82
- package/dist/commands/pcheck/types.d.ts.map +0 -1
- package/dist/commands/pcheck/types.js +0 -5
- package/dist/commands/pcheck/types.js.map +0 -1
- package/dist/commands/porch/consultation.d.ts +0 -56
- package/dist/commands/porch/consultation.d.ts.map +0 -1
- package/dist/commands/porch/consultation.js +0 -330
- package/dist/commands/porch/consultation.js.map +0 -1
- package/dist/commands/porch/notifications.d.ts +0 -99
- package/dist/commands/porch/notifications.d.ts.map +0 -1
- package/dist/commands/porch/notifications.js +0 -223
- package/dist/commands/porch/notifications.js.map +0 -1
- package/dist/commands/porch/plan-parser.d.ts +0 -38
- package/dist/commands/porch/plan-parser.d.ts.map +0 -1
- package/dist/commands/porch/plan-parser.js +0 -166
- package/dist/commands/porch/plan-parser.js.map +0 -1
- package/dist/commands/porch/protocol-loader.d.ts +0 -46
- package/dist/commands/porch/protocol-loader.d.ts.map +0 -1
- package/dist/commands/porch/protocol-loader.js +0 -253
- package/dist/commands/porch/protocol-loader.js.map +0 -1
- package/dist/commands/porch/signal-parser.d.ts +0 -88
- package/dist/commands/porch/signal-parser.d.ts.map +0 -1
- package/dist/commands/porch/signal-parser.js +0 -148
- package/dist/commands/porch/signal-parser.js.map +0 -1
- package/dist/commands/tower.d.ts +0 -16
- package/dist/commands/tower.d.ts.map +0 -1
- package/dist/commands/tower.js +0 -21
- package/dist/commands/tower.js.map +0 -1
- package/skeleton/config.json +0 -7
- package/skeleton/porch/protocols/bugfix.json +0 -85
- package/skeleton/porch/protocols/spider.json +0 -135
- package/skeleton/porch/protocols/tick.json +0 -76
- package/skeleton/protocols/spider/prompts/defend.md +0 -215
- package/skeleton/protocols/spider/prompts/evaluate.md +0 -241
- package/skeleton/protocols/spider/prompts/implement.md +0 -149
- package/skeleton/protocols/spider/protocol.json +0 -210
- package/skeleton/protocols/spider/templates/review.md +0 -207
- package/templates/dashboard/css/activity.css +0 -151
- package/templates/dashboard/js/activity.js +0 -112
- /package/skeleton/protocols/{spider → spir}/templates/spec.md +0 -0
package/templates/tower.html
CHANGED
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
|
6
|
+
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
7
|
+
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
8
|
+
<meta name="theme-color" content="#252525">
|
|
9
|
+
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🗼</text></svg>">
|
|
10
|
+
<title>Agent Farm Tower</title>
|
|
7
11
|
<style>
|
|
8
12
|
* {
|
|
9
13
|
box-sizing: border-box;
|
|
@@ -199,6 +203,36 @@
|
|
|
199
203
|
overflow: hidden;
|
|
200
204
|
}
|
|
201
205
|
|
|
206
|
+
.instance.gate-pending {
|
|
207
|
+
border-color: #f59e0b;
|
|
208
|
+
animation: gate-pulse 2s infinite;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
@keyframes gate-pulse {
|
|
212
|
+
0%, 100% { border-color: #f59e0b; }
|
|
213
|
+
50% { border-color: #d97706; }
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.gate-indicator {
|
|
217
|
+
padding: 8px 20px;
|
|
218
|
+
background: rgba(245, 158, 11, 0.15);
|
|
219
|
+
border-bottom: 1px solid var(--border);
|
|
220
|
+
font-size: 14px;
|
|
221
|
+
color: #f59e0b;
|
|
222
|
+
display: flex;
|
|
223
|
+
align-items: center;
|
|
224
|
+
gap: 8px;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.gate-indicator .gate-name {
|
|
228
|
+
font-weight: 600;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.gate-indicator .gate-builder {
|
|
232
|
+
color: var(--text-muted);
|
|
233
|
+
font-size: 12px;
|
|
234
|
+
}
|
|
235
|
+
|
|
202
236
|
.instance-header {
|
|
203
237
|
display: flex;
|
|
204
238
|
justify-content: space-between;
|
|
@@ -388,6 +422,11 @@
|
|
|
388
422
|
gap: 24px;
|
|
389
423
|
}
|
|
390
424
|
|
|
425
|
+
.new-shell-row {
|
|
426
|
+
margin-top: 8px;
|
|
427
|
+
padding-top: 8px;
|
|
428
|
+
}
|
|
429
|
+
|
|
391
430
|
/* Recents section */
|
|
392
431
|
.recents-section {
|
|
393
432
|
margin-top: 32px;
|
|
@@ -603,6 +642,61 @@
|
|
|
603
642
|
}
|
|
604
643
|
}
|
|
605
644
|
|
|
645
|
+
/* Cloud status */
|
|
646
|
+
.cloud-status {
|
|
647
|
+
display: inline-flex;
|
|
648
|
+
align-items: center;
|
|
649
|
+
gap: 8px;
|
|
650
|
+
font-size: 14px;
|
|
651
|
+
color: var(--text-secondary);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
.cloud-dot {
|
|
655
|
+
width: 8px;
|
|
656
|
+
height: 8px;
|
|
657
|
+
border-radius: 50%;
|
|
658
|
+
display: inline-block;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
.cloud-dot--green { background: var(--status-running); }
|
|
662
|
+
.cloud-dot--yellow { background: #eab308; }
|
|
663
|
+
.cloud-dot--red { background: #ef4444; }
|
|
664
|
+
.cloud-dot--gray { background: var(--text-muted); }
|
|
665
|
+
|
|
666
|
+
.cloud-link {
|
|
667
|
+
color: var(--accent);
|
|
668
|
+
text-decoration: none;
|
|
669
|
+
font-size: 13px;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
.cloud-link:hover {
|
|
673
|
+
text-decoration: underline;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
.cloud-uptime {
|
|
677
|
+
color: var(--text-muted);
|
|
678
|
+
font-size: 12px;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
.cloud-btn {
|
|
682
|
+
padding: 4px 10px;
|
|
683
|
+
border-radius: 4px;
|
|
684
|
+
border: 1px solid var(--border);
|
|
685
|
+
background: var(--bg-tertiary);
|
|
686
|
+
color: var(--text-secondary);
|
|
687
|
+
cursor: pointer;
|
|
688
|
+
font-size: 12px;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
.cloud-btn:hover {
|
|
692
|
+
background: #333;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
.cloud-btn:disabled {
|
|
696
|
+
opacity: 0.5;
|
|
697
|
+
cursor: default;
|
|
698
|
+
}
|
|
699
|
+
|
|
606
700
|
/* Reduced motion */
|
|
607
701
|
@media (prefers-reduced-motion: reduce) {
|
|
608
702
|
.status-dot.running,
|
|
@@ -611,6 +705,183 @@
|
|
|
611
705
|
}
|
|
612
706
|
}
|
|
613
707
|
|
|
708
|
+
/* Mobile optimizations */
|
|
709
|
+
@media (max-width: 600px) {
|
|
710
|
+
body {
|
|
711
|
+
padding-bottom: env(safe-area-inset-bottom, 0);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
.header {
|
|
715
|
+
padding: 16px;
|
|
716
|
+
padding-top: calc(16px + env(safe-area-inset-top, 0));
|
|
717
|
+
flex-wrap: wrap;
|
|
718
|
+
gap: 12px;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
.header h1 {
|
|
722
|
+
font-size: 18px;
|
|
723
|
+
width: 100%;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
.header h1 .emoji {
|
|
727
|
+
font-size: 22px;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
.header-actions {
|
|
731
|
+
width: 100%;
|
|
732
|
+
justify-content: flex-end;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/* 1. Hide Share button on mobile (tunnel is for reaching phone, not FROM phone) */
|
|
736
|
+
#share-btn {
|
|
737
|
+
display: none !important;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
/* 7. Reduce section spacing */
|
|
741
|
+
.main {
|
|
742
|
+
padding: 12px;
|
|
743
|
+
padding-left: calc(12px + env(safe-area-inset-left, 0));
|
|
744
|
+
padding-right: calc(12px + env(safe-area-inset-right, 0));
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
.section-header {
|
|
748
|
+
margin-bottom: 8px;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
.instances {
|
|
752
|
+
gap: 10px;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
.btn {
|
|
756
|
+
min-height: 44px;
|
|
757
|
+
min-width: 44px;
|
|
758
|
+
padding: 12px 16px;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
.btn-small {
|
|
762
|
+
min-height: 44px;
|
|
763
|
+
padding: 10px 14px;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/* 2. Keep project name + status badge + Restart/Stop on one line */
|
|
767
|
+
.instance-header {
|
|
768
|
+
flex-wrap: wrap;
|
|
769
|
+
gap: 8px;
|
|
770
|
+
padding: 12px 16px;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
.instance-actions {
|
|
774
|
+
margin-left: auto;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/* 3. Hide project path row on mobile */
|
|
778
|
+
.instance-path-row {
|
|
779
|
+
display: none;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/* 4. Compact terminal list (Overview, Architect, shells) */
|
|
783
|
+
.port-item {
|
|
784
|
+
flex-direction: row;
|
|
785
|
+
align-items: center;
|
|
786
|
+
padding: 8px 12px;
|
|
787
|
+
gap: 8px;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
.port-actions {
|
|
791
|
+
width: auto;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
.port-actions a {
|
|
795
|
+
display: flex;
|
|
796
|
+
align-items: center;
|
|
797
|
+
justify-content: center;
|
|
798
|
+
padding: 6px 12px;
|
|
799
|
+
flex: 0;
|
|
800
|
+
/* min-height handled by @media (pointer: coarse) at 44px */
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
.instance-body {
|
|
804
|
+
padding: 12px;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/* 5. Compact New Shell row */
|
|
808
|
+
.new-shell-row {
|
|
809
|
+
margin-top: 4px;
|
|
810
|
+
padding-top: 4px;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
/* 6. Compact Recent Projects */
|
|
814
|
+
.recent-item {
|
|
815
|
+
flex-direction: row;
|
|
816
|
+
align-items: center;
|
|
817
|
+
padding: 12px 16px;
|
|
818
|
+
gap: 8px;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
.recent-path {
|
|
822
|
+
display: none;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
.recent-time {
|
|
826
|
+
font-size: 12px;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
/* 7. Reduce section spacing (continued) */
|
|
830
|
+
.recents-section {
|
|
831
|
+
margin-top: 16px;
|
|
832
|
+
padding-top: 16px;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
.instance-meta {
|
|
836
|
+
margin-top: 8px;
|
|
837
|
+
padding-top: 8px;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
.launch-section {
|
|
841
|
+
padding: 16px;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
.launch-form {
|
|
845
|
+
flex-direction: column;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
.launch-form input[type="text"] {
|
|
849
|
+
min-height: 44px;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
.btn-launch {
|
|
853
|
+
width: 100%;
|
|
854
|
+
min-height: 44px;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
.dialog-box {
|
|
858
|
+
min-width: auto;
|
|
859
|
+
width: calc(100% - 32px);
|
|
860
|
+
margin: 16px;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
.toast-container {
|
|
864
|
+
left: 16px;
|
|
865
|
+
right: 16px;
|
|
866
|
+
bottom: calc(16px + env(safe-area-inset-bottom, 0));
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
/* Touch-friendly tap targets */
|
|
871
|
+
@media (pointer: coarse) {
|
|
872
|
+
.btn, .port-actions a, .autocomplete-item, .recent-item {
|
|
873
|
+
min-height: 44px;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
.copy-btn {
|
|
877
|
+
min-width: 44px;
|
|
878
|
+
min-height: 44px;
|
|
879
|
+
display: flex;
|
|
880
|
+
align-items: center;
|
|
881
|
+
justify-content: center;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
|
|
614
885
|
/* Dialog styles */
|
|
615
886
|
.dialog-overlay {
|
|
616
887
|
position: fixed;
|
|
@@ -680,6 +951,7 @@
|
|
|
680
951
|
Agent Farm Control Tower
|
|
681
952
|
</h1>
|
|
682
953
|
<div class="header-actions">
|
|
954
|
+
<span id="cloud-status"></span>
|
|
683
955
|
<button class="btn" onclick="refresh()">Refresh</button>
|
|
684
956
|
</div>
|
|
685
957
|
</header>
|
|
@@ -733,6 +1005,7 @@
|
|
|
733
1005
|
</div>
|
|
734
1006
|
</div>
|
|
735
1007
|
</div>
|
|
1008
|
+
|
|
736
1009
|
</main>
|
|
737
1010
|
|
|
738
1011
|
<div class="toast-container" id="toast-container"></div>
|
|
@@ -742,23 +1015,153 @@
|
|
|
742
1015
|
let runningInstances = [];
|
|
743
1016
|
let recentInstances = [];
|
|
744
1017
|
|
|
1018
|
+
// Auth helper: get headers with auth token if available
|
|
1019
|
+
function getAuthHeaders() {
|
|
1020
|
+
const key = localStorage.getItem('codev-web-key');
|
|
1021
|
+
return key ? { 'Authorization': `Bearer ${key}` } : {};
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
// Auth helper: make authenticated fetch request
|
|
1025
|
+
async function authFetch(url, options = {}) {
|
|
1026
|
+
const headers = { ...getAuthHeaders(), ...(options.headers || {}) };
|
|
1027
|
+
const response = await fetch(url, { ...options, headers });
|
|
1028
|
+
|
|
1029
|
+
// If 401, clear key and redirect to login
|
|
1030
|
+
if (response.status === 401) {
|
|
1031
|
+
localStorage.removeItem('codev-web-key');
|
|
1032
|
+
location.reload();
|
|
1033
|
+
throw new Error('Unauthorized');
|
|
1034
|
+
}
|
|
1035
|
+
return response;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
// Logout function
|
|
1039
|
+
function logout() {
|
|
1040
|
+
localStorage.removeItem('codev-web-key');
|
|
1041
|
+
window.location.href = './';
|
|
1042
|
+
}
|
|
1043
|
+
|
|
745
1044
|
// Initialize
|
|
746
1045
|
async function init() {
|
|
1046
|
+
// Request notification permission
|
|
1047
|
+
if ('Notification' in window && Notification.permission === 'default') {
|
|
1048
|
+
try {
|
|
1049
|
+
await Notification.requestPermission();
|
|
1050
|
+
} catch (e) {
|
|
1051
|
+
// Ignore errors, notifications are optional
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
// Subscribe to SSE for push notifications
|
|
1056
|
+
subscribeToEvents();
|
|
1057
|
+
|
|
747
1058
|
await refresh();
|
|
748
1059
|
// Poll every 5 seconds
|
|
749
1060
|
setInterval(refresh, 5000);
|
|
750
1061
|
}
|
|
751
1062
|
|
|
1063
|
+
// SSE subscription for real-time notifications
|
|
1064
|
+
// Uses fetch + ReadableStream to support Authorization header
|
|
1065
|
+
let sseController = null;
|
|
1066
|
+
|
|
1067
|
+
async function subscribeToEvents() {
|
|
1068
|
+
// Abort any existing connection
|
|
1069
|
+
if (sseController) {
|
|
1070
|
+
sseController.abort();
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
sseController = new AbortController();
|
|
1074
|
+
|
|
1075
|
+
try {
|
|
1076
|
+
const response = await fetch('./api/events', {
|
|
1077
|
+
headers: getAuthHeaders(),
|
|
1078
|
+
signal: sseController.signal,
|
|
1079
|
+
});
|
|
1080
|
+
|
|
1081
|
+
if (!response.ok) {
|
|
1082
|
+
console.log('SSE connection failed:', response.status);
|
|
1083
|
+
setTimeout(subscribeToEvents, 5000);
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
const reader = response.body.getReader();
|
|
1088
|
+
const decoder = new TextDecoder();
|
|
1089
|
+
let buffer = '';
|
|
1090
|
+
|
|
1091
|
+
while (true) {
|
|
1092
|
+
const { done, value } = await reader.read();
|
|
1093
|
+
|
|
1094
|
+
if (done) {
|
|
1095
|
+
console.log('SSE stream ended, reconnecting...');
|
|
1096
|
+
setTimeout(subscribeToEvents, 5000);
|
|
1097
|
+
return;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1101
|
+
|
|
1102
|
+
// Parse SSE format: "data: {...}\n\n"
|
|
1103
|
+
const lines = buffer.split('\n\n');
|
|
1104
|
+
buffer = lines.pop() || ''; // Keep incomplete message in buffer
|
|
1105
|
+
|
|
1106
|
+
for (const chunk of lines) {
|
|
1107
|
+
const dataMatch = chunk.match(/^data:\s*(.+)$/m);
|
|
1108
|
+
if (!dataMatch) continue;
|
|
1109
|
+
|
|
1110
|
+
try {
|
|
1111
|
+
const data = JSON.parse(dataMatch[1]);
|
|
1112
|
+
|
|
1113
|
+
if (data.type === 'connected') {
|
|
1114
|
+
console.log('SSE connected:', data.id);
|
|
1115
|
+
continue;
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
// Show browser notification
|
|
1119
|
+
if ('Notification' in window && Notification.permission === 'granted') {
|
|
1120
|
+
const notification = new Notification(data.title, {
|
|
1121
|
+
body: data.body,
|
|
1122
|
+
icon: '/favicon.ico',
|
|
1123
|
+
tag: 'tower-notification-' + data.id,
|
|
1124
|
+
});
|
|
1125
|
+
|
|
1126
|
+
// Auto-close after 5 seconds
|
|
1127
|
+
setTimeout(() => notification.close(), 5000);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
// Also show in-app toast
|
|
1131
|
+
showToast(`${data.title}: ${data.body}`, data.type || 'info');
|
|
1132
|
+
|
|
1133
|
+
// Refresh to show updated status
|
|
1134
|
+
refresh();
|
|
1135
|
+
} catch (e) {
|
|
1136
|
+
console.error('SSE parse error:', e);
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
} catch (e) {
|
|
1141
|
+
if (e.name === 'AbortError') {
|
|
1142
|
+
// Intentional abort, don't reconnect
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1145
|
+
console.error('SSE error:', e);
|
|
1146
|
+
setTimeout(subscribeToEvents, 5000);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
|
|
752
1150
|
// Refresh data from API
|
|
753
1151
|
async function refresh() {
|
|
754
1152
|
try {
|
|
755
|
-
const
|
|
756
|
-
|
|
1153
|
+
const [statusResponse, cloudStatus] = await Promise.all([
|
|
1154
|
+
authFetch('./api/status'),
|
|
1155
|
+
fetchCloudStatus(),
|
|
1156
|
+
]);
|
|
757
1157
|
|
|
758
|
-
|
|
1158
|
+
if (!statusResponse.ok) throw new Error('Failed to fetch status');
|
|
1159
|
+
|
|
1160
|
+
const data = await statusResponse.json();
|
|
759
1161
|
runningInstances = (data.instances || []).filter(i => i.running);
|
|
760
1162
|
recentInstances = (data.instances || []).filter(i => !i.running);
|
|
761
1163
|
render();
|
|
1164
|
+
renderCloudStatus(cloudStatus);
|
|
762
1165
|
} catch (err) {
|
|
763
1166
|
console.error('Refresh error:', err);
|
|
764
1167
|
showToast('Failed to refresh: ' + err.message, 'error');
|
|
@@ -774,7 +1177,7 @@
|
|
|
774
1177
|
<div class="empty-state">
|
|
775
1178
|
<div class="icon">📭</div>
|
|
776
1179
|
<h2>No running instances</h2>
|
|
777
|
-
<p>Start a new instance below or run <code>af start</code> in a project directory.</p>
|
|
1180
|
+
<p>Start a new instance below or run <code>af dash start</code> in a project directory.</p>
|
|
778
1181
|
</div>
|
|
779
1182
|
`;
|
|
780
1183
|
} else {
|
|
@@ -810,28 +1213,69 @@
|
|
|
810
1213
|
function renderInstance(instance) {
|
|
811
1214
|
const statusClass = instance.running ? 'running' : 'stopped';
|
|
812
1215
|
const statusText = instance.running ? 'Running' : 'Stopped';
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
1216
|
+
const hasGate = instance.gateStatus?.hasGate;
|
|
1217
|
+
|
|
1218
|
+
// Render terminals list - always show Overview first, then individual terminals
|
|
1219
|
+
const terminals = instance.terminals || [];
|
|
1220
|
+
let terminalsHtml = '';
|
|
1221
|
+
|
|
1222
|
+
if (instance.running) {
|
|
1223
|
+
// Always show Overview link first (opens split view with Architect + Status panel)
|
|
1224
|
+
terminalsHtml = `
|
|
1225
|
+
<div class="port-item">
|
|
1226
|
+
<div class="port-info">
|
|
1227
|
+
<span class="port-status active"></span>
|
|
1228
|
+
<span class="port-type">Overview</span>
|
|
1229
|
+
</div>
|
|
1230
|
+
<div class="port-actions">
|
|
1231
|
+
<a href="${escapeHtml(relUrl(instance.proxyUrl))}" target="_blank">Open</a>
|
|
1232
|
+
</div>
|
|
820
1233
|
</div>
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
1234
|
+
`;
|
|
1235
|
+
|
|
1236
|
+
// Then show individual terminals (open full-screen terminal view)
|
|
1237
|
+
if (terminals.length > 0) {
|
|
1238
|
+
terminalsHtml += terminals.map(terminal => `
|
|
1239
|
+
<div class="port-item">
|
|
1240
|
+
<div class="port-info">
|
|
1241
|
+
<span class="port-status ${terminal.active ? 'active' : 'inactive'}"></span>
|
|
1242
|
+
<span class="port-type">${escapeHtml(terminal.label)}</span>
|
|
1243
|
+
</div>
|
|
1244
|
+
<div class="port-actions">
|
|
1245
|
+
<a href="${escapeHtml(relUrl(terminal.url))}&fullscreen=1" target="_blank">Open</a>
|
|
1246
|
+
</div>
|
|
1247
|
+
</div>
|
|
1248
|
+
`).join('');
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
// Add "New Shell" button for this instance
|
|
1252
|
+
terminalsHtml += `
|
|
1253
|
+
<div class="port-item new-shell-row" style="border-top: 1px dashed var(--border);">
|
|
1254
|
+
<div class="port-info">
|
|
1255
|
+
<span class="port-status" style="background: var(--accent);"></span>
|
|
1256
|
+
<span class="port-type">New Shell</span>
|
|
1257
|
+
</div>
|
|
1258
|
+
<div class="port-actions">
|
|
1259
|
+
<button class="btn btn-small" onclick="createShell('${escapeHtml(instance.projectPath)}')">+ Create</button>
|
|
1260
|
+
</div>
|
|
825
1261
|
</div>
|
|
826
|
-
|
|
827
|
-
|
|
1262
|
+
`;
|
|
1263
|
+
}
|
|
828
1264
|
|
|
829
1265
|
const lastUsed = instance.lastUsed
|
|
830
1266
|
? formatDate(instance.lastUsed)
|
|
831
1267
|
: 'Never';
|
|
832
1268
|
|
|
1269
|
+
const gateIndicatorHtml = hasGate ? `
|
|
1270
|
+
<div class="gate-indicator">
|
|
1271
|
+
<span>⏳</span>
|
|
1272
|
+
<span class="gate-name">${escapeHtml(instance.gateStatus.gateName || 'approval')}</span>
|
|
1273
|
+
${instance.gateStatus.builderId ? `<span class="gate-builder">(${escapeHtml(instance.gateStatus.builderId)})</span>` : ''}
|
|
1274
|
+
</div>
|
|
1275
|
+
` : '';
|
|
1276
|
+
|
|
833
1277
|
return `
|
|
834
|
-
<div class="instance">
|
|
1278
|
+
<div class="instance ${hasGate ? 'gate-pending' : ''}" data-project="${escapeHtml(instance.projectPath)}">
|
|
835
1279
|
<div class="instance-header">
|
|
836
1280
|
<div class="instance-title">
|
|
837
1281
|
<span class="instance-name">${escapeHtml(instance.projectName)}</span>
|
|
@@ -842,13 +1286,14 @@
|
|
|
842
1286
|
</div>
|
|
843
1287
|
<div class="instance-actions">
|
|
844
1288
|
${instance.running ? `
|
|
845
|
-
<button class="btn btn-small" onclick="restartInstance(
|
|
846
|
-
<button class="btn btn-small btn-danger" onclick="stopInstance(${instance.
|
|
1289
|
+
<button class="btn btn-small" onclick="restartInstance('${escapeHtml(instance.projectPath)}')">Restart</button>
|
|
1290
|
+
<button class="btn btn-small btn-danger" onclick="stopInstance('${escapeHtml(instance.projectPath)}')">Stop</button>
|
|
847
1291
|
` : `
|
|
848
1292
|
<button class="btn btn-small btn-primary" onclick="launchPath('${escapeHtml(instance.projectPath)}')">Start</button>
|
|
849
1293
|
`}
|
|
850
1294
|
</div>
|
|
851
1295
|
</div>
|
|
1296
|
+
${gateIndicatorHtml}
|
|
852
1297
|
<div class="instance-path-row">
|
|
853
1298
|
<span class="instance-path" title="${escapeHtml(instance.projectPath)}">
|
|
854
1299
|
${escapeHtml(instance.projectPath)}
|
|
@@ -857,11 +1302,10 @@
|
|
|
857
1302
|
</div>
|
|
858
1303
|
<div class="instance-body">
|
|
859
1304
|
<div class="ports-list">
|
|
860
|
-
${
|
|
1305
|
+
${terminalsHtml}
|
|
861
1306
|
</div>
|
|
862
1307
|
<div class="instance-meta">
|
|
863
1308
|
<span>Last active: ${lastUsed}</span>
|
|
864
|
-
<span>Port block: ${instance.basePort}-${instance.basePort + 99}</span>
|
|
865
1309
|
</div>
|
|
866
1310
|
</div>
|
|
867
1311
|
</div>
|
|
@@ -952,7 +1396,7 @@
|
|
|
952
1396
|
}
|
|
953
1397
|
|
|
954
1398
|
try {
|
|
955
|
-
const response = await
|
|
1399
|
+
const response = await authFetch('./api/browse?path=' + encodeURIComponent(inputPath));
|
|
956
1400
|
const data = await response.json();
|
|
957
1401
|
suggestions = data.suggestions || [];
|
|
958
1402
|
selectedIndex = -1;
|
|
@@ -1007,7 +1451,7 @@
|
|
|
1007
1451
|
// Launch a specific path (from recents)
|
|
1008
1452
|
async function launchPath(projectPath) {
|
|
1009
1453
|
try {
|
|
1010
|
-
const response = await
|
|
1454
|
+
const response = await authFetch('./api/launch', {
|
|
1011
1455
|
method: 'POST',
|
|
1012
1456
|
headers: { 'Content-Type': 'application/json' },
|
|
1013
1457
|
body: JSON.stringify({ projectPath })
|
|
@@ -1030,13 +1474,13 @@
|
|
|
1030
1474
|
}
|
|
1031
1475
|
}
|
|
1032
1476
|
|
|
1033
|
-
// Stop an instance by
|
|
1034
|
-
async function stopInstance(
|
|
1477
|
+
// Stop an instance by project path
|
|
1478
|
+
async function stopInstance(projectPath) {
|
|
1035
1479
|
try {
|
|
1036
|
-
const response = await
|
|
1480
|
+
const response = await authFetch('./api/stop', {
|
|
1037
1481
|
method: 'POST',
|
|
1038
1482
|
headers: { 'Content-Type': 'application/json' },
|
|
1039
|
-
body: JSON.stringify({
|
|
1483
|
+
body: JSON.stringify({ projectPath })
|
|
1040
1484
|
});
|
|
1041
1485
|
|
|
1042
1486
|
const result = await response.json();
|
|
@@ -1053,20 +1497,20 @@
|
|
|
1053
1497
|
}
|
|
1054
1498
|
|
|
1055
1499
|
// Restart an instance
|
|
1056
|
-
async function restartInstance(
|
|
1500
|
+
async function restartInstance(projectPath) {
|
|
1057
1501
|
try {
|
|
1058
1502
|
// First stop
|
|
1059
|
-
await
|
|
1503
|
+
await authFetch('./api/stop', {
|
|
1060
1504
|
method: 'POST',
|
|
1061
1505
|
headers: { 'Content-Type': 'application/json' },
|
|
1062
|
-
body: JSON.stringify({
|
|
1506
|
+
body: JSON.stringify({ projectPath })
|
|
1063
1507
|
});
|
|
1064
1508
|
|
|
1065
1509
|
// Wait a moment for processes to die
|
|
1066
1510
|
await new Promise(r => setTimeout(r, 1000));
|
|
1067
1511
|
|
|
1068
1512
|
// Then start
|
|
1069
|
-
const response = await
|
|
1513
|
+
const response = await authFetch('./api/launch', {
|
|
1070
1514
|
method: 'POST',
|
|
1071
1515
|
headers: { 'Content-Type': 'application/json' },
|
|
1072
1516
|
body: JSON.stringify({ projectPath })
|
|
@@ -1096,7 +1540,7 @@
|
|
|
1096
1540
|
}
|
|
1097
1541
|
|
|
1098
1542
|
try {
|
|
1099
|
-
const response = await
|
|
1543
|
+
const response = await authFetch('./api/launch', {
|
|
1100
1544
|
method: 'POST',
|
|
1101
1545
|
headers: { 'Content-Type': 'application/json' },
|
|
1102
1546
|
body: JSON.stringify({ projectPath })
|
|
@@ -1122,6 +1566,34 @@
|
|
|
1122
1566
|
}
|
|
1123
1567
|
}
|
|
1124
1568
|
|
|
1569
|
+
// Create a new shell for a running instance (via tower proxy)
|
|
1570
|
+
async function createShell(projectPath) {
|
|
1571
|
+
try {
|
|
1572
|
+
// Use tower proxy to route to the project's dashboard API
|
|
1573
|
+
const encodedPath = toBase64URL(projectPath);
|
|
1574
|
+
const response = await authFetch(`./project/${encodedPath}/api/tabs/shell`, {
|
|
1575
|
+
method: 'POST',
|
|
1576
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1577
|
+
});
|
|
1578
|
+
|
|
1579
|
+
if (!response.ok) {
|
|
1580
|
+
const errorText = await response.text();
|
|
1581
|
+
throw new Error(errorText || 'Failed to create shell');
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
const result = await response.json();
|
|
1585
|
+
|
|
1586
|
+
if (result.success === false) {
|
|
1587
|
+
throw new Error(result.error || 'Failed to create shell');
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
showToast(`Shell created: ${result.name || 'shell'}`, 'success');
|
|
1591
|
+
setTimeout(refresh, 1000);
|
|
1592
|
+
} catch (err) {
|
|
1593
|
+
showToast('Failed to create shell: ' + err.message, 'error');
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1125
1597
|
// Format date for display
|
|
1126
1598
|
function formatDate(isoString) {
|
|
1127
1599
|
const date = new Date(isoString);
|
|
@@ -1159,6 +1631,13 @@
|
|
|
1159
1631
|
}
|
|
1160
1632
|
}
|
|
1161
1633
|
|
|
1634
|
+
// Convert absolute paths to relative so links work behind reverse proxies.
|
|
1635
|
+
// E.g. "/project/abc/" → "./project/abc/"
|
|
1636
|
+
function relUrl(path) {
|
|
1637
|
+
if (path && path.startsWith('/')) return '.' + path;
|
|
1638
|
+
return path || '';
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1162
1641
|
// HTML escape
|
|
1163
1642
|
function escapeHtml(str) {
|
|
1164
1643
|
if (!str) return '';
|
|
@@ -1170,6 +1649,23 @@
|
|
|
1170
1649
|
.replace(/'/g, ''');
|
|
1171
1650
|
}
|
|
1172
1651
|
|
|
1652
|
+
// Base64URL encoding (RFC 4648) for project paths
|
|
1653
|
+
// IMPORTANT: Use TextEncoder for Unicode support (btoa only handles Latin-1)
|
|
1654
|
+
function toBase64URL(str) {
|
|
1655
|
+
// Encode string to UTF-8 bytes, then to Base64, then to Base64URL
|
|
1656
|
+
const bytes = new TextEncoder().encode(str);
|
|
1657
|
+
const base64 = btoa(String.fromCharCode(...bytes));
|
|
1658
|
+
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
// Generate proxy URL for a project
|
|
1662
|
+
// All terminals are now multiplexed on a single port via WebSocket (Spec 0085)
|
|
1663
|
+
// The React dashboard handles tab selection internally
|
|
1664
|
+
function getProxyUrl(instance, portType) {
|
|
1665
|
+
const encodedPath = toBase64URL(instance.projectPath);
|
|
1666
|
+
return `./project/${encodedPath}/`;
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1173
1669
|
// Toast notifications
|
|
1174
1670
|
function showToast(message, type = 'info') {
|
|
1175
1671
|
const container = document.getElementById('toast-container');
|
|
@@ -1219,7 +1715,7 @@
|
|
|
1219
1715
|
hideCreateProjectDialog();
|
|
1220
1716
|
|
|
1221
1717
|
try {
|
|
1222
|
-
const response = await
|
|
1718
|
+
const response = await authFetch('./api/create', {
|
|
1223
1719
|
method: 'POST',
|
|
1224
1720
|
headers: { 'Content-Type': 'application/json' },
|
|
1225
1721
|
body: JSON.stringify({ parent, name })
|
|
@@ -1252,6 +1748,116 @@
|
|
|
1252
1748
|
}
|
|
1253
1749
|
});
|
|
1254
1750
|
|
|
1751
|
+
// Cloud status
|
|
1752
|
+
let cloudLoading = false;
|
|
1753
|
+
|
|
1754
|
+
async function fetchCloudStatus() {
|
|
1755
|
+
try {
|
|
1756
|
+
const res = await authFetch('./api/tunnel/status');
|
|
1757
|
+
if (res.status === 404) return null;
|
|
1758
|
+
if (!res.ok) return { state: 'error' };
|
|
1759
|
+
return await res.json();
|
|
1760
|
+
} catch {
|
|
1761
|
+
return null;
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
function formatUptime(ms) {
|
|
1766
|
+
const s = Math.floor(ms / 1000);
|
|
1767
|
+
if (s < 60) return s + 's';
|
|
1768
|
+
if (s < 3600) return Math.floor(s / 60) + 'm ' + (s % 60) + 's';
|
|
1769
|
+
const h = Math.floor(s / 3600);
|
|
1770
|
+
const m = Math.floor((s % 3600) / 60);
|
|
1771
|
+
return h + 'h ' + m + 'm';
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
function renderCloudStatus(status) {
|
|
1775
|
+
const el = document.getElementById('cloud-status');
|
|
1776
|
+
if (!status || status.state === 'error') {
|
|
1777
|
+
el.innerHTML = `
|
|
1778
|
+
<span class="cloud-status">
|
|
1779
|
+
<span class="cloud-dot cloud-dot--gray"></span>
|
|
1780
|
+
Cloud: not registered
|
|
1781
|
+
</span>`;
|
|
1782
|
+
return;
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1785
|
+
if (!status.registered) {
|
|
1786
|
+
el.innerHTML = `
|
|
1787
|
+
<span class="cloud-status">
|
|
1788
|
+
<span class="cloud-dot cloud-dot--gray"></span>
|
|
1789
|
+
Cloud: not registered
|
|
1790
|
+
</span>`;
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
if (status.state === 'auth_failed') {
|
|
1795
|
+
el.innerHTML = `
|
|
1796
|
+
<span class="cloud-status">
|
|
1797
|
+
<span class="cloud-dot cloud-dot--red"></span>
|
|
1798
|
+
Cloud: auth failed
|
|
1799
|
+
</span>`;
|
|
1800
|
+
return;
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
if (status.state === 'connecting') {
|
|
1804
|
+
el.innerHTML = `
|
|
1805
|
+
<span class="cloud-status">
|
|
1806
|
+
<span class="cloud-dot cloud-dot--yellow"></span>
|
|
1807
|
+
Cloud: connecting...
|
|
1808
|
+
</span>`;
|
|
1809
|
+
return;
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
if (status.state === 'connected') {
|
|
1813
|
+
const uptimeStr = status.uptime != null ? ' <span class="cloud-uptime">' + formatUptime(status.uptime) + '</span>' : '';
|
|
1814
|
+
const openLink = status.accessUrl ? ' <a href="' + escapeHtml(status.accessUrl) + '" target="_blank" rel="noopener" class="cloud-link">Open</a>' : '';
|
|
1815
|
+
el.innerHTML = `
|
|
1816
|
+
<span class="cloud-status">
|
|
1817
|
+
<span class="cloud-dot cloud-dot--green"></span>
|
|
1818
|
+
Cloud: ${escapeHtml(status.towerName || 'connected')}
|
|
1819
|
+
${uptimeStr}
|
|
1820
|
+
${openLink}
|
|
1821
|
+
<button class="cloud-btn" onclick="cloudDisconnect()" ${cloudLoading ? 'disabled' : ''}>Disconnect</button>
|
|
1822
|
+
</span>`;
|
|
1823
|
+
return;
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
// Disconnected
|
|
1827
|
+
el.innerHTML = `
|
|
1828
|
+
<span class="cloud-status">
|
|
1829
|
+
<span class="cloud-dot cloud-dot--gray"></span>
|
|
1830
|
+
Cloud: disconnected
|
|
1831
|
+
<button class="cloud-btn" onclick="cloudConnect()" ${cloudLoading ? 'disabled' : ''}>Connect</button>
|
|
1832
|
+
</span>`;
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
async function cloudConnect() {
|
|
1836
|
+
cloudLoading = true;
|
|
1837
|
+
renderCloudStatus({ registered: true, state: 'connecting' });
|
|
1838
|
+
try {
|
|
1839
|
+
await authFetch('./api/tunnel/connect', { method: 'POST' });
|
|
1840
|
+
showToast('Connecting to cloud...', 'success');
|
|
1841
|
+
} catch (err) {
|
|
1842
|
+
showToast('Connect failed: ' + err.message, 'error');
|
|
1843
|
+
}
|
|
1844
|
+
cloudLoading = false;
|
|
1845
|
+
// Refresh will pick up new status
|
|
1846
|
+
setTimeout(refresh, 2000);
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
async function cloudDisconnect() {
|
|
1850
|
+
cloudLoading = true;
|
|
1851
|
+
try {
|
|
1852
|
+
await authFetch('./api/tunnel/disconnect', { method: 'POST' });
|
|
1853
|
+
showToast('Disconnected from cloud', 'success');
|
|
1854
|
+
} catch (err) {
|
|
1855
|
+
showToast('Disconnect failed: ' + err.message, 'error');
|
|
1856
|
+
}
|
|
1857
|
+
cloudLoading = false;
|
|
1858
|
+
setTimeout(refresh, 1000);
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1255
1861
|
// Initialize
|
|
1256
1862
|
init();
|
|
1257
1863
|
</script>
|