@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
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `POST /api/agent-lifecycle`: the one write-only agent-state route (Spec 1595,
|
|
3
|
+
* Constraint 16).
|
|
4
|
+
*
|
|
5
|
+
* An agent's lifecycle reporter posts one `AgentLifecycleEvent` per harness hook.
|
|
6
|
+
* The route validates it strictly against the contract and its limits, resolves
|
|
7
|
+
* the launch identity to the agent Tower knows, applies it to the in-memory
|
|
8
|
+
* store, and answers an empty 204. It writes nothing else: no PTY, no mailbox,
|
|
9
|
+
* no database. There is no read route; state is served on the overview.
|
|
10
|
+
*
|
|
11
|
+
* Auth is the existing `isRequestAllowed` choke point in `handleRequest`; this
|
|
12
|
+
* route is not on the public allowlist. A rejection is a 4xx carrying only an
|
|
13
|
+
* error code. The reporter ignores every response.
|
|
14
|
+
*/
|
|
15
|
+
import { isAbsolute } from 'node:path';
|
|
16
|
+
import { readBody } from '../../utils/server-utils.js';
|
|
17
|
+
/** Request body cap, in bytes. */
|
|
18
|
+
export const MAX_LIFECYCLE_BODY_BYTES = 8192;
|
|
19
|
+
export const MAX_PATH_LENGTH = 4096;
|
|
20
|
+
export const MAX_NAME_LENGTH = 128;
|
|
21
|
+
export const MAX_SESSION_ID_LENGTH = 128;
|
|
22
|
+
export const MAX_TOOL_LENGTH = 64;
|
|
23
|
+
export const MAX_SUMMARY_LENGTH = 200;
|
|
24
|
+
const EVENT_NAMES = new Set([
|
|
25
|
+
'session-started',
|
|
26
|
+
'turn-started',
|
|
27
|
+
'tool-activity',
|
|
28
|
+
'needs-input',
|
|
29
|
+
'turn-ended',
|
|
30
|
+
]);
|
|
31
|
+
const NEEDS_INPUT_KINDS = new Set(['permission', 'question', 'other']);
|
|
32
|
+
const EVENT_KEYS = new Set(['agent', 'sessionId', 'event', 'at', 'needsInput', 'backgroundWork']);
|
|
33
|
+
const BUILDER_KEYS = new Set(['kind', 'worktreePath']);
|
|
34
|
+
const ARCHITECT_KEYS = new Set(['kind', 'workspacePath', 'name']);
|
|
35
|
+
const DETAIL_KEYS = new Set(['kind', 'tool', 'summary']);
|
|
36
|
+
// eslint-disable-next-line no-control-regex
|
|
37
|
+
const CONTROL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f]/;
|
|
38
|
+
function isRecord(value) {
|
|
39
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
40
|
+
}
|
|
41
|
+
function hasOnlyKeys(value, allowed) {
|
|
42
|
+
return Object.keys(value).every(key => allowed.has(key));
|
|
43
|
+
}
|
|
44
|
+
function isBoundedString(value, maxLength) {
|
|
45
|
+
return typeof value === 'string' && value.length > 0 && value.length <= maxLength;
|
|
46
|
+
}
|
|
47
|
+
function isPlainText(value, maxLength) {
|
|
48
|
+
return isBoundedString(value, maxLength) && !CONTROL_CHARACTERS.test(value);
|
|
49
|
+
}
|
|
50
|
+
function isAbsolutePath(value) {
|
|
51
|
+
return isPlainText(value, MAX_PATH_LENGTH) && isAbsolute(value);
|
|
52
|
+
}
|
|
53
|
+
function parseIdentity(value) {
|
|
54
|
+
if (!isRecord(value))
|
|
55
|
+
return null;
|
|
56
|
+
if (value.kind === 'builder') {
|
|
57
|
+
if (!hasOnlyKeys(value, BUILDER_KEYS) || !isAbsolutePath(value.worktreePath))
|
|
58
|
+
return null;
|
|
59
|
+
return { kind: 'builder', worktreePath: value.worktreePath };
|
|
60
|
+
}
|
|
61
|
+
if (value.kind === 'architect') {
|
|
62
|
+
if (!hasOnlyKeys(value, ARCHITECT_KEYS) || !isAbsolutePath(value.workspacePath))
|
|
63
|
+
return null;
|
|
64
|
+
if (!isPlainText(value.name, MAX_NAME_LENGTH))
|
|
65
|
+
return null;
|
|
66
|
+
return { kind: 'architect', workspacePath: value.workspacePath, name: value.name };
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
function parseDetail(value) {
|
|
71
|
+
if (!isRecord(value) || !hasOnlyKeys(value, DETAIL_KEYS))
|
|
72
|
+
return null;
|
|
73
|
+
if (typeof value.kind !== 'string' || !NEEDS_INPUT_KINDS.has(value.kind))
|
|
74
|
+
return null;
|
|
75
|
+
const detail = { kind: value.kind };
|
|
76
|
+
if (value.tool !== undefined) {
|
|
77
|
+
if (!isPlainText(value.tool, MAX_TOOL_LENGTH))
|
|
78
|
+
return null;
|
|
79
|
+
detail.tool = value.tool;
|
|
80
|
+
}
|
|
81
|
+
if (value.summary !== undefined) {
|
|
82
|
+
if (!isPlainText(value.summary, MAX_SUMMARY_LENGTH))
|
|
83
|
+
return null;
|
|
84
|
+
detail.summary = value.summary;
|
|
85
|
+
}
|
|
86
|
+
return detail;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Validate a parsed body against the `AgentLifecycleEvent` contract, or `null`.
|
|
90
|
+
* Strict: unknown keys anywhere are rejected, `needsInput` is accepted only on a
|
|
91
|
+
* `needs-input` event and `backgroundWork` only on `turn-ended`.
|
|
92
|
+
*/
|
|
93
|
+
export function parseLifecycleEvent(value) {
|
|
94
|
+
if (!isRecord(value) || !hasOnlyKeys(value, EVENT_KEYS))
|
|
95
|
+
return null;
|
|
96
|
+
const agent = parseIdentity(value.agent);
|
|
97
|
+
if (agent === null)
|
|
98
|
+
return null;
|
|
99
|
+
if (!isPlainText(value.sessionId, MAX_SESSION_ID_LENGTH))
|
|
100
|
+
return null;
|
|
101
|
+
if (typeof value.event !== 'string' || !EVENT_NAMES.has(value.event))
|
|
102
|
+
return null;
|
|
103
|
+
if (typeof value.at !== 'number' || !Number.isFinite(value.at) || value.at <= 0)
|
|
104
|
+
return null;
|
|
105
|
+
const event = {
|
|
106
|
+
agent,
|
|
107
|
+
sessionId: value.sessionId,
|
|
108
|
+
event: value.event,
|
|
109
|
+
at: value.at,
|
|
110
|
+
};
|
|
111
|
+
if (value.needsInput !== undefined) {
|
|
112
|
+
if (event.event !== 'needs-input')
|
|
113
|
+
return null;
|
|
114
|
+
const detail = parseDetail(value.needsInput);
|
|
115
|
+
if (detail === null)
|
|
116
|
+
return null;
|
|
117
|
+
event.needsInput = detail;
|
|
118
|
+
}
|
|
119
|
+
if (value.backgroundWork !== undefined) {
|
|
120
|
+
if (event.event !== 'turn-ended' || typeof value.backgroundWork !== 'boolean')
|
|
121
|
+
return null;
|
|
122
|
+
event.backgroundWork = value.backgroundWork;
|
|
123
|
+
}
|
|
124
|
+
return event;
|
|
125
|
+
}
|
|
126
|
+
function reject(res, status, code) {
|
|
127
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
128
|
+
res.end(JSON.stringify({ error: code }));
|
|
129
|
+
}
|
|
130
|
+
/** Handle one lifecycle report. Auth has already passed in `handleRequest`. */
|
|
131
|
+
export async function handleAgentLifecycle(req, res, deps) {
|
|
132
|
+
let raw;
|
|
133
|
+
try {
|
|
134
|
+
raw = await readBody(req, MAX_LIFECYCLE_BODY_BYTES);
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
if (err instanceof Error && err.message === 'Request body too large') {
|
|
138
|
+
reject(res, 413, 'BODY_TOO_LARGE');
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
reject(res, 400, 'UNREADABLE_BODY');
|
|
142
|
+
}
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
let parsed;
|
|
146
|
+
try {
|
|
147
|
+
parsed = JSON.parse(raw);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
reject(res, 400, 'INVALID_JSON');
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const event = parseLifecycleEvent(parsed);
|
|
154
|
+
if (event === null) {
|
|
155
|
+
reject(res, 400, 'INVALID_EVENT');
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const agent = deps.resolve(event.agent);
|
|
159
|
+
if (agent === null) {
|
|
160
|
+
reject(res, 404, 'UNKNOWN_AGENT');
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (deps.store.apply(agent.workspacePath, agent.agentId, event) === 'future') {
|
|
164
|
+
reject(res, 400, 'AT_IN_FUTURE');
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
res.writeHead(204);
|
|
168
|
+
res.end();
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/agent-farm/servers/agent-state/route.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serve an agent's attention state on the overview (Spec 1595).
|
|
3
|
+
*
|
|
4
|
+
* Gathers Tower's facts about one agent (porch's `blocked`, the caller already
|
|
5
|
+
* holds; the published liveness; the stored reported activity) and hands them to
|
|
6
|
+
* the one projection policy in codev-core. Called per request: nothing here is
|
|
7
|
+
* cached, so a served row is never older than the store and the liveness sweep.
|
|
8
|
+
*/
|
|
9
|
+
import type { ServedAgentState } from '@cluesmith/codev-types';
|
|
10
|
+
import { type AgentStateStore } from './store.js';
|
|
11
|
+
import { type AgentLiveness } from './liveness.js';
|
|
12
|
+
/** The porch facts the overview already computed for the agent. */
|
|
13
|
+
export interface AgentPorchFacts {
|
|
14
|
+
/** Whether porch reports a requested, pending gate (`detectBlocked` is non-null). */
|
|
15
|
+
blocked: boolean;
|
|
16
|
+
blockedSince: string | null;
|
|
17
|
+
/** The builder's display phase; `''` for an architect. */
|
|
18
|
+
phase: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ServeAgentStateOptions {
|
|
21
|
+
store?: AgentStateStore;
|
|
22
|
+
liveness?: (workspacePath: string, agentId: string) => AgentLiveness | undefined;
|
|
23
|
+
now?: () => number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The served state for the agent `(workspacePath, agentId)`, keyed as the store
|
|
27
|
+
* and liveness key it: the normalized workspace path and the canonical agent id
|
|
28
|
+
* (a builder's lowercased role id, an architect's name). `null` when unknown.
|
|
29
|
+
*/
|
|
30
|
+
export declare function serveAgentState(workspacePath: string, agentId: string, porch: AgentPorchFacts, options?: ServeAgentStateOptions): ServedAgentState | null;
|
|
31
|
+
//# sourceMappingURL=serve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../../../src/agent-farm/servers/agent-state/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAM/D,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAErE,mEAAmE;AACnE,MAAM,WAAW,eAAe;IAC9B,qFAAqF;IACrF,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;IACjF,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAoBD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,eAAe,EACtB,OAAO,GAAE,sBAA2B,GACnC,gBAAgB,GAAG,IAAI,CAYzB"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serve an agent's attention state on the overview (Spec 1595).
|
|
3
|
+
*
|
|
4
|
+
* Gathers Tower's facts about one agent (porch's `blocked`, the caller already
|
|
5
|
+
* holds; the published liveness; the stored reported activity) and hands them to
|
|
6
|
+
* the one projection policy in codev-core. Called per request: nothing here is
|
|
7
|
+
* cached, so a served row is never older than the store and the liveness sweep.
|
|
8
|
+
*/
|
|
9
|
+
import { projectAgentState, } from '@cluesmith/codev-core/agent-state';
|
|
10
|
+
import { agentStateStore } from './store.js';
|
|
11
|
+
import { getAgentLiveness } from './liveness.js';
|
|
12
|
+
function livenessFact(liveness) {
|
|
13
|
+
if (liveness === undefined)
|
|
14
|
+
return null;
|
|
15
|
+
return { alive: liveness.alive, since: new Date(liveness.since).toISOString() };
|
|
16
|
+
}
|
|
17
|
+
function reportedFact(store, workspacePath, agentId) {
|
|
18
|
+
const stored = store.get(workspacePath, agentId);
|
|
19
|
+
if (stored === undefined)
|
|
20
|
+
return null;
|
|
21
|
+
const fact = {
|
|
22
|
+
activity: stored.activity,
|
|
23
|
+
since: new Date(stored.activitySince).toISOString(),
|
|
24
|
+
at: new Date(stored.reportedAt).toISOString(),
|
|
25
|
+
backgroundWork: stored.backgroundWork,
|
|
26
|
+
};
|
|
27
|
+
if (stored.needsInput !== undefined)
|
|
28
|
+
fact.needsInput = stored.needsInput;
|
|
29
|
+
return fact;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The served state for the agent `(workspacePath, agentId)`, keyed as the store
|
|
33
|
+
* and liveness key it: the normalized workspace path and the canonical agent id
|
|
34
|
+
* (a builder's lowercased role id, an architect's name). `null` when unknown.
|
|
35
|
+
*/
|
|
36
|
+
export function serveAgentState(workspacePath, agentId, porch, options = {}) {
|
|
37
|
+
const store = options.store ?? agentStateStore;
|
|
38
|
+
const liveness = options.liveness ?? getAgentLiveness;
|
|
39
|
+
const now = options.now ?? Date.now;
|
|
40
|
+
return projectAgentState({
|
|
41
|
+
blocked: porch.blocked,
|
|
42
|
+
blockedSince: porch.blockedSince,
|
|
43
|
+
phase: porch.phase,
|
|
44
|
+
liveness: livenessFact(liveness(workspacePath, agentId)),
|
|
45
|
+
reported: reportedFact(store, workspacePath, agentId),
|
|
46
|
+
now: new Date(now()).toISOString(),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../../src/agent-farm/servers/agent-state/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,iBAAiB,GAGlB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAwB,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAsB,MAAM,eAAe,CAAC;AAiBrE,SAAS,YAAY,CAAC,QAAmC;IACvD,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACxC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;AAClF,CAAC;AAED,SAAS,YAAY,CAAC,KAAsB,EAAE,aAAqB,EAAE,OAAe;IAClF,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IACjD,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,IAAI,GAAyB;QACjC,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,KAAK,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE;QACnD,EAAE,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE;QAC7C,cAAc,EAAE,MAAM,CAAC,cAAc;KACtC,CAAC;IACF,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS;QAAE,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IACzE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,aAAqB,EACrB,OAAe,EACf,KAAsB,EACtB,UAAkC,EAAE;IAEpC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,eAAe,CAAC;IAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,gBAAgB,CAAC;IACtD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACpC,OAAO,iBAAiB,CAAC;QACvB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACxD,QAAQ,EAAE,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,CAAC;QACrD,GAAG,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE;KACnC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tower's in-memory agent activity store (Spec 1595).
|
|
3
|
+
*
|
|
4
|
+
* Holds, per agent, the latest activity its harness reported through the
|
|
5
|
+
* lifecycle route: the harness session id, the activity and when it began, the
|
|
6
|
+
* hook time of the latest accepted report, whether background work is pending,
|
|
7
|
+
* and the needs-input detail while (and only while) the agent needs input.
|
|
8
|
+
*
|
|
9
|
+
* Memory only, by owner ruling (2026-10-21): nothing here is ever written to
|
|
10
|
+
* `global.db` or any other store, so no served state can outlive the Tower
|
|
11
|
+
* process that received its report. A fresh store holds nothing.
|
|
12
|
+
*
|
|
13
|
+
* Keys are `(normalized workspace path, canonical agent id)`; callers resolve
|
|
14
|
+
* both through `resolveAgentIdentity` before touching the store.
|
|
15
|
+
*
|
|
16
|
+
* Ordering (SC17): a report older than the stored hook time is ignored; a report
|
|
17
|
+
* from a different harness session supersedes the stored one only with a newer
|
|
18
|
+
* hook time; a hook time more than `MAX_FUTURE_SKEW_MS` ahead of Tower's clock is
|
|
19
|
+
* rejected.
|
|
20
|
+
*
|
|
21
|
+
* Background work (SC5): a turn end with `backgroundWork: true` holds the agent
|
|
22
|
+
* `working`. A later same-session turn end that makes no background-work claim
|
|
23
|
+
* (the field absent) does not release that hold; a new turn does.
|
|
24
|
+
*/
|
|
25
|
+
import { EventEmitter } from 'node:events';
|
|
26
|
+
import type { AgentActivity, AgentLifecycleEvent, NeedsInputDetail } from '@cluesmith/codev-types';
|
|
27
|
+
/** How far ahead of Tower's clock a report's hook time may be. */
|
|
28
|
+
export declare const MAX_FUTURE_SKEW_MS = 60000;
|
|
29
|
+
/** Raised on every accepted report that changes a served field. */
|
|
30
|
+
export declare const AGENT_STATE_CHANGED = "agent-state-changed";
|
|
31
|
+
/** One agent's reported activity, as held in memory. */
|
|
32
|
+
export interface StoredAgentActivity {
|
|
33
|
+
/** The harness session the activity belongs to. */
|
|
34
|
+
sessionId: string;
|
|
35
|
+
activity: AgentActivity;
|
|
36
|
+
/** Hook time (epoch ms) at which `activity` began. */
|
|
37
|
+
activitySince: number;
|
|
38
|
+
/** Hook time (epoch ms) of the latest report that set the served state; the served `at`. */
|
|
39
|
+
reportedAt: number;
|
|
40
|
+
/**
|
|
41
|
+
* Hook time (epoch ms) of the latest accepted report, including one that
|
|
42
|
+
* changed nothing served. The ordering watermark (SC17): never behind `reportedAt`.
|
|
43
|
+
*/
|
|
44
|
+
latestHookAt: number;
|
|
45
|
+
/** True when the agent ended its turn with its own background work running. */
|
|
46
|
+
backgroundWork: boolean;
|
|
47
|
+
/** Present only while `activity` is `needs-input`. */
|
|
48
|
+
needsInput?: NeedsInputDetail;
|
|
49
|
+
}
|
|
50
|
+
/** The payload of `AGENT_STATE_CHANGED`. */
|
|
51
|
+
export interface AgentStateChange {
|
|
52
|
+
workspacePath: string;
|
|
53
|
+
agentId: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* What `apply` did with a report: `changed` (accepted, a served field moved),
|
|
57
|
+
* `unchanged` (accepted, nothing served moved), `stale` (ignored by ordering),
|
|
58
|
+
* or `future` (rejected: hook time implausibly far ahead).
|
|
59
|
+
*/
|
|
60
|
+
export type ApplyOutcome = 'changed' | 'unchanged' | 'stale' | 'future';
|
|
61
|
+
export declare class AgentStateStore extends EventEmitter {
|
|
62
|
+
private readonly now;
|
|
63
|
+
private readonly entries;
|
|
64
|
+
constructor(now?: () => number);
|
|
65
|
+
/** The stored activity for an agent, or `undefined` when it has reported nothing. */
|
|
66
|
+
get(workspacePath: string, agentId: string): StoredAgentActivity | undefined;
|
|
67
|
+
/** Apply one validated report for a resolved agent. */
|
|
68
|
+
apply(workspacePath: string, agentId: string, event: AgentLifecycleEvent): ApplyOutcome;
|
|
69
|
+
/** Every agent the store holds state for. */
|
|
70
|
+
agents(): AgentStateChange[];
|
|
71
|
+
/** Forget an agent's reported state (it was removed). */
|
|
72
|
+
drop(workspacePath: string, agentId: string): void;
|
|
73
|
+
}
|
|
74
|
+
/** Tower's one store. Nothing subscribes to its change event except the broadcaster. */
|
|
75
|
+
export declare const agentStateStore: AgentStateStore;
|
|
76
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../src/agent-farm/servers/agent-state/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAEnG,kEAAkE;AAClE,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAEzC,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AAEzD,wDAAwD;AACxD,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,aAAa,CAAC;IACxB,sDAAsD;IACtD,aAAa,EAAE,MAAM,CAAC;IACtB,4FAA4F;IAC5F,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,cAAc,EAAE,OAAO,CAAC;IACxB,sDAAsD;IACtD,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAED,4CAA4C;AAC5C,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AAyDxE,qBAAa,eAAgB,SAAQ,YAAY;IAGnC,OAAO,CAAC,QAAQ,CAAC,GAAG;IAFhC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0C;gBAErC,GAAG,GAAE,MAAM,MAAiB;IAIzD,qFAAqF;IACrF,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS;IAI5E,uDAAuD;IACvD,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,YAAY;IA8CvF,6CAA6C;IAC7C,MAAM,IAAI,gBAAgB,EAAE;IAS5B,yDAAyD;IACzD,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;CAGnD;AAED,wFAAwF;AACxF,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tower's in-memory agent activity store (Spec 1595).
|
|
3
|
+
*
|
|
4
|
+
* Holds, per agent, the latest activity its harness reported through the
|
|
5
|
+
* lifecycle route: the harness session id, the activity and when it began, the
|
|
6
|
+
* hook time of the latest accepted report, whether background work is pending,
|
|
7
|
+
* and the needs-input detail while (and only while) the agent needs input.
|
|
8
|
+
*
|
|
9
|
+
* Memory only, by owner ruling (2026-10-21): nothing here is ever written to
|
|
10
|
+
* `global.db` or any other store, so no served state can outlive the Tower
|
|
11
|
+
* process that received its report. A fresh store holds nothing.
|
|
12
|
+
*
|
|
13
|
+
* Keys are `(normalized workspace path, canonical agent id)`; callers resolve
|
|
14
|
+
* both through `resolveAgentIdentity` before touching the store.
|
|
15
|
+
*
|
|
16
|
+
* Ordering (SC17): a report older than the stored hook time is ignored; a report
|
|
17
|
+
* from a different harness session supersedes the stored one only with a newer
|
|
18
|
+
* hook time; a hook time more than `MAX_FUTURE_SKEW_MS` ahead of Tower's clock is
|
|
19
|
+
* rejected.
|
|
20
|
+
*
|
|
21
|
+
* Background work (SC5): a turn end with `backgroundWork: true` holds the agent
|
|
22
|
+
* `working`. A later same-session turn end that makes no background-work claim
|
|
23
|
+
* (the field absent) does not release that hold; a new turn does.
|
|
24
|
+
*/
|
|
25
|
+
import { EventEmitter } from 'node:events';
|
|
26
|
+
/** How far ahead of Tower's clock a report's hook time may be. */
|
|
27
|
+
export const MAX_FUTURE_SKEW_MS = 60_000;
|
|
28
|
+
/** Raised on every accepted report that changes a served field. */
|
|
29
|
+
export const AGENT_STATE_CHANGED = 'agent-state-changed';
|
|
30
|
+
function storeKey(workspacePath, agentId) {
|
|
31
|
+
return `${workspacePath}\0${agentId}`;
|
|
32
|
+
}
|
|
33
|
+
function sameDetail(a, b) {
|
|
34
|
+
if (a === undefined || b === undefined)
|
|
35
|
+
return a === b;
|
|
36
|
+
return a.kind === b.kind && a.tool === b.tool && a.summary === b.summary;
|
|
37
|
+
}
|
|
38
|
+
/** The activity a lifecycle event moves the agent into. */
|
|
39
|
+
function activityFor(event) {
|
|
40
|
+
switch (event.event) {
|
|
41
|
+
case 'session-started':
|
|
42
|
+
return 'idle';
|
|
43
|
+
case 'turn-started':
|
|
44
|
+
case 'tool-activity':
|
|
45
|
+
return 'working';
|
|
46
|
+
case 'needs-input':
|
|
47
|
+
return 'needs-input';
|
|
48
|
+
case 'turn-ended':
|
|
49
|
+
if (event.backgroundWork === true)
|
|
50
|
+
return 'working';
|
|
51
|
+
return 'idle';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* True when `event` is a turn end that makes no background-work claim, arriving
|
|
56
|
+
* while the same session's turn end with background work is held. Such a report
|
|
57
|
+
* carries nothing new: Claude's 60 s `idle_prompt` (the second chance for a lost
|
|
58
|
+
* turn end) fires while the agent's own background task still runs, and must not
|
|
59
|
+
* end the background-work hold early. Real-session finding, Phase 8.
|
|
60
|
+
*/
|
|
61
|
+
function repeatsBackgroundTurnEnd(event, previous) {
|
|
62
|
+
return event.event === 'turn-ended'
|
|
63
|
+
&& event.backgroundWork === undefined
|
|
64
|
+
&& previous !== undefined
|
|
65
|
+
&& previous.sessionId === event.sessionId
|
|
66
|
+
&& previous.backgroundWork;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The needs-input detail for an accepted `needs-input` report. A report without
|
|
70
|
+
* a tool (the redundant permission notification names none) keeps the detail
|
|
71
|
+
* already held for the same episode.
|
|
72
|
+
*/
|
|
73
|
+
function detailFor(event, previous) {
|
|
74
|
+
const continuesEpisode = previous !== undefined
|
|
75
|
+
&& previous.sessionId === event.sessionId
|
|
76
|
+
&& previous.activity === 'needs-input';
|
|
77
|
+
if (continuesEpisode && previous.needsInput !== undefined && event.needsInput?.tool === undefined) {
|
|
78
|
+
return previous.needsInput;
|
|
79
|
+
}
|
|
80
|
+
return event.needsInput;
|
|
81
|
+
}
|
|
82
|
+
export class AgentStateStore extends EventEmitter {
|
|
83
|
+
now;
|
|
84
|
+
entries = new Map();
|
|
85
|
+
constructor(now = Date.now) {
|
|
86
|
+
super();
|
|
87
|
+
this.now = now;
|
|
88
|
+
}
|
|
89
|
+
/** The stored activity for an agent, or `undefined` when it has reported nothing. */
|
|
90
|
+
get(workspacePath, agentId) {
|
|
91
|
+
return this.entries.get(storeKey(workspacePath, agentId));
|
|
92
|
+
}
|
|
93
|
+
/** Apply one validated report for a resolved agent. */
|
|
94
|
+
apply(workspacePath, agentId, event) {
|
|
95
|
+
if (event.at > this.now() + MAX_FUTURE_SKEW_MS)
|
|
96
|
+
return 'future';
|
|
97
|
+
const key = storeKey(workspacePath, agentId);
|
|
98
|
+
const previous = this.entries.get(key);
|
|
99
|
+
if (previous !== undefined) {
|
|
100
|
+
if (event.at < previous.latestHookAt)
|
|
101
|
+
return 'stale';
|
|
102
|
+
if (event.sessionId !== previous.sessionId && event.at === previous.latestHookAt)
|
|
103
|
+
return 'stale';
|
|
104
|
+
}
|
|
105
|
+
if (previous !== undefined && repeatsBackgroundTurnEnd(event, previous)) {
|
|
106
|
+
// The hold and its served time stay; only the ordering watermark moves, so a
|
|
107
|
+
// delayed report older than this one is still ignored.
|
|
108
|
+
this.entries.set(key, { ...previous, latestHookAt: event.at });
|
|
109
|
+
return 'unchanged';
|
|
110
|
+
}
|
|
111
|
+
const activity = activityFor(event);
|
|
112
|
+
let activitySince = event.at;
|
|
113
|
+
if (previous !== undefined && previous.sessionId === event.sessionId && previous.activity === activity) {
|
|
114
|
+
activitySince = previous.activitySince;
|
|
115
|
+
}
|
|
116
|
+
const next = {
|
|
117
|
+
sessionId: event.sessionId,
|
|
118
|
+
activity,
|
|
119
|
+
activitySince,
|
|
120
|
+
reportedAt: event.at,
|
|
121
|
+
latestHookAt: event.at,
|
|
122
|
+
backgroundWork: event.event === 'turn-ended' && event.backgroundWork === true,
|
|
123
|
+
};
|
|
124
|
+
if (activity === 'needs-input') {
|
|
125
|
+
const detail = detailFor(event, previous);
|
|
126
|
+
if (detail !== undefined)
|
|
127
|
+
next.needsInput = detail;
|
|
128
|
+
}
|
|
129
|
+
this.entries.set(key, next);
|
|
130
|
+
const changed = previous === undefined
|
|
131
|
+
|| previous.activity !== next.activity
|
|
132
|
+
|| previous.reportedAt !== next.reportedAt
|
|
133
|
+
|| previous.backgroundWork !== next.backgroundWork
|
|
134
|
+
|| !sameDetail(previous.needsInput, next.needsInput);
|
|
135
|
+
if (!changed)
|
|
136
|
+
return 'unchanged';
|
|
137
|
+
const change = { workspacePath, agentId };
|
|
138
|
+
this.emit(AGENT_STATE_CHANGED, change);
|
|
139
|
+
return 'changed';
|
|
140
|
+
}
|
|
141
|
+
/** Every agent the store holds state for. */
|
|
142
|
+
agents() {
|
|
143
|
+
const agents = [];
|
|
144
|
+
for (const key of this.entries.keys()) {
|
|
145
|
+
const separator = key.indexOf('\0');
|
|
146
|
+
agents.push({ workspacePath: key.slice(0, separator), agentId: key.slice(separator + 1) });
|
|
147
|
+
}
|
|
148
|
+
return agents;
|
|
149
|
+
}
|
|
150
|
+
/** Forget an agent's reported state (it was removed). */
|
|
151
|
+
drop(workspacePath, agentId) {
|
|
152
|
+
this.entries.delete(storeKey(workspacePath, agentId));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/** Tower's one store. Nothing subscribes to its change event except the broadcaster. */
|
|
156
|
+
export const agentStateStore = new AgentStateStore();
|
|
157
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../src/agent-farm/servers/agent-state/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { KeyedSerializer } from '../write-queue.js';
|
|
2
|
+
export declare const DEFAULT_DECISIONS_FILE = "codev/state/pending-decisions.md";
|
|
3
|
+
/** How long the state flag may reuse a workspace's configured path. */
|
|
4
|
+
export declare const CONFIGURED_PATH_MEMO_MS = 5000;
|
|
5
|
+
export type DecisionsLog = (level: 'INFO' | 'ERROR' | 'WARN', message: string) => void;
|
|
6
|
+
export type ResolvedDecisionsPath = {
|
|
7
|
+
inside: true;
|
|
8
|
+
/** The symlink-resolved file the route reads and replaces. */
|
|
9
|
+
canonicalPath: string;
|
|
10
|
+
/** The configured path, relative to the workspace root, for display. */
|
|
11
|
+
displayPath: string;
|
|
12
|
+
/** Whether a regular file is there. */
|
|
13
|
+
exists: boolean;
|
|
14
|
+
} | {
|
|
15
|
+
inside: false;
|
|
16
|
+
displayPath: string;
|
|
17
|
+
canonicalPath: string;
|
|
18
|
+
};
|
|
19
|
+
/** At most one write per canonical decisions file runs at a time. */
|
|
20
|
+
export declare const decisionsWriteQueue: KeyedSerializer;
|
|
21
|
+
/**
|
|
22
|
+
* The workspace's configured decisions path (relative to its root). `fresh` reads the
|
|
23
|
+
* config now — the routes always do; otherwise a result up to
|
|
24
|
+
* {@link CONFIGURED_PATH_MEMO_MS} old is reused, because the state flag is polled every
|
|
25
|
+
* second by every open dashboard. The memo holds only the configured path (or the
|
|
26
|
+
* config error), never the decisions file's content. Throws the config error.
|
|
27
|
+
*/
|
|
28
|
+
export declare function configuredDecisionsPath(workspacePath: string, { fresh }: {
|
|
29
|
+
fresh: boolean;
|
|
30
|
+
}): string;
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the configured path against the workspace root. Both are canonicalized
|
|
33
|
+
* (symlinks followed; a missing target through its nearest existing ancestor), and a
|
|
34
|
+
* canonical target outside the canonical root is reported as `inside: false`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveDecisionsPath(workspacePath: string, configuredPath: string): Promise<ResolvedDecisionsPath>;
|
|
37
|
+
/**
|
|
38
|
+
* Whether the Decisions tab should show: the configured file exists inside the
|
|
39
|
+
* workspace. Uses the memoized configured path. A config error is logged and reads as
|
|
40
|
+
* false — it must never fail the state response; the decisions routes report it in full.
|
|
41
|
+
*/
|
|
42
|
+
export declare function decisionsFilePresent(workspacePath: string, log: DecisionsLog): Promise<boolean>;
|
|
43
|
+
/**
|
|
44
|
+
* Replace `target` with `text`: write a temporary file in the same directory with the
|
|
45
|
+
* target's permissions, fsync it, and rename it over the target. The temporary file is
|
|
46
|
+
* removed if any step fails, leaving the target untouched. `target` must be the
|
|
47
|
+
* canonical path, so a symlink pointing at it is left in place.
|
|
48
|
+
*/
|
|
49
|
+
export declare function writeFileAtomic(target: string, text: string): Promise<void>;
|
|
50
|
+
//# sourceMappingURL=file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../../../src/agent-farm/servers/decisions/file.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,eAAO,MAAM,sBAAsB,qCAAqC,CAAC;AAEzE,uEAAuE;AACvE,eAAO,MAAM,uBAAuB,OAAQ,CAAC;AAE7C,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAEvF,MAAM,MAAM,qBAAqB,GAC7B;IACE,MAAM,EAAE,IAAI,CAAC;IACb,8DAA8D;IAC9D,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,MAAM,EAAE,OAAO,CAAC;CACjB,GACD;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC;AAMlE,qEAAqE;AACrE,eAAO,MAAM,mBAAmB,iBAAwB,CAAC;AAkBzD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAWpG;AAuBD;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAWxH;AAKD;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAarG;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBjF"}
|