@herdctl/core 0.0.1 → 0.1.0

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.
Files changed (284) hide show
  1. package/dist/config/__tests__/agent.test.js +61 -13
  2. package/dist/config/__tests__/agent.test.js.map +1 -1
  3. package/dist/config/__tests__/merge.test.js +10 -3
  4. package/dist/config/__tests__/merge.test.js.map +1 -1
  5. package/dist/config/__tests__/schema.test.js +350 -1
  6. package/dist/config/__tests__/schema.test.js.map +1 -1
  7. package/dist/config/index.d.ts +1 -1
  8. package/dist/config/index.d.ts.map +1 -1
  9. package/dist/config/index.js +3 -1
  10. package/dist/config/index.js.map +1 -1
  11. package/dist/config/schema.d.ts +841 -27
  12. package/dist/config/schema.d.ts.map +1 -1
  13. package/dist/config/schema.js +129 -10
  14. package/dist/config/schema.js.map +1 -1
  15. package/dist/fleet-manager/__tests__/coverage.test.js +14 -331
  16. package/dist/fleet-manager/__tests__/coverage.test.js.map +1 -1
  17. package/dist/fleet-manager/__tests__/errors.test.js +1 -49
  18. package/dist/fleet-manager/__tests__/errors.test.js.map +1 -1
  19. package/dist/fleet-manager/__tests__/integration.test.js +114 -0
  20. package/dist/fleet-manager/__tests__/integration.test.js.map +1 -1
  21. package/dist/fleet-manager/__tests__/job-control.test.js +13 -14
  22. package/dist/fleet-manager/__tests__/job-control.test.js.map +1 -1
  23. package/dist/fleet-manager/__tests__/reload.test.js +12 -2
  24. package/dist/fleet-manager/__tests__/reload.test.js.map +1 -1
  25. package/dist/fleet-manager/__tests__/status-queries.test.js +6 -0
  26. package/dist/fleet-manager/__tests__/status-queries.test.js.map +1 -1
  27. package/dist/fleet-manager/__tests__/trigger.test.js +10 -2
  28. package/dist/fleet-manager/__tests__/trigger.test.js.map +1 -1
  29. package/dist/fleet-manager/config-reload.d.ts +164 -0
  30. package/dist/fleet-manager/config-reload.d.ts.map +1 -0
  31. package/dist/fleet-manager/config-reload.js +445 -0
  32. package/dist/fleet-manager/config-reload.js.map +1 -0
  33. package/dist/fleet-manager/context.d.ts +76 -0
  34. package/dist/fleet-manager/context.d.ts.map +1 -0
  35. package/dist/fleet-manager/context.js +11 -0
  36. package/dist/fleet-manager/context.js.map +1 -0
  37. package/dist/fleet-manager/errors.d.ts +0 -25
  38. package/dist/fleet-manager/errors.d.ts.map +1 -1
  39. package/dist/fleet-manager/errors.js +0 -38
  40. package/dist/fleet-manager/errors.js.map +1 -1
  41. package/dist/fleet-manager/event-emitters.d.ts +123 -0
  42. package/dist/fleet-manager/event-emitters.d.ts.map +1 -0
  43. package/dist/fleet-manager/event-emitters.js +136 -0
  44. package/dist/fleet-manager/event-emitters.js.map +1 -0
  45. package/dist/fleet-manager/event-types.d.ts +0 -15
  46. package/dist/fleet-manager/event-types.d.ts.map +1 -1
  47. package/dist/fleet-manager/fleet-manager.d.ts +40 -653
  48. package/dist/fleet-manager/fleet-manager.d.ts.map +1 -1
  49. package/dist/fleet-manager/fleet-manager.js +95 -1720
  50. package/dist/fleet-manager/fleet-manager.js.map +1 -1
  51. package/dist/fleet-manager/index.d.ts +13 -2
  52. package/dist/fleet-manager/index.d.ts.map +1 -1
  53. package/dist/fleet-manager/index.js +19 -6
  54. package/dist/fleet-manager/index.js.map +1 -1
  55. package/dist/fleet-manager/job-control.d.ts +67 -0
  56. package/dist/fleet-manager/job-control.d.ts.map +1 -0
  57. package/dist/fleet-manager/job-control.js +333 -0
  58. package/dist/fleet-manager/job-control.js.map +1 -0
  59. package/dist/fleet-manager/log-streaming.d.ts +171 -0
  60. package/dist/fleet-manager/log-streaming.d.ts.map +1 -0
  61. package/dist/fleet-manager/log-streaming.js +503 -0
  62. package/dist/fleet-manager/log-streaming.js.map +1 -0
  63. package/dist/fleet-manager/schedule-executor.d.ts +63 -0
  64. package/dist/fleet-manager/schedule-executor.d.ts.map +1 -0
  65. package/dist/fleet-manager/schedule-executor.js +209 -0
  66. package/dist/fleet-manager/schedule-executor.js.map +1 -0
  67. package/dist/fleet-manager/schedule-management.d.ts +71 -0
  68. package/dist/fleet-manager/schedule-management.d.ts.map +1 -0
  69. package/dist/fleet-manager/schedule-management.js +171 -0
  70. package/dist/fleet-manager/schedule-management.js.map +1 -0
  71. package/dist/fleet-manager/status-queries.d.ts +105 -0
  72. package/dist/fleet-manager/status-queries.d.ts.map +1 -0
  73. package/dist/fleet-manager/status-queries.js +247 -0
  74. package/dist/fleet-manager/status-queries.js.map +1 -0
  75. package/dist/fleet-manager/types.d.ts +0 -39
  76. package/dist/fleet-manager/types.d.ts.map +1 -1
  77. package/dist/runner/__tests__/job-executor.test.js +206 -1
  78. package/dist/runner/__tests__/job-executor.test.js.map +1 -1
  79. package/dist/runner/job-executor.d.ts +9 -0
  80. package/dist/runner/job-executor.d.ts.map +1 -1
  81. package/dist/runner/job-executor.js +78 -4
  82. package/dist/runner/job-executor.js.map +1 -1
  83. package/dist/runner/message-processor.d.ts.map +1 -1
  84. package/dist/runner/message-processor.js +53 -0
  85. package/dist/runner/message-processor.js.map +1 -1
  86. package/dist/runner/types.d.ts +3 -1
  87. package/dist/runner/types.d.ts.map +1 -1
  88. package/dist/scheduler/__tests__/cron.test.d.ts +2 -0
  89. package/dist/scheduler/__tests__/cron.test.d.ts.map +1 -0
  90. package/dist/scheduler/__tests__/cron.test.js +867 -0
  91. package/dist/scheduler/__tests__/cron.test.js.map +1 -0
  92. package/dist/scheduler/__tests__/scheduler.test.js +164 -5
  93. package/dist/scheduler/__tests__/scheduler.test.js.map +1 -1
  94. package/dist/scheduler/cron.d.ts +126 -0
  95. package/dist/scheduler/cron.d.ts.map +1 -0
  96. package/dist/scheduler/cron.js +390 -0
  97. package/dist/scheduler/cron.js.map +1 -0
  98. package/dist/scheduler/errors.d.ts +81 -1
  99. package/dist/scheduler/errors.d.ts.map +1 -1
  100. package/dist/scheduler/errors.js +81 -6
  101. package/dist/scheduler/errors.js.map +1 -1
  102. package/dist/scheduler/index.d.ts +1 -0
  103. package/dist/scheduler/index.d.ts.map +1 -1
  104. package/dist/scheduler/index.js +2 -0
  105. package/dist/scheduler/index.js.map +1 -1
  106. package/dist/scheduler/schedule-runner.d.ts +2 -2
  107. package/dist/scheduler/schedule-runner.d.ts.map +1 -1
  108. package/dist/scheduler/schedule-runner.js +20 -8
  109. package/dist/scheduler/schedule-runner.js.map +1 -1
  110. package/dist/scheduler/scheduler.d.ts +4 -4
  111. package/dist/scheduler/scheduler.d.ts.map +1 -1
  112. package/dist/scheduler/scheduler.js +95 -20
  113. package/dist/scheduler/scheduler.js.map +1 -1
  114. package/dist/scheduler/types.d.ts +1 -1
  115. package/dist/scheduler/types.d.ts.map +1 -1
  116. package/dist/state/schemas/job-metadata.d.ts +2 -2
  117. package/package.json +33 -8
  118. package/.turbo/turbo-build.log +0 -4
  119. package/.turbo/turbo-test.log +0 -219
  120. package/.turbo/turbo-typecheck.log +0 -4
  121. package/coverage/base.css +0 -224
  122. package/coverage/block-navigation.js +0 -87
  123. package/coverage/coverage-final.json +0 -51
  124. package/coverage/favicon.png +0 -0
  125. package/coverage/index.html +0 -251
  126. package/coverage/prettify.css +0 -1
  127. package/coverage/prettify.js +0 -2
  128. package/coverage/sort-arrow-sprite.png +0 -0
  129. package/coverage/sorter.js +0 -210
  130. package/coverage/src/config/index.html +0 -191
  131. package/coverage/src/config/index.ts.html +0 -442
  132. package/coverage/src/config/interpolate.ts.html +0 -652
  133. package/coverage/src/config/loader.ts.html +0 -1501
  134. package/coverage/src/config/merge.ts.html +0 -823
  135. package/coverage/src/config/parser.ts.html +0 -1213
  136. package/coverage/src/config/schema.ts.html +0 -1123
  137. package/coverage/src/fleet-manager/errors.ts.html +0 -2326
  138. package/coverage/src/fleet-manager/event-types.ts.html +0 -1219
  139. package/coverage/src/fleet-manager/fleet-manager.ts.html +0 -7030
  140. package/coverage/src/fleet-manager/index.html +0 -206
  141. package/coverage/src/fleet-manager/index.ts.html +0 -469
  142. package/coverage/src/fleet-manager/job-manager.ts.html +0 -2074
  143. package/coverage/src/fleet-manager/job-queue.ts.html +0 -2479
  144. package/coverage/src/fleet-manager/types.ts.html +0 -2602
  145. package/coverage/src/index.html +0 -116
  146. package/coverage/src/index.ts.html +0 -181
  147. package/coverage/src/runner/errors.ts.html +0 -1006
  148. package/coverage/src/runner/index.html +0 -191
  149. package/coverage/src/runner/index.ts.html +0 -256
  150. package/coverage/src/runner/job-executor.ts.html +0 -1429
  151. package/coverage/src/runner/message-processor.ts.html +0 -1150
  152. package/coverage/src/runner/sdk-adapter.ts.html +0 -658
  153. package/coverage/src/runner/types.ts.html +0 -559
  154. package/coverage/src/scheduler/errors.ts.html +0 -388
  155. package/coverage/src/scheduler/index.html +0 -206
  156. package/coverage/src/scheduler/index.ts.html +0 -244
  157. package/coverage/src/scheduler/interval.ts.html +0 -652
  158. package/coverage/src/scheduler/schedule-runner.ts.html +0 -1411
  159. package/coverage/src/scheduler/schedule-state.ts.html +0 -718
  160. package/coverage/src/scheduler/scheduler.ts.html +0 -1795
  161. package/coverage/src/scheduler/types.ts.html +0 -733
  162. package/coverage/src/state/directory.ts.html +0 -736
  163. package/coverage/src/state/errors.ts.html +0 -376
  164. package/coverage/src/state/fleet-state.ts.html +0 -937
  165. package/coverage/src/state/index.html +0 -221
  166. package/coverage/src/state/index.ts.html +0 -322
  167. package/coverage/src/state/job-metadata.ts.html +0 -1420
  168. package/coverage/src/state/job-output.ts.html +0 -1033
  169. package/coverage/src/state/schemas/fleet-state.ts.html +0 -445
  170. package/coverage/src/state/schemas/index.html +0 -176
  171. package/coverage/src/state/schemas/index.ts.html +0 -286
  172. package/coverage/src/state/schemas/job-metadata.ts.html +0 -628
  173. package/coverage/src/state/schemas/job-output.ts.html +0 -616
  174. package/coverage/src/state/schemas/session-info.ts.html +0 -361
  175. package/coverage/src/state/session.ts.html +0 -844
  176. package/coverage/src/state/types.ts.html +0 -262
  177. package/coverage/src/state/utils/atomic.ts.html +0 -748
  178. package/coverage/src/state/utils/index.html +0 -146
  179. package/coverage/src/state/utils/index.ts.html +0 -103
  180. package/coverage/src/state/utils/reads.ts.html +0 -1621
  181. package/coverage/src/work-sources/adapters/github.ts.html +0 -3583
  182. package/coverage/src/work-sources/adapters/index.html +0 -131
  183. package/coverage/src/work-sources/adapters/index.ts.html +0 -277
  184. package/coverage/src/work-sources/errors.ts.html +0 -298
  185. package/coverage/src/work-sources/index.html +0 -176
  186. package/coverage/src/work-sources/index.ts.html +0 -529
  187. package/coverage/src/work-sources/manager.ts.html +0 -1324
  188. package/coverage/src/work-sources/registry.ts.html +0 -619
  189. package/coverage/src/work-sources/types.ts.html +0 -568
  190. package/dist/fleet-manager/__tests__/event-helpers.test.d.ts +0 -7
  191. package/dist/fleet-manager/__tests__/event-helpers.test.d.ts.map +0 -1
  192. package/dist/fleet-manager/__tests__/event-helpers.test.js +0 -368
  193. package/dist/fleet-manager/__tests__/event-helpers.test.js.map +0 -1
  194. package/src/config/__tests__/agent.test.ts +0 -864
  195. package/src/config/__tests__/interpolate.test.ts +0 -644
  196. package/src/config/__tests__/loader.test.ts +0 -784
  197. package/src/config/__tests__/merge.test.ts +0 -751
  198. package/src/config/__tests__/parser.test.ts +0 -533
  199. package/src/config/__tests__/schema.test.ts +0 -873
  200. package/src/config/index.ts +0 -119
  201. package/src/config/interpolate.ts +0 -189
  202. package/src/config/loader.ts +0 -472
  203. package/src/config/merge.ts +0 -246
  204. package/src/config/parser.ts +0 -376
  205. package/src/config/schema.ts +0 -346
  206. package/src/fleet-manager/__tests__/coverage.test.ts +0 -2869
  207. package/src/fleet-manager/__tests__/errors.test.ts +0 -660
  208. package/src/fleet-manager/__tests__/event-helpers.test.ts +0 -448
  209. package/src/fleet-manager/__tests__/integration.test.ts +0 -1209
  210. package/src/fleet-manager/__tests__/job-control.test.ts +0 -283
  211. package/src/fleet-manager/__tests__/job-manager.test.ts +0 -869
  212. package/src/fleet-manager/__tests__/job-queue.test.ts +0 -401
  213. package/src/fleet-manager/__tests__/reload.test.ts +0 -751
  214. package/src/fleet-manager/__tests__/status-queries.test.ts +0 -595
  215. package/src/fleet-manager/__tests__/trigger.test.ts +0 -601
  216. package/src/fleet-manager/errors.ts +0 -747
  217. package/src/fleet-manager/event-types.ts +0 -378
  218. package/src/fleet-manager/fleet-manager.ts +0 -2315
  219. package/src/fleet-manager/index.ts +0 -128
  220. package/src/fleet-manager/job-manager.ts +0 -663
  221. package/src/fleet-manager/job-queue.ts +0 -798
  222. package/src/fleet-manager/types.ts +0 -839
  223. package/src/index.ts +0 -32
  224. package/src/runner/__tests__/errors.test.ts +0 -382
  225. package/src/runner/__tests__/job-executor.test.ts +0 -1708
  226. package/src/runner/__tests__/message-processor.test.ts +0 -960
  227. package/src/runner/__tests__/sdk-adapter.test.ts +0 -626
  228. package/src/runner/errors.ts +0 -307
  229. package/src/runner/index.ts +0 -57
  230. package/src/runner/job-executor.ts +0 -448
  231. package/src/runner/message-processor.ts +0 -355
  232. package/src/runner/sdk-adapter.ts +0 -191
  233. package/src/runner/types.ts +0 -158
  234. package/src/scheduler/__tests__/errors.test.ts +0 -159
  235. package/src/scheduler/__tests__/interval.test.ts +0 -515
  236. package/src/scheduler/__tests__/schedule-runner.test.ts +0 -798
  237. package/src/scheduler/__tests__/schedule-state.test.ts +0 -671
  238. package/src/scheduler/__tests__/scheduler.test.ts +0 -1280
  239. package/src/scheduler/errors.ts +0 -101
  240. package/src/scheduler/index.ts +0 -53
  241. package/src/scheduler/interval.ts +0 -189
  242. package/src/scheduler/schedule-runner.ts +0 -442
  243. package/src/scheduler/schedule-state.ts +0 -211
  244. package/src/scheduler/scheduler.ts +0 -570
  245. package/src/scheduler/types.ts +0 -216
  246. package/src/state/__tests__/directory.test.ts +0 -595
  247. package/src/state/__tests__/fleet-state.test.ts +0 -868
  248. package/src/state/__tests__/job-metadata-schema.test.ts +0 -414
  249. package/src/state/__tests__/job-metadata.test.ts +0 -831
  250. package/src/state/__tests__/job-output.test.ts +0 -856
  251. package/src/state/__tests__/session-schema.test.ts +0 -378
  252. package/src/state/__tests__/session.test.ts +0 -604
  253. package/src/state/directory.ts +0 -217
  254. package/src/state/errors.ts +0 -97
  255. package/src/state/fleet-state.ts +0 -284
  256. package/src/state/index.ts +0 -79
  257. package/src/state/job-metadata.ts +0 -445
  258. package/src/state/job-output.ts +0 -316
  259. package/src/state/schemas/__tests__/job-output.test.ts +0 -338
  260. package/src/state/schemas/fleet-state.ts +0 -120
  261. package/src/state/schemas/index.ts +0 -67
  262. package/src/state/schemas/job-metadata.ts +0 -181
  263. package/src/state/schemas/job-output.ts +0 -177
  264. package/src/state/schemas/session-info.ts +0 -92
  265. package/src/state/session.ts +0 -253
  266. package/src/state/types.ts +0 -59
  267. package/src/state/utils/__tests__/atomic.test.ts +0 -723
  268. package/src/state/utils/__tests__/reads.test.ts +0 -1071
  269. package/src/state/utils/atomic.ts +0 -221
  270. package/src/state/utils/index.ts +0 -6
  271. package/src/state/utils/reads.ts +0 -512
  272. package/src/work-sources/__tests__/github.test.ts +0 -1800
  273. package/src/work-sources/__tests__/manager.test.ts +0 -529
  274. package/src/work-sources/__tests__/registry.test.ts +0 -477
  275. package/src/work-sources/__tests__/types.test.ts +0 -479
  276. package/src/work-sources/adapters/github.ts +0 -1166
  277. package/src/work-sources/adapters/index.ts +0 -64
  278. package/src/work-sources/errors.ts +0 -71
  279. package/src/work-sources/index.ts +0 -148
  280. package/src/work-sources/manager.ts +0 -413
  281. package/src/work-sources/registry.ts +0 -178
  282. package/src/work-sources/types.ts +0 -161
  283. package/tsconfig.json +0 -9
  284. package/vitest.config.ts +0 -19
@@ -1,747 +0,0 @@
1
- /**
2
- * Error classes for fleet manager operations
3
- *
4
- * Provides typed errors with descriptive messages and error codes for fleet manager failures.
5
- * All errors extend FleetManagerError and include relevant context for debugging.
6
- */
7
-
8
- // =============================================================================
9
- // Error Codes
10
- // =============================================================================
11
-
12
- /**
13
- * Error codes for fleet manager errors
14
- * These codes provide a stable identifier for error types that can be used
15
- * for programmatic error handling.
16
- */
17
- export const FleetManagerErrorCode = {
18
- // Base error
19
- FLEET_MANAGER_ERROR: "FLEET_MANAGER_ERROR",
20
-
21
- // Configuration errors
22
- CONFIGURATION_ERROR: "CONFIGURATION_ERROR",
23
- CONFIG_LOAD_ERROR: "CONFIG_LOAD_ERROR",
24
-
25
- // Not found errors
26
- AGENT_NOT_FOUND: "AGENT_NOT_FOUND",
27
- JOB_NOT_FOUND: "JOB_NOT_FOUND",
28
- SCHEDULE_NOT_FOUND: "SCHEDULE_NOT_FOUND",
29
-
30
- // State errors
31
- INVALID_STATE: "INVALID_STATE",
32
- STATE_DIR_ERROR: "STATE_DIR_ERROR",
33
-
34
- // Operational errors
35
- CONCURRENCY_LIMIT: "CONCURRENCY_LIMIT",
36
- SHUTDOWN_ERROR: "SHUTDOWN_ERROR",
37
-
38
- // Job control errors (US-6)
39
- JOB_CANCEL_ERROR: "JOB_CANCEL_ERROR",
40
- JOB_FORK_ERROR: "JOB_FORK_ERROR",
41
- } as const;
42
-
43
- export type FleetManagerErrorCode =
44
- (typeof FleetManagerErrorCode)[keyof typeof FleetManagerErrorCode];
45
-
46
- // =============================================================================
47
- // Base Error Class
48
- // =============================================================================
49
-
50
- /**
51
- * Base error class for all fleet manager errors
52
- *
53
- * All fleet manager errors extend this class and include:
54
- * - A unique error code for programmatic handling
55
- * - Descriptive error messages
56
- * - Optional cause for error chaining
57
- */
58
- export class FleetManagerError extends Error {
59
- /** Error code for programmatic handling */
60
- public readonly code: FleetManagerErrorCode;
61
-
62
- constructor(
63
- message: string,
64
- options?: { cause?: Error; code?: FleetManagerErrorCode }
65
- ) {
66
- super(message);
67
- this.name = "FleetManagerError";
68
- this.cause = options?.cause;
69
- this.code = options?.code ?? FleetManagerErrorCode.FLEET_MANAGER_ERROR;
70
- }
71
- }
72
-
73
- // =============================================================================
74
- // Configuration Errors
75
- // =============================================================================
76
-
77
- /**
78
- * Validation error detail for configuration errors
79
- */
80
- export interface ValidationError {
81
- /** Path to the invalid field (e.g., "agents[0].schedules[0].interval") */
82
- path: string;
83
- /** Description of the validation error */
84
- message: string;
85
- /** The invalid value, if available */
86
- value?: unknown;
87
- }
88
-
89
- /**
90
- * Error thrown when configuration is invalid or cannot be loaded
91
- *
92
- * This error is thrown when:
93
- * - The configuration file cannot be found or read
94
- * - The configuration YAML is malformed
95
- * - The configuration fails schema validation
96
- * - Agent definitions are invalid
97
- *
98
- * @example
99
- * ```typescript
100
- * try {
101
- * await fleetManager.initialize();
102
- * } catch (error) {
103
- * if (error instanceof ConfigurationError) {
104
- * console.error(`Config error at ${error.configPath}:`);
105
- * for (const ve of error.validationErrors) {
106
- * console.error(` - ${ve.path}: ${ve.message}`);
107
- * }
108
- * }
109
- * }
110
- * ```
111
- */
112
- export class ConfigurationError extends FleetManagerError {
113
- /** The path to the configuration file that failed */
114
- public readonly configPath?: string;
115
-
116
- /** Detailed validation errors, if any */
117
- public readonly validationErrors: ValidationError[];
118
-
119
- constructor(
120
- message: string,
121
- options?: {
122
- configPath?: string;
123
- validationErrors?: ValidationError[];
124
- cause?: Error;
125
- }
126
- ) {
127
- const validationErrors = options?.validationErrors ?? [];
128
- const fullMessage = ConfigurationError.buildMessage(
129
- message,
130
- options?.configPath,
131
- validationErrors
132
- );
133
-
134
- super(fullMessage, {
135
- cause: options?.cause,
136
- code: FleetManagerErrorCode.CONFIGURATION_ERROR,
137
- });
138
- this.name = "ConfigurationError";
139
- this.configPath = options?.configPath;
140
- this.validationErrors = validationErrors;
141
- }
142
-
143
- /**
144
- * Build a detailed error message including validation errors
145
- */
146
- private static buildMessage(
147
- message: string,
148
- configPath?: string,
149
- validationErrors?: ValidationError[]
150
- ): string {
151
- const parts = [message];
152
-
153
- if (configPath) {
154
- parts.push(`Config file: ${configPath}`);
155
- }
156
-
157
- if (validationErrors && validationErrors.length > 0) {
158
- parts.push("Validation errors:");
159
- for (const ve of validationErrors) {
160
- parts.push(` - ${ve.path}: ${ve.message}`);
161
- }
162
- }
163
-
164
- return parts.join("\n");
165
- }
166
-
167
- /**
168
- * Check if this error has validation errors
169
- */
170
- hasValidationErrors(): boolean {
171
- return this.validationErrors.length > 0;
172
- }
173
- }
174
-
175
- // =============================================================================
176
- // Not Found Errors
177
- // =============================================================================
178
-
179
- /**
180
- * Error thrown when a requested agent is not found
181
- *
182
- * This error is thrown when:
183
- * - Attempting to run an agent that doesn't exist in the configuration
184
- * - Attempting to get status for an unknown agent
185
- * - Referencing an agent name that hasn't been defined
186
- *
187
- * @example
188
- * ```typescript
189
- * try {
190
- * await fleetManager.runAgent('nonexistent-agent');
191
- * } catch (error) {
192
- * if (error instanceof AgentNotFoundError) {
193
- * console.error(`Agent "${error.agentName}" not found`);
194
- * console.log('Available agents:', fleetManager.getAgentNames());
195
- * }
196
- * }
197
- * ```
198
- */
199
- export class AgentNotFoundError extends FleetManagerError {
200
- /** The name of the agent that was not found */
201
- public readonly agentName: string;
202
-
203
- /** Optional list of available agent names for helpful error messages */
204
- public readonly availableAgents?: string[];
205
-
206
- constructor(
207
- agentName: string,
208
- options?: { availableAgents?: string[]; cause?: Error }
209
- ) {
210
- const message = AgentNotFoundError.buildMessage(
211
- agentName,
212
- options?.availableAgents
213
- );
214
- super(message, {
215
- cause: options?.cause,
216
- code: FleetManagerErrorCode.AGENT_NOT_FOUND,
217
- });
218
- this.name = "AgentNotFoundError";
219
- this.agentName = agentName;
220
- this.availableAgents = options?.availableAgents;
221
- }
222
-
223
- private static buildMessage(
224
- agentName: string,
225
- availableAgents?: string[]
226
- ): string {
227
- let message = `Agent "${agentName}" not found`;
228
-
229
- if (availableAgents && availableAgents.length > 0) {
230
- message += `. Available agents: ${availableAgents.join(", ")}`;
231
- } else if (availableAgents && availableAgents.length === 0) {
232
- message += ". No agents are configured.";
233
- }
234
-
235
- return message;
236
- }
237
- }
238
-
239
- /**
240
- * Error thrown when a requested job is not found
241
- *
242
- * This error is thrown when:
243
- * - Attempting to get status for a job that doesn't exist
244
- * - Attempting to cancel a job that has already completed or doesn't exist
245
- * - Referencing a job ID that is unknown
246
- *
247
- * @example
248
- * ```typescript
249
- * try {
250
- * const status = await fleetManager.getJobStatus('unknown-job-id');
251
- * } catch (error) {
252
- * if (error instanceof JobNotFoundError) {
253
- * console.error(`Job "${error.jobId}" not found`);
254
- * }
255
- * }
256
- * ```
257
- */
258
- export class JobNotFoundError extends FleetManagerError {
259
- /** The ID of the job that was not found */
260
- public readonly jobId: string;
261
-
262
- constructor(jobId: string, options?: { cause?: Error }) {
263
- super(`Job "${jobId}" not found`, {
264
- cause: options?.cause,
265
- code: FleetManagerErrorCode.JOB_NOT_FOUND,
266
- });
267
- this.name = "JobNotFoundError";
268
- this.jobId = jobId;
269
- }
270
- }
271
-
272
- /**
273
- * Error thrown when a requested schedule is not found
274
- *
275
- * This error is thrown when:
276
- * - Attempting to trigger a schedule that doesn't exist
277
- * - Attempting to enable/disable a schedule that doesn't exist
278
- * - Referencing a schedule name that hasn't been defined for an agent
279
- *
280
- * @example
281
- * ```typescript
282
- * try {
283
- * await fleetManager.triggerSchedule('my-agent', 'nonexistent-schedule');
284
- * } catch (error) {
285
- * if (error instanceof ScheduleNotFoundError) {
286
- * console.error(
287
- * `Schedule "${error.scheduleName}" not found for agent "${error.agentName}"`
288
- * );
289
- * }
290
- * }
291
- * ```
292
- */
293
- export class ScheduleNotFoundError extends FleetManagerError {
294
- /** The name of the agent the schedule was expected to belong to */
295
- public readonly agentName: string;
296
-
297
- /** The name of the schedule that was not found */
298
- public readonly scheduleName: string;
299
-
300
- /** Optional list of available schedule names for helpful error messages */
301
- public readonly availableSchedules?: string[];
302
-
303
- constructor(
304
- agentName: string,
305
- scheduleName: string,
306
- options?: { availableSchedules?: string[]; cause?: Error }
307
- ) {
308
- const message = ScheduleNotFoundError.buildMessage(
309
- agentName,
310
- scheduleName,
311
- options?.availableSchedules
312
- );
313
- super(message, {
314
- cause: options?.cause,
315
- code: FleetManagerErrorCode.SCHEDULE_NOT_FOUND,
316
- });
317
- this.name = "ScheduleNotFoundError";
318
- this.agentName = agentName;
319
- this.scheduleName = scheduleName;
320
- this.availableSchedules = options?.availableSchedules;
321
- }
322
-
323
- private static buildMessage(
324
- agentName: string,
325
- scheduleName: string,
326
- availableSchedules?: string[]
327
- ): string {
328
- let message = `Schedule "${scheduleName}" not found for agent "${agentName}"`;
329
-
330
- if (availableSchedules && availableSchedules.length > 0) {
331
- message += `. Available schedules: ${availableSchedules.join(", ")}`;
332
- } else if (availableSchedules && availableSchedules.length === 0) {
333
- message += `. Agent "${agentName}" has no schedules configured.`;
334
- }
335
-
336
- return message;
337
- }
338
- }
339
-
340
- // =============================================================================
341
- // State Errors
342
- // =============================================================================
343
-
344
- /**
345
- * Error thrown when an operation is attempted in an invalid state
346
- *
347
- * This error is thrown when:
348
- * - start() is called before initialize()
349
- * - initialize() is called when already initialized
350
- * - Operations are attempted while in an incompatible state
351
- * - State transitions are invalid
352
- *
353
- * @example
354
- * ```typescript
355
- * try {
356
- * await fleetManager.start(); // without calling initialize() first
357
- * } catch (error) {
358
- * if (error instanceof InvalidStateError) {
359
- * console.error(
360
- * `Cannot ${error.operation}: current state is "${error.currentState}", ` +
361
- * `expected "${error.expectedState}"`
362
- * );
363
- * }
364
- * }
365
- * ```
366
- */
367
- export class InvalidStateError extends FleetManagerError {
368
- /** The current state of the fleet manager */
369
- public readonly currentState: string;
370
-
371
- /** The state(s) expected/required for the operation */
372
- public readonly expectedState: string | string[];
373
-
374
- /** The operation that was attempted */
375
- public readonly operation: string;
376
-
377
- constructor(
378
- operation: string,
379
- currentState: string,
380
- expectedState: string | string[],
381
- options?: { cause?: Error }
382
- ) {
383
- const expected = Array.isArray(expectedState)
384
- ? expectedState.join(" or ")
385
- : expectedState;
386
-
387
- super(
388
- `Cannot ${operation}: fleet manager is in "${currentState}" state, must be "${expected}"`,
389
- {
390
- cause: options?.cause,
391
- code: FleetManagerErrorCode.INVALID_STATE,
392
- }
393
- );
394
- this.name = "InvalidStateError";
395
- this.operation = operation;
396
- this.currentState = currentState;
397
- this.expectedState = expectedState;
398
- }
399
- }
400
-
401
- /**
402
- * Error thrown when the fleet manager is not in the correct state for an operation
403
- *
404
- * @deprecated Use InvalidStateError instead. This class is kept for backwards compatibility.
405
- */
406
- export class FleetManagerStateError extends InvalidStateError {
407
- constructor(
408
- operation: string,
409
- currentState: string,
410
- requiredState: string | string[]
411
- ) {
412
- super(operation, currentState, requiredState);
413
- this.name = "FleetManagerStateError";
414
- }
415
-
416
- /**
417
- * Alias for expectedState for backwards compatibility
418
- */
419
- get requiredState(): string | string[] {
420
- return this.expectedState;
421
- }
422
- }
423
-
424
- // =============================================================================
425
- // Operational Errors
426
- // =============================================================================
427
-
428
- /**
429
- * Error thrown when an operation would exceed concurrency limits
430
- *
431
- * This error is thrown when:
432
- * - Attempting to start a new job when the agent has reached its concurrent job limit
433
- * - Attempting to run more jobs than the system allows
434
- *
435
- * @example
436
- * ```typescript
437
- * try {
438
- * await fleetManager.runAgent('my-agent');
439
- * } catch (error) {
440
- * if (error instanceof ConcurrencyLimitError) {
441
- * console.error(
442
- * `Agent "${error.agentName}" has ${error.currentJobs}/${error.limit} jobs running. ` +
443
- * `Please wait for a job to complete.`
444
- * );
445
- * }
446
- * }
447
- * ```
448
- */
449
- export class ConcurrencyLimitError extends FleetManagerError {
450
- /** The name of the agent that hit the concurrency limit */
451
- public readonly agentName: string;
452
-
453
- /** The current number of running jobs for this agent */
454
- public readonly currentJobs: number;
455
-
456
- /** The maximum allowed concurrent jobs for this agent */
457
- public readonly limit: number;
458
-
459
- constructor(
460
- agentName: string,
461
- currentJobs: number,
462
- limit: number,
463
- options?: { cause?: Error }
464
- ) {
465
- super(
466
- `Agent "${agentName}" has reached its concurrency limit: ${currentJobs}/${limit} jobs running`,
467
- {
468
- cause: options?.cause,
469
- code: FleetManagerErrorCode.CONCURRENCY_LIMIT,
470
- }
471
- );
472
- this.name = "ConcurrencyLimitError";
473
- this.agentName = agentName;
474
- this.currentJobs = currentJobs;
475
- this.limit = limit;
476
- }
477
-
478
- /**
479
- * Check if the limit is completely maxed out (no room for more jobs)
480
- */
481
- isAtLimit(): boolean {
482
- return this.currentJobs >= this.limit;
483
- }
484
- }
485
-
486
- // =============================================================================
487
- // Configuration Loading Errors (kept for backwards compatibility)
488
- // =============================================================================
489
-
490
- /**
491
- * Error thrown when configuration loading fails
492
- *
493
- * @deprecated Use ConfigurationError instead for new code.
494
- * This class is kept for backwards compatibility.
495
- */
496
- export class FleetManagerConfigError extends FleetManagerError {
497
- /** The path that was being loaded */
498
- public readonly configPath?: string;
499
-
500
- constructor(
501
- message: string,
502
- configPath?: string,
503
- options?: { cause?: Error }
504
- ) {
505
- super(message, {
506
- cause: options?.cause,
507
- code: FleetManagerErrorCode.CONFIG_LOAD_ERROR,
508
- });
509
- this.name = "FleetManagerConfigError";
510
- this.configPath = configPath;
511
- }
512
- }
513
-
514
- // =============================================================================
515
- // State Directory Errors
516
- // =============================================================================
517
-
518
- /**
519
- * Error thrown when state directory initialization fails
520
- *
521
- * This wraps state directory errors with fleet manager context.
522
- */
523
- export class FleetManagerStateDirError extends FleetManagerError {
524
- /** The state directory path */
525
- public readonly stateDir: string;
526
-
527
- constructor(message: string, stateDir: string, options?: { cause?: Error }) {
528
- super(message, {
529
- cause: options?.cause,
530
- code: FleetManagerErrorCode.STATE_DIR_ERROR,
531
- });
532
- this.name = "FleetManagerStateDirError";
533
- this.stateDir = stateDir;
534
- }
535
- }
536
-
537
- // =============================================================================
538
- // Shutdown Errors
539
- // =============================================================================
540
-
541
- /**
542
- * Error thrown when fleet manager shutdown fails
543
- *
544
- * This is thrown when the fleet manager cannot shut down cleanly.
545
- */
546
- export class FleetManagerShutdownError extends FleetManagerError {
547
- /** Whether the shutdown timed out */
548
- public readonly timedOut: boolean;
549
-
550
- constructor(
551
- message: string,
552
- options: { timedOut: boolean; cause?: Error }
553
- ) {
554
- super(message, {
555
- cause: options.cause,
556
- code: FleetManagerErrorCode.SHUTDOWN_ERROR,
557
- });
558
- this.name = "FleetManagerShutdownError";
559
- this.timedOut = options.timedOut;
560
- }
561
-
562
- /**
563
- * Check if the shutdown failed due to timeout
564
- */
565
- isTimeout(): boolean {
566
- return this.timedOut;
567
- }
568
- }
569
-
570
- // =============================================================================
571
- // Job Control Errors (US-6)
572
- // =============================================================================
573
-
574
- /**
575
- * Error thrown when job cancellation fails
576
- *
577
- * This error is thrown when:
578
- * - The job process cannot be terminated
579
- * - The job is in an invalid state for cancellation
580
- * - An error occurs during the cancellation process
581
- *
582
- * @example
583
- * ```typescript
584
- * try {
585
- * await manager.cancelJob('job-2024-01-15-abc123');
586
- * } catch (error) {
587
- * if (error instanceof JobCancelError) {
588
- * console.error(`Failed to cancel job: ${error.message}`);
589
- * console.error(`Job ID: ${error.jobId}`);
590
- * }
591
- * }
592
- * ```
593
- */
594
- export class JobCancelError extends FleetManagerError {
595
- /** The ID of the job that failed to cancel */
596
- public readonly jobId: string;
597
-
598
- /** The reason the cancellation failed */
599
- public readonly reason: 'not_running' | 'process_error' | 'timeout' | 'unknown';
600
-
601
- constructor(
602
- jobId: string,
603
- reason: 'not_running' | 'process_error' | 'timeout' | 'unknown',
604
- options?: { message?: string; cause?: Error }
605
- ) {
606
- const defaultMessages: Record<typeof reason, string> = {
607
- not_running: `Job "${jobId}" is not running and cannot be cancelled`,
608
- process_error: `Failed to terminate process for job "${jobId}"`,
609
- timeout: `Timeout waiting for job "${jobId}" to terminate`,
610
- unknown: `Unknown error cancelling job "${jobId}"`,
611
- };
612
-
613
- super(options?.message ?? defaultMessages[reason], {
614
- cause: options?.cause,
615
- code: FleetManagerErrorCode.JOB_CANCEL_ERROR,
616
- });
617
- this.name = "JobCancelError";
618
- this.jobId = jobId;
619
- this.reason = reason;
620
- }
621
- }
622
-
623
- /**
624
- * Error thrown when job forking fails
625
- *
626
- * This error is thrown when:
627
- * - The original job cannot be found
628
- * - The original job has no session to fork
629
- * - An error occurs during the fork process
630
- *
631
- * @example
632
- * ```typescript
633
- * try {
634
- * await manager.forkJob('job-2024-01-15-abc123');
635
- * } catch (error) {
636
- * if (error instanceof JobForkError) {
637
- * console.error(`Failed to fork job: ${error.message}`);
638
- * console.error(`Original Job ID: ${error.originalJobId}`);
639
- * }
640
- * }
641
- * ```
642
- */
643
- export class JobForkError extends FleetManagerError {
644
- /** The ID of the original job that failed to fork */
645
- public readonly originalJobId: string;
646
-
647
- /** The reason the fork failed */
648
- public readonly reason: 'no_session' | 'job_not_found' | 'agent_not_found' | 'unknown';
649
-
650
- constructor(
651
- originalJobId: string,
652
- reason: 'no_session' | 'job_not_found' | 'agent_not_found' | 'unknown',
653
- options?: { message?: string; cause?: Error }
654
- ) {
655
- const defaultMessages: Record<typeof reason, string> = {
656
- no_session: `Job "${originalJobId}" has no session ID and cannot be forked`,
657
- job_not_found: `Job "${originalJobId}" not found`,
658
- agent_not_found: `Agent for job "${originalJobId}" not found`,
659
- unknown: `Unknown error forking job "${originalJobId}"`,
660
- };
661
-
662
- super(options?.message ?? defaultMessages[reason], {
663
- cause: options?.cause,
664
- code: FleetManagerErrorCode.JOB_FORK_ERROR,
665
- });
666
- this.name = "JobForkError";
667
- this.originalJobId = originalJobId;
668
- this.reason = reason;
669
- }
670
- }
671
-
672
- // =============================================================================
673
- // Type Guards
674
- // =============================================================================
675
-
676
- /**
677
- * Type guard to check if an error is a FleetManagerError
678
- */
679
- export function isFleetManagerError(error: unknown): error is FleetManagerError {
680
- return error instanceof FleetManagerError;
681
- }
682
-
683
- /**
684
- * Type guard to check if an error is a ConfigurationError
685
- */
686
- export function isConfigurationError(
687
- error: unknown
688
- ): error is ConfigurationError {
689
- return error instanceof ConfigurationError;
690
- }
691
-
692
- /**
693
- * Type guard to check if an error is an AgentNotFoundError
694
- */
695
- export function isAgentNotFoundError(
696
- error: unknown
697
- ): error is AgentNotFoundError {
698
- return error instanceof AgentNotFoundError;
699
- }
700
-
701
- /**
702
- * Type guard to check if an error is a JobNotFoundError
703
- */
704
- export function isJobNotFoundError(error: unknown): error is JobNotFoundError {
705
- return error instanceof JobNotFoundError;
706
- }
707
-
708
- /**
709
- * Type guard to check if an error is a ScheduleNotFoundError
710
- */
711
- export function isScheduleNotFoundError(
712
- error: unknown
713
- ): error is ScheduleNotFoundError {
714
- return error instanceof ScheduleNotFoundError;
715
- }
716
-
717
- /**
718
- * Type guard to check if an error is an InvalidStateError
719
- */
720
- export function isInvalidStateError(
721
- error: unknown
722
- ): error is InvalidStateError {
723
- return error instanceof InvalidStateError;
724
- }
725
-
726
- /**
727
- * Type guard to check if an error is a ConcurrencyLimitError
728
- */
729
- export function isConcurrencyLimitError(
730
- error: unknown
731
- ): error is ConcurrencyLimitError {
732
- return error instanceof ConcurrencyLimitError;
733
- }
734
-
735
- /**
736
- * Type guard to check if an error is a JobCancelError
737
- */
738
- export function isJobCancelError(error: unknown): error is JobCancelError {
739
- return error instanceof JobCancelError;
740
- }
741
-
742
- /**
743
- * Type guard to check if an error is a JobForkError
744
- */
745
- export function isJobForkError(error: unknown): error is JobForkError {
746
- return error instanceof JobForkError;
747
- }