@cluesmith/codev 3.3.3 → 3.3.5
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-BuflRUi6.js +220 -0
- package/dashboard-dist/assets/index-BuflRUi6.js.map +1 -0
- package/dashboard-dist/assets/index-r3bZzLmX.css +32 -0
- package/dashboard-dist/index.html +2 -2
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +48 -0
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/ide.d.ts +20 -0
- package/dist/agent-farm/commands/ide.d.ts.map +1 -0
- package/dist/agent-farm/commands/ide.js +138 -0
- package/dist/agent-farm/commands/ide.js.map +1 -0
- package/dist/agent-farm/commands/inbox.d.ts.map +1 -1
- package/dist/agent-farm/commands/inbox.js +15 -3
- package/dist/agent-farm/commands/inbox.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 +40 -6
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js +28 -9
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
- package/dist/agent-farm/commands/tower.d.ts +21 -9
- package/dist/agent-farm/commands/tower.d.ts.map +1 -1
- package/dist/agent-farm/commands/tower.js +90 -30
- package/dist/agent-farm/commands/tower.js.map +1 -1
- package/dist/agent-farm/db/tower-owner.d.ts +168 -0
- package/dist/agent-farm/db/tower-owner.d.ts.map +1 -0
- package/dist/agent-farm/db/tower-owner.js +369 -0
- package/dist/agent-farm/db/tower-owner.js.map +1 -0
- package/dist/agent-farm/db/types.d.ts +30 -5
- 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/ide-record.d.ts +65 -0
- package/dist/agent-farm/lib/ide-record.d.ts.map +1 -0
- package/dist/agent-farm/lib/ide-record.js +118 -0
- package/dist/agent-farm/lib/ide-record.js.map +1 -0
- package/dist/agent-farm/lib/tunnel-client.d.ts +22 -0
- package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.js +53 -5
- package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
- 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 +308 -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 +4 -0
- package/dist/agent-farm/servers/decisions/stamp.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/stamp.js +171 -0
- package/dist/agent-farm/servers/decisions/stamp.js.map +1 -0
- package/dist/agent-farm/servers/gate-profiles.d.ts +23 -2
- package/dist/agent-farm/servers/gate-profiles.d.ts.map +1 -1
- package/dist/agent-farm/servers/gate-profiles.js +43 -2
- package/dist/agent-farm/servers/gate-profiles.js.map +1 -1
- package/dist/agent-farm/servers/ide-forward.d.ts +62 -0
- package/dist/agent-farm/servers/ide-forward.d.ts.map +1 -0
- package/dist/agent-farm/servers/ide-forward.js +274 -0
- package/dist/agent-farm/servers/ide-forward.js.map +1 -0
- package/dist/agent-farm/servers/ide-server.d.ts +68 -0
- package/dist/agent-farm/servers/ide-server.d.ts.map +1 -0
- package/dist/agent-farm/servers/ide-server.js +281 -0
- package/dist/agent-farm/servers/ide-server.js.map +1 -0
- package/dist/agent-farm/servers/mailbox-delivery.d.ts +213 -4
- package/dist/agent-farm/servers/mailbox-delivery.d.ts.map +1 -1
- package/dist/agent-farm/servers/mailbox-delivery.js +489 -68
- package/dist/agent-farm/servers/mailbox-delivery.js.map +1 -1
- package/dist/agent-farm/servers/mailbox-wiring.d.ts +18 -4
- package/dist/agent-farm/servers/mailbox-wiring.d.ts.map +1 -1
- package/dist/agent-farm/servers/mailbox-wiring.js +94 -21
- package/dist/agent-farm/servers/mailbox-wiring.js.map +1 -1
- package/dist/agent-farm/servers/message-write.d.ts +138 -11
- package/dist/agent-farm/servers/message-write.d.ts.map +1 -1
- package/dist/agent-farm/servers/message-write.js +144 -35
- package/dist/agent-farm/servers/message-write.js.map +1 -1
- package/dist/agent-farm/servers/overview.d.ts +32 -15
- package/dist/agent-farm/servers/overview.d.ts.map +1 -1
- package/dist/agent-farm/servers/overview.js +181 -103
- package/dist/agent-farm/servers/overview.js.map +1 -1
- package/dist/agent-farm/servers/render-gate.d.ts +53 -0
- package/dist/agent-farm/servers/render-gate.d.ts.map +1 -1
- package/dist/agent-farm/servers/render-gate.js +135 -24
- package/dist/agent-farm/servers/render-gate.js.map +1 -1
- package/dist/agent-farm/servers/session-submit.d.ts +7 -4
- package/dist/agent-farm/servers/session-submit.d.ts.map +1 -1
- package/dist/agent-farm/servers/session-submit.js +7 -4
- package/dist/agent-farm/servers/session-submit.js.map +1 -1
- package/dist/agent-farm/servers/tower-cron.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-cron.js +4 -1
- package/dist/agent-farm/servers/tower-cron.js.map +1 -1
- package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-instances.js +6 -7
- 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 +116 -18
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +64 -7
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.js +53 -8
- package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.js +18 -1
- package/dist/agent-farm/servers/tower-websocket.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 +21 -6
- package/dist/agent-farm/utils/message-format.js.map +1 -1
- package/dist/agent-farm/utils/port.d.ts +22 -0
- package/dist/agent-farm/utils/port.d.ts.map +1 -0
- package/dist/agent-farm/utils/port.js +35 -0
- package/dist/agent-farm/utils/port.js.map +1 -0
- package/dist/agent-farm/utils/server-utils.d.ts +26 -0
- package/dist/agent-farm/utils/server-utils.d.ts.map +1 -1
- package/dist/agent-farm/utils/server-utils.js +36 -0
- package/dist/agent-farm/utils/server-utils.js.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- 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 +117 -3
- package/dist/commands/consult/index.js.map +1 -1
- package/dist/commands/consult/tree-tripwire.d.ts +177 -0
- package/dist/commands/consult/tree-tripwire.d.ts.map +1 -0
- package/dist/commands/consult/tree-tripwire.js +356 -0
- package/dist/commands/consult/tree-tripwire.js.map +1 -0
- package/dist/commands/doctor.d.ts +69 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +163 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/generate-image.d.ts +5 -0
- package/dist/commands/generate-image.d.ts.map +1 -1
- package/dist/commands/generate-image.js +225 -4
- package/dist/commands/generate-image.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/types.d.ts +2 -0
- package/dist/commands/porch/types.d.ts.map +1 -1
- package/dist/lib/agent-env.d.ts +95 -0
- package/dist/lib/agent-env.d.ts.map +1 -0
- package/dist/lib/agent-env.js +137 -0
- package/dist/lib/agent-env.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 +10 -0
- package/dist/lib/forge-contracts.d.ts.map +1 -1
- package/dist/lib/forge-contracts.js.map +1 -1
- package/dist/lib/forge-rate-limit.d.ts +45 -0
- package/dist/lib/forge-rate-limit.d.ts.map +1 -0
- package/dist/lib/forge-rate-limit.js +89 -0
- package/dist/lib/forge-rate-limit.js.map +1 -0
- package/dist/lib/forge.d.ts +28 -0
- package/dist/lib/forge.d.ts.map +1 -1
- package/dist/lib/forge.js +63 -10
- package/dist/lib/forge.js.map +1 -1
- package/dist/lib/github.d.ts +13 -1
- package/dist/lib/github.d.ts.map +1 -1
- package/dist/lib/github.js +58 -15
- package/dist/lib/github.js.map +1 -1
- package/dist/lib/test-env.d.ts +17 -0
- package/dist/lib/test-env.d.ts.map +1 -1
- package/dist/lib/test-env.js +20 -0
- package/dist/lib/test-env.js.map +1 -1
- package/dist/terminal/pty-session.d.ts +122 -4
- package/dist/terminal/pty-session.d.ts.map +1 -1
- package/dist/terminal/pty-session.js +142 -7
- package/dist/terminal/pty-session.js.map +1 -1
- package/dist/terminal/session-manager.d.ts +23 -2
- package/dist/terminal/session-manager.d.ts.map +1 -1
- package/dist/terminal/session-manager.js +115 -36
- package/dist/terminal/session-manager.js.map +1 -1
- package/dist/terminal/session-screen.d.ts +34 -5
- package/dist/terminal/session-screen.d.ts.map +1 -1
- package/dist/terminal/session-screen.js +52 -6
- package/dist/terminal/session-screen.js.map +1 -1
- package/dist/terminal/terminal-replies.d.ts +102 -0
- package/dist/terminal/terminal-replies.d.ts.map +1 -0
- package/dist/terminal/terminal-replies.js +181 -0
- package/dist/terminal/terminal-replies.js.map +1 -0
- package/package.json +4 -4
- package/scripts/forge/github/pr-list.sh +6 -2
- package/scripts/forge/github/pr-search.sh +4 -2
- package/scripts/forge/gitlab/issue-search.sh +1 -0
- package/scripts/forge/gitlab/pr-search.sh +35 -2
- package/scripts/forge/linear/auth-status.sh +1 -0
- package/scripts/forge/linear/issue-comment.sh +1 -0
- package/scripts/forge/linear/issue-list.sh +1 -0
- package/scripts/forge/linear/issue-search.sh +1 -0
- package/scripts/forge/linear/issue-view.sh +1 -0
- package/scripts/forge/linear/recently-closed.sh +1 -0
- package/scripts/forge/linear/user-identity.sh +1 -0
- package/skeleton/.claude/skills/afx/SKILL.md +15 -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/consult/SKILL.md +9 -0
- package/skeleton/.claude/skills/generate-image/SKILL.md +19 -2
- package/skeleton/.claude/skills/porch/SKILL.md +18 -0
- package/skeleton/.codex/skills/afx/SKILL.md +15 -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/consult/SKILL.md +9 -0
- package/skeleton/.codex/skills/generate-image/SKILL.md +19 -2
- package/skeleton/.codex/skills/porch/SKILL.md +18 -0
- 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 +71 -2
- package/skeleton/resources/commands/consult.md +9 -2
- package/skeleton/roles/consultant.md +32 -0
- package/skeleton/templates/AGENTS.md +1 -1
- package/skeleton/templates/CLAUDE.md +1 -1
- package/skeleton/templates/cheatsheet.md +1 -1
- package/dashboard-dist/assets/index-CUIjS_Vb.js +0 -199
- package/dashboard-dist/assets/index-CUIjS_Vb.js.map +0 -1
- package/dashboard-dist/assets/index-DnYLy5C_.css +0 -32
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tower-routes.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/servers/tower-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"tower-routes.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/servers/tower-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAc7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAMxE,OAAO,KAAK,EAAE,SAAS,EAAsB,MAAM,kBAAkB,CAAC;AAwCtE,OAAO,EAAgC,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAyD3F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAsChD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAC;IAChB,mGAAmG;IACnG,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,kBAAkB,EAAE,MAAM,cAAc,GAAG,IAAI,CAAC;IAChD,qBAAqB,EAAE,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACjH,YAAY,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC;IAC7C,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAkED,wBAAsB,aAAa,CACjC,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,GAAG,EAAE,YAAY,GAChB,OAAO,CAAC,IAAI,CAAC,CA+If;AAwsCD;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,eAAe,CAAC,EACzD,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,GAC3D,OAAO,CAAC,kBAAkB,CAAC,CA4C7B;AAguBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAKH,wBAAgB,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,GAAG,EAAE,GAAG,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAgCpG"}
|
|
@@ -21,23 +21,29 @@ 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
25
|
const execAsync = promisify(exec);
|
|
25
|
-
import { getBuilders, setArchitectByName } from '../state.js';
|
|
26
|
+
import { getArchitectByName, getBuilders, setArchitectByName } from '../state.js';
|
|
27
|
+
import { DEFAULT_ARCHITECT_NAME } from '../utils/architect-name.js';
|
|
26
28
|
import { DEFAULT_COLS, defaultSessionOptions } from '../../terminal/index.js';
|
|
27
29
|
import { parseJsonBody, isRequestAllowed, isAllowedOrigin, isAllowedHost, getExpectedKey, escapeHtml } from '../utils/server-utils.js';
|
|
28
|
-
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';
|
|
29
31
|
import { isRateLimited, normalizeWorkspacePath, getLanguageForExt, getMimeTypeForFile, serveStaticFile, persistableCommand, logSessionIdentity, } from './tower-utils.js';
|
|
30
32
|
import { handleTunnelEndpoint } from './tower-tunnel.js';
|
|
33
|
+
import { handleIdeApi } from './ide-server.js';
|
|
34
|
+
import { matchIdePrefix, forwardIdeHttp } from './ide-forward.js';
|
|
31
35
|
import { getWorktreeConfig, getActivityHooks } from '../utils/config.js';
|
|
32
36
|
import { ensureCodevConfigWatcher } from './codev-config-watcher.js';
|
|
37
|
+
import { handleDecisionsGet, handleDecisionsRule } from './decisions/routes.js';
|
|
38
|
+
import { decisionsFilePresent } from './decisions/file.js';
|
|
33
39
|
import { hasTeam, loadTeamMembers, loadMessages } from '../../lib/team.js';
|
|
34
40
|
import { fetchTeamGitHubData } from '../../lib/team-github.js';
|
|
35
41
|
import { resolveTarget, resolveAgentInRegistry, broadcastMessage, isResolveError } from './tower-messages.js';
|
|
36
42
|
import { handleCommandRoute, COMMAND_ROUTE } from './command-relay.js';
|
|
37
43
|
import { handleCanvasRoute, CANVAS_ROUTE_PREFIX } from './canvas-relay.js';
|
|
38
|
-
import { formatArchitectMessage, formatArchitectToBuilderMessage, formatBuilderMessage, formatUserViaVsCodeMessage, isSafeSenderId, messageTooLargeError, MAX_MESSAGE_BYTES, } from '../utils/message-format.js';
|
|
39
|
-
import { writeMessageToSession, writeEscapeToSession } from './message-write.js';
|
|
40
|
-
import { makeDeliveryPorts, getMailboxDrainer } from './mailbox-wiring.js';
|
|
44
|
+
import { formatArchitectMessage, formatArchitectToBuilderMessage, formatBuilderMessage, formatUserViaVsCodeMessage, formatUserViaDecisionsTabMessage, isSafeSenderId, messageLimitError, messageTooLargeError, MAX_MESSAGE_BYTES, } from '../utils/message-format.js';
|
|
45
|
+
import { writeMessageToSession, writeEscapeToSession, writeStrategyForApp } from './message-write.js';
|
|
46
|
+
import { makeDeliveryPorts, getMailboxDrainer, resolveProfileForSession } from './mailbox-wiring.js';
|
|
41
47
|
import { deliverAgentMailSerialized } from './mailbox-delivery.js';
|
|
42
48
|
import { deliverCronMail, CRON_SENDER } from './cron-delivery.js';
|
|
43
49
|
import { enqueue as enqueueMailbox, getById as getMailboxById, markDelivered as markMailboxDelivered, listHeld as listHeldMailbox, dismiss as dismissMailbox, } from '../db/mailbox.js';
|
|
@@ -55,7 +61,7 @@ import { submitToSession, OPERATOR_SUBMIT_WAIT_CEILING_MS } from './session-subm
|
|
|
55
61
|
import { scheduleDelayedSend, validateDelaySeconds } from './delayed-send.js';
|
|
56
62
|
import { getKnownWorkspacePaths, getInstances, getDirectorySuggestions, launchInstance, killTerminalWithShellper, instancesReady, stopInstance, addArchitect, removeArchitect, } from './tower-instances.js';
|
|
57
63
|
import { OverviewCache } from './overview.js';
|
|
58
|
-
import { fetchIssue, fetchPR, searchIssues, fetchPRList, fetchCurrentUser, parseLinkedIssue, parseArea, } from '../../lib/github.js';
|
|
64
|
+
import { fetchIssue, fetchPR, searchIssues, fetchPRList, fetchCurrentUser, probeGhGraphqlRateLimit, parseLinkedIssue, parseArea, } from '../../lib/github.js';
|
|
59
65
|
import { computeAnalytics } from './analytics.js';
|
|
60
66
|
import { getAllTasks, executeTask, getTaskId } from './tower-cron.js';
|
|
61
67
|
import { getGlobalDb } from '../db/index.js';
|
|
@@ -66,7 +72,8 @@ import { getWorkspaceTerminals, getTerminalManager, getWorkspaceTerminalsEntry,
|
|
|
66
72
|
const __filename = fileURLToPath(import.meta.url);
|
|
67
73
|
const __dirname = path.dirname(__filename);
|
|
68
74
|
// Singleton cache for overview endpoint (Spec 0126 Phase 4)
|
|
69
|
-
|
|
75
|
+
// #1645: the gh reset probe is enabled here, in Tower, and nowhere else.
|
|
76
|
+
const overviewCache = new OverviewCache({ probe: probeGhGraphqlRateLimit });
|
|
70
77
|
const ROUTES = {
|
|
71
78
|
'GET /health': (_req, res, _url, ctx) => handleHealthCheck(res, ctx),
|
|
72
79
|
'GET /api/shellpers/husks': (_req, res, _url, ctx) => handleHuskPreview(res, ctx),
|
|
@@ -159,6 +166,18 @@ export async function handleRequest(req, res, ctx) {
|
|
|
159
166
|
return await handler(req, res, url, ctx);
|
|
160
167
|
}
|
|
161
168
|
// Pattern-based routes (require regex or prefix matching)
|
|
169
|
+
// IDE management endpoint: /api/ide (Issue #1668). Local-only — blocked from
|
|
170
|
+
// the tunnel in tunnel-client (like /api/tunnel/*) — and reached only after
|
|
171
|
+
// the isRequestAllowed key check above. Drives the IDE server lifecycle.
|
|
172
|
+
if (url.pathname === '/api/ide') {
|
|
173
|
+
return await handleIdeApi(req, res, ctx.log);
|
|
174
|
+
}
|
|
175
|
+
// IDE prefix forward: /ide/* → local IDE server (Issue #1668). A post-auth
|
|
176
|
+
// handler: isRequestAllowed above is the whole trust boundary (the forward
|
|
177
|
+
// adds no per-folder authorization). Path + query forwarded unchanged.
|
|
178
|
+
if (matchIdePrefix(url.pathname)) {
|
|
179
|
+
return await forwardIdeHttp(req, res, ctx.log);
|
|
180
|
+
}
|
|
162
181
|
// Tunnel endpoints: /api/tunnel/* (Spec 0097 Phase 4)
|
|
163
182
|
if (url.pathname.startsWith('/api/tunnel/')) {
|
|
164
183
|
const tunnelSub = url.pathname.slice('/api/tunnel/'.length);
|
|
@@ -224,6 +243,10 @@ export async function handleRequest(req, res, ctx) {
|
|
|
224
243
|
}
|
|
225
244
|
catch (err) {
|
|
226
245
|
ctx.log('ERROR', `Request error: ${err.message}`);
|
|
246
|
+
// A handler may fail after it has answered (the Decisions route keeps working past its
|
|
247
|
+
// `res.end()`); a second writeHead would throw ERR_HTTP_HEADERS_SENT out of here.
|
|
248
|
+
if (res.headersSent)
|
|
249
|
+
return;
|
|
227
250
|
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
228
251
|
res.end(JSON.stringify({ error: err.message }));
|
|
229
252
|
}
|
|
@@ -610,9 +633,11 @@ async function handleTerminalCreate(req, res, ctx) {
|
|
|
610
633
|
if (requestPersistence && shellperManager && command && cwd) {
|
|
611
634
|
try {
|
|
612
635
|
const sessionId = crypto.randomUUID();
|
|
613
|
-
// Strip
|
|
614
|
-
|
|
615
|
-
|
|
636
|
+
// Strip Claude Code session markers so spawned Claude processes don't
|
|
637
|
+
// detect nesting and disable transcript saving (#1219). `env` is normally
|
|
638
|
+
// absent — `createPtySession` sends no env — so this is the path by which
|
|
639
|
+
// Tower's own environment becomes every builder's environment.
|
|
640
|
+
const sessionEnv = sanitizeAgentEnv(env || process.env);
|
|
616
641
|
const client = await shellperManager.createSession({
|
|
617
642
|
sessionId,
|
|
618
643
|
command,
|
|
@@ -667,7 +692,7 @@ async function handleTerminalCreate(req, res, ctx) {
|
|
|
667
692
|
// Fallback: non-persistent session (graceful degradation per plan)
|
|
668
693
|
// Shellper is the only persistence backend for new sessions.
|
|
669
694
|
if (!info) {
|
|
670
|
-
info = await manager.createSession({ command, args, cols, rows, cwd, env, label });
|
|
695
|
+
info = await manager.createSession({ command, args, cols, rows, cwd, env: env && sanitizeAgentEnv(env), label });
|
|
671
696
|
persistent = false;
|
|
672
697
|
if (workspacePath && termType && roleId) {
|
|
673
698
|
const entry = getWorkspaceTerminalsEntry(normalizeWorkspacePath(workspacePath));
|
|
@@ -750,6 +775,9 @@ async function handleTerminalRoutes(req, res, url, match) {
|
|
|
750
775
|
res.end(JSON.stringify({ error: 'NOT_FOUND', message: `Session ${terminalId} not found` }));
|
|
751
776
|
return;
|
|
752
777
|
}
|
|
778
|
+
// Deliberately the default `'external'` origin (Issue #1473): this is a foreign writer, so
|
|
779
|
+
// its bytes count as input at the delivery gate and are reply-filtered on the way — both
|
|
780
|
+
// for free, because the recording lives inside `write()` rather than at each call site.
|
|
753
781
|
session.write(body.data);
|
|
754
782
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
755
783
|
res.end(JSON.stringify({ ok: true }));
|
|
@@ -1311,6 +1339,9 @@ function formatMessageForTarget(isArchitectTarget, from, toAgent, message, raw)
|
|
|
1311
1339
|
// header, so the architect can tell it from a peer-architect instruction.
|
|
1312
1340
|
if (isArchitectTarget && from === VSCODE_USER_SENDER)
|
|
1313
1341
|
return formatUserViaVsCodeMessage(toAgent, message, undefined, raw);
|
|
1342
|
+
// #1828: likewise the owner's ruling relayed by the Decisions tab — never a builder frame.
|
|
1343
|
+
if (isArchitectTarget && from === DECISIONS_TAB_SENDER)
|
|
1344
|
+
return formatUserViaDecisionsTabMessage(toAgent, message, raw);
|
|
1314
1345
|
if (isArchitectTarget && from)
|
|
1315
1346
|
return formatBuilderMessage(from, toAgent, message, undefined, raw); // builder → architect
|
|
1316
1347
|
// any → builder: thread the sender so an `architect:<name>` origin is named in the
|
|
@@ -1376,6 +1407,45 @@ export async function deliverCronMessage(task, message, log) {
|
|
|
1376
1407
|
log('WARN', `Cron '${task.name}': target '${task.target}' not found — message not delivered`);
|
|
1377
1408
|
return { outcome: 'unresolved', reason: null, detail: null, mailboxId: null };
|
|
1378
1409
|
}
|
|
1410
|
+
/**
|
|
1411
|
+
* Tell a workspace's hub architect about a ruling the owner just wrote from the
|
|
1412
|
+
* Decisions tab (#1828). The hub is the architect registered as `main` and no other:
|
|
1413
|
+
* the registry's "first registered" order is by name (#1633), so a workspace without
|
|
1414
|
+
* `main` gets no notice rather than a guess, and a `main` that is offline holds it
|
|
1415
|
+
* (`no-live-pty`). One mailbox row is persisted, then offered to the same gated delivery
|
|
1416
|
+
* `handleSend` uses; a busy line holds it for the backstop. Throws, persisting nothing,
|
|
1417
|
+
* when `main` is not registered or the notice is over the send limit.
|
|
1418
|
+
*/
|
|
1419
|
+
async function notifyHubOfRuling(workspacePath, message, log) {
|
|
1420
|
+
const tooLarge = messageLimitError(message);
|
|
1421
|
+
if (tooLarge)
|
|
1422
|
+
throw new Error(tooLarge);
|
|
1423
|
+
const toAgent = DEFAULT_ARCHITECT_NAME;
|
|
1424
|
+
if (!getArchitectByName(workspacePath, toAgent)) {
|
|
1425
|
+
throw new Error(`no architect named '${toAgent}' is registered in workspace ${workspacePath}`);
|
|
1426
|
+
}
|
|
1427
|
+
const db = getGlobalDb();
|
|
1428
|
+
const row = enqueueMailbox(db, {
|
|
1429
|
+
workspacePath,
|
|
1430
|
+
toAgent,
|
|
1431
|
+
body: message,
|
|
1432
|
+
formattedMessage: formatMessageForTarget(true, DECISIONS_TAB_SENDER, toAgent, message, false),
|
|
1433
|
+
fromAgent: DECISIONS_TAB_SENDER,
|
|
1434
|
+
fromWorkspace: workspacePath,
|
|
1435
|
+
});
|
|
1436
|
+
const ports = makeDeliveryPorts(log);
|
|
1437
|
+
ports.onHeldStateChange();
|
|
1438
|
+
try {
|
|
1439
|
+
const outcome = await deliverAgentMailSerialized(ports, db, workspacePath, toAgent);
|
|
1440
|
+
getMailboxDrainer().noteOutcome(workspacePath, toAgent, outcome);
|
|
1441
|
+
}
|
|
1442
|
+
catch (err) {
|
|
1443
|
+
log('ERROR', `Decisions notice delivery errored for ${toAgent} (row ${row.id.slice(0, 8)}... stays held): ${err.message}`);
|
|
1444
|
+
}
|
|
1445
|
+
const stored = getMailboxById(db, row.id);
|
|
1446
|
+
const fate = stored?.status === 'delivered' ? 'delivered' : `held (${stored?.reason ?? 'unknown'})`;
|
|
1447
|
+
log('INFO', `Decisions notice ${fate} → ${toAgent} @ ${path.basename(workspacePath)} (mailbox ${row.id.slice(0, 8)}...)`);
|
|
1448
|
+
}
|
|
1379
1449
|
/**
|
|
1380
1450
|
* Persist a `held` mailbox row and write the Spec 1313 `held` send response. Used
|
|
1381
1451
|
* for both dead-session cases (no live PTY, held `no-live-pty`). The row exists
|
|
@@ -1837,7 +1907,10 @@ async function handleSend(req, res, ctx) {
|
|
|
1837
1907
|
let degraded = false;
|
|
1838
1908
|
await submitToSession(result.terminalId, () => {
|
|
1839
1909
|
session.write('\x03'); // Ctrl+C
|
|
1840
|
-
|
|
1910
|
+
// Issue #1567: the same per-harness write strategy the gated path uses — an
|
|
1911
|
+
// interrupt to an opted-out harness must not be bracketed just because it bypassed
|
|
1912
|
+
// the gate.
|
|
1913
|
+
return writeMessageToSession(session, formattedMessage, noEnter, 100, writeStrategyForApp(resolveProfileForSession(session)?.app));
|
|
1841
1914
|
}, undefined, {
|
|
1842
1915
|
waitCeilingMs: OPERATOR_SUBMIT_WAIT_CEILING_MS,
|
|
1843
1916
|
onCeilingExpired: (waitedMs) => {
|
|
@@ -1905,6 +1978,13 @@ async function handleSend(req, res, ctx) {
|
|
|
1905
1978
|
// completed write); the backstop drainer will retry. Report held, not a 500.
|
|
1906
1979
|
ctx.log('ERROR', `Delivery attempt errored for ${toAgent} (row ${row.id.slice(0, 8)}... stays held): ${err.message}`);
|
|
1907
1980
|
}
|
|
1981
|
+
// Issue #1473: this pass ran OUTSIDE the drainer, so hand it the outcome — otherwise a hold
|
|
1982
|
+
// on recent terminal input arms no re-drain here, and the send an operator is watching falls
|
|
1983
|
+
// through to the quiescence trigger or the backstop instead of clearing after one settle.
|
|
1984
|
+
// That is exactly the latency the re-drain exists to remove, in the case where somebody is
|
|
1985
|
+
// waiting for it. A no-op for every other outcome.
|
|
1986
|
+
if (outcome)
|
|
1987
|
+
getMailboxDrainer().noteOutcome(result.workspacePath, toAgent, outcome);
|
|
1908
1988
|
const stored = getMailboxById(db, row.id);
|
|
1909
1989
|
if (stored?.status === 'delivered') {
|
|
1910
1990
|
ctx.log('INFO', `Message delivered: ${from ?? 'unknown'} → ${toAgent} (terminal ${result.terminalId.slice(0, 8)}...)`);
|
|
@@ -1927,6 +2007,15 @@ async function handleSend(req, res, ctx) {
|
|
|
1927
2007
|
...(outcome?.delivered.includes(row.id) && outcome.verified !== undefined
|
|
1928
2008
|
? { verified: outcome.verified }
|
|
1929
2009
|
: {}),
|
|
2010
|
+
// Issue #1473. `verified` alone was not enough for the SENDER — the case that motivated
|
|
2011
|
+
// it is a human's Enter submitting our half-written body, where the header landed, so
|
|
2012
|
+
// `verified` is `true` (or absent) and this human read a plain "Message delivered". The
|
|
2013
|
+
// cause says which flag it is: `input-raced` (may be truncated or submitted early) or
|
|
2014
|
+
// `no-echo` (header never appeared). Same id guard as `verified` — reported only when
|
|
2015
|
+
// THIS pass is the one that delivered THIS row.
|
|
2016
|
+
...(outcome?.delivered.includes(row.id) && outcome.unverifiedCause !== undefined
|
|
2017
|
+
? { unverifiedCause: outcome.unverifiedCause }
|
|
2018
|
+
: {}),
|
|
1930
2019
|
});
|
|
1931
2020
|
return;
|
|
1932
2021
|
}
|
|
@@ -2357,7 +2446,7 @@ async function handleWorkspaceRoutes(req, res, ctx, url) {
|
|
|
2357
2446
|
const apiPath = subPath.replace(/^api\/?/, '');
|
|
2358
2447
|
// GET /api/state - Return workspace state (architect, builders, shells)
|
|
2359
2448
|
if (req.method === 'GET' && (apiPath === 'state' || apiPath === '')) {
|
|
2360
|
-
return handleWorkspaceState(res, workspacePath);
|
|
2449
|
+
return handleWorkspaceState(res, ctx, workspacePath);
|
|
2361
2450
|
}
|
|
2362
2451
|
// POST /api/tabs/shell - Create a new shell terminal
|
|
2363
2452
|
if (req.method === 'POST' && apiPath === 'tabs/shell') {
|
|
@@ -2437,6 +2526,14 @@ async function handleWorkspaceRoutes(req, res, ctx, url) {
|
|
|
2437
2526
|
if (req.method === 'GET' && apiPath === 'team') {
|
|
2438
2527
|
return handleWorkspaceTeam(res, workspacePath);
|
|
2439
2528
|
}
|
|
2529
|
+
// GET /api/decisions, POST /api/decisions/rule — the Decisions tab (Spec 1819).
|
|
2530
|
+
// The file is the configured one; neither route takes a path from the request.
|
|
2531
|
+
if (req.method === 'GET' && apiPath === 'decisions') {
|
|
2532
|
+
return handleDecisionsGet(res, workspacePath);
|
|
2533
|
+
}
|
|
2534
|
+
if (req.method === 'POST' && apiPath === 'decisions/rule') {
|
|
2535
|
+
return handleDecisionsRule(req, res, workspacePath, ctx.log, message => notifyHubOfRuling(workspacePath, message, ctx.log));
|
|
2536
|
+
}
|
|
2440
2537
|
// GET /api/annotate/:tabId/* — Serve rich annotator template and sub-APIs
|
|
2441
2538
|
const annotateMatch = apiPath.match(/^annotate\/([^/]+)(\/(.*))?$/);
|
|
2442
2539
|
if (annotateMatch) {
|
|
@@ -2547,7 +2644,7 @@ async function handleWorkspaceRoutes(req, res, ctx, url) {
|
|
|
2547
2644
|
// ============================================================================
|
|
2548
2645
|
// Workspace API sub-handlers
|
|
2549
2646
|
// ============================================================================
|
|
2550
|
-
async function handleWorkspaceState(res, workspacePath) {
|
|
2647
|
+
async function handleWorkspaceState(res, ctx, workspacePath) {
|
|
2551
2648
|
// Rehydrate wsTerminals (SQLite sync + shellper reconnect) before reading.
|
|
2552
2649
|
// Shared with /api/overview so both endpoints always see a freshly-reconciled
|
|
2553
2650
|
// entry — see getRehydratedTerminalsEntry doc.
|
|
@@ -2570,6 +2667,7 @@ async function handleWorkspaceState(res, workspacePath) {
|
|
|
2570
2667
|
return undefined;
|
|
2571
2668
|
} })(),
|
|
2572
2669
|
teamEnabled: await hasTeam(path.join(workspacePath, 'codev', 'team')),
|
|
2670
|
+
decisionsEnabled: await decisionsFilePresent(workspacePath, ctx.log),
|
|
2573
2671
|
};
|
|
2574
2672
|
// Spec 761: build the architects collection from entry.architects (skip dead
|
|
2575
2673
|
// sessions, main-first). Shared with /api/overview via `liveArchitects`
|
|
@@ -2694,9 +2792,9 @@ async function handleWorkspaceShellCreate(res, ctx, workspacePath) {
|
|
|
2694
2792
|
if (shellperManager) {
|
|
2695
2793
|
try {
|
|
2696
2794
|
const sessionId = crypto.randomUUID();
|
|
2697
|
-
// Strip
|
|
2698
|
-
|
|
2699
|
-
|
|
2795
|
+
// Strip Claude Code session markers so spawned Claude processes don't
|
|
2796
|
+
// detect nesting and disable transcript saving (#1219).
|
|
2797
|
+
const shellEnv = sanitizeAgentEnv(process.env);
|
|
2700
2798
|
// Inject session identity for afx rename (Spec 468)
|
|
2701
2799
|
shellEnv['SHELLPER_SESSION_ID'] = sessionId;
|
|
2702
2800
|
shellEnv['TOWER_PORT'] = String(ctx.port);
|
|
@@ -2757,7 +2855,7 @@ async function handleWorkspaceShellCreate(res, ctx, workspacePath) {
|
|
|
2757
2855
|
args: shellArgs,
|
|
2758
2856
|
cwd: workspacePath,
|
|
2759
2857
|
label: `Shell ${shellId.replace('shell-', '')}`,
|
|
2760
|
-
env: process.env,
|
|
2858
|
+
env: sanitizeAgentEnv(process.env),
|
|
2761
2859
|
});
|
|
2762
2860
|
const entry = getWorkspaceTerminalsEntry(workspacePath);
|
|
2763
2861
|
entry.shells.set(shellId, session.id);
|