@cluesmith/codev 3.3.4 → 3.3.6
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-BjcqV9Vv.css +32 -0
- package/dashboard-dist/assets/index-b7GnZV2i.js +220 -0
- package/dashboard-dist/assets/index-b7GnZV2i.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 +50 -17
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/architect.d.ts.map +1 -1
- package/dist/agent-farm/commands/architect.js +5 -1
- package/dist/agent-farm/commands/architect.js.map +1 -1
- package/dist/agent-farm/commands/attach.d.ts +1 -1
- package/dist/agent-farm/commands/attach.d.ts.map +1 -1
- package/dist/agent-farm/commands/cleanup.d.ts +1 -1
- package/dist/agent-farm/commands/cleanup.d.ts.map +1 -1
- package/dist/agent-farm/commands/cleanup.js +2 -1
- package/dist/agent-farm/commands/cleanup.js.map +1 -1
- package/dist/agent-farm/commands/decisions.d.ts +25 -0
- package/dist/agent-farm/commands/decisions.d.ts.map +1 -0
- package/dist/agent-farm/commands/decisions.js +54 -0
- package/dist/agent-farm/commands/decisions.js.map +1 -0
- package/dist/agent-farm/commands/ide.d.ts +32 -3
- package/dist/agent-farm/commands/ide.d.ts.map +1 -1
- package/dist/agent-farm/commands/ide.js +180 -19
- package/dist/agent-farm/commands/ide.js.map +1 -1
- package/dist/agent-farm/commands/reset/context.d.ts +4 -2
- package/dist/agent-farm/commands/reset/context.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/context.js +12 -4
- package/dist/agent-farm/commands/reset/context.js.map +1 -1
- package/dist/agent-farm/commands/send.d.ts +3 -2
- package/dist/agent-farm/commands/send.d.ts.map +1 -1
- package/dist/agent-farm/commands/send.js +35 -21
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.d.ts +7 -0
- package/dist/agent-farm/commands/spawn-worktree.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js +63 -20
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
- package/dist/agent-farm/commands/spawn.d.ts +17 -0
- package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn.js +41 -19
- package/dist/agent-farm/commands/spawn.js.map +1 -1
- package/dist/agent-farm/lib/builder-lookup.d.ts +3 -2
- package/dist/agent-farm/lib/builder-lookup.d.ts.map +1 -1
- package/dist/agent-farm/lib/builder-lookup.js +24 -9
- package/dist/agent-farm/lib/builder-lookup.js.map +1 -1
- package/dist/agent-farm/lib/ide-extensions.d.ts +82 -0
- package/dist/agent-farm/lib/ide-extensions.d.ts.map +1 -0
- package/dist/agent-farm/lib/ide-extensions.js +179 -0
- package/dist/agent-farm/lib/ide-extensions.js.map +1 -0
- package/dist/agent-farm/lib/ide-record.d.ts +6 -1
- package/dist/agent-farm/lib/ide-record.d.ts.map +1 -1
- package/dist/agent-farm/lib/ide-record.js +8 -1
- package/dist/agent-farm/lib/ide-record.js.map +1 -1
- package/dist/agent-farm/lib/ide-version.d.ts +97 -0
- package/dist/agent-farm/lib/ide-version.d.ts.map +1 -0
- package/dist/agent-farm/lib/ide-version.js +224 -0
- package/dist/agent-farm/lib/ide-version.js.map +1 -0
- package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.js +7 -3
- package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
- package/dist/agent-farm/servers/agent-state/broadcast.d.ts +19 -0
- package/dist/agent-farm/servers/agent-state/broadcast.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/broadcast.js +30 -0
- package/dist/agent-farm/servers/agent-state/broadcast.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/identity.d.ts +50 -0
- package/dist/agent-farm/servers/agent-state/identity.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/identity.js +120 -0
- package/dist/agent-farm/servers/agent-state/identity.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/liveness.d.ts +107 -0
- package/dist/agent-farm/servers/agent-state/liveness.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/liveness.js +224 -0
- package/dist/agent-farm/servers/agent-state/liveness.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/route.d.ts +38 -0
- package/dist/agent-farm/servers/agent-state/route.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/route.js +170 -0
- package/dist/agent-farm/servers/agent-state/route.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/serve.d.ts +31 -0
- package/dist/agent-farm/servers/agent-state/serve.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/serve.js +49 -0
- package/dist/agent-farm/servers/agent-state/serve.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/store.d.ts +76 -0
- package/dist/agent-farm/servers/agent-state/store.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/store.js +157 -0
- package/dist/agent-farm/servers/agent-state/store.js.map +1 -0
- package/dist/agent-farm/servers/decisions/file.d.ts +50 -0
- package/dist/agent-farm/servers/decisions/file.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/file.js +146 -0
- package/dist/agent-farm/servers/decisions/file.js.map +1 -0
- package/dist/agent-farm/servers/decisions/grammar.d.ts +36 -0
- package/dist/agent-farm/servers/decisions/grammar.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/grammar.js +109 -0
- package/dist/agent-farm/servers/decisions/grammar.js.map +1 -0
- package/dist/agent-farm/servers/decisions/notice.d.ts +11 -0
- package/dist/agent-farm/servers/decisions/notice.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/notice.js +18 -0
- package/dist/agent-farm/servers/decisions/notice.js.map +1 -0
- package/dist/agent-farm/servers/decisions/parse.d.ts +36 -0
- package/dist/agent-farm/servers/decisions/parse.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/parse.js +338 -0
- package/dist/agent-farm/servers/decisions/parse.js.map +1 -0
- package/dist/agent-farm/servers/decisions/routes.d.ts +17 -0
- package/dist/agent-farm/servers/decisions/routes.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/routes.js +160 -0
- package/dist/agent-farm/servers/decisions/routes.js.map +1 -0
- package/dist/agent-farm/servers/decisions/splice.d.ts +26 -0
- package/dist/agent-farm/servers/decisions/splice.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/splice.js +120 -0
- package/dist/agent-farm/servers/decisions/splice.js.map +1 -0
- package/dist/agent-farm/servers/decisions/stamp.d.ts +8 -0
- package/dist/agent-farm/servers/decisions/stamp.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/stamp.js +195 -0
- package/dist/agent-farm/servers/decisions/stamp.js.map +1 -0
- package/dist/agent-farm/servers/decisions/template.d.ts +2 -0
- package/dist/agent-farm/servers/decisions/template.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/template.js +15 -0
- package/dist/agent-farm/servers/decisions/template.js.map +1 -0
- package/dist/agent-farm/servers/ide-server.d.ts +28 -8
- package/dist/agent-farm/servers/ide-server.d.ts.map +1 -1
- package/dist/agent-farm/servers/ide-server.js +147 -50
- package/dist/agent-farm/servers/ide-server.js.map +1 -1
- package/dist/agent-farm/servers/overview.d.ts +31 -4
- package/dist/agent-farm/servers/overview.d.ts.map +1 -1
- package/dist/agent-farm/servers/overview.js +235 -55
- package/dist/agent-farm/servers/overview.js.map +1 -1
- package/dist/agent-farm/servers/tower-instances.d.ts +14 -1
- package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-instances.js +51 -9
- package/dist/agent-farm/servers/tower-instances.js.map +1 -1
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-routes.js +113 -14
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +35 -1
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts +25 -0
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.js +128 -4
- package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
- package/dist/agent-farm/servers/tower-utils.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-utils.js +18 -5
- package/dist/agent-farm/servers/tower-utils.js.map +1 -1
- package/dist/agent-farm/utils/builder-worktree-identity.d.ts +39 -0
- package/dist/agent-farm/utils/builder-worktree-identity.d.ts.map +1 -0
- package/dist/agent-farm/utils/builder-worktree-identity.js +42 -0
- package/dist/agent-farm/utils/builder-worktree-identity.js.map +1 -0
- package/dist/agent-farm/utils/harness.d.ts +71 -0
- package/dist/agent-farm/utils/harness.d.ts.map +1 -1
- package/dist/agent-farm/utils/harness.js +153 -0
- package/dist/agent-farm/utils/harness.js.map +1 -1
- package/dist/agent-farm/utils/lifecycle-reporter.d.ts +79 -0
- package/dist/agent-farm/utils/lifecycle-reporter.d.ts.map +1 -0
- package/dist/agent-farm/utils/lifecycle-reporter.js +347 -0
- package/dist/agent-farm/utils/lifecycle-reporter.js.map +1 -0
- 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 +16 -0
- package/dist/agent-farm/utils/message-format.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +17 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt.d.ts +16 -2
- package/dist/commands/adopt.d.ts.map +1 -1
- package/dist/commands/adopt.js +67 -23
- package/dist/commands/adopt.js.map +1 -1
- package/dist/commands/bootstrap-docs.d.ts +132 -0
- package/dist/commands/bootstrap-docs.d.ts.map +1 -0
- package/dist/commands/bootstrap-docs.js +725 -0
- package/dist/commands/bootstrap-docs.js.map +1 -0
- package/dist/commands/consult/index.d.ts +20 -1
- package/dist/commands/consult/index.d.ts.map +1 -1
- package/dist/commands/consult/index.js +70 -3
- package/dist/commands/consult/index.js.map +1 -1
- package/dist/commands/consult/tree-tripwire.d.ts +2 -75
- package/dist/commands/consult/tree-tripwire.d.ts.map +1 -1
- package/dist/commands/consult/tree-tripwire.js +7 -184
- package/dist/commands/consult/tree-tripwire.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +36 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/porch/checks.d.ts +7 -1
- package/dist/commands/porch/checks.d.ts.map +1 -1
- package/dist/commands/porch/checks.js +77 -14
- package/dist/commands/porch/checks.js.map +1 -1
- package/dist/commands/porch/index.d.ts +38 -1
- package/dist/commands/porch/index.d.ts.map +1 -1
- package/dist/commands/porch/index.js +79 -43
- package/dist/commands/porch/index.js.map +1 -1
- package/dist/commands/porch/protocol.d.ts +4 -3
- package/dist/commands/porch/protocol.d.ts.map +1 -1
- package/dist/commands/porch/protocol.js +32 -5
- package/dist/commands/porch/protocol.js.map +1 -1
- package/dist/commands/porch/state.d.ts +0 -4
- package/dist/commands/porch/state.d.ts.map +1 -1
- package/dist/commands/porch/state.js +23 -10
- package/dist/commands/porch/state.js.map +1 -1
- package/dist/commands/porch/types.d.ts +2 -0
- package/dist/commands/porch/types.d.ts.map +1 -1
- package/dist/commands/update.d.ts +5 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +73 -18
- package/dist/commands/update.js.map +1 -1
- package/dist/lib/agent-env.d.ts +31 -1
- package/dist/lib/agent-env.d.ts.map +1 -1
- package/dist/lib/agent-env.js +38 -1
- package/dist/lib/agent-env.js.map +1 -1
- package/dist/lib/agent-process.d.ts +23 -0
- package/dist/lib/agent-process.d.ts.map +1 -0
- package/dist/lib/agent-process.js +24 -0
- package/dist/lib/agent-process.js.map +1 -0
- package/dist/lib/config.d.ts +8 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/forge-contracts.d.ts +9 -3
- package/dist/lib/forge-contracts.d.ts.map +1 -1
- package/dist/lib/forge-contracts.js.map +1 -1
- package/dist/lib/forge.d.ts +8 -5
- package/dist/lib/forge.d.ts.map +1 -1
- package/dist/lib/forge.js +57 -1
- package/dist/lib/forge.js.map +1 -1
- package/dist/lib/github.d.ts.map +1 -1
- package/dist/lib/github.js +38 -0
- package/dist/lib/github.js.map +1 -1
- package/dist/lib/governance-bootstrap.d.ts +155 -0
- package/dist/lib/governance-bootstrap.d.ts.map +1 -0
- package/dist/lib/governance-bootstrap.js +469 -0
- package/dist/lib/governance-bootstrap.js.map +1 -0
- package/dist/lib/issue-id.d.ts +34 -0
- package/dist/lib/issue-id.d.ts.map +1 -0
- package/dist/lib/issue-id.js +61 -0
- package/dist/lib/issue-id.js.map +1 -0
- package/dist/lib/scaffold.d.ts +4 -0
- package/dist/lib/scaffold.d.ts.map +1 -1
- package/dist/lib/scaffold.js +29 -5
- package/dist/lib/scaffold.js.map +1 -1
- package/dist/lib/shipped-skill-hashes.d.ts +10 -0
- package/dist/lib/shipped-skill-hashes.d.ts.map +1 -0
- package/dist/lib/shipped-skill-hashes.js +197 -0
- package/dist/lib/shipped-skill-hashes.js.map +1 -0
- package/dist/lib/skill-refresh.d.ts +90 -0
- package/dist/lib/skill-refresh.d.ts.map +1 -0
- package/dist/lib/skill-refresh.js +267 -0
- package/dist/lib/skill-refresh.js.map +1 -0
- package/dist/lib/tree-snapshot.d.ts +172 -0
- package/dist/lib/tree-snapshot.d.ts.map +1 -0
- package/dist/lib/tree-snapshot.js +393 -0
- package/dist/lib/tree-snapshot.js.map +1 -0
- package/dist/terminal/pty-session.d.ts +5 -0
- package/dist/terminal/pty-session.d.ts.map +1 -1
- package/dist/terminal/pty-session.js +7 -0
- package/dist/terminal/pty-session.js.map +1 -1
- package/ide-extension/codev-vscode.vsix +0 -0
- package/ide-extension/manifest.json +7 -0
- package/package.json +8 -6
- package/scripts/forge/jira/_lib.sh +113 -0
- package/scripts/forge/jira/auth-status.sh +29 -0
- package/scripts/forge/jira/issue-comment.sh +23 -0
- package/scripts/forge/jira/issue-list.sh +32 -0
- package/scripts/forge/jira/issue-search.sh +40 -0
- package/scripts/forge/jira/issue-view.sh +41 -0
- package/scripts/forge/jira/recently-closed.sh +81 -0
- package/scripts/forge/jira/user-identity.sh +18 -0
- package/skeleton/.claude/skills/afx/SKILL.md +51 -0
- package/skeleton/.claude/skills/arch-init/SKILL.md +56 -9
- package/skeleton/.claude/skills/arch-save/SKILL.md +100 -9
- package/skeleton/.claude/skills/codev/SKILL.md +18 -2
- package/skeleton/.claude/skills/consult/SKILL.md +9 -0
- package/skeleton/.claude/skills/porch/SKILL.md +18 -0
- package/skeleton/.claude/skills/update-arch-docs/SKILL.md +28 -2
- package/skeleton/.codex/skills/afx/SKILL.md +51 -0
- package/skeleton/.codex/skills/arch-init/SKILL.md +56 -9
- package/skeleton/.codex/skills/arch-save/SKILL.md +100 -9
- package/skeleton/.codex/skills/codev/SKILL.md +18 -2
- package/skeleton/.codex/skills/consult/SKILL.md +9 -0
- package/skeleton/.codex/skills/porch/SKILL.md +18 -0
- package/skeleton/.codex/skills/update-arch-docs/SKILL.md +28 -2
- package/skeleton/protocol-schema.json +6 -0
- package/skeleton/protocols/maintain/protocol.md +5 -0
- package/skeleton/protocols/pir/prompts/review.md +0 -1
- package/skeleton/protocols/protocol-schema.json +6 -0
- package/skeleton/resources/commands/agent-farm.md +156 -0
- package/skeleton/resources/commands/codev.md +47 -0
- package/skeleton/resources/commands/consult.md +9 -2
- package/skeleton/resources/commands/overview.md +1 -0
- package/skeleton/resources/decision-protocol.md +215 -0
- package/skeleton/resources/workflow-reference.md +12 -0
- package/skeleton/roles/architect.md +6 -0
- package/skeleton/templates/bootstrap-docs-prompt.md +16 -0
- package/skeleton/templates/bootstrap-docs-review-prompt.md +19 -0
- package/skeleton/templates/cheatsheet.md +2 -1
- package/dashboard-dist/assets/index-DZf6pNPE.js +0 -199
- package/dashboard-dist/assets/index-DZf6pNPE.js.map +0 -1
- package/dashboard-dist/assets/index-DnYLy5C_.css +0 -32
|
@@ -21,24 +21,27 @@ import { decodeWorkspacePath } from '../lib/tower-client.js';
|
|
|
21
21
|
import { readCloudConfig } from '../lib/cloud-config.js';
|
|
22
22
|
import { fileURLToPath } from 'node:url';
|
|
23
23
|
import { version } from '../../version.js';
|
|
24
|
-
import { sanitizeAgentEnv } from '../../lib/agent-env.js';
|
|
24
|
+
import { sanitizeAgentEnv, withTowerPort } from '../../lib/agent-env.js';
|
|
25
25
|
const execAsync = promisify(exec);
|
|
26
|
-
import { getBuilders, setArchitectByName } from '../state.js';
|
|
26
|
+
import { getArchitectByName, getBuilders, setArchitectByName } from '../state.js';
|
|
27
|
+
import { DEFAULT_ARCHITECT_NAME } from '../utils/architect-name.js';
|
|
27
28
|
import { DEFAULT_COLS, defaultSessionOptions } from '../../terminal/index.js';
|
|
28
29
|
import { parseJsonBody, isRequestAllowed, isAllowedOrigin, isAllowedHost, getExpectedKey, escapeHtml } from '../utils/server-utils.js';
|
|
29
|
-
import { TOWER_KEY_HEADER, LEGACY_WEB_KEY_HEADER, VSCODE_USER_SENDER } from '@cluesmith/codev-types';
|
|
30
|
+
import { TOWER_KEY_HEADER, LEGACY_WEB_KEY_HEADER, VSCODE_USER_SENDER, DECISIONS_TAB_SENDER } from '@cluesmith/codev-types';
|
|
30
31
|
import { isRateLimited, normalizeWorkspacePath, getLanguageForExt, getMimeTypeForFile, serveStaticFile, persistableCommand, logSessionIdentity, } from './tower-utils.js';
|
|
31
32
|
import { handleTunnelEndpoint } from './tower-tunnel.js';
|
|
32
33
|
import { handleIdeApi } from './ide-server.js';
|
|
33
34
|
import { matchIdePrefix, forwardIdeHttp } from './ide-forward.js';
|
|
34
35
|
import { getWorktreeConfig, getActivityHooks } from '../utils/config.js';
|
|
35
36
|
import { ensureCodevConfigWatcher } from './codev-config-watcher.js';
|
|
37
|
+
import { handleDecisionsGet, handleDecisionsRule } from './decisions/routes.js';
|
|
38
|
+
import { decisionsFilePresent } from './decisions/file.js';
|
|
36
39
|
import { hasTeam, loadTeamMembers, loadMessages } from '../../lib/team.js';
|
|
37
40
|
import { fetchTeamGitHubData } from '../../lib/team-github.js';
|
|
38
41
|
import { resolveTarget, resolveAgentInRegistry, broadcastMessage, isResolveError } from './tower-messages.js';
|
|
39
42
|
import { handleCommandRoute, COMMAND_ROUTE } from './command-relay.js';
|
|
40
43
|
import { handleCanvasRoute, CANVAS_ROUTE_PREFIX } from './canvas-relay.js';
|
|
41
|
-
import { formatArchitectMessage, formatArchitectToBuilderMessage, formatBuilderMessage, formatUserViaVsCodeMessage, isSafeSenderId, messageTooLargeError, MAX_MESSAGE_BYTES, } from '../utils/message-format.js';
|
|
44
|
+
import { formatArchitectMessage, formatArchitectToBuilderMessage, formatBuilderMessage, formatUserViaVsCodeMessage, formatUserViaDecisionsTabMessage, isSafeSenderId, messageLimitError, messageTooLargeError, MAX_MESSAGE_BYTES, } from '../utils/message-format.js';
|
|
42
45
|
import { writeMessageToSession, writeEscapeToSession, writeStrategyForApp } from './message-write.js';
|
|
43
46
|
import { makeDeliveryPorts, getMailboxDrainer, resolveProfileForSession } from './mailbox-wiring.js';
|
|
44
47
|
import { deliverAgentMailSerialized } from './mailbox-delivery.js';
|
|
@@ -56,8 +59,12 @@ import { submitToSession, OPERATOR_SUBMIT_WAIT_CEILING_MS } from './session-subm
|
|
|
56
59
|
// triggers a gated drain (see handleSend), so a delayed message delivers onto a
|
|
57
60
|
// render-verified empty prompt like any normal send — never force-injected.
|
|
58
61
|
import { scheduleDelayedSend, validateDelaySeconds } from './delayed-send.js';
|
|
59
|
-
import { getKnownWorkspacePaths, getInstances, getDirectorySuggestions, launchInstance, killTerminalWithShellper, instancesReady, stopInstance, addArchitect, removeArchitect, } from './tower-instances.js';
|
|
62
|
+
import { getKnownWorkspacePaths, getAllKnownWorkspacePaths, getInstances, getDirectorySuggestions, launchInstance, killTerminalWithShellper, instancesReady, stopInstance, addArchitect, removeArchitect, } from './tower-instances.js';
|
|
60
63
|
import { OverviewCache } from './overview.js';
|
|
64
|
+
import { handleAgentLifecycle } from './agent-state/route.js';
|
|
65
|
+
import { agentStateStore } from './agent-state/store.js';
|
|
66
|
+
import { resolveAgentIdentity } from './agent-state/identity.js';
|
|
67
|
+
import { serveAgentState } from './agent-state/serve.js';
|
|
61
68
|
import { fetchIssue, fetchPR, searchIssues, fetchPRList, fetchCurrentUser, probeGhGraphqlRateLimit, parseLinkedIssue, parseArea, } from '../../lib/github.js';
|
|
62
69
|
import { computeAnalytics } from './analytics.js';
|
|
63
70
|
import { getAllTasks, executeTask, getTaskId } from './tower-cron.js';
|
|
@@ -90,6 +97,11 @@ const ROUTES = {
|
|
|
90
97
|
'POST /api/overview/refresh': (_req, res, _url, ctx) => handleOverviewRefresh(res, ctx),
|
|
91
98
|
'GET /api/events': (req, res, _url, ctx) => handleSSEEvents(req, res, ctx),
|
|
92
99
|
'POST /api/notify': (req, res, _url, ctx) => handleNotify(req, res, ctx),
|
|
100
|
+
// Spec 1595: write-only lifecycle ingestion; key-authenticated like every non-public route.
|
|
101
|
+
'POST /api/agent-lifecycle': (req, res) => handleAgentLifecycle(req, res, {
|
|
102
|
+
store: agentStateStore,
|
|
103
|
+
resolve: identity => resolveAgentIdentity(identity),
|
|
104
|
+
}),
|
|
93
105
|
'GET /api/browse': (_req, res, url) => handleBrowse(res, url),
|
|
94
106
|
'POST /api/create': (req, res, _url, ctx) => handleCreateWorkspace(req, res, ctx),
|
|
95
107
|
'POST /api/launch': (req, res) => handleLaunchInstance(req, res),
|
|
@@ -240,6 +252,10 @@ export async function handleRequest(req, res, ctx) {
|
|
|
240
252
|
}
|
|
241
253
|
catch (err) {
|
|
242
254
|
ctx.log('ERROR', `Request error: ${err.message}`);
|
|
255
|
+
// A handler may fail after it has answered (the Decisions route keeps working past its
|
|
256
|
+
// `res.end()`); a second writeHead would throw ERR_HTTP_HEADERS_SENT out of here.
|
|
257
|
+
if (res.headersSent)
|
|
258
|
+
return;
|
|
243
259
|
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
244
260
|
res.end(JSON.stringify({ error: err.message }));
|
|
245
261
|
}
|
|
@@ -576,7 +592,9 @@ async function handleWorkspaceAction(req, res, ctx, match) {
|
|
|
576
592
|
}
|
|
577
593
|
// POST /api/workspaces/:path/deactivate
|
|
578
594
|
if (req.method === 'POST' && action === 'deactivate') {
|
|
579
|
-
|
|
595
|
+
// Unfiltered on purpose (#1809): a stray architect left running in a builder
|
|
596
|
+
// worktree is excluded from the listing but must still be stoppable.
|
|
597
|
+
const knownPaths = getAllKnownWorkspacePaths();
|
|
580
598
|
const resolvedPath = fs.existsSync(workspacePath) ? fs.realpathSync(workspacePath) : workspacePath;
|
|
581
599
|
const isKnown = knownPaths.some((p) => p === workspacePath || p === resolvedPath);
|
|
582
600
|
if (!isKnown) {
|
|
@@ -629,8 +647,9 @@ async function handleTerminalCreate(req, res, ctx) {
|
|
|
629
647
|
// Strip Claude Code session markers so spawned Claude processes don't
|
|
630
648
|
// detect nesting and disable transcript saving (#1219). `env` is normally
|
|
631
649
|
// absent — `createPtySession` sends no env — so this is the path by which
|
|
632
|
-
// Tower's own environment becomes every builder's environment.
|
|
633
|
-
|
|
650
|
+
// Tower's own environment becomes every builder's environment. Spec 1595:
|
|
651
|
+
// Tower's port is set last, so an inherited value never survives.
|
|
652
|
+
const sessionEnv = withTowerPort(sanitizeAgentEnv(env || process.env), ctx.port);
|
|
634
653
|
const client = await shellperManager.createSession({
|
|
635
654
|
sessionId,
|
|
636
655
|
command,
|
|
@@ -685,7 +704,10 @@ async function handleTerminalCreate(req, res, ctx) {
|
|
|
685
704
|
// Fallback: non-persistent session (graceful degradation per plan)
|
|
686
705
|
// Shellper is the only persistence backend for new sessions.
|
|
687
706
|
if (!info) {
|
|
688
|
-
|
|
707
|
+
// Spec 1595: the manager merges this over its own base env, so Tower's port
|
|
708
|
+
// reaches the session whether or not the client supplied an env.
|
|
709
|
+
const sessionEnv = withTowerPort(sanitizeAgentEnv(env ?? {}), ctx.port);
|
|
710
|
+
info = await manager.createSession({ command, args, cols, rows, cwd, env: sessionEnv, label });
|
|
689
711
|
persistent = false;
|
|
690
712
|
if (workspacePath && termType && roleId) {
|
|
691
713
|
const entry = getWorkspaceTerminalsEntry(normalizeWorkspacePath(workspacePath));
|
|
@@ -916,19 +938,29 @@ async function handleStatus(res) {
|
|
|
916
938
|
* dashboard-state handler (`/api/state`) and the overview handler
|
|
917
939
|
* (`/api/overview`), so the two payloads list an identical set and can't drift.
|
|
918
940
|
* Extracted verbatim from the dashboard-state builder's former inline loop.
|
|
941
|
+
*
|
|
942
|
+
* Spec 1595: each architect also carries its served `agentState` (read by
|
|
943
|
+
* `(workspace, name)` from the agent-state store and liveness, projected per
|
|
944
|
+
* request) and its session's `lastDataAt`, for the sdk's staleness rule.
|
|
919
945
|
*/
|
|
920
|
-
function liveArchitects(entry, manager) {
|
|
946
|
+
function liveArchitects(entry, manager, workspacePath) {
|
|
947
|
+
const agentWorkspace = normalizeWorkspacePath(workspacePath);
|
|
921
948
|
const architects = [];
|
|
922
949
|
for (const [architectName, terminalId] of entry.architects) {
|
|
923
950
|
const session = manager.getSession(terminalId);
|
|
924
951
|
if (!session)
|
|
925
952
|
continue;
|
|
953
|
+
let lastDataAt = null;
|
|
954
|
+
if (Number.isFinite(session.lastDataAt))
|
|
955
|
+
lastDataAt = new Date(session.lastDataAt).toISOString();
|
|
926
956
|
architects.push({
|
|
927
957
|
name: architectName,
|
|
928
958
|
port: 0,
|
|
929
959
|
pid: session.pid || 0,
|
|
930
960
|
terminalId,
|
|
931
961
|
persistent: isSessionPersistent(terminalId, session),
|
|
962
|
+
agentState: serveAgentState(agentWorkspace, architectName, { blocked: false, blockedSince: null, phase: '' }),
|
|
963
|
+
lastDataAt,
|
|
932
964
|
});
|
|
933
965
|
}
|
|
934
966
|
const mainIdx = architects.findIndex(a => a.name === 'main');
|
|
@@ -987,11 +1019,27 @@ async function handleOverview(res, url, workspaceOverride, ctx) {
|
|
|
987
1019
|
}
|
|
988
1020
|
builder.lastDataAt = new Date(ptySession.lastDataAt).toISOString();
|
|
989
1021
|
}
|
|
1022
|
+
// Spec 1595: project the served agent state over EVERY listed builder, not
|
|
1023
|
+
// inside the loop above, which skips a builder whose session is gone (the
|
|
1024
|
+
// case liveness reports as dead). Every listed builder is registered: the
|
|
1025
|
+
// list is filtered to `entry.builders`, and its `roleId` is the lowercased
|
|
1026
|
+
// registry key, the same key the store and liveness use. `blocked` reuses the
|
|
1027
|
+
// gate the overview already detected (no second parse of status.yaml).
|
|
1028
|
+
const agentWorkspace = normalizeWorkspacePath(workspaceRoot);
|
|
1029
|
+
for (const builder of data.builders) {
|
|
1030
|
+
if (builder.roleId === null)
|
|
1031
|
+
continue;
|
|
1032
|
+
builder.agentState = serveAgentState(agentWorkspace, builder.roleId, {
|
|
1033
|
+
blocked: builder.blocked !== null,
|
|
1034
|
+
blockedSince: builder.blockedSince,
|
|
1035
|
+
phase: builder.phase,
|
|
1036
|
+
});
|
|
1037
|
+
}
|
|
990
1038
|
// Issue 1104: enrich with the live architects (main-first) so the VSCode
|
|
991
1039
|
// Agents tree can render its architect tier and attribution badge straight
|
|
992
1040
|
// off the overview cache. Same `liveArchitects` helper (and so the same set)
|
|
993
1041
|
// the dashboard-state handler uses.
|
|
994
|
-
data.architects = liveArchitects(entry, terminalManager);
|
|
1042
|
+
data.architects = liveArchitects(entry, terminalManager, workspaceRoot);
|
|
995
1043
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
996
1044
|
res.end(JSON.stringify(data));
|
|
997
1045
|
}
|
|
@@ -1332,6 +1380,9 @@ function formatMessageForTarget(isArchitectTarget, from, toAgent, message, raw)
|
|
|
1332
1380
|
// header, so the architect can tell it from a peer-architect instruction.
|
|
1333
1381
|
if (isArchitectTarget && from === VSCODE_USER_SENDER)
|
|
1334
1382
|
return formatUserViaVsCodeMessage(toAgent, message, undefined, raw);
|
|
1383
|
+
// #1828: likewise the owner's ruling relayed by the Decisions tab — never a builder frame.
|
|
1384
|
+
if (isArchitectTarget && from === DECISIONS_TAB_SENDER)
|
|
1385
|
+
return formatUserViaDecisionsTabMessage(toAgent, message, raw);
|
|
1335
1386
|
if (isArchitectTarget && from)
|
|
1336
1387
|
return formatBuilderMessage(from, toAgent, message, undefined, raw); // builder → architect
|
|
1337
1388
|
// any → builder: thread the sender so an `architect:<name>` origin is named in the
|
|
@@ -1397,6 +1448,45 @@ export async function deliverCronMessage(task, message, log) {
|
|
|
1397
1448
|
log('WARN', `Cron '${task.name}': target '${task.target}' not found — message not delivered`);
|
|
1398
1449
|
return { outcome: 'unresolved', reason: null, detail: null, mailboxId: null };
|
|
1399
1450
|
}
|
|
1451
|
+
/**
|
|
1452
|
+
* Tell a workspace's hub architect about a ruling the owner just wrote from the
|
|
1453
|
+
* Decisions tab (#1828). The hub is the architect registered as `main` and no other:
|
|
1454
|
+
* the registry's "first registered" order is by name (#1633), so a workspace without
|
|
1455
|
+
* `main` gets no notice rather than a guess, and a `main` that is offline holds it
|
|
1456
|
+
* (`no-live-pty`). One mailbox row is persisted, then offered to the same gated delivery
|
|
1457
|
+
* `handleSend` uses; a busy line holds it for the backstop. Throws, persisting nothing,
|
|
1458
|
+
* when `main` is not registered or the notice is over the send limit.
|
|
1459
|
+
*/
|
|
1460
|
+
async function notifyHubOfRuling(workspacePath, message, log) {
|
|
1461
|
+
const tooLarge = messageLimitError(message);
|
|
1462
|
+
if (tooLarge)
|
|
1463
|
+
throw new Error(tooLarge);
|
|
1464
|
+
const toAgent = DEFAULT_ARCHITECT_NAME;
|
|
1465
|
+
if (!getArchitectByName(workspacePath, toAgent)) {
|
|
1466
|
+
throw new Error(`no architect named '${toAgent}' is registered in workspace ${workspacePath}`);
|
|
1467
|
+
}
|
|
1468
|
+
const db = getGlobalDb();
|
|
1469
|
+
const row = enqueueMailbox(db, {
|
|
1470
|
+
workspacePath,
|
|
1471
|
+
toAgent,
|
|
1472
|
+
body: message,
|
|
1473
|
+
formattedMessage: formatMessageForTarget(true, DECISIONS_TAB_SENDER, toAgent, message, false),
|
|
1474
|
+
fromAgent: DECISIONS_TAB_SENDER,
|
|
1475
|
+
fromWorkspace: workspacePath,
|
|
1476
|
+
});
|
|
1477
|
+
const ports = makeDeliveryPorts(log);
|
|
1478
|
+
ports.onHeldStateChange();
|
|
1479
|
+
try {
|
|
1480
|
+
const outcome = await deliverAgentMailSerialized(ports, db, workspacePath, toAgent);
|
|
1481
|
+
getMailboxDrainer().noteOutcome(workspacePath, toAgent, outcome);
|
|
1482
|
+
}
|
|
1483
|
+
catch (err) {
|
|
1484
|
+
log('ERROR', `Decisions notice delivery errored for ${toAgent} (row ${row.id.slice(0, 8)}... stays held): ${err.message}`);
|
|
1485
|
+
}
|
|
1486
|
+
const stored = getMailboxById(db, row.id);
|
|
1487
|
+
const fate = stored?.status === 'delivered' ? 'delivered' : `held (${stored?.reason ?? 'unknown'})`;
|
|
1488
|
+
log('INFO', `Decisions notice ${fate} → ${toAgent} @ ${path.basename(workspacePath)} (mailbox ${row.id.slice(0, 8)}...)`);
|
|
1489
|
+
}
|
|
1400
1490
|
/**
|
|
1401
1491
|
* Persist a `held` mailbox row and write the Spec 1313 `held` send response. Used
|
|
1402
1492
|
* for both dead-session cases (no live PTY, held `no-live-pty`). The row exists
|
|
@@ -2397,7 +2487,7 @@ async function handleWorkspaceRoutes(req, res, ctx, url) {
|
|
|
2397
2487
|
const apiPath = subPath.replace(/^api\/?/, '');
|
|
2398
2488
|
// GET /api/state - Return workspace state (architect, builders, shells)
|
|
2399
2489
|
if (req.method === 'GET' && (apiPath === 'state' || apiPath === '')) {
|
|
2400
|
-
return handleWorkspaceState(res, workspacePath);
|
|
2490
|
+
return handleWorkspaceState(res, ctx, workspacePath);
|
|
2401
2491
|
}
|
|
2402
2492
|
// POST /api/tabs/shell - Create a new shell terminal
|
|
2403
2493
|
if (req.method === 'POST' && apiPath === 'tabs/shell') {
|
|
@@ -2477,6 +2567,14 @@ async function handleWorkspaceRoutes(req, res, ctx, url) {
|
|
|
2477
2567
|
if (req.method === 'GET' && apiPath === 'team') {
|
|
2478
2568
|
return handleWorkspaceTeam(res, workspacePath);
|
|
2479
2569
|
}
|
|
2570
|
+
// GET /api/decisions, POST /api/decisions/rule — the Decisions tab (Spec 1819).
|
|
2571
|
+
// The file is the configured one; neither route takes a path from the request.
|
|
2572
|
+
if (req.method === 'GET' && apiPath === 'decisions') {
|
|
2573
|
+
return handleDecisionsGet(res, workspacePath);
|
|
2574
|
+
}
|
|
2575
|
+
if (req.method === 'POST' && apiPath === 'decisions/rule') {
|
|
2576
|
+
return handleDecisionsRule(req, res, workspacePath, ctx.log, message => notifyHubOfRuling(workspacePath, message, ctx.log));
|
|
2577
|
+
}
|
|
2480
2578
|
// GET /api/annotate/:tabId/* — Serve rich annotator template and sub-APIs
|
|
2481
2579
|
const annotateMatch = apiPath.match(/^annotate\/([^/]+)(\/(.*))?$/);
|
|
2482
2580
|
if (annotateMatch) {
|
|
@@ -2587,7 +2685,7 @@ async function handleWorkspaceRoutes(req, res, ctx, url) {
|
|
|
2587
2685
|
// ============================================================================
|
|
2588
2686
|
// Workspace API sub-handlers
|
|
2589
2687
|
// ============================================================================
|
|
2590
|
-
async function handleWorkspaceState(res, workspacePath) {
|
|
2688
|
+
async function handleWorkspaceState(res, ctx, workspacePath) {
|
|
2591
2689
|
// Rehydrate wsTerminals (SQLite sync + shellper reconnect) before reading.
|
|
2592
2690
|
// Shared with /api/overview so both endpoints always see a freshly-reconciled
|
|
2593
2691
|
// entry — see getRehydratedTerminalsEntry doc.
|
|
@@ -2610,13 +2708,14 @@ async function handleWorkspaceState(res, workspacePath) {
|
|
|
2610
2708
|
return undefined;
|
|
2611
2709
|
} })(),
|
|
2612
2710
|
teamEnabled: await hasTeam(path.join(workspacePath, 'codev', 'team')),
|
|
2711
|
+
decisionsEnabled: await decisionsFilePresent(workspacePath, ctx.log),
|
|
2613
2712
|
};
|
|
2614
2713
|
// Spec 761: build the architects collection from entry.architects (skip dead
|
|
2615
2714
|
// sessions, main-first). Shared with /api/overview via `liveArchitects`
|
|
2616
2715
|
// (Issue 1104) so both payloads list an identical set.
|
|
2617
2716
|
// Spec 755: the scalar `state.architect` is preserved as a backward-compat
|
|
2618
2717
|
// pointer to the same default architect (architects[0] when present).
|
|
2619
|
-
const architects = liveArchitects(entry, manager);
|
|
2718
|
+
const architects = liveArchitects(entry, manager, workspacePath);
|
|
2620
2719
|
state.architects = architects;
|
|
2621
2720
|
state.architect = architects[0] ?? null;
|
|
2622
2721
|
// Add shells from refreshed cache
|