@cleocode/core 2026.3.57 → 2026.3.59
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/dist/agents/agent-registry.d.ts +206 -0
- package/dist/agents/agent-registry.d.ts.map +1 -0
- package/dist/agents/agent-schema.d.ts.map +1 -1
- package/dist/agents/execution-learning.d.ts +223 -0
- package/dist/agents/execution-learning.d.ts.map +1 -0
- package/dist/agents/health-monitor.d.ts +161 -0
- package/dist/agents/health-monitor.d.ts.map +1 -0
- package/dist/agents/index.d.ts +4 -1
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/retry.d.ts +57 -4
- package/dist/agents/retry.d.ts.map +1 -1
- package/dist/backfill/index.d.ts +83 -0
- package/dist/backfill/index.d.ts.map +1 -0
- package/dist/bootstrap.d.ts +1 -1
- package/dist/config.d.ts +47 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6985 -5068
- package/dist/index.js.map +4 -4
- package/dist/intelligence/adaptive-validation.d.ts +151 -0
- package/dist/intelligence/adaptive-validation.d.ts.map +1 -0
- package/dist/intelligence/impact.d.ts +34 -1
- package/dist/intelligence/impact.d.ts.map +1 -1
- package/dist/intelligence/index.d.ts +7 -2
- package/dist/intelligence/index.d.ts.map +1 -1
- package/dist/intelligence/types.d.ts +60 -0
- package/dist/intelligence/types.d.ts.map +1 -1
- package/dist/internal.d.ts +8 -4
- package/dist/internal.d.ts.map +1 -1
- package/dist/lib/index.d.ts +10 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/retry.d.ts +128 -0
- package/dist/lib/retry.d.ts.map +1 -0
- package/dist/nexus/sharing/index.d.ts +48 -2
- package/dist/nexus/sharing/index.d.ts.map +1 -1
- package/dist/sessions/session-enforcement.d.ts.map +1 -1
- package/dist/stats/index.d.ts +1 -0
- package/dist/stats/index.d.ts.map +1 -1
- package/dist/stats/workflow-telemetry.d.ts +89 -0
- package/dist/stats/workflow-telemetry.d.ts.map +1 -0
- package/dist/store/brain-schema.d.ts.map +1 -1
- package/dist/store/converters.d.ts.map +1 -1
- package/dist/store/cross-db-cleanup.d.ts +93 -0
- package/dist/store/cross-db-cleanup.d.ts.map +1 -0
- package/dist/store/db-helpers.d.ts.map +1 -1
- package/dist/store/migration-sqlite.d.ts.map +1 -1
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
- package/dist/store/sqlite.d.ts.map +1 -1
- package/dist/store/task-store.d.ts.map +1 -1
- package/dist/store/tasks-schema.d.ts +18 -3
- package/dist/store/tasks-schema.d.ts.map +1 -1
- package/dist/store/validation-schemas.d.ts +32 -0
- package/dist/store/validation-schemas.d.ts.map +1 -1
- package/dist/tasks/add.d.ts +10 -1
- package/dist/tasks/add.d.ts.map +1 -1
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/enforcement.d.ts +22 -0
- package/dist/tasks/enforcement.d.ts.map +1 -0
- package/dist/tasks/epic-enforcement.d.ts +199 -0
- package/dist/tasks/epic-enforcement.d.ts.map +1 -0
- package/dist/tasks/index.d.ts +1 -1
- package/dist/tasks/index.d.ts.map +1 -1
- package/dist/tasks/pipeline-stage.d.ts +181 -0
- package/dist/tasks/pipeline-stage.d.ts.map +1 -0
- package/dist/tasks/update.d.ts +2 -0
- package/dist/tasks/update.d.ts.map +1 -1
- package/migrations/drizzle-brain/20260321000001_t033-brain-indexes/migration.sql +12 -0
- package/migrations/drizzle-brain/20260321000001_t033-brain-indexes/snapshot.json +1232 -0
- package/migrations/drizzle-tasks/20260321000000_t033-connection-health/migration.sql +518 -0
- package/migrations/drizzle-tasks/20260321000000_t033-connection-health/snapshot.json +4312 -0
- package/migrations/drizzle-tasks/20260321000002_t060-pipeline-stage-binding/migration.sql +82 -0
- package/migrations/drizzle-tasks/20260321000002_t060-pipeline-stage-binding/snapshot.json +9 -0
- package/package.json +5 -5
- package/schemas/config.schema.json +37 -1547
- package/src/__tests__/sharing.test.ts +24 -0
- package/src/agents/__tests__/agent-registry.test.ts +351 -0
- package/src/agents/__tests__/execution-learning.test.ts +684 -0
- package/src/agents/__tests__/health-monitor.test.ts +332 -0
- package/src/agents/__tests__/registry.test.ts +30 -2
- package/src/agents/agent-registry.ts +394 -0
- package/src/agents/agent-schema.ts +5 -0
- package/src/agents/execution-learning.ts +675 -0
- package/src/agents/health-monitor.ts +279 -0
- package/src/agents/index.ts +37 -1
- package/src/agents/retry.ts +57 -4
- package/src/backfill/index.ts +309 -0
- package/src/bootstrap.ts +1 -1
- package/src/config.ts +126 -0
- package/src/index.ts +8 -1
- package/src/intelligence/__tests__/adaptive-validation.test.ts +694 -0
- package/src/intelligence/__tests__/impact.test.ts +165 -1
- package/src/intelligence/adaptive-validation.ts +764 -0
- package/src/intelligence/impact.ts +203 -0
- package/src/intelligence/index.ts +19 -0
- package/src/intelligence/types.ts +76 -0
- package/src/internal.ts +39 -0
- package/src/lib/__tests__/retry.test.ts +321 -0
- package/src/lib/index.ts +16 -0
- package/src/lib/retry.ts +224 -0
- package/src/lifecycle/__tests__/chain-store.test.ts +7 -0
- package/src/lifecycle/__tests__/tessera-engine.test.ts +52 -0
- package/src/nexus/sharing/index.ts +142 -2
- package/src/sessions/__tests__/session-edge-cases.test.ts +24 -1
- package/src/sessions/session-enforcement.ts +13 -2
- package/src/stats/index.ts +7 -0
- package/src/stats/workflow-telemetry.ts +502 -0
- package/src/store/__tests__/migration-safety.test.ts +3 -0
- package/src/store/__tests__/session-store.test.ts +132 -1
- package/src/store/__tests__/task-store.test.ts +22 -1
- package/src/store/__tests__/test-db-helper.ts +29 -2
- package/src/store/brain-schema.ts +4 -1
- package/src/store/converters.ts +2 -0
- package/src/store/cross-db-cleanup.ts +192 -0
- package/src/store/db-helpers.ts +2 -0
- package/src/store/migration-sqlite.ts +6 -0
- package/src/store/sqlite-data-accessor.ts +20 -28
- package/src/store/sqlite.ts +14 -2
- package/src/store/task-store.ts +6 -0
- package/src/store/tasks-schema.ts +59 -20
- package/src/tasks/__tests__/add.test.ts +16 -0
- package/src/tasks/__tests__/complete-unblocks.test.ts +10 -1
- package/src/tasks/__tests__/complete.test.ts +11 -2
- package/src/tasks/__tests__/epic-enforcement.test.ts +909 -0
- package/src/tasks/__tests__/minimal-test.test.ts +28 -0
- package/src/tasks/__tests__/pipeline-stage.test.ts +403 -0
- package/src/tasks/__tests__/update.test.ts +40 -6
- package/src/tasks/add.ts +128 -2
- package/src/tasks/complete.ts +29 -17
- package/src/tasks/enforcement.ts +127 -0
- package/src/tasks/epic-enforcement.ts +364 -0
- package/src/tasks/index.ts +1 -0
- package/src/tasks/pipeline-stage.ts +293 -0
- package/src/tasks/update.ts +62 -0
- package/templates/config.template.json +34 -111
- package/templates/global-config.template.json +24 -40
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent registry with capacity tracking for load balancing.
|
|
3
|
+
*
|
|
4
|
+
* Provides task-count-based capacity queries, specialization lookup,
|
|
5
|
+
* and performance recording on top of the existing `agent_instances` schema.
|
|
6
|
+
*
|
|
7
|
+
* Capacity model: each agent has a maximum of {@link MAX_TASKS_PER_AGENT}
|
|
8
|
+
* concurrent tasks. "Remaining capacity" is that constant minus the number of
|
|
9
|
+
* tasks currently assigned to an active agent instance.
|
|
10
|
+
*
|
|
11
|
+
* Specializations are stored as a `specializations` array inside the agent's
|
|
12
|
+
* `metadata_json` column. Use {@link updateAgentSpecializations} to write them.
|
|
13
|
+
*
|
|
14
|
+
* Performance recording delegates to the existing `recordAgentExecution`
|
|
15
|
+
* function in `execution-learning.ts` and wraps it with a simpler metrics
|
|
16
|
+
* interface suited for load-balancer callers.
|
|
17
|
+
*
|
|
18
|
+
* @module agents/agent-registry
|
|
19
|
+
* @task T041
|
|
20
|
+
* @epic T038
|
|
21
|
+
*/
|
|
22
|
+
import { type AgentInstanceRow, type AgentType } from './agent-schema.js';
|
|
23
|
+
import { type AgentExecutionOutcome } from './execution-learning.js';
|
|
24
|
+
/**
|
|
25
|
+
* Maximum number of tasks that can be concurrently assigned to one agent.
|
|
26
|
+
* Used as the upper bound for task-count-based capacity calculation.
|
|
27
|
+
*/
|
|
28
|
+
export declare const MAX_TASKS_PER_AGENT = 5;
|
|
29
|
+
/**
|
|
30
|
+
* Task-count-based capacity for a single agent instance.
|
|
31
|
+
*/
|
|
32
|
+
export interface AgentCapacity {
|
|
33
|
+
/** Agent instance ID. */
|
|
34
|
+
agentId: string;
|
|
35
|
+
/** Agent type classification. */
|
|
36
|
+
agentType: AgentType;
|
|
37
|
+
/** Current status of the agent. */
|
|
38
|
+
status: AgentInstanceRow['status'];
|
|
39
|
+
/** Number of tasks currently assigned to this agent. */
|
|
40
|
+
activeTasks: number;
|
|
41
|
+
/** Number of additional tasks this agent can accept (max - active). */
|
|
42
|
+
remainingCapacity: number;
|
|
43
|
+
/** Maximum tasks this agent can hold ({@link MAX_TASKS_PER_AGENT}). */
|
|
44
|
+
maxCapacity: number;
|
|
45
|
+
/** Whether this agent can accept new tasks. */
|
|
46
|
+
available: boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Metrics provided when recording agent performance.
|
|
50
|
+
*/
|
|
51
|
+
export interface AgentPerformanceMetrics {
|
|
52
|
+
/** Task ID that was processed. */
|
|
53
|
+
taskId: string;
|
|
54
|
+
/** Task type label (e.g. "epic", "task", "subtask"). */
|
|
55
|
+
taskType: string;
|
|
56
|
+
/** Outcome of the agent's work on the task. */
|
|
57
|
+
outcome: AgentExecutionOutcome;
|
|
58
|
+
/** Optional task labels for richer pattern classification. */
|
|
59
|
+
taskLabels?: string[];
|
|
60
|
+
/** Session ID the agent was operating under. */
|
|
61
|
+
sessionId?: string;
|
|
62
|
+
/** Duration of execution in milliseconds. */
|
|
63
|
+
durationMs?: number;
|
|
64
|
+
/** Error message if outcome is "failure". */
|
|
65
|
+
errorMessage?: string;
|
|
66
|
+
/** Error classification if outcome is "failure". */
|
|
67
|
+
errorType?: 'retriable' | 'permanent' | 'unknown';
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get task-count-based remaining capacity for an agent.
|
|
71
|
+
*
|
|
72
|
+
* Remaining capacity = {@link MAX_TASKS_PER_AGENT} minus the number of tasks
|
|
73
|
+
* currently routed to this agent instance (tracked via the `task_id` column
|
|
74
|
+
* on `agent_instances` — each instance handles one task at a time; child agents
|
|
75
|
+
* spawned by an orchestrator appear as sibling rows referencing the same
|
|
76
|
+
* `parent_agent_id`).
|
|
77
|
+
*
|
|
78
|
+
* For capacity purposes the "active tasks" count is derived from the number of
|
|
79
|
+
* non-terminal sibling rows that share the same `parent_agent_id` as this
|
|
80
|
+
* agent, plus 1 for the agent's own current task when `task_id` is set.
|
|
81
|
+
*
|
|
82
|
+
* @remarks
|
|
83
|
+
* Agents in terminal states (`stopped`, `crashed`) always return 0 remaining
|
|
84
|
+
* capacity because they cannot accept work.
|
|
85
|
+
*
|
|
86
|
+
* @param agentId - Agent instance ID (agt_...) to check
|
|
87
|
+
* @param cwd - Working directory used to resolve tasks.db path
|
|
88
|
+
* @returns Capacity breakdown or null if the agent does not exist
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* const cap = await getAgentCapacity('agt_20260321120000_ab12cd', '/project');
|
|
93
|
+
* if (cap && cap.available) {
|
|
94
|
+
* console.log(`Agent can take ${cap.remainingCapacity} more tasks`);
|
|
95
|
+
* }
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export declare function getAgentCapacity(agentId: string, cwd?: string): Promise<AgentCapacity | null>;
|
|
99
|
+
/**
|
|
100
|
+
* List all non-terminal agents sorted by remaining task capacity (descending).
|
|
101
|
+
*
|
|
102
|
+
* Returns agents with the most available slots first, enabling callers to
|
|
103
|
+
* select the least-loaded agent for new work assignment.
|
|
104
|
+
*
|
|
105
|
+
* @remarks
|
|
106
|
+
* Only agents in `active` or `idle` states are included — `starting` agents
|
|
107
|
+
* are excluded because they may not yet be ready to accept work.
|
|
108
|
+
* Terminal agents (`stopped`, `crashed`) are always omitted.
|
|
109
|
+
*
|
|
110
|
+
* @param agentType - Optional filter to limit results to one agent type
|
|
111
|
+
* @param cwd - Working directory used to resolve tasks.db path
|
|
112
|
+
* @returns Array of capacity entries sorted highest remaining capacity first
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* const agents = await getAgentsByCapacity('executor', '/project');
|
|
117
|
+
* const best = agents[0]; // most available slots
|
|
118
|
+
* if (best && best.available) {
|
|
119
|
+
* await assignTask(best.agentId, taskId);
|
|
120
|
+
* }
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
export declare function getAgentsByCapacity(agentType?: AgentType, cwd?: string): Promise<AgentCapacity[]>;
|
|
124
|
+
/**
|
|
125
|
+
* Get the specialization/skills list for an agent.
|
|
126
|
+
*
|
|
127
|
+
* Specializations are stored as a string array under the `specializations`
|
|
128
|
+
* key in the agent's `metadata_json` column. An empty array is returned when
|
|
129
|
+
* the field is absent or the agent is not found.
|
|
130
|
+
*
|
|
131
|
+
* @remarks
|
|
132
|
+
* Write specializations with {@link updateAgentSpecializations} when
|
|
133
|
+
* registering or updating an agent. The metadata column is a free-form JSON
|
|
134
|
+
* blob — specializations are one namespaced key inside it.
|
|
135
|
+
*
|
|
136
|
+
* @param agentId - Agent instance ID (agt_...)
|
|
137
|
+
* @param cwd - Working directory used to resolve tasks.db path
|
|
138
|
+
* @returns Array of specialization strings (empty if none recorded)
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* const skills = await getAgentSpecializations('agt_20260321120000_ab12cd', '/project');
|
|
143
|
+
* // ['typescript', 'testing', 'documentation']
|
|
144
|
+
* if (skills.includes('typescript')) {
|
|
145
|
+
* console.log('Agent can handle TypeScript tasks');
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
export declare function getAgentSpecializations(agentId: string, cwd?: string): Promise<string[]>;
|
|
150
|
+
/**
|
|
151
|
+
* Update the specializations list stored in an agent's metadata.
|
|
152
|
+
*
|
|
153
|
+
* Merges the new list into the existing `metadata_json` object, preserving
|
|
154
|
+
* any other keys already present. Returns the updated specializations list,
|
|
155
|
+
* or null if the agent was not found.
|
|
156
|
+
*
|
|
157
|
+
* @remarks
|
|
158
|
+
* This is a write-side companion to {@link getAgentSpecializations}. Call it
|
|
159
|
+
* after {@link registerAgent} to record the skills an agent was spawned with.
|
|
160
|
+
*
|
|
161
|
+
* @param agentId - Agent instance ID (agt_...)
|
|
162
|
+
* @param specializations - New specializations list (replaces existing)
|
|
163
|
+
* @param cwd - Working directory used to resolve tasks.db path
|
|
164
|
+
* @returns Updated specializations list, or null if agent not found
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* await updateAgentSpecializations(
|
|
169
|
+
* 'agt_20260321120000_ab12cd',
|
|
170
|
+
* ['typescript', 'testing'],
|
|
171
|
+
* '/project',
|
|
172
|
+
* );
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
export declare function updateAgentSpecializations(agentId: string, specializations: string[], cwd?: string): Promise<string[] | null>;
|
|
176
|
+
/**
|
|
177
|
+
* Record agent performance metrics to the BRAIN execution history.
|
|
178
|
+
*
|
|
179
|
+
* Translates a simplified {@link AgentPerformanceMetrics} object into the
|
|
180
|
+
* {@link AgentExecutionEvent} format expected by `execution-learning.ts` and
|
|
181
|
+
* delegates to {@link recordAgentExecution}. The agent type is resolved from
|
|
182
|
+
* the `agent_instances` table so callers only need to supply the agent ID.
|
|
183
|
+
*
|
|
184
|
+
* @remarks
|
|
185
|
+
* Recording is best-effort — if brain.db is unavailable the error is swallowed
|
|
186
|
+
* and null is returned, consistent with the rest of the execution-learning
|
|
187
|
+
* module. Agent lifecycle code is never disrupted by a brain write failure.
|
|
188
|
+
*
|
|
189
|
+
* @param agentId - Agent instance ID whose performance is being recorded
|
|
190
|
+
* @param metrics - Performance metrics for the task that was processed
|
|
191
|
+
* @param cwd - Working directory used to resolve tasks.db and brain.db paths
|
|
192
|
+
* @returns The brain decision ID if recorded, null on failure or not found
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```ts
|
|
196
|
+
* const decisionId = await recordAgentPerformance('agt_20260321120000_ab12cd', {
|
|
197
|
+
* taskId: 'T041',
|
|
198
|
+
* taskType: 'task',
|
|
199
|
+
* outcome: 'success',
|
|
200
|
+
* durationMs: 4200,
|
|
201
|
+
* sessionId: 'ses_20260321_abc',
|
|
202
|
+
* }, '/project');
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
export declare function recordAgentPerformance(agentId: string, metrics: AgentPerformanceMetrics, cwd?: string): Promise<string | null>;
|
|
206
|
+
//# sourceMappingURL=agent-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-registry.d.ts","sourceRoot":"","sources":["../../src/agents/agent-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,SAAS,EAAkB,MAAM,mBAAmB,CAAC;AAC1F,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,yBAAyB,CAAC;AAOjC;;;GAGG;AACH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAMrC;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,SAAS,EAAE,SAAS,CAAC;IACrB,mCAAmC;IACnC,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACnC,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,OAAO,EAAE,qBAAqB,CAAC;IAC/B,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,SAAS,CAAC,EAAE,WAAW,GAAG,WAAW,GAAG,SAAS,CAAC;CACnD;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA+C/B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,CAAC,EAAE,SAAS,EACrB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,aAAa,EAAE,CAAC,CAc1B;AAiBD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAkB9F;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,EAAE,EACzB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAwB1B;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,uBAAuB,EAChC,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAyBxB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-schema.d.ts","sourceRoot":"","sources":["../../src/agents/agent-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,iEAAiE;AACjE,eAAO,MAAM,uBAAuB,wEAO1B,CAAC;AAEX,4CAA4C;AAC5C,eAAO,MAAM,WAAW,uGAQd,CAAC;AAMX,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"agent-schema.d.ts","sourceRoot":"","sources":["../../src/agents/agent-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,iEAAiE;AACjE,eAAO,MAAM,uBAAuB,wEAO1B,CAAC;AAEX,4CAA4C;AAC5C,eAAO,MAAM,WAAW,uGAQd,CAAC;AAMX,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8B1B,CAAC;AAMF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBzB,CAAC;AAMF,MAAM,MAAM,gBAAgB,GAAG,OAAO,cAAc,CAAC,YAAY,CAAC;AAClE,MAAM,MAAM,mBAAmB,GAAG,OAAO,cAAc,CAAC,YAAY,CAAC;AACrE,MAAM,MAAM,gBAAgB,GAAG,OAAO,aAAa,CAAC,YAAY,CAAC;AACjE,MAAM,MAAM,mBAAmB,GAAG,OAAO,aAAa,CAAC,YAAY,CAAC;AACpE,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAC3E,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AACrD,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,WAAW,GAAG,SAAS,CAAC"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Execution Learning — Agent dimension BRAIN integration.
|
|
3
|
+
*
|
|
4
|
+
* Tracks which agent types succeed or fail on which task types, logs agent
|
|
5
|
+
* decisions to brain_decisions with structured context, provides queries to
|
|
6
|
+
* retrieve agent performance history, and implements basic self-healing by
|
|
7
|
+
* recording failure patterns as brain_observations and surfacing healing
|
|
8
|
+
* suggestions when the same failure pattern recurs.
|
|
9
|
+
*
|
|
10
|
+
* This module bridges the agent registry (tasks.db) with the cognitive
|
|
11
|
+
* memory layer (brain.db) without introducing circular dependencies:
|
|
12
|
+
* - Tasks.db agent tables: agent_instances, agent_error_log (agent-schema.ts)
|
|
13
|
+
* - Brain.db tables: brain_decisions, brain_patterns, brain_observations
|
|
14
|
+
*
|
|
15
|
+
* All brain.db writes are best-effort — failures are silently swallowed so
|
|
16
|
+
* agent lifecycle events never fail due to a brain.db write error.
|
|
17
|
+
*
|
|
18
|
+
* @module agents/execution-learning
|
|
19
|
+
* @task T034
|
|
20
|
+
* @epic T029
|
|
21
|
+
*/
|
|
22
|
+
import type { BrainDataAccessor } from '../store/brain-accessor.js';
|
|
23
|
+
import type { BrainDecisionRow, BrainObservationRow, BrainPatternRow } from '../store/brain-schema.js';
|
|
24
|
+
import type { AgentType } from './agent-schema.js';
|
|
25
|
+
/**
|
|
26
|
+
* The outcome of an agent's execution attempt on a task.
|
|
27
|
+
*/
|
|
28
|
+
export type AgentExecutionOutcome = 'success' | 'failure' | 'partial';
|
|
29
|
+
/**
|
|
30
|
+
* Context recorded when an agent completes or fails a task.
|
|
31
|
+
*/
|
|
32
|
+
export interface AgentExecutionEvent {
|
|
33
|
+
/** Agent instance ID (agt_...). */
|
|
34
|
+
agentId: string;
|
|
35
|
+
/** Agent type classification. */
|
|
36
|
+
agentType: AgentType;
|
|
37
|
+
/** Task ID that was attempted. */
|
|
38
|
+
taskId: string;
|
|
39
|
+
/** Task type: 'epic' | 'task' | 'subtask'. */
|
|
40
|
+
taskType: string;
|
|
41
|
+
/** Task labels for richer pattern classification. */
|
|
42
|
+
taskLabels?: string[];
|
|
43
|
+
/** Execution outcome. */
|
|
44
|
+
outcome: AgentExecutionOutcome;
|
|
45
|
+
/** Error message if outcome is 'failure'. */
|
|
46
|
+
errorMessage?: string;
|
|
47
|
+
/** Error classification if outcome is 'failure'. */
|
|
48
|
+
errorType?: 'retriable' | 'permanent' | 'unknown';
|
|
49
|
+
/** Session ID the agent was running under. */
|
|
50
|
+
sessionId?: string;
|
|
51
|
+
/** Duration of execution in milliseconds (optional). */
|
|
52
|
+
durationMs?: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Summary of an agent type's execution performance on a task type.
|
|
56
|
+
*/
|
|
57
|
+
export interface AgentPerformanceSummary {
|
|
58
|
+
/** Agent type. */
|
|
59
|
+
agentType: AgentType;
|
|
60
|
+
/** Task type this summary is for. */
|
|
61
|
+
taskType: string;
|
|
62
|
+
/** Total execution attempts tracked. */
|
|
63
|
+
totalAttempts: number;
|
|
64
|
+
/** Number of successful attempts. */
|
|
65
|
+
successCount: number;
|
|
66
|
+
/** Number of failed attempts. */
|
|
67
|
+
failureCount: number;
|
|
68
|
+
/** Success rate [0.0 – 1.0]. */
|
|
69
|
+
successRate: number;
|
|
70
|
+
/** Most recent attempt outcome. */
|
|
71
|
+
lastOutcome: AgentExecutionOutcome | null;
|
|
72
|
+
/** Timestamp of the most recent tracked decision. */
|
|
73
|
+
lastSeenAt: string | null;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* A self-healing suggestion derived from failure pattern history.
|
|
77
|
+
*/
|
|
78
|
+
export interface HealingSuggestion {
|
|
79
|
+
/** Pattern ID from brain_patterns. */
|
|
80
|
+
patternId: string;
|
|
81
|
+
/** Human-readable description of the failure pattern. */
|
|
82
|
+
failurePattern: string;
|
|
83
|
+
/** Times this pattern has been seen. */
|
|
84
|
+
frequency: number;
|
|
85
|
+
/** Mitigation / suggested next action. */
|
|
86
|
+
suggestion: string;
|
|
87
|
+
/** How confident the system is in this suggestion [0.0 – 1.0]. */
|
|
88
|
+
confidence: number;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Record an agent execution event to brain_decisions.
|
|
92
|
+
*
|
|
93
|
+
* Each event becomes a `tactical` decision entry describing which agent type
|
|
94
|
+
* handled which task type and whether it succeeded. This gives the BRAIN
|
|
95
|
+
* system a queryable history of agent-task execution for pattern extraction.
|
|
96
|
+
*
|
|
97
|
+
* The call is best-effort — if brain.db is unavailable the error is swallowed
|
|
98
|
+
* and null is returned so agent lifecycle code is never disrupted.
|
|
99
|
+
*
|
|
100
|
+
* @param event - Execution event to record
|
|
101
|
+
* @param cwd - Working directory (resolves brain.db path)
|
|
102
|
+
* @returns The stored decision row, or null on failure
|
|
103
|
+
*/
|
|
104
|
+
export declare function recordAgentExecution(event: AgentExecutionEvent, cwd?: string): Promise<BrainDecisionRow | null>;
|
|
105
|
+
/**
|
|
106
|
+
* Internal implementation that accepts a pre-constructed accessor.
|
|
107
|
+
* Separated for testability without touching the real file system.
|
|
108
|
+
*
|
|
109
|
+
* @internal
|
|
110
|
+
*/
|
|
111
|
+
export declare function _recordAgentExecutionWithAccessor(event: AgentExecutionEvent, brain: BrainDataAccessor): Promise<BrainDecisionRow | null>;
|
|
112
|
+
/**
|
|
113
|
+
* Retrieve agent execution performance history from brain_decisions.
|
|
114
|
+
*
|
|
115
|
+
* Queries all `tactical` decisions recorded by `recordAgentExecution` and
|
|
116
|
+
* aggregates them into per-(agentType, taskType) performance summaries.
|
|
117
|
+
*
|
|
118
|
+
* @param filters - Optional filters to narrow results
|
|
119
|
+
* @param cwd - Working directory
|
|
120
|
+
* @returns Array of performance summaries sorted by agentType then taskType
|
|
121
|
+
*/
|
|
122
|
+
export declare function getAgentPerformanceHistory(filters?: {
|
|
123
|
+
agentType?: AgentType;
|
|
124
|
+
taskType?: string;
|
|
125
|
+
limit?: number;
|
|
126
|
+
}, cwd?: string): Promise<AgentPerformanceSummary[]>;
|
|
127
|
+
/**
|
|
128
|
+
* Internal implementation with injected accessor for testability.
|
|
129
|
+
*
|
|
130
|
+
* @internal
|
|
131
|
+
*/
|
|
132
|
+
export declare function _getAgentPerformanceHistoryWithAccessor(filters: {
|
|
133
|
+
agentType?: AgentType;
|
|
134
|
+
taskType?: string;
|
|
135
|
+
limit?: number;
|
|
136
|
+
}, brain: BrainDataAccessor): Promise<AgentPerformanceSummary[]>;
|
|
137
|
+
/**
|
|
138
|
+
* Record a task failure pattern to brain_patterns.
|
|
139
|
+
*
|
|
140
|
+
* When a task fails, the (agentType, taskType, errorType) combination is
|
|
141
|
+
* stored as a `failure` pattern in brain.db. On subsequent failures matching
|
|
142
|
+
* the same combination, the frequency counter is incremented and the success
|
|
143
|
+
* rate updated. This data is what powers `getSelfHealingSuggestions`.
|
|
144
|
+
*
|
|
145
|
+
* The call is best-effort and never throws.
|
|
146
|
+
*
|
|
147
|
+
* @param event - A failure execution event (outcome must be 'failure')
|
|
148
|
+
* @param cwd - Working directory
|
|
149
|
+
* @returns The upserted pattern row, or null on error
|
|
150
|
+
*/
|
|
151
|
+
export declare function recordFailurePattern(event: AgentExecutionEvent, cwd?: string): Promise<BrainPatternRow | null>;
|
|
152
|
+
/**
|
|
153
|
+
* Internal implementation with injected accessor.
|
|
154
|
+
*
|
|
155
|
+
* @internal
|
|
156
|
+
*/
|
|
157
|
+
export declare function _recordFailurePatternWithAccessor(event: AgentExecutionEvent, brain: BrainDataAccessor): Promise<BrainPatternRow | null>;
|
|
158
|
+
/**
|
|
159
|
+
* Store a healing strategy observation to brain_observations.
|
|
160
|
+
*
|
|
161
|
+
* When a failure pattern reaches a significant frequency threshold (≥ 3),
|
|
162
|
+
* a `change` observation is recorded to represent the healing action
|
|
163
|
+
* recommended for future recurrences of the same pattern.
|
|
164
|
+
*
|
|
165
|
+
* The call is best-effort and never throws.
|
|
166
|
+
*
|
|
167
|
+
* @param event - The failure event that triggered healing
|
|
168
|
+
* @param strategy - Human-readable healing strategy description
|
|
169
|
+
* @param cwd - Working directory
|
|
170
|
+
* @returns The stored observation row, or null on error
|
|
171
|
+
*/
|
|
172
|
+
export declare function storeHealingStrategy(event: AgentExecutionEvent, strategy: string, cwd?: string): Promise<BrainObservationRow | null>;
|
|
173
|
+
/**
|
|
174
|
+
* Internal implementation with injected accessor.
|
|
175
|
+
*
|
|
176
|
+
* @internal
|
|
177
|
+
*/
|
|
178
|
+
export declare function _storeHealingStrategyWithAccessor(event: AgentExecutionEvent, strategy: string, brain: BrainDataAccessor): Promise<BrainObservationRow | null>;
|
|
179
|
+
/**
|
|
180
|
+
* Get self-healing suggestions for a given agent type and task type.
|
|
181
|
+
*
|
|
182
|
+
* Queries brain_patterns for known failure patterns matching the
|
|
183
|
+
* (agentType, taskType) combination and returns healing suggestions
|
|
184
|
+
* ordered by frequency (most-seen first).
|
|
185
|
+
*
|
|
186
|
+
* Returns an empty array if no failure patterns are found or brain.db
|
|
187
|
+
* is unavailable.
|
|
188
|
+
*
|
|
189
|
+
* @param agentType - The agent type to check
|
|
190
|
+
* @param taskType - The task type to check
|
|
191
|
+
* @param cwd - Working directory
|
|
192
|
+
* @returns Array of healing suggestions, highest frequency first
|
|
193
|
+
*/
|
|
194
|
+
export declare function getSelfHealingSuggestions(agentType: AgentType, taskType: string, cwd?: string): Promise<HealingSuggestion[]>;
|
|
195
|
+
/**
|
|
196
|
+
* Internal implementation with injected accessor.
|
|
197
|
+
*
|
|
198
|
+
* @internal
|
|
199
|
+
*/
|
|
200
|
+
export declare function _getSelfHealingSuggestionsWithAccessor(agentType: AgentType, taskType: string, brain: BrainDataAccessor): Promise<HealingSuggestion[]>;
|
|
201
|
+
/**
|
|
202
|
+
* Full agent lifecycle event processor.
|
|
203
|
+
*
|
|
204
|
+
* Convenience function that:
|
|
205
|
+
* 1. Records the execution event to brain_decisions
|
|
206
|
+
* 2. On failure: records/updates the failure pattern in brain_patterns
|
|
207
|
+
* 3. On failure with frequency ≥ 3: stores a healing strategy observation
|
|
208
|
+
*
|
|
209
|
+
* Returns a structured result with the recorded IDs and any healing
|
|
210
|
+
* suggestions that now apply.
|
|
211
|
+
*
|
|
212
|
+
* All operations are best-effort — the call never throws.
|
|
213
|
+
*
|
|
214
|
+
* @param event - The execution event
|
|
215
|
+
* @param cwd - Working directory
|
|
216
|
+
*/
|
|
217
|
+
export declare function processAgentLifecycleEvent(event: AgentExecutionEvent, cwd?: string): Promise<{
|
|
218
|
+
decisionId: string | null;
|
|
219
|
+
patternId: string | null;
|
|
220
|
+
observationId: string | null;
|
|
221
|
+
healingSuggestions: HealingSuggestion[];
|
|
222
|
+
}>;
|
|
223
|
+
//# sourceMappingURL=execution-learning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-learning.d.ts","sourceRoot":"","sources":["../../src/agents/execution-learning.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Health Monitoring -- Heartbeat and crash detection for live agent instances.
|
|
3
|
+
*
|
|
4
|
+
* Provides the public-facing health API specified by T039:
|
|
5
|
+
* - `recordHeartbeat` — update last_heartbeat for a live agent
|
|
6
|
+
* - `checkAgentHealth` — check health of a specific agent by ID
|
|
7
|
+
* - `detectStaleAgents` — find agents whose heartbeat is older than threshold
|
|
8
|
+
* - `detectCrashedAgents` — find active agents with no heartbeat for >3 min
|
|
9
|
+
*
|
|
10
|
+
* These functions delegate to the lower-level `registry.ts` primitives
|
|
11
|
+
* (`heartbeat`, `checkAgentHealth`, `listAgentInstances`) and add the
|
|
12
|
+
* named, task-spec-aligned surface required for T039.
|
|
13
|
+
*
|
|
14
|
+
* @module agents/health-monitor
|
|
15
|
+
* @task T039
|
|
16
|
+
* @epic T038
|
|
17
|
+
*/
|
|
18
|
+
import type { AgentInstanceRow, AgentInstanceStatus } from './agent-schema.js';
|
|
19
|
+
/** Default heartbeat interval (30 seconds) per BRAIN spec. */
|
|
20
|
+
export declare const HEARTBEAT_INTERVAL_MS = 30000;
|
|
21
|
+
/** Default staleness threshold: 3 minutes without a heartbeat. */
|
|
22
|
+
export declare const STALE_THRESHOLD_MS: number;
|
|
23
|
+
/**
|
|
24
|
+
* Health status of a specific agent instance.
|
|
25
|
+
*/
|
|
26
|
+
export interface AgentHealthStatus {
|
|
27
|
+
/** Agent instance ID. */
|
|
28
|
+
agentId: string;
|
|
29
|
+
/** Current DB status. */
|
|
30
|
+
status: AgentInstanceStatus;
|
|
31
|
+
/** ISO timestamp of the last recorded heartbeat. */
|
|
32
|
+
lastHeartbeat: string;
|
|
33
|
+
/** Milliseconds since the last heartbeat (at call time). */
|
|
34
|
+
heartbeatAgeMs: number;
|
|
35
|
+
/** Whether the agent is considered healthy (heartbeat within threshold). */
|
|
36
|
+
healthy: boolean;
|
|
37
|
+
/** Whether the agent is considered stale (heartbeat older than threshold). */
|
|
38
|
+
stale: boolean;
|
|
39
|
+
/** Threshold used for staleness determination (ms). */
|
|
40
|
+
thresholdMs: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Record a heartbeat for an agent instance.
|
|
44
|
+
*
|
|
45
|
+
* Updates `last_heartbeat` to the current time and returns the agent's
|
|
46
|
+
* current {@link AgentInstanceStatus}. Returns `null` if the agent does not
|
|
47
|
+
* exist or is already in a terminal state (`stopped` / `crashed`).
|
|
48
|
+
*
|
|
49
|
+
* This is the primary mechanism by which long-running agents signal liveness.
|
|
50
|
+
* Call this every {@link HEARTBEAT_INTERVAL_MS} (30 s) from the agent loop.
|
|
51
|
+
*
|
|
52
|
+
* @param agentId - The agent instance ID (e.g. `agt_20260322120000_a1b2c3`)
|
|
53
|
+
* @param cwd - Working directory used to resolve the tasks.db path (optional)
|
|
54
|
+
* @returns The agent's current status, or `null` if not found / terminal
|
|
55
|
+
*
|
|
56
|
+
* @remarks
|
|
57
|
+
* Terminal agents (`stopped`, `crashed`) will NOT have their heartbeat
|
|
58
|
+
* updated — the existing status is returned as-is so callers can detect
|
|
59
|
+
* external shutdown signals.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* // Inside the agent's main loop:
|
|
64
|
+
* const heartbeatTimer = setInterval(async () => {
|
|
65
|
+
* const status = await recordHeartbeat(agentId);
|
|
66
|
+
* if (status === 'stopped' || status === null) {
|
|
67
|
+
* // Orchestrator shut us down — exit cleanly
|
|
68
|
+
* clearInterval(heartbeatTimer);
|
|
69
|
+
* process.exit(0);
|
|
70
|
+
* }
|
|
71
|
+
* }, HEARTBEAT_INTERVAL_MS);
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare function recordHeartbeat(agentId: string, cwd?: string): Promise<AgentInstanceStatus | null>;
|
|
75
|
+
/**
|
|
76
|
+
* Check the health of a specific agent instance by ID.
|
|
77
|
+
*
|
|
78
|
+
* Queries the agent's current record and returns a structured
|
|
79
|
+
* {@link AgentHealthStatus} describing staleness, heartbeat age, and
|
|
80
|
+
* whether the agent is considered healthy relative to `thresholdMs`.
|
|
81
|
+
*
|
|
82
|
+
* Returns `null` if the agent ID is not found in the database.
|
|
83
|
+
*
|
|
84
|
+
* @param agentId - The agent instance ID to check
|
|
85
|
+
* @param thresholdMs - Staleness threshold in milliseconds (default: 3 minutes)
|
|
86
|
+
* @param cwd - Working directory used to resolve the tasks.db path (optional)
|
|
87
|
+
* @returns {@link AgentHealthStatus} or `null` if the agent does not exist
|
|
88
|
+
*
|
|
89
|
+
* @remarks
|
|
90
|
+
* Returns null if the agent is not found. A non-null result includes
|
|
91
|
+
* staleness status based on the threshold comparison.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* const health = await checkAgentHealth('agt_20260322120000_a1b2c3');
|
|
96
|
+
* if (health && health.stale) {
|
|
97
|
+
* console.log(`Agent stale for ${health.heartbeatAgeMs}ms — presumed crashed`);
|
|
98
|
+
* }
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export declare function checkAgentHealth(agentId: string, thresholdMs?: number, cwd?: string): Promise<AgentHealthStatus | null>;
|
|
102
|
+
/**
|
|
103
|
+
* Find all non-terminal agents whose last heartbeat is older than `thresholdMs`.
|
|
104
|
+
*
|
|
105
|
+
* "Stale" means an agent with status `starting`, `active`, or `idle` has
|
|
106
|
+
* not sent a heartbeat within the threshold window. This is a precursor to
|
|
107
|
+
* crash detection — a stale agent may still recover if it is under heavy load.
|
|
108
|
+
*
|
|
109
|
+
* Agents with status `stopped` or `crashed` are excluded — they are already
|
|
110
|
+
* in a terminal state and do not participate in the heartbeat protocol.
|
|
111
|
+
*
|
|
112
|
+
* @param thresholdMs - Staleness threshold in ms (default: 3 minutes / 180 000 ms)
|
|
113
|
+
* @param cwd - Working directory used to resolve the tasks.db path (optional)
|
|
114
|
+
* @returns Array of {@link AgentHealthStatus} for each stale agent, sorted by
|
|
115
|
+
* heartbeat age descending (most-stale first)
|
|
116
|
+
*
|
|
117
|
+
* @remarks
|
|
118
|
+
* The default threshold matches the crash-detection window specified in T039:
|
|
119
|
+
* "timeout detection after 3 minutes".
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* const stale = await detectStaleAgents();
|
|
124
|
+
* for (const s of stale) {
|
|
125
|
+
* console.log(`${s.agentId} has been stale for ${s.heartbeatAgeMs / 1000}s`);
|
|
126
|
+
* }
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export declare function detectStaleAgents(thresholdMs?: number, cwd?: string): Promise<AgentHealthStatus[]>;
|
|
130
|
+
/**
|
|
131
|
+
* Find agents with status `active` whose heartbeat has been silent for
|
|
132
|
+
* longer than `thresholdMs`, and mark them as `crashed` in the database.
|
|
133
|
+
*
|
|
134
|
+
* An agent is considered crashed when it:
|
|
135
|
+
* 1. Has status `active` (not `idle`, `starting`, `stopped`, or `crashed`)
|
|
136
|
+
* 2. Has not sent a heartbeat for longer than `thresholdMs`
|
|
137
|
+
*
|
|
138
|
+
* Each detected agent is immediately marked `crashed` via {@link markCrashed},
|
|
139
|
+
* incrementing its error count and writing a reason to `agent_error_log`.
|
|
140
|
+
*
|
|
141
|
+
* @param thresholdMs - Crash threshold in ms (default: 3 minutes / 180 000 ms)
|
|
142
|
+
* @param cwd - Working directory used to resolve the tasks.db path (optional)
|
|
143
|
+
* @returns Array of agent instance rows for each agent that was just marked
|
|
144
|
+
* `crashed`, sorted by last heartbeat ascending (oldest first).
|
|
145
|
+
*
|
|
146
|
+
* @remarks
|
|
147
|
+
* This function is WRITE-side: it mutates the database. Callers should run
|
|
148
|
+
* it on a schedule (e.g. every 60 s) from an orchestrator or health watchdog.
|
|
149
|
+
* For a read-only view, use {@link detectStaleAgents} instead.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```ts
|
|
153
|
+
* // Inside an orchestrator health watchdog:
|
|
154
|
+
* const crashed = await detectCrashedAgents();
|
|
155
|
+
* if (crashed.length > 0) {
|
|
156
|
+
* logger.warn({ crashed: crashed.map(a => a.id) }, 'Agents marked crashed');
|
|
157
|
+
* }
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
export declare function detectCrashedAgents(thresholdMs?: number, cwd?: string): Promise<AgentInstanceRow[]>;
|
|
161
|
+
//# sourceMappingURL=health-monitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health-monitor.d.ts","sourceRoot":"","sources":["../../src/agents/health-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAO/E,8DAA8D;AAC9D,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAE5C,kEAAkE;AAClE,eAAO,MAAM,kBAAkB,QAAa,CAAC;AAS7C;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,oDAAoD;IACpD,aAAa,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,cAAc,EAAE,MAAM,CAAC;IACvB,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,KAAK,EAAE,OAAO,CAAC;IACf,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;CACrB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAErC;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAA2B,EACxC,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAMnC;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,GAAE,MAA2B,EACxC,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAO9B;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,GAAE,MAA2B,EACxC,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA6B7B"}
|
package/dist/agents/index.d.ts
CHANGED
|
@@ -10,8 +10,11 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @module agents
|
|
12
12
|
*/
|
|
13
|
+
export { type AgentCapacity, type AgentPerformanceMetrics, getAgentCapacity, getAgentSpecializations, getAgentsByCapacity, MAX_TASKS_PER_AGENT, recordAgentPerformance, updateAgentSpecializations, } from './agent-registry.js';
|
|
13
14
|
export { AGENT_INSTANCE_STATUSES, AGENT_TYPES, type AgentErrorLogRow, type AgentErrorType, type AgentInstanceRow, type AgentInstanceStatus, type AgentType, agentErrorLog, agentInstances, type NewAgentErrorLogRow, type NewAgentInstanceRow, } from './agent-schema.js';
|
|
14
15
|
export { type CapacitySummary, findLeastLoadedAgent, getAvailableCapacity, getCapacitySummary, isOverloaded, updateCapacity, } from './capacity.js';
|
|
15
|
-
export { type
|
|
16
|
+
export { type AgentExecutionEvent, type AgentExecutionOutcome, type AgentPerformanceSummary, getAgentPerformanceHistory, getSelfHealingSuggestions, type HealingSuggestion, processAgentLifecycleEvent, recordAgentExecution, recordFailurePattern, storeHealingStrategy, } from './execution-learning.js';
|
|
17
|
+
export { type AgentHealthStatus, checkAgentHealth, detectCrashedAgents, detectStaleAgents, HEARTBEAT_INTERVAL_MS, recordHeartbeat, STALE_THRESHOLD_MS, } from './health-monitor.js';
|
|
18
|
+
export { type AgentHealthReport, checkAgentHealth as findStaleAgentRows, classifyError, deregisterAgent, generateAgentId, getAgentErrorHistory, getAgentInstance, getHealthReport, heartbeat, incrementTasksCompleted, type ListAgentFilters, listAgentInstances, markCrashed, type RegisterAgentOptions, registerAgent, type UpdateStatusOptions, updateAgentStatus, } from './registry.js';
|
|
16
19
|
export { type AgentRecoveryResult, calculateDelay, createRetryPolicy, DEFAULT_RETRY_POLICY, type RetryPolicy, type RetryResult, recoverCrashedAgents, shouldRetry, withRetry, } from './retry.js';
|
|
17
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EACL,uBAAuB,EACvB,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,aAAa,EACb,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,KAAK,eAAe,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,EACZ,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,KAAK,iBAAiB,EACtB,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,kBAAkB,EAClB,WAAW,EACX,KAAK,oBAAoB,EACzB,aAAa,EACb,KAAK,mBAAmB,EACxB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,KAAK,mBAAmB,EACxB,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,oBAAoB,EACpB,WAAW,EACX,SAAS,GACV,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,uBAAuB,EAC5B,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,uBAAuB,EACvB,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,aAAa,EACb,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,KAAK,eAAe,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,EACZ,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,0BAA0B,EAC1B,yBAAyB,EACzB,KAAK,iBAAiB,EACtB,0BAA0B,EAC1B,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,KAAK,iBAAiB,EACtB,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EACL,KAAK,iBAAiB,EACtB,gBAAgB,IAAI,kBAAkB,EACtC,aAAa,EACb,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,kBAAkB,EAClB,WAAW,EACX,KAAK,oBAAoB,EACzB,aAAa,EACb,KAAK,mBAAmB,EACxB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,KAAK,mBAAmB,EACxB,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,oBAAoB,EACpB,WAAW,EACX,SAAS,GACV,MAAM,YAAY,CAAC"}
|