@fleettools/server 0.1.0 → 0.2.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.
- package/package.json +6 -2
- package/tsconfig.json +7 -1
- package/.flightline/checkpoints.db +0 -0
- package/.flightline/ctk/04a5510b-1e09-40c6-91c8-399c22138708.json +0 -9
- package/.flightline/ctk/0ecde721-7827-4039-995a-974e24493cc5.json +0 -9
- package/.flightline/ctk/268bbdbd-ddd7-46b2-845f-56a138aa518a.json +0 -9
- package/.flightline/ctk/6f476f2e-776c-407a-b441-b9365c0bae95.json +0 -9
- package/.flightline/ctk/7e10d0d5-fbc2-4661-af03-53de89e064db.json +0 -9
- package/.flightline/ctk/90783096-b7d4-49c5-8153-3c35018a2e61.json +0 -9
- package/.flightline/ctk/9a3b6d18-8a46-4728-90aa-279800a8e397.json +0 -9
- package/.flightline/ctk/ae30e192-b386-4ee2-899c-93f86785d3f3.json +0 -9
- package/.flightline/ctk/d0e9c49e-10df-413e-8cf7-37232b1838ca.json +0 -9
- package/.flightline/ctk/eae1a12b-2e9d-4c3f-8619-dafbb1346e96.json +0 -9
- package/.flightline/mailboxes/mbx_00dae6ba-0b5e-4a8d-a86d-93c8640872c3/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_05b0bfa9-c4f5-4f68-ba75-6202820f49c3/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_0a6b8fb2-729e-4385-8241-839c36b929d7/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_0abca4ab-8e34-409c-997f-481e80e450dc/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_173e5fb9-8203-418d-93c2-4f8c91f2d842/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_22b62201-0570-4ce8-b0a7-0f4b445f6d9e/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_2724efb1-76e1-4147-9620-4defcc65510f/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_35b8bfcd-5a54-48f1-8759-cb1f8ffe775d/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_3bc5193a-604d-4f52-be00-e56277643358/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_3bd500f3-c111-427a-8cd7-a004125d6dc1/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_45ce9ae8-5299-44dc-a1b5-4d63914a9609/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_4779c645-1efc-4c76-ab21-ff93f973ee8f/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_482237cf-87c8-486e-a24d-0941be2f480d/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_4b7e23c8-5680-4edd-a276-88803dd5fb6f/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_4dd3b945-d846-4c7a-94eb-6eeb25a0dc6b/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_4ec41a62-62bb-4be4-b3ce-282d5a33acce/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_4ff7ee7e-0c8a-43d6-a829-7c62c10af3b0/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_7661e4fb-a919-4af1-86f7-3eaef22f1d81/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_7ca872bb-69ab-4e7d-a7c6-4888ec8e7749/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_7e6d5707-2aa5-4770-a7be-6b1be93d0d87/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_87bef50d-3c59-429b-a995-5872f6278c37/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_88d1ea56-0b69-48c4-9fcf-ce1e1f7527ba/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_8bfb6bd7-07d1-4836-ae9d-3c93668c6dfe/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_93355083-e95b-4341-b625-56fcc1e4fc0c/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_999fd94c-ca56-4fec-8d30-8b677cf40ad6/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_a039fd15-7ee1-4bd6-906d-55dea8d0e489/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_a0b7363f-7cc6-4940-8e29-2dc85793a77d/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_a31e8b61-9643-4c78-939d-d1696d0420d9/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_acc51591-256c-4bed-9a51-514b1811f4cd/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_b1efebd9-5981-49fa-8775-20fa00d0c902/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_ba9d4c61-39a3-4852-95d7-bd34e3605a43/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_c549b60f-65fd-48d5-8cd6-2f053292b112/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_d0f839a5-3ab9-42e2-b438-df5825d049fe/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_d826d57e-9817-4f3c-ab94-2bfafa352f6d/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_da102f37-632c-4c0b-be4c-4270a74c06b9/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_df4506f5-67f2-4cf6-9113-93994b76f39b/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_e038e93b-87ea-4122-9578-6540018697b7/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_e0c171c5-407f-44dc-9ef9-e26e8b99ceac/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_e64770bf-7220-4d0f-848c-d751ea1c7376/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_e7f0edda-0fab-484d-ab4d-d8a8e363cd14/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_ec7d9118-8594-4d79-bf79-f43afdfaf156/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_ee06ec01-03e4-485a-ae2b-d8bdb6e7a3a8/manifest.json +0 -6
- package/.flightline/mailboxes/mbx_fd467681-f9cf-4a54-b06a-836df6de2ccc/manifest.json +0 -6
- package/.flightline/progress.db +0 -0
- package/.flightline/recovery.log +0 -1
- package/.flightline/tasks.db +0 -0
- package/.flightline/tech-orders/to_0c93d981-6b4e-4055-8678-f39c009d1db1.json +0 -11
- package/.flightline/tech-orders/to_1862f8ed-c487-4914-9f1e-528af6d4f053.json +0 -11
- package/.flightline/tech-orders/to_2335a57d-f400-4efa-b108-e13ece57520d.json +0 -11
- package/.flightline/tech-orders/to_2bd8dbdd-ac57-4b84-b977-33a3637d10d1.json +0 -11
- package/.flightline/tech-orders/to_37057c01-39b5-403a-991f-afb186abde95.json +0 -11
- package/.flightline/tech-orders/to_9e7288bb-c0fd-488a-a83d-1e9337bd0f1f.json +0 -11
- package/.flightline/tech-orders/to_aa0fe80b-9de7-40f6-a106-353b5bca10bd.json +0 -11
- package/.flightline/tech-orders/to_c1a0f480-c863-4203-a070-76ad77137845.json +0 -11
- package/.flightline/tech-orders/to_cf1e882a-cf56-45a4-8d19-494925e5f449.json +0 -11
- package/.flightline/work-orders/wo_5a29168d-5fb4-41d7-8dac-1d1151d9248f/manifest.json +0 -15
- package/.flightline/work-orders/wo_6c8c38bb-17a1-4885-ada4-dbfc5cc12d7a/manifest.json +0 -15
- package/.flightline/work-orders/wo_cadeb9b2-ea42-4491-b429-e2d467942b5c/manifest.json +0 -12
- package/.flightline/work-orders/wo_cc7b669c-16c4-4ef7-8a76-d1813219d0be/manifest.json +0 -15
- package/dist/agent-lifecycle.js +0 -148
- package/dist/agent-spawner.js +0 -460
- package/dist/agent-validation.js +0 -111
- package/dist/index.js +0 -255
- package/dist/server/api/src/coordination/agent-lifecycle.d.ts +0 -12
- package/dist/server/api/src/coordination/agent-lifecycle.d.ts.map +0 -1
- package/dist/server/api/src/coordination/agent-lifecycle.js +0 -12
- package/dist/server/api/src/coordination/agent-lifecycle.js.map +0 -1
- package/dist/server/api/src/coordination/agent-runner.d.ts +0 -9
- package/dist/server/api/src/coordination/agent-runner.d.ts.map +0 -1
- package/dist/server/api/src/coordination/agent-runner.js +0 -416
- package/dist/server/api/src/coordination/agent-runner.js.map +0 -1
- package/dist/server/api/src/coordination/agent-spawner-routes.d.ts +0 -7
- package/dist/server/api/src/coordination/agent-spawner-routes.d.ts.map +0 -1
- package/dist/server/api/src/coordination/agent-spawner-routes.js +0 -321
- package/dist/server/api/src/coordination/agent-spawner-routes.js.map +0 -1
- package/dist/server/api/src/coordination/agent-spawner.d.ts +0 -187
- package/dist/server/api/src/coordination/agent-spawner.d.ts.map +0 -1
- package/dist/server/api/src/coordination/agent-spawner.js +0 -712
- package/dist/server/api/src/coordination/agent-spawner.js.map +0 -1
- package/dist/server/api/src/coordination/agents.d.ts +0 -13
- package/dist/server/api/src/coordination/agents.d.ts.map +0 -1
- package/dist/server/api/src/coordination/agents.js +0 -464
- package/dist/server/api/src/coordination/agents.js.map +0 -1
- package/dist/server/api/src/coordination/checkpoint-routes.d.ts +0 -33
- package/dist/server/api/src/coordination/checkpoint-routes.d.ts.map +0 -1
- package/dist/server/api/src/coordination/checkpoint-routes.js +0 -323
- package/dist/server/api/src/coordination/checkpoint-routes.js.map +0 -1
- package/dist/server/api/src/coordination/conflict-resolver.d.ts +0 -152
- package/dist/server/api/src/coordination/conflict-resolver.d.ts.map +0 -1
- package/dist/server/api/src/coordination/conflict-resolver.js +0 -502
- package/dist/server/api/src/coordination/conflict-resolver.js.map +0 -1
- package/dist/server/api/src/coordination/missions.d.ts +0 -9
- package/dist/server/api/src/coordination/missions.d.ts.map +0 -1
- package/dist/server/api/src/coordination/missions.js +0 -148
- package/dist/server/api/src/coordination/missions.js.map +0 -1
- package/dist/server/api/src/coordination/monitor.d.ts +0 -175
- package/dist/server/api/src/coordination/monitor.d.ts.map +0 -1
- package/dist/server/api/src/coordination/monitor.js +0 -410
- package/dist/server/api/src/coordination/monitor.js.map +0 -1
- package/dist/server/api/src/coordination/notifier.d.ts +0 -160
- package/dist/server/api/src/coordination/notifier.d.ts.map +0 -1
- package/dist/server/api/src/coordination/notifier.js +0 -422
- package/dist/server/api/src/coordination/notifier.js.map +0 -1
- package/dist/server/api/src/coordination/progress-tracker.d.ts +0 -98
- package/dist/server/api/src/coordination/progress-tracker.d.ts.map +0 -1
- package/dist/server/api/src/coordination/progress-tracker.js +0 -323
- package/dist/server/api/src/coordination/progress-tracker.js.map +0 -1
- package/dist/server/api/src/coordination/recovery-manager.d.ts +0 -135
- package/dist/server/api/src/coordination/recovery-manager.d.ts.map +0 -1
- package/dist/server/api/src/coordination/recovery-manager.js +0 -435
- package/dist/server/api/src/coordination/recovery-manager.js.map +0 -1
- package/dist/server/api/src/coordination/task-decomposer.d.ts +0 -90
- package/dist/server/api/src/coordination/task-decomposer.d.ts.map +0 -1
- package/dist/server/api/src/coordination/task-decomposer.js +0 -412
- package/dist/server/api/src/coordination/task-decomposer.js.map +0 -1
- package/dist/server/api/src/coordination/task-queue-routes.d.ts +0 -7
- package/dist/server/api/src/coordination/task-queue-routes.d.ts.map +0 -1
- package/dist/server/api/src/coordination/task-queue-routes.js +0 -266
- package/dist/server/api/src/coordination/task-queue-routes.js.map +0 -1
- package/dist/server/api/src/coordination/task-queue.d.ts +0 -104
- package/dist/server/api/src/coordination/task-queue.d.ts.map +0 -1
- package/dist/server/api/src/coordination/task-queue.js +0 -378
- package/dist/server/api/src/coordination/task-queue.js.map +0 -1
- package/dist/server/api/src/coordination/tasks.d.ts +0 -7
- package/dist/server/api/src/coordination/tasks.d.ts.map +0 -1
- package/dist/server/api/src/coordination/tasks.js +0 -59
- package/dist/server/api/src/coordination/tasks.js.map +0 -1
- package/dist/server/api/src/decomposition/cli.d.ts +0 -18
- package/dist/server/api/src/decomposition/cli.d.ts.map +0 -1
- package/dist/server/api/src/decomposition/cli.js +0 -191
- package/dist/server/api/src/decomposition/cli.js.map +0 -1
- package/dist/server/api/src/decomposition/codebase-analyzer.d.ts +0 -59
- package/dist/server/api/src/decomposition/codebase-analyzer.d.ts.map +0 -1
- package/dist/server/api/src/decomposition/codebase-analyzer.js +0 -274
- package/dist/server/api/src/decomposition/codebase-analyzer.js.map +0 -1
- package/dist/server/api/src/decomposition/dependency-resolver.d.ts +0 -68
- package/dist/server/api/src/decomposition/dependency-resolver.d.ts.map +0 -1
- package/dist/server/api/src/decomposition/dependency-resolver.js +0 -261
- package/dist/server/api/src/decomposition/dependency-resolver.js.map +0 -1
- package/dist/server/api/src/decomposition/index.d.ts +0 -17
- package/dist/server/api/src/decomposition/index.d.ts.map +0 -1
- package/dist/server/api/src/decomposition/index.js +0 -19
- package/dist/server/api/src/decomposition/index.js.map +0 -1
- package/dist/server/api/src/decomposition/parallelization.d.ts +0 -40
- package/dist/server/api/src/decomposition/parallelization.d.ts.map +0 -1
- package/dist/server/api/src/decomposition/parallelization.js +0 -144
- package/dist/server/api/src/decomposition/parallelization.js.map +0 -1
- package/dist/server/api/src/decomposition/planner.d.ts +0 -84
- package/dist/server/api/src/decomposition/planner.d.ts.map +0 -1
- package/dist/server/api/src/decomposition/planner.js +0 -415
- package/dist/server/api/src/decomposition/planner.js.map +0 -1
- package/dist/server/api/src/decomposition/routes.d.ts +0 -13
- package/dist/server/api/src/decomposition/routes.d.ts.map +0 -1
- package/dist/server/api/src/decomposition/routes.js +0 -114
- package/dist/server/api/src/decomposition/routes.js.map +0 -1
- package/dist/server/api/src/decomposition/strategies.d.ts +0 -43
- package/dist/server/api/src/decomposition/strategies.d.ts.map +0 -1
- package/dist/server/api/src/decomposition/strategies.js +0 -147
- package/dist/server/api/src/decomposition/strategies.js.map +0 -1
- package/dist/server/api/src/decomposition/types.d.ts +0 -1090
- package/dist/server/api/src/decomposition/types.d.ts.map +0 -1
- package/dist/server/api/src/decomposition/types.js +0 -65
- package/dist/server/api/src/decomposition/types.js.map +0 -1
- package/dist/server/api/src/decomposition/validator.d.ts +0 -84
- package/dist/server/api/src/decomposition/validator.d.ts.map +0 -1
- package/dist/server/api/src/decomposition/validator.js +0 -314
- package/dist/server/api/src/decomposition/validator.js.map +0 -1
- package/dist/server/api/src/flightline/ctk.d.ts +0 -2
- package/dist/server/api/src/flightline/ctk.d.ts.map +0 -1
- package/dist/server/api/src/flightline/ctk.js +0 -114
- package/dist/server/api/src/flightline/ctk.js.map +0 -1
- package/dist/server/api/src/flightline/tech-orders.d.ts +0 -2
- package/dist/server/api/src/flightline/tech-orders.d.ts.map +0 -1
- package/dist/server/api/src/flightline/tech-orders.js +0 -74
- package/dist/server/api/src/flightline/tech-orders.js.map +0 -1
- package/dist/server/api/src/flightline/work-orders.d.ts +0 -2
- package/dist/server/api/src/flightline/work-orders.d.ts.map +0 -1
- package/dist/server/api/src/flightline/work-orders.js +0 -178
- package/dist/server/api/src/flightline/work-orders.js.map +0 -1
- package/dist/server/api/src/index.d.ts +0 -3
- package/dist/server/api/src/index.d.ts.map +0 -1
- package/dist/server/api/src/index.js +0 -192
- package/dist/server/api/src/index.js.map +0 -1
- package/dist/server/api/src/middleware/agent-validation.d.ts +0 -161
- package/dist/server/api/src/middleware/agent-validation.d.ts.map +0 -1
- package/dist/server/api/src/middleware/agent-validation.js +0 -112
- package/dist/server/api/src/middleware/agent-validation.js.map +0 -1
- package/dist/server/api/src/middleware/error-handler.d.ts +0 -8
- package/dist/server/api/src/middleware/error-handler.d.ts.map +0 -1
- package/dist/server/api/src/middleware/error-handler.js +0 -54
- package/dist/server/api/src/middleware/error-handler.js.map +0 -1
- package/dist/server/api/src/middleware/logger.d.ts +0 -8
- package/dist/server/api/src/middleware/logger.d.ts.map +0 -1
- package/dist/server/api/src/middleware/logger.js +0 -31
- package/dist/server/api/src/middleware/logger.js.map +0 -1
- package/dist/server/api/src/middleware/validation.d.ts +0 -322
- package/dist/server/api/src/middleware/validation.d.ts.map +0 -1
- package/dist/server/api/src/middleware/validation.js +0 -189
- package/dist/server/api/src/middleware/validation.js.map +0 -1
- package/dist/server/api/src/squawk/blocker-handler.d.ts +0 -111
- package/dist/server/api/src/squawk/blocker-handler.d.ts.map +0 -1
- package/dist/server/api/src/squawk/blocker-handler.js +0 -262
- package/dist/server/api/src/squawk/blocker-handler.js.map +0 -1
- package/dist/server/api/src/squawk/coordinator.d.ts +0 -2
- package/dist/server/api/src/squawk/coordinator.d.ts.map +0 -1
- package/dist/server/api/src/squawk/coordinator.js +0 -24
- package/dist/server/api/src/squawk/coordinator.js.map +0 -1
- package/dist/server/api/src/squawk/cursor.d.ts +0 -2
- package/dist/server/api/src/squawk/cursor.d.ts.map +0 -1
- package/dist/server/api/src/squawk/cursor.js +0 -55
- package/dist/server/api/src/squawk/cursor.js.map +0 -1
- package/dist/server/api/src/squawk/dependency-resolver.d.ts +0 -107
- package/dist/server/api/src/squawk/dependency-resolver.d.ts.map +0 -1
- package/dist/server/api/src/squawk/dependency-resolver.js +0 -324
- package/dist/server/api/src/squawk/dependency-resolver.js.map +0 -1
- package/dist/server/api/src/squawk/dispatch-orchestrator.d.ts +0 -117
- package/dist/server/api/src/squawk/dispatch-orchestrator.d.ts.map +0 -1
- package/dist/server/api/src/squawk/dispatch-orchestrator.js +0 -296
- package/dist/server/api/src/squawk/dispatch-orchestrator.js.map +0 -1
- package/dist/server/api/src/squawk/lock-coordinator.d.ts +0 -118
- package/dist/server/api/src/squawk/lock-coordinator.d.ts.map +0 -1
- package/dist/server/api/src/squawk/lock-coordinator.js +0 -279
- package/dist/server/api/src/squawk/lock-coordinator.js.map +0 -1
- package/dist/server/api/src/squawk/lock.d.ts +0 -2
- package/dist/server/api/src/squawk/lock.d.ts.map +0 -1
- package/dist/server/api/src/squawk/lock.js +0 -87
- package/dist/server/api/src/squawk/lock.js.map +0 -1
- package/dist/server/api/src/squawk/mailbox.d.ts +0 -2
- package/dist/server/api/src/squawk/mailbox.d.ts.map +0 -1
- package/dist/server/api/src/squawk/mailbox.js +0 -66
- package/dist/server/api/src/squawk/mailbox.js.map +0 -1
- package/dist/server/api/src/squawk/spawning.d.ts +0 -79
- package/dist/server/api/src/squawk/spawning.d.ts.map +0 -1
- package/dist/server/api/src/squawk/spawning.js +0 -226
- package/dist/server/api/src/squawk/spawning.js.map +0 -1
- package/dist/server/api/src/squawk/specialist-tools.d.ts +0 -206
- package/dist/server/api/src/squawk/specialist-tools.d.ts.map +0 -1
- package/dist/server/api/src/squawk/specialist-tools.js +0 -411
- package/dist/server/api/src/squawk/specialist-tools.js.map +0 -1
- package/dist/server/api/src/types/api.d.ts +0 -63
- package/dist/server/api/src/types/api.d.ts.map +0 -1
- package/dist/server/api/src/types/api.js +0 -5
- package/dist/server/api/src/types/api.js.map +0 -1
- package/dist/squawk/src/db/index.d.ts +0 -30
- package/dist/squawk/src/db/index.d.ts.map +0 -1
- package/dist/squawk/src/db/index.js +0 -329
- package/dist/squawk/src/db/index.js.map +0 -1
- package/dist/squawk/src/db/sqlite.d.ts +0 -31
- package/dist/squawk/src/db/sqlite.d.ts.map +0 -1
- package/dist/squawk/src/db/sqlite.js +0 -558
- package/dist/squawk/src/db/sqlite.js.map +0 -1
- package/dist/squawk/src/db/types.d.ts +0 -611
- package/dist/squawk/src/db/types.d.ts.map +0 -1
- package/dist/squawk/src/db/types.js +0 -4
- package/dist/squawk/src/db/types.js.map +0 -1
- package/dist/task-queue.js +0 -377
- package/dist/validation.js +0 -188
- package/e2e-integration.test.ts +0 -290
- package/integration.test.ts +0 -186
- package/phase1-integration.test.ts +0 -455
- package/phase2-verification.test.ts +0 -135
- package/server.log +0 -58
- package/src/agent-runner.js +0 -877
- package/src/coordination/agent-lifecycle.ts +0 -13
- package/src/coordination/agent-runner.ts +0 -479
- package/src/coordination/agent-spawner-routes.ts +0 -340
- package/src/coordination/agent-spawner.ts +0 -885
- package/src/coordination/agents.ts +0 -525
- package/src/coordination/checkpoint-routes.ts +0 -382
- package/src/coordination/conflict-resolver.ts +0 -640
- package/src/coordination/missions.ts +0 -219
- package/src/coordination/monitor.ts +0 -593
- package/src/coordination/notifier.ts +0 -547
- package/src/coordination/progress-tracker.ts +0 -410
- package/src/coordination/recovery-manager.ts +0 -531
- package/src/coordination/task-decomposer.ts +0 -491
- package/src/coordination/task-queue-routes.ts +0 -284
- package/src/coordination/task-queue.ts +0 -480
- package/src/coordination/tasks.ts +0 -72
- package/src/flightline/ctk.ts +0 -131
- package/src/flightline/tech-orders.ts +0 -85
- package/src/flightline/work-orders.ts +0 -202
- package/src/index.ts +0 -211
- package/src/middleware/agent-validation.ts +0 -130
- package/src/middleware/error-handler.ts +0 -59
- package/src/middleware/logger.ts +0 -37
- package/src/middleware/validation.ts +0 -235
- package/src/squawk/coordinator.ts +0 -26
- package/src/squawk/cursor.ts +0 -62
- package/src/squawk/lock.ts +0 -98
- package/src/squawk/mailbox.ts +0 -75
- package/src/types/api.ts +0 -71
- package/test-api.ts +0 -310
- package/test-enhanced-agents.ts +0 -428
|
@@ -1,885 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Spawner for FleetTools Coordination System
|
|
3
|
-
*
|
|
4
|
-
* Manages agent lifecycle: spawning, monitoring, and termination
|
|
5
|
-
* Integrates with Squawk mailbox system for coordination
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { randomUUID } from 'node:crypto';
|
|
9
|
-
import path from 'node:path';
|
|
10
|
-
|
|
11
|
-
export enum AgentType {
|
|
12
|
-
FRONTEND = 'frontend',
|
|
13
|
-
BACKEND = 'backend',
|
|
14
|
-
TESTING = 'testing',
|
|
15
|
-
DOCUMENTATION = 'documentation',
|
|
16
|
-
SECURITY = 'security',
|
|
17
|
-
PERFORMANCE = 'performance'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export enum AgentStatus {
|
|
21
|
-
SPAWNING = 'spawning',
|
|
22
|
-
RUNNING = 'running',
|
|
23
|
-
IDLE = 'idle',
|
|
24
|
-
BUSY = 'busy',
|
|
25
|
-
ERROR = 'error',
|
|
26
|
-
TERMINATED = 'terminated',
|
|
27
|
-
FAILED = 'failed'
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface AgentHandle {
|
|
31
|
-
id: string;
|
|
32
|
-
type: AgentType;
|
|
33
|
-
pid?: number;
|
|
34
|
-
status: AgentStatus;
|
|
35
|
-
mailboxId: string;
|
|
36
|
-
createdAt: string;
|
|
37
|
-
updatedAt: string;
|
|
38
|
-
metadata: Record<string, any>;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface AgentSpawnRequest {
|
|
42
|
-
type: AgentType;
|
|
43
|
-
task?: string;
|
|
44
|
-
metadata?: Record<string, any>;
|
|
45
|
-
config?: AgentConfig;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export interface AgentConfig {
|
|
49
|
-
timeout?: number;
|
|
50
|
-
retries?: number;
|
|
51
|
-
resources?: {
|
|
52
|
-
memory?: string;
|
|
53
|
-
cpu?: string;
|
|
54
|
-
};
|
|
55
|
-
environment?: Record<string, string>;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface AgentMonitor {
|
|
59
|
-
status: AgentStatus;
|
|
60
|
-
uptime?: number;
|
|
61
|
-
lastHeartbeat?: string;
|
|
62
|
-
resourceUsage?: {
|
|
63
|
-
memory: number;
|
|
64
|
-
cpu: number;
|
|
65
|
-
};
|
|
66
|
-
errors: Array<{
|
|
67
|
-
timestamp: string;
|
|
68
|
-
error: string;
|
|
69
|
-
count: number;
|
|
70
|
-
}>;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export class AgentSpawner {
|
|
74
|
-
private agents: Map<string, AgentHandle> = new Map();
|
|
75
|
-
private mailboxPath: string;
|
|
76
|
-
private heartbeatInterval?: ReturnType<typeof setInterval>;
|
|
77
|
-
private recoveryInterval?: ReturnType<typeof setInterval>;
|
|
78
|
-
private readonly heartbeatTimeout = 60000; // 60 seconds
|
|
79
|
-
private readonly recoveryEnabled = true;
|
|
80
|
-
|
|
81
|
-
constructor(mailboxPath?: string) {
|
|
82
|
-
this.mailboxPath = mailboxPath || path.join(process.cwd(), '.flightline', 'mailboxes');
|
|
83
|
-
this.startHeartbeatMonitoring();
|
|
84
|
-
this.startRecoveryMonitoring();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Spawn a new agent with timeout and retry logic
|
|
89
|
-
*/
|
|
90
|
-
async spawn(request: AgentSpawnRequest): Promise<AgentHandle> {
|
|
91
|
-
const agentId = `agt_${randomUUID()}`;
|
|
92
|
-
const mailboxId = `mbx_${randomUUID()}`;
|
|
93
|
-
const timeout = request.config?.timeout || 300000;
|
|
94
|
-
const maxRetries = request.config?.retries || 3;
|
|
95
|
-
|
|
96
|
-
const agent: AgentHandle = {
|
|
97
|
-
id: agentId,
|
|
98
|
-
type: request.type,
|
|
99
|
-
status: AgentStatus.SPAWNING,
|
|
100
|
-
mailboxId,
|
|
101
|
-
createdAt: new Date().toISOString(),
|
|
102
|
-
updatedAt: new Date().toISOString(),
|
|
103
|
-
metadata: {
|
|
104
|
-
...request.metadata,
|
|
105
|
-
spawnRequest: request,
|
|
106
|
-
spawnAttempts: 0,
|
|
107
|
-
maxRetries
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
let lastError: any = null;
|
|
112
|
-
|
|
113
|
-
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
114
|
-
try {
|
|
115
|
-
agent.metadata!.spawnAttempts = attempt;
|
|
116
|
-
agent.updatedAt = new Date().toISOString();
|
|
117
|
-
|
|
118
|
-
await this.createMailbox(mailboxId, agentId);
|
|
119
|
-
|
|
120
|
-
const pid = await this.executeAgentSpawn(agent, request);
|
|
121
|
-
agent.pid = pid;
|
|
122
|
-
agent.status = AgentStatus.RUNNING;
|
|
123
|
-
agent.updatedAt = new Date().toISOString();
|
|
124
|
-
|
|
125
|
-
this.agents.set(agentId, agent);
|
|
126
|
-
|
|
127
|
-
console.log(`✓ Agent spawned: ${agentId} (${request.type}) - attempt ${attempt}`);
|
|
128
|
-
return agent;
|
|
129
|
-
} catch (error: any) {
|
|
130
|
-
lastError = error;
|
|
131
|
-
agent.status = AgentStatus.FAILED;
|
|
132
|
-
agent.updatedAt = new Date().toISOString();
|
|
133
|
-
|
|
134
|
-
console.error(`✗ Agent spawn attempt ${attempt} failed:`, error.message);
|
|
135
|
-
|
|
136
|
-
if (attempt < maxRetries) {
|
|
137
|
-
const retryDelay = Math.min(5000 * attempt, 15000);
|
|
138
|
-
console.log(`Retrying agent spawn in ${retryDelay}ms...`);
|
|
139
|
-
await new Promise(resolve => setTimeout(resolve, retryDelay));
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
await this.cleanupFailedSpawn(agentId);
|
|
143
|
-
} catch (cleanupError: any) {
|
|
144
|
-
console.error(`Cleanup failed:`, cleanupError.message);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
agent.status = AgentStatus.FAILED;
|
|
151
|
-
agent.updatedAt = new Date().toISOString();
|
|
152
|
-
agent.metadata!.lastError = lastError?.message || 'Unknown error';
|
|
153
|
-
this.agents.set(agentId, agent);
|
|
154
|
-
|
|
155
|
-
console.error(`✗ Agent spawn failed after ${maxRetries} attempts: ${agentId}`);
|
|
156
|
-
throw new Error(`Agent spawn failed after ${maxRetries} attempts: ${lastError?.message}`);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Monitor agent status and health with comprehensive checks
|
|
161
|
-
*/
|
|
162
|
-
async monitor(agentId: string): Promise<AgentMonitor> {
|
|
163
|
-
const agent = this.agents.get(agentId);
|
|
164
|
-
if (!agent) {
|
|
165
|
-
throw new Error(`Agent not found: ${agentId}`);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const monitor: AgentMonitor = {
|
|
169
|
-
status: agent.status,
|
|
170
|
-
uptime: this.calculateUptime(agent.createdAt),
|
|
171
|
-
lastHeartbeat: await this.getLastHeartbeat(agentId),
|
|
172
|
-
resourceUsage: await this.getAgentResourceUsage(agentId),
|
|
173
|
-
errors: await this.getAgentErrors(agentId)
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
if (agent.pid) {
|
|
177
|
-
try {
|
|
178
|
-
process.kill(agent.pid, 0);
|
|
179
|
-
monitor.status = AgentStatus.RUNNING;
|
|
180
|
-
|
|
181
|
-
if (agent.status !== AgentStatus.RUNNING) {
|
|
182
|
-
agent.status = AgentStatus.RUNNING;
|
|
183
|
-
agent.updatedAt = new Date().toISOString();
|
|
184
|
-
this.agents.set(agentId, agent);
|
|
185
|
-
}
|
|
186
|
-
} catch {
|
|
187
|
-
monitor.status = AgentStatus.TERMINATED;
|
|
188
|
-
agent.status = AgentStatus.TERMINATED;
|
|
189
|
-
agent.updatedAt = new Date().toISOString();
|
|
190
|
-
this.agents.set(agentId, agent);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (monitor.errors && monitor.errors.length > 5) {
|
|
195
|
-
monitor.status = AgentStatus.ERROR;
|
|
196
|
-
agent.status = AgentStatus.ERROR;
|
|
197
|
-
agent.updatedAt = new Date().toISOString();
|
|
198
|
-
this.agents.set(agentId, agent);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
return monitor;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Terminate an agent
|
|
206
|
-
*/
|
|
207
|
-
async terminate(agentId: string, graceful = true): Promise<void> {
|
|
208
|
-
const agent = this.agents.get(agentId);
|
|
209
|
-
if (!agent) {
|
|
210
|
-
throw new Error(`Agent not found: ${agentId}`);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
console.log(`Terminating agent: ${agentId} (${agent.type})`);
|
|
214
|
-
|
|
215
|
-
try {
|
|
216
|
-
if (agent.pid) {
|
|
217
|
-
if (graceful) {
|
|
218
|
-
process.kill(agent.pid, 'SIGTERM');
|
|
219
|
-
|
|
220
|
-
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
221
|
-
|
|
222
|
-
try {
|
|
223
|
-
process.kill(agent.pid, 0);
|
|
224
|
-
process.kill(agent.pid, 'SIGKILL');
|
|
225
|
-
console.log(`⚠️ Force killed agent: ${agentId}`);
|
|
226
|
-
} catch {
|
|
227
|
-
console.log(`✓ Agent terminated gracefully: ${agentId}`);
|
|
228
|
-
}
|
|
229
|
-
} else {
|
|
230
|
-
process.kill(agent.pid, 'SIGKILL');
|
|
231
|
-
console.log(`✓ Agent terminated: ${agentId}`);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
await this.cleanupMailbox(agent.mailboxId);
|
|
236
|
-
|
|
237
|
-
agent.status = AgentStatus.TERMINATED;
|
|
238
|
-
agent.updatedAt = new Date().toISOString();
|
|
239
|
-
|
|
240
|
-
console.log(`✓ Agent cleanup complete: ${agentId}`);
|
|
241
|
-
} catch (error: any) {
|
|
242
|
-
agent.status = AgentStatus.ERROR;
|
|
243
|
-
agent.updatedAt = new Date().toISOString();
|
|
244
|
-
|
|
245
|
-
console.error(`✗ Error terminating agent ${agentId}:`, error.message);
|
|
246
|
-
throw new Error(`Agent termination failed: ${error.message}`);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Get all active agents
|
|
252
|
-
*/
|
|
253
|
-
getActiveAgents(): AgentHandle[] {
|
|
254
|
-
return Array.from(this.agents.values()).filter(
|
|
255
|
-
agent => agent.status === AgentStatus.RUNNING ||
|
|
256
|
-
agent.status === AgentStatus.IDLE ||
|
|
257
|
-
agent.status === AgentStatus.BUSY
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Get agents by type
|
|
263
|
-
*/
|
|
264
|
-
getAgentsByType(type: AgentType): AgentHandle[] {
|
|
265
|
-
return Array.from(this.agents.values()).filter(agent => agent.type === type);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Get agent by ID
|
|
270
|
-
*/
|
|
271
|
-
getAgent(agentId: string): AgentHandle | undefined {
|
|
272
|
-
return this.agents.get(agentId);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
private async createMailbox(mailboxId: string, agentId: string): Promise<void> {
|
|
276
|
-
const mailboxDir = path.join(this.mailboxPath, mailboxId);
|
|
277
|
-
|
|
278
|
-
await this.ensureDirectory(mailboxDir);
|
|
279
|
-
|
|
280
|
-
const manifest = {
|
|
281
|
-
id: mailboxId,
|
|
282
|
-
agentId,
|
|
283
|
-
createdAt: new Date().toISOString(),
|
|
284
|
-
type: 'agent-mailbox'
|
|
285
|
-
};
|
|
286
|
-
|
|
287
|
-
const manifestPath = path.join(mailboxDir, 'manifest.json');
|
|
288
|
-
await this.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
private async cleanupMailbox(mailboxId: string): Promise<void> {
|
|
292
|
-
const mailboxDir = path.join(this.mailboxPath, mailboxId);
|
|
293
|
-
|
|
294
|
-
try {
|
|
295
|
-
await this.removeDirectory(mailboxDir);
|
|
296
|
-
console.log(`✓ Cleaned up mailbox: ${mailboxId}`);
|
|
297
|
-
} catch (error: any) {
|
|
298
|
-
console.error(`⚠️ Failed to cleanup mailbox ${mailboxId}:`, error.message);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
private async executeAgentSpawn(agent: AgentHandle, request: AgentSpawnRequest): Promise<number> {
|
|
303
|
-
const { spawn } = await import('node:child_process');
|
|
304
|
-
|
|
305
|
-
return new Promise((resolve, reject) => {
|
|
306
|
-
const args = [
|
|
307
|
-
'src/agent-runner.js',
|
|
308
|
-
'--agent-id', agent.id,
|
|
309
|
-
'--agent-type', agent.type,
|
|
310
|
-
'--mailbox-id', agent.mailboxId,
|
|
311
|
-
'--task', request.task || ''
|
|
312
|
-
];
|
|
313
|
-
|
|
314
|
-
if (request.config?.timeout) {
|
|
315
|
-
args.push('--timeout', request.config.timeout.toString());
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const childProcess = spawn('bun', args, {
|
|
319
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
320
|
-
detached: false,
|
|
321
|
-
cwd: process.cwd()
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
childProcess.on('spawn', () => {
|
|
325
|
-
console.log(`Agent process spawned with PID: ${childProcess.pid}`);
|
|
326
|
-
resolve(childProcess.pid!);
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
childProcess.on('error', (error) => {
|
|
330
|
-
console.error(`Failed to spawn agent process:`, error);
|
|
331
|
-
reject(error);
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
if (childProcess.stdout) {
|
|
335
|
-
childProcess.stdout.on('data', (data) => {
|
|
336
|
-
console.log(`[${agent.id}] ${data.toString().trim()}`);
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (childProcess.stderr) {
|
|
341
|
-
childProcess.stderr.on('data', (data) => {
|
|
342
|
-
console.error(`[${agent.id}] ERROR: ${data.toString().trim()}`);
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
childProcess.on('close', (code) => {
|
|
347
|
-
if (code !== 0) {
|
|
348
|
-
console.log(`Agent ${agent.id} exited with code: ${code}`);
|
|
349
|
-
}
|
|
350
|
-
});
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
private async cleanupFailedSpawn(agentId: string): Promise<void> {
|
|
355
|
-
try {
|
|
356
|
-
const agent = this.agents.get(agentId);
|
|
357
|
-
if (agent?.pid) {
|
|
358
|
-
try {
|
|
359
|
-
process.kill(agent.pid, 'SIGKILL');
|
|
360
|
-
console.log(`✓ Cleaned up process ${agent.pid}`);
|
|
361
|
-
} catch {
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
const agentHandle = this.agents.get(agentId);
|
|
366
|
-
if (agentHandle?.mailboxId) {
|
|
367
|
-
await this.cleanupMailbox(agentHandle.mailboxId);
|
|
368
|
-
}
|
|
369
|
-
} catch (error: any) {
|
|
370
|
-
console.error(`Cleanup error for ${agentId}:`, error.message);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
private async getLastHeartbeat(agentId: string): Promise<string | undefined> {
|
|
375
|
-
const agent = this.agents.get(agentId);
|
|
376
|
-
return agent?.metadata?.lastHeartbeat;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
private async getAgentErrors(agentId: string): Promise<Array<{ timestamp: string; error: string; count: number }>> {
|
|
380
|
-
const agent = this.agents.get(agentId);
|
|
381
|
-
return agent?.metadata?.errors || [];
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
private async getAgentResourceUsage(agentId: string): Promise<{ memory: number; cpu: number } | undefined> {
|
|
385
|
-
const agent = this.agents.get(agentId);
|
|
386
|
-
if (agent?.pid) {
|
|
387
|
-
try {
|
|
388
|
-
// Get actual resource usage using process information
|
|
389
|
-
const usage = await this.getProcessResourceUsage(agent.pid);
|
|
390
|
-
|
|
391
|
-
// Store usage history for trend analysis
|
|
392
|
-
this.storeResourceHistory(agentId, usage);
|
|
393
|
-
|
|
394
|
-
return usage;
|
|
395
|
-
} catch (error) {
|
|
396
|
-
console.warn(`Failed to get resource usage for agent ${agentId}:`, error);
|
|
397
|
-
return undefined;
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
return undefined;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
private async getProcessResourceUsage(pid: number): Promise<{ memory: number; cpu: number }> {
|
|
404
|
-
try {
|
|
405
|
-
// Try to get actual process resource usage
|
|
406
|
-
if (process.platform === 'linux') {
|
|
407
|
-
return await this.getLinuxProcessUsage(pid);
|
|
408
|
-
} else if (process.platform === 'darwin') {
|
|
409
|
-
return await this.getMacOSProcessUsage(pid);
|
|
410
|
-
} else {
|
|
411
|
-
// Fallback to mock data for other platforms
|
|
412
|
-
return this.getMockResourceUsage();
|
|
413
|
-
}
|
|
414
|
-
} catch (error) {
|
|
415
|
-
// Fallback to mock data if actual measurement fails
|
|
416
|
-
return this.getMockResourceUsage();
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
private async getLinuxProcessUsage(pid: number): Promise<{ memory: number; cpu: number }> {
|
|
421
|
-
const { exec } = await import('node:child_process');
|
|
422
|
-
|
|
423
|
-
return new Promise((resolve, reject) => {
|
|
424
|
-
exec(`ps -p ${pid} -o %mem,%cpu --no-headers`, (error, stdout) => {
|
|
425
|
-
if (error) {
|
|
426
|
-
reject(error);
|
|
427
|
-
return;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
const match = stdout.trim().match(/\s*(\d+\.?\d*)\s+(\d+\.?\d*)/);
|
|
431
|
-
if (match) {
|
|
432
|
-
resolve({
|
|
433
|
-
memory: parseFloat(match[1]) * 10, // Convert percentage to MB estimate
|
|
434
|
-
cpu: parseFloat(match[2])
|
|
435
|
-
});
|
|
436
|
-
} else {
|
|
437
|
-
reject(new Error('Failed to parse process usage'));
|
|
438
|
-
}
|
|
439
|
-
});
|
|
440
|
-
});
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
private async getMacOSProcessUsage(pid: number): Promise<{ memory: number; cpu: number }> {
|
|
444
|
-
const { exec } = await import('node:child_process');
|
|
445
|
-
|
|
446
|
-
return new Promise((resolve, reject) => {
|
|
447
|
-
exec(`ps -p ${pid} -o %mem,%cpu -r`, (error, stdout) => {
|
|
448
|
-
if (error) {
|
|
449
|
-
reject(error);
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
const lines = stdout.trim().split('\n');
|
|
454
|
-
if (lines.length > 1) {
|
|
455
|
-
const match = lines[1].match(/\s*(\d+\.?\d*)\s+(\d+\.?\d*)/);
|
|
456
|
-
if (match) {
|
|
457
|
-
resolve({
|
|
458
|
-
memory: parseFloat(match[1]) * 10, // Convert percentage to MB estimate
|
|
459
|
-
cpu: parseFloat(match[2])
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
reject(new Error('Failed to parse macOS process usage'));
|
|
465
|
-
});
|
|
466
|
-
});
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
private getMockResourceUsage(): { memory: number; cpu: number } {
|
|
470
|
-
return {
|
|
471
|
-
memory: Math.floor(Math.random() * 200) + 50,
|
|
472
|
-
cpu: Math.floor(Math.random() * 60) + 5
|
|
473
|
-
};
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
private storeResourceHistory(agentId: string, usage: { memory: number; cpu: number }): void {
|
|
477
|
-
const agent = this.agents.get(agentId);
|
|
478
|
-
if (!agent) return;
|
|
479
|
-
|
|
480
|
-
const history = agent.metadata?.resourceHistory || [];
|
|
481
|
-
history.push({
|
|
482
|
-
timestamp: new Date().toISOString(),
|
|
483
|
-
...usage
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
// Keep only last 100 data points
|
|
487
|
-
const recentHistory = history.slice(-100);
|
|
488
|
-
|
|
489
|
-
agent.metadata = {
|
|
490
|
-
...agent.metadata,
|
|
491
|
-
resourceHistory: recentHistory,
|
|
492
|
-
lastResourceCheck: new Date().toISOString()
|
|
493
|
-
};
|
|
494
|
-
|
|
495
|
-
this.agents.set(agentId, agent);
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
async getResourceHistory(agentId: string): Promise<Array<{ timestamp: string; memory: number; cpu: number }>> {
|
|
499
|
-
const agent = this.agents.get(agentId);
|
|
500
|
-
return agent?.metadata?.resourceHistory || [];
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
async getResourceTrends(agentId: string): Promise<{
|
|
504
|
-
avgMemory: number;
|
|
505
|
-
avgCpu: number;
|
|
506
|
-
peakMemory: number;
|
|
507
|
-
peakCpu: number;
|
|
508
|
-
}> {
|
|
509
|
-
const history = await this.getResourceHistory(agentId);
|
|
510
|
-
|
|
511
|
-
if (history.length === 0) {
|
|
512
|
-
return { avgMemory: 0, avgCpu: 0, peakMemory: 0, peakCpu: 0 };
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
const memoryValues = history.map(h => h.memory);
|
|
516
|
-
const cpuValues = history.map(h => h.cpu);
|
|
517
|
-
|
|
518
|
-
return {
|
|
519
|
-
avgMemory: memoryValues.reduce((a, b) => a + b, 0) / memoryValues.length,
|
|
520
|
-
avgCpu: cpuValues.reduce((a, b) => a + b, 0) / cpuValues.length,
|
|
521
|
-
peakMemory: Math.max(...memoryValues),
|
|
522
|
-
peakCpu: Math.max(...cpuValues)
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
async updateHeartbeat(agentId: string): Promise<void> {
|
|
527
|
-
const agent = this.agents.get(agentId);
|
|
528
|
-
if (!agent) return;
|
|
529
|
-
|
|
530
|
-
agent.metadata = {
|
|
531
|
-
...agent.metadata,
|
|
532
|
-
lastHeartbeat: new Date().toISOString()
|
|
533
|
-
};
|
|
534
|
-
agent.updatedAt = new Date().toISOString();
|
|
535
|
-
|
|
536
|
-
this.agents.set(agentId, agent);
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
async logError(agentId: string, error: string): Promise<void> {
|
|
540
|
-
const agent = this.agents.get(agentId);
|
|
541
|
-
if (!agent) return;
|
|
542
|
-
|
|
543
|
-
const errors = agent.metadata?.errors || [];
|
|
544
|
-
const errorEntry = {
|
|
545
|
-
timestamp: new Date().toISOString(),
|
|
546
|
-
error,
|
|
547
|
-
count: 1
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
const existingError = errors.find(e => e.error === error);
|
|
551
|
-
if (existingError) {
|
|
552
|
-
existingError.count++;
|
|
553
|
-
existingError.timestamp = new Date().toISOString();
|
|
554
|
-
} else {
|
|
555
|
-
errors.push(errorEntry);
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
agent.metadata = {
|
|
559
|
-
...agent.metadata,
|
|
560
|
-
errors: errors.slice(-10)
|
|
561
|
-
};
|
|
562
|
-
agent.updatedAt = new Date().toISOString();
|
|
563
|
-
|
|
564
|
-
this.agents.set(agentId, agent);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
private calculateUptime(createdAt: string): number {
|
|
568
|
-
const created = new Date(createdAt).getTime();
|
|
569
|
-
const now = Date.now();
|
|
570
|
-
return Math.floor((now - created) / 1000);
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
private async ensureDirectory(dirPath: string): Promise<void> {
|
|
574
|
-
const { mkdir } = await import('node:fs/promises');
|
|
575
|
-
await mkdir(dirPath, { recursive: true });
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
private async writeFile(filePath: string, content: string): Promise<void> {
|
|
579
|
-
const { writeFile } = await import('node:fs/promises');
|
|
580
|
-
await writeFile(filePath, content, 'utf-8');
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
private async removeDirectory(dirPath: string): Promise<void> {
|
|
584
|
-
const { rm } = await import('node:fs/promises');
|
|
585
|
-
await rm(dirPath, { recursive: true, force: true });
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
/**
|
|
589
|
-
* Start heartbeat monitoring for all agents
|
|
590
|
-
*/
|
|
591
|
-
private startHeartbeatMonitoring(): void {
|
|
592
|
-
this.heartbeatInterval = setInterval(async () => {
|
|
593
|
-
await this.checkAgentHeartbeats();
|
|
594
|
-
}, 30000); // Check every 30 seconds
|
|
595
|
-
|
|
596
|
-
console.log('✓ Agent heartbeat monitoring started');
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
/**
|
|
600
|
-
* Start automatic recovery monitoring
|
|
601
|
-
*/
|
|
602
|
-
private startRecoveryMonitoring(): void {
|
|
603
|
-
if (!this.recoveryEnabled) return;
|
|
604
|
-
|
|
605
|
-
this.recoveryInterval = setInterval(async () => {
|
|
606
|
-
await this.performRecoveryChecks();
|
|
607
|
-
}, 60000); // Check every minute
|
|
608
|
-
|
|
609
|
-
console.log('✓ Agent recovery monitoring started');
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
/**
|
|
613
|
-
* Check heartbeats for all running agents
|
|
614
|
-
*/
|
|
615
|
-
private async checkAgentHeartbeats(): Promise<void> {
|
|
616
|
-
const now = Date.now();
|
|
617
|
-
const agentsToCheck = Array.from(this.agents.values())
|
|
618
|
-
.filter(agent => agent.status === AgentStatus.RUNNING || agent.status === AgentStatus.BUSY);
|
|
619
|
-
|
|
620
|
-
for (const agent of agentsToCheck) {
|
|
621
|
-
const lastHeartbeat = agent.metadata?.lastHeartbeat;
|
|
622
|
-
|
|
623
|
-
if (lastHeartbeat) {
|
|
624
|
-
const lastHeartbeatTime = new Date(lastHeartbeat).getTime();
|
|
625
|
-
const timeSinceLastHeartbeat = now - lastHeartbeatTime;
|
|
626
|
-
|
|
627
|
-
if (timeSinceLastHeartbeat > this.heartbeatTimeout) {
|
|
628
|
-
console.warn(`⚠️ Agent ${agent.id} missed heartbeat (${timeSinceLastHeartbeat}ms ago)`);
|
|
629
|
-
await this.handleMissedHeartbeat(agent);
|
|
630
|
-
}
|
|
631
|
-
} else {
|
|
632
|
-
console.warn(`⚠️ Agent ${agent.id} has no heartbeat recorded`);
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
/**
|
|
638
|
-
* Handle missed heartbeat scenarios
|
|
639
|
-
*/
|
|
640
|
-
private async handleMissedHeartbeat(agent: AgentHandle): Promise<void> {
|
|
641
|
-
// Check if process is still running
|
|
642
|
-
if (agent.pid) {
|
|
643
|
-
try {
|
|
644
|
-
process.kill(agent.pid, 0); // Check if process exists
|
|
645
|
-
|
|
646
|
-
// Process exists but no heartbeat - might be stuck
|
|
647
|
-
agent.status = AgentStatus.ERROR;
|
|
648
|
-
agent.metadata = {
|
|
649
|
-
...agent.metadata,
|
|
650
|
-
error: 'Missed heartbeat but process running',
|
|
651
|
-
missedHeartbeatAt: new Date().toISOString()
|
|
652
|
-
};
|
|
653
|
-
agent.updatedAt = new Date().toISOString();
|
|
654
|
-
|
|
655
|
-
this.agents.set(agent.id, agent);
|
|
656
|
-
|
|
657
|
-
console.warn(`⚠️ Agent ${agent.id} marked as error due to missed heartbeat`);
|
|
658
|
-
|
|
659
|
-
// Send recovery event
|
|
660
|
-
await this.sendRecoveryEvent(agent, 'missed_heartbeat');
|
|
661
|
-
} catch {
|
|
662
|
-
// Process doesn't exist - agent died
|
|
663
|
-
agent.status = AgentStatus.FAILED;
|
|
664
|
-
agent.metadata = {
|
|
665
|
-
...agent.metadata,
|
|
666
|
-
error: 'Process died - no heartbeat received',
|
|
667
|
-
diedAt: new Date().toISOString()
|
|
668
|
-
};
|
|
669
|
-
agent.updatedAt = new Date().toISOString();
|
|
670
|
-
|
|
671
|
-
this.agents.set(agent.id, agent);
|
|
672
|
-
|
|
673
|
-
console.error(`❌ Agent ${agent.id} failed - process died`);
|
|
674
|
-
|
|
675
|
-
// Attempt recovery
|
|
676
|
-
await this.attemptAgentRecovery(agent);
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
/**
|
|
682
|
-
* Perform recovery checks and attempts
|
|
683
|
-
*/
|
|
684
|
-
private async performRecoveryChecks(): Promise<void> {
|
|
685
|
-
const failedAgents = Array.from(this.agents.values())
|
|
686
|
-
.filter(agent => agent.status === AgentStatus.FAILED || agent.status === AgentStatus.ERROR);
|
|
687
|
-
|
|
688
|
-
for (const agent of failedAgents) {
|
|
689
|
-
const lastRecoveryAttempt = agent.metadata?.lastRecoveryAttempt;
|
|
690
|
-
const now = Date.now();
|
|
691
|
-
|
|
692
|
-
// Only attempt recovery if not tried recently (5 minute cooldown)
|
|
693
|
-
if (!lastRecoveryAttempt || (now - new Date(lastRecoveryAttempt).getTime() > 300000)) {
|
|
694
|
-
await this.attemptAgentRecovery(agent);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
/**
|
|
700
|
-
* Attempt to recover a failed agent
|
|
701
|
-
*/
|
|
702
|
-
private async attemptAgentRecovery(agent: AgentHandle): Promise<void> {
|
|
703
|
-
console.log(`🔄 Attempting to recover agent ${agent.id}...`);
|
|
704
|
-
|
|
705
|
-
try {
|
|
706
|
-
// Mark recovery attempt
|
|
707
|
-
agent.metadata = {
|
|
708
|
-
...agent.metadata,
|
|
709
|
-
lastRecoveryAttempt: new Date().toISOString(),
|
|
710
|
-
recoveryAttempts: (agent.metadata?.recoveryAttempts || 0) + 1
|
|
711
|
-
};
|
|
712
|
-
|
|
713
|
-
// Check if we've exceeded max recovery attempts
|
|
714
|
-
if (agent.metadata.recoveryAttempts > 3) {
|
|
715
|
-
console.error(`❌ Agent ${agent.id} exceeded max recovery attempts`);
|
|
716
|
-
await this.sendRecoveryEvent(agent, 'recovery_exhausted');
|
|
717
|
-
return;
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
// Clean up existing process if any
|
|
721
|
-
if (agent.pid) {
|
|
722
|
-
try {
|
|
723
|
-
process.kill(agent.pid, 'SIGKILL');
|
|
724
|
-
} catch {
|
|
725
|
-
// Process already dead
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
// Get original spawn request
|
|
730
|
-
const spawnRequest = agent.metadata?.spawnRequest;
|
|
731
|
-
if (!spawnRequest) {
|
|
732
|
-
console.error(`❌ Cannot recover agent ${agent.id} - no spawn request found`);
|
|
733
|
-
return;
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
// Attempt to respawn with same configuration
|
|
737
|
-
const newAgentId = `agt_${randomUUID()}`;
|
|
738
|
-
agent.id = newAgentId;
|
|
739
|
-
agent.status = AgentStatus.SPAWNING;
|
|
740
|
-
agent.updatedAt = new Date().toISOString();
|
|
741
|
-
|
|
742
|
-
// Create new mailbox
|
|
743
|
-
const newMailboxId = `mbx_${randomUUID()}`;
|
|
744
|
-
await this.createMailbox(newMailboxId, newAgentId);
|
|
745
|
-
|
|
746
|
-
// Spawn new process
|
|
747
|
-
const newPid = await this.executeAgentSpawn(agent, spawnRequest);
|
|
748
|
-
agent.pid = newPid;
|
|
749
|
-
agent.mailboxId = newMailboxId;
|
|
750
|
-
agent.status = AgentStatus.RUNNING;
|
|
751
|
-
agent.updatedAt = new Date().toISOString();
|
|
752
|
-
|
|
753
|
-
// Update agent in registry
|
|
754
|
-
this.agents.delete(agent.id.replace(newAgentId, '')); // Remove old ID if different
|
|
755
|
-
this.agents.set(newAgentId, agent);
|
|
756
|
-
|
|
757
|
-
console.log(`✅ Agent ${newAgentId} recovered successfully`);
|
|
758
|
-
await this.sendRecoveryEvent(agent, 'recovery_success');
|
|
759
|
-
|
|
760
|
-
} catch (error: any) {
|
|
761
|
-
console.error(`❌ Agent ${agent.id} recovery failed:`, error.message);
|
|
762
|
-
|
|
763
|
-
agent.status = AgentStatus.FAILED;
|
|
764
|
-
agent.metadata = {
|
|
765
|
-
...agent.metadata,
|
|
766
|
-
recoveryError: error.message,
|
|
767
|
-
recoveryFailedAt: new Date().toISOString()
|
|
768
|
-
};
|
|
769
|
-
agent.updatedAt = new Date().toISOString();
|
|
770
|
-
|
|
771
|
-
await this.sendRecoveryEvent(agent, 'recovery_failed');
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
/**
|
|
776
|
-
* Send recovery event notifications
|
|
777
|
-
*/
|
|
778
|
-
private async sendRecoveryEvent(agent: AgentHandle, eventType: string): Promise<void> {
|
|
779
|
-
try {
|
|
780
|
-
const event = {
|
|
781
|
-
type: 'agent_recovery',
|
|
782
|
-
agentId: agent.id,
|
|
783
|
-
agentType: agent.type,
|
|
784
|
-
eventType,
|
|
785
|
-
timestamp: new Date().toISOString(),
|
|
786
|
-
metadata: {
|
|
787
|
-
status: agent.status,
|
|
788
|
-
recoveryAttempts: agent.metadata?.recoveryAttempts || 0,
|
|
789
|
-
lastError: agent.metadata?.error || agent.metadata?.recoveryError
|
|
790
|
-
}
|
|
791
|
-
};
|
|
792
|
-
|
|
793
|
-
// In a real implementation, this would send to notification system
|
|
794
|
-
console.log(`📢 Recovery event: ${eventType} for agent ${agent.id}`);
|
|
795
|
-
console.log(` Event:`, JSON.stringify(event, null, 2));
|
|
796
|
-
|
|
797
|
-
} catch (error: any) {
|
|
798
|
-
console.error(`Failed to send recovery event:`, error.message);
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
/**
|
|
803
|
-
* Get agent health status with detailed metrics
|
|
804
|
-
*/
|
|
805
|
-
async getAgentHealth(agentId: string): Promise<{
|
|
806
|
-
status: AgentStatus;
|
|
807
|
-
isHealthy: boolean;
|
|
808
|
-
lastHeartbeat?: string;
|
|
809
|
-
uptime?: number;
|
|
810
|
-
resourceUsage?: { memory: number; cpu: number };
|
|
811
|
-
errors: Array<{ timestamp: string; error: string; count: number }>;
|
|
812
|
-
recoveryAttempts?: number;
|
|
813
|
-
}> {
|
|
814
|
-
const monitor = await this.monitor(agentId);
|
|
815
|
-
const agent = this.agents.get(agentId);
|
|
816
|
-
|
|
817
|
-
const now = Date.now();
|
|
818
|
-
const lastHeartbeat = agent?.metadata?.lastHeartbeat;
|
|
819
|
-
const isHealthy = monitor.status === AgentStatus.RUNNING &&
|
|
820
|
-
(!lastHeartbeat || (now - new Date(lastHeartbeat).getTime() < this.heartbeatTimeout));
|
|
821
|
-
|
|
822
|
-
return {
|
|
823
|
-
status: monitor.status,
|
|
824
|
-
isHealthy,
|
|
825
|
-
lastHeartbeat,
|
|
826
|
-
uptime: monitor.uptime,
|
|
827
|
-
resourceUsage: monitor.resourceUsage,
|
|
828
|
-
errors: monitor.errors,
|
|
829
|
-
recoveryAttempts: agent?.metadata?.recoveryAttempts || 0
|
|
830
|
-
};
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
/**
|
|
834
|
-
* Get system-wide agent health summary
|
|
835
|
-
*/
|
|
836
|
-
async getSystemHealth(): Promise<{
|
|
837
|
-
totalAgents: number;
|
|
838
|
-
healthyAgents: number;
|
|
839
|
-
unhealthyAgents: number;
|
|
840
|
-
recoveringAgents: number;
|
|
841
|
-
failedAgents: number;
|
|
842
|
-
overallHealth: 'healthy' | 'degraded' | 'critical';
|
|
843
|
-
}> {
|
|
844
|
-
const allAgents = Array.from(this.agents.values());
|
|
845
|
-
const healthChecks = await Promise.all(
|
|
846
|
-
allAgents.map(agent => this.getAgentHealth(agent.id))
|
|
847
|
-
);
|
|
848
|
-
|
|
849
|
-
const healthy = healthChecks.filter(h => h.isHealthy).length;
|
|
850
|
-
const unhealthy = healthChecks.filter(h => !h.isHealthy && h.status !== AgentStatus.FAILED).length;
|
|
851
|
-
const failed = healthChecks.filter(h => h.status === AgentStatus.FAILED).length;
|
|
852
|
-
const recovering = allAgents.filter(a => a.metadata?.recoveryAttempts > 0).length;
|
|
853
|
-
|
|
854
|
-
const total = allAgents.length;
|
|
855
|
-
let overallHealth: 'healthy' | 'degraded' | 'critical' = 'healthy';
|
|
856
|
-
|
|
857
|
-
if (failed / total > 0.3) {
|
|
858
|
-
overallHealth = 'critical';
|
|
859
|
-
} else if (unhealthy / total > 0.2) {
|
|
860
|
-
overallHealth = 'degraded';
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
return {
|
|
864
|
-
totalAgents: total,
|
|
865
|
-
healthyAgents: healthy,
|
|
866
|
-
unhealthyAgents: unhealthy,
|
|
867
|
-
recoveringAgents: recovering,
|
|
868
|
-
failedAgents: failed,
|
|
869
|
-
overallHealth
|
|
870
|
-
};
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
/**
|
|
874
|
-
* Cleanup method to stop monitoring intervals
|
|
875
|
-
*/
|
|
876
|
-
cleanup(): void {
|
|
877
|
-
if (this.heartbeatInterval) {
|
|
878
|
-
clearInterval(this.heartbeatInterval);
|
|
879
|
-
}
|
|
880
|
-
if (this.recoveryInterval) {
|
|
881
|
-
clearInterval(this.recoveryInterval);
|
|
882
|
-
}
|
|
883
|
-
console.log('✓ Agent monitoring stopped');
|
|
884
|
-
}
|
|
885
|
-
}
|