kynjal-cli 4.0.0 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/appliance/gguf-engine.d.ts +91 -0
- package/dist/src/appliance/gguf-engine.d.ts.map +1 -0
- package/dist/src/appliance/gguf-engine.js +286 -525
- package/dist/src/appliance/gguf-engine.js.map +1 -1
- package/dist/src/appliance/ruvllm-bridge.d.ts +102 -0
- package/dist/src/appliance/ruvllm-bridge.d.ts.map +1 -0
- package/dist/src/appliance/ruvllm-bridge.js +203 -403
- package/dist/src/appliance/ruvllm-bridge.js.map +1 -1
- package/dist/src/appliance/rvfa-builder.d.ts +44 -0
- package/dist/src/appliance/rvfa-builder.d.ts.map +1 -0
- package/dist/src/appliance/rvfa-builder.js +154 -208
- package/dist/src/appliance/rvfa-builder.js.map +1 -1
- package/dist/src/appliance/rvfa-distribution.d.ts +97 -0
- package/dist/src/appliance/rvfa-distribution.d.ts.map +1 -0
- package/dist/src/appliance/rvfa-distribution.js +260 -423
- package/dist/src/appliance/rvfa-distribution.js.map +1 -1
- package/dist/src/appliance/rvfa-format.d.ts +111 -0
- package/dist/src/appliance/rvfa-format.d.ts.map +1 -0
- package/dist/src/appliance/rvfa-format.js +128 -200
- package/dist/src/appliance/rvfa-format.js.map +1 -1
- package/dist/src/appliance/rvfa-runner.d.ts +69 -0
- package/dist/src/appliance/rvfa-runner.d.ts.map +1 -0
- package/dist/src/appliance/rvfa-runner.js +168 -304
- package/dist/src/appliance/rvfa-runner.js.map +1 -1
- package/dist/src/appliance/rvfa-signing.d.ts +123 -0
- package/dist/src/appliance/rvfa-signing.d.ts.map +1 -0
- package/dist/src/appliance/rvfa-signing.js +173 -295
- package/dist/src/appliance/rvfa-signing.js.map +1 -1
- package/dist/src/benchmarks/pretrain/index.d.ts +58 -0
- package/dist/src/benchmarks/pretrain/index.d.ts.map +1 -0
- package/dist/src/benchmarks/pretrain/index.js +331 -542
- package/dist/src/benchmarks/pretrain/index.js.map +1 -1
- package/dist/src/commands/agent.js +574 -697
- package/dist/src/commands/agent.js.map +1 -1
- package/dist/src/commands/analyze.js +1218 -1548
- package/dist/src/commands/analyze.js.map +1 -1
- package/dist/src/commands/appliance-advanced.js +158 -267
- package/dist/src/commands/appliance-advanced.js.map +1 -1
- package/dist/src/commands/appliance.js +318 -493
- package/dist/src/commands/appliance.js.map +1 -1
- package/dist/src/commands/benchmark.js +372 -523
- package/dist/src/commands/benchmark.js.map +1 -1
- package/dist/src/commands/claims.js +274 -364
- package/dist/src/commands/claims.js.map +1 -1
- package/dist/src/commands/cleanup.js +113 -157
- package/dist/src/commands/cleanup.js.map +1 -1
- package/dist/src/commands/completions.js +477 -118
- package/dist/src/commands/completions.js.map +1 -1
- package/dist/src/commands/config.js +237 -303
- package/dist/src/commands/config.js.map +1 -1
- package/dist/src/commands/daemon.js +487 -596
- package/dist/src/commands/daemon.js.map +1 -1
- package/dist/src/commands/deployment.js +194 -275
- package/dist/src/commands/deployment.js.map +1 -1
- package/dist/src/commands/doctor.js +504 -686
- package/dist/src/commands/doctor.js.map +1 -1
- package/dist/src/commands/embeddings.js +1293 -1543
- package/dist/src/commands/embeddings.js.map +1 -1
- package/dist/src/commands/guidance.js +449 -596
- package/dist/src/commands/guidance.js.map +1 -1
- package/dist/src/commands/hive-mind.js +854 -938
- package/dist/src/commands/hive-mind.js.map +1 -1
- package/dist/src/commands/hooks.js +3112 -3519
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/commands/index.d.ts +115 -0
- package/dist/src/commands/index.d.ts.map +1 -0
- package/dist/src/commands/index.js +126 -308
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/init.js +788 -940
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/issues.js +383 -558
- package/dist/src/commands/issues.js.map +1 -1
- package/dist/src/commands/mcp.js +493 -605
- package/dist/src/commands/mcp.js.map +1 -1
- package/dist/src/commands/memory.js +833 -1026
- package/dist/src/commands/memory.js.map +1 -1
- package/dist/src/commands/migrate.js +282 -347
- package/dist/src/commands/migrate.js.map +1 -1
- package/dist/src/commands/neural.js +1289 -1563
- package/dist/src/commands/neural.js.map +1 -1
- package/dist/src/commands/performance.js +497 -643
- package/dist/src/commands/performance.js.map +1 -1
- package/dist/src/commands/plugins.js +668 -841
- package/dist/src/commands/plugins.js.map +1 -1
- package/dist/src/commands/process.js +392 -447
- package/dist/src/commands/process.js.map +1 -1
- package/dist/src/commands/progress.js +162 -256
- package/dist/src/commands/progress.js.map +1 -1
- package/dist/src/commands/providers.js +150 -220
- package/dist/src/commands/providers.js.map +1 -1
- package/dist/src/commands/route.js +520 -665
- package/dist/src/commands/route.js.map +1 -1
- package/dist/src/commands/ruvector/backup.js +505 -651
- package/dist/src/commands/ruvector/backup.js.map +1 -1
- package/dist/src/commands/ruvector/benchmark.js +349 -401
- package/dist/src/commands/ruvector/benchmark.js.map +1 -1
- package/dist/src/commands/ruvector/import.js +224 -266
- package/dist/src/commands/ruvector/import.js.map +1 -1
- package/dist/src/commands/ruvector/index.js +37 -75
- package/dist/src/commands/ruvector/index.js.map +1 -1
- package/dist/src/commands/ruvector/init.js +336 -359
- package/dist/src/commands/ruvector/init.js.map +1 -1
- package/dist/src/commands/ruvector/migrate.js +335 -322
- package/dist/src/commands/ruvector/migrate.js.map +1 -1
- package/dist/src/commands/ruvector/optimize.js +375 -431
- package/dist/src/commands/ruvector/optimize.js.map +1 -1
- package/dist/src/commands/ruvector/setup.js +703 -117
- package/dist/src/commands/ruvector/setup.js.map +1 -1
- package/dist/src/commands/ruvector/status.js +364 -419
- package/dist/src/commands/ruvector/status.js.map +1 -1
- package/dist/src/commands/security.js +485 -608
- package/dist/src/commands/security.js.map +1 -1
- package/dist/src/commands/session.js +504 -626
- package/dist/src/commands/session.js.map +1 -1
- package/dist/src/commands/start.js +267 -364
- package/dist/src/commands/start.js.map +1 -1
- package/dist/src/commands/status.js +380 -486
- package/dist/src/commands/status.js.map +1 -1
- package/dist/src/commands/swarm.js +408 -488
- package/dist/src/commands/swarm.js.map +1 -1
- package/dist/src/commands/task.js +423 -538
- package/dist/src/commands/task.js.map +1 -1
- package/dist/src/commands/transfer-store.js +322 -412
- package/dist/src/commands/transfer-store.js.map +1 -1
- package/dist/src/commands/update.js +196 -291
- package/dist/src/commands/update.js.map +1 -1
- package/dist/src/commands/workflow.js +386 -486
- package/dist/src/commands/workflow.js.map +1 -1
- package/dist/src/config-adapter.d.ts +15 -0
- package/dist/src/config-adapter.d.ts.map +1 -0
- package/dist/src/config-adapter.js +38 -39
- package/dist/src/config-adapter.js.map +1 -1
- package/dist/src/index.d.ts +77 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +309 -411
- package/dist/src/index.js.map +1 -1
- package/dist/src/infrastructure/in-memory-repositories.d.ts +68 -0
- package/dist/src/infrastructure/in-memory-repositories.d.ts.map +1 -0
- package/dist/src/infrastructure/in-memory-repositories.js +246 -507
- package/dist/src/infrastructure/in-memory-repositories.js.map +1 -1
- package/dist/src/init/claudemd-generator.d.ts +25 -0
- package/dist/src/init/claudemd-generator.d.ts.map +1 -0
- package/dist/src/init/claudemd-generator.js +368 -78
- package/dist/src/init/claudemd-generator.js.map +1 -1
- package/dist/src/init/executor.d.ts +41 -0
- package/dist/src/init/executor.d.ts.map +1 -0
- package/dist/src/init/executor.js +1307 -996
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/helpers-generator.d.ts +60 -0
- package/dist/src/init/helpers-generator.d.ts.map +1 -0
- package/dist/src/init/helpers-generator.js +657 -12
- package/dist/src/init/helpers-generator.js.map +1 -1
- package/dist/src/init/index.d.ts +1 -1
- package/dist/src/init/index.d.ts.map +1 -1
- package/dist/src/init/index.js +1 -1
- package/dist/src/init/index.js.map +1 -1
- package/dist/src/init/mcp-generator.js +33 -37
- package/dist/src/init/mcp-generator.js.map +1 -1
- package/dist/src/init/settings-generator.js +76 -77
- package/dist/src/init/settings-generator.js.map +1 -1
- package/dist/src/init/statusline-generator.js +801 -3
- package/dist/src/init/statusline-generator.js.map +1 -1
- package/dist/src/init/types.d.ts +1 -1
- package/dist/src/init/types.d.ts.map +1 -1
- package/dist/src/init/types.js +76 -59
- package/dist/src/init/types.js.map +1 -1
- package/dist/src/mcp-client.d.ts +92 -0
- package/dist/src/mcp-client.d.ts.map +1 -0
- package/dist/src/mcp-client.js +81 -125
- package/dist/src/mcp-client.js.map +1 -1
- package/dist/src/mcp-server.d.ts +161 -0
- package/dist/src/mcp-server.d.ts.map +1 -0
- package/dist/src/mcp-server.js +470 -757
- package/dist/src/mcp-server.js.map +1 -1
- package/dist/src/mcp-tools/agent-tools.js +391 -492
- package/dist/src/mcp-tools/agent-tools.js.map +1 -1
- package/dist/src/mcp-tools/agentdb-tools.js +332 -533
- package/dist/src/mcp-tools/agentdb-tools.js.map +1 -1
- package/dist/src/mcp-tools/analyze-tools.js +172 -236
- package/dist/src/mcp-tools/analyze-tools.js.map +1 -1
- package/dist/src/mcp-tools/auto-install.d.ts +83 -0
- package/dist/src/mcp-tools/auto-install.d.ts.map +1 -0
- package/dist/src/mcp-tools/auto-install.js +80 -142
- package/dist/src/mcp-tools/auto-install.js.map +1 -1
- package/dist/src/mcp-tools/browser-tools.js +252 -375
- package/dist/src/mcp-tools/browser-tools.js.map +1 -1
- package/dist/src/mcp-tools/claims-tools.js +473 -565
- package/dist/src/mcp-tools/claims-tools.js.map +1 -1
- package/dist/src/mcp-tools/config-tools.js +197 -272
- package/dist/src/mcp-tools/config-tools.js.map +1 -1
- package/dist/src/mcp-tools/coordination-tools.js +500 -572
- package/dist/src/mcp-tools/coordination-tools.js.map +1 -1
- package/dist/src/mcp-tools/daa-tools.js +286 -364
- package/dist/src/mcp-tools/daa-tools.js.map +1 -1
- package/dist/src/mcp-tools/embeddings-tools.js +582 -693
- package/dist/src/mcp-tools/embeddings-tools.js.map +1 -1
- package/dist/src/mcp-tools/github-tools.js +260 -311
- package/dist/src/mcp-tools/github-tools.js.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.js +573 -640
- package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.js +2215 -2648
- package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
- package/dist/src/mcp-tools/memory-tools.js +350 -505
- package/dist/src/mcp-tools/memory-tools.js.map +1 -1
- package/dist/src/mcp-tools/neural-tools.js +315 -412
- package/dist/src/mcp-tools/neural-tools.js.map +1 -1
- package/dist/src/mcp-tools/performance-tools.js +420 -480
- package/dist/src/mcp-tools/performance-tools.js.map +1 -1
- package/dist/src/mcp-tools/progress-tools.js +204 -278
- package/dist/src/mcp-tools/progress-tools.js.map +1 -1
- package/dist/src/mcp-tools/ruvllm-tools.js +163 -279
- package/dist/src/mcp-tools/ruvllm-tools.js.map +1 -1
- package/dist/src/mcp-tools/security-tools.js +297 -429
- package/dist/src/mcp-tools/security-tools.js.map +1 -1
- package/dist/src/mcp-tools/session-tools.js +185 -234
- package/dist/src/mcp-tools/session-tools.js.map +1 -1
- package/dist/src/mcp-tools/swarm-tools.js +207 -260
- package/dist/src/mcp-tools/swarm-tools.js.map +1 -1
- package/dist/src/mcp-tools/system-tools.js +276 -325
- package/dist/src/mcp-tools/system-tools.js.map +1 -1
- package/dist/src/mcp-tools/task-tools.js +270 -336
- package/dist/src/mcp-tools/task-tools.js.map +1 -1
- package/dist/src/mcp-tools/terminal-tools.js +148 -196
- package/dist/src/mcp-tools/terminal-tools.js.map +1 -1
- package/dist/src/mcp-tools/transfer-tools.js +186 -333
- package/dist/src/mcp-tools/transfer-tools.js.map +1 -1
- package/dist/src/mcp-tools/types.d.ts +31 -0
- package/dist/src/mcp-tools/types.d.ts.map +1 -0
- package/dist/src/mcp-tools/wasm-agent-tools.js +133 -280
- package/dist/src/mcp-tools/wasm-agent-tools.js.map +1 -1
- package/dist/src/mcp-tools/workflow-tools.js +405 -450
- package/dist/src/mcp-tools/workflow-tools.js.map +1 -1
- package/dist/src/memory/ewc-consolidation.d.ts +295 -0
- package/dist/src/memory/ewc-consolidation.d.ts.map +1 -0
- package/dist/src/memory/ewc-consolidation.js +190 -303
- package/dist/src/memory/ewc-consolidation.js.map +1 -1
- package/dist/src/memory/intelligence.d.ts +338 -0
- package/dist/src/memory/intelligence.d.ts.map +1 -0
- package/dist/src/memory/intelligence.js +569 -794
- package/dist/src/memory/intelligence.js.map +1 -1
- package/dist/src/memory/memory-bridge.d.ts +407 -0
- package/dist/src/memory/memory-bridge.d.ts.map +1 -0
- package/dist/src/memory/memory-bridge.js +1170 -1640
- package/dist/src/memory/memory-bridge.js.map +1 -1
- package/dist/src/memory/memory-initializer.d.ts +412 -0
- package/dist/src/memory/memory-initializer.d.ts.map +1 -0
- package/dist/src/memory/memory-initializer.js +1836 -1851
- package/dist/src/memory/memory-initializer.js.map +1 -1
- package/dist/src/memory/sona-optimizer.d.ts +227 -0
- package/dist/src/memory/sona-optimizer.d.ts.map +1 -0
- package/dist/src/memory/sona-optimizer.js +199 -329
- package/dist/src/memory/sona-optimizer.js.map +1 -1
- package/dist/src/output.d.ts +2 -2
- package/dist/src/output.d.ts.map +1 -1
- package/dist/src/output.js +242 -272
- package/dist/src/output.js.map +1 -1
- package/dist/src/parser.d.ts +51 -0
- package/dist/src/parser.d.ts.map +1 -0
- package/dist/src/parser.js +140 -187
- package/dist/src/parser.js.map +1 -1
- package/dist/src/plugins/manager.d.ts +133 -0
- package/dist/src/plugins/manager.d.ts.map +1 -0
- package/dist/src/plugins/manager.js +285 -521
- package/dist/src/plugins/manager.js.map +1 -1
- package/dist/src/plugins/store/discovery.d.ts +88 -0
- package/dist/src/plugins/store/discovery.d.ts.map +1 -0
- package/dist/src/plugins/store/discovery.js +271 -358
- package/dist/src/plugins/store/discovery.js.map +1 -1
- package/dist/src/plugins/store/index.d.ts +76 -0
- package/dist/src/plugins/store/index.d.ts.map +1 -0
- package/dist/src/plugins/store/index.js +48 -105
- package/dist/src/plugins/store/index.js.map +1 -1
- package/dist/src/plugins/store/search.d.ts +46 -0
- package/dist/src/plugins/store/search.d.ts.map +1 -0
- package/dist/src/plugins/store/search.js +69 -107
- package/dist/src/plugins/store/search.js.map +1 -1
- package/dist/src/plugins/store/types.d.ts +274 -0
- package/dist/src/plugins/store/types.d.ts.map +1 -0
- package/dist/src/plugins/tests/demo-plugin-store.js +113 -160
- package/dist/src/plugins/tests/demo-plugin-store.js.map +1 -1
- package/dist/src/plugins/tests/standalone-test.js +172 -223
- package/dist/src/plugins/tests/standalone-test.js.map +1 -1
- package/dist/src/plugins/tests/test-plugin-store.js +190 -228
- package/dist/src/plugins/tests/test-plugin-store.js.map +1 -1
- package/dist/src/production/circuit-breaker.d.ts +101 -0
- package/dist/src/production/circuit-breaker.d.ts.map +1 -0
- package/dist/src/production/circuit-breaker.js +62 -126
- package/dist/src/production/circuit-breaker.js.map +1 -1
- package/dist/src/production/error-handler.d.ts +92 -0
- package/dist/src/production/error-handler.d.ts.map +1 -0
- package/dist/src/production/error-handler.js +86 -156
- package/dist/src/production/error-handler.js.map +1 -1
- package/dist/src/production/monitoring.d.ts +161 -0
- package/dist/src/production/monitoring.d.ts.map +1 -0
- package/dist/src/production/monitoring.js +139 -220
- package/dist/src/production/monitoring.js.map +1 -1
- package/dist/src/production/rate-limiter.d.ts +80 -0
- package/dist/src/production/rate-limiter.d.ts.map +1 -0
- package/dist/src/production/rate-limiter.js +74 -93
- package/dist/src/production/rate-limiter.js.map +1 -1
- package/dist/src/production/retry.d.ts +48 -0
- package/dist/src/production/retry.d.ts.map +1 -0
- package/dist/src/production/retry.js +75 -167
- package/dist/src/production/retry.js.map +1 -1
- package/dist/src/prompt.d.ts +44 -0
- package/dist/src/prompt.d.ts.map +1 -0
- package/dist/src/prompt.js +436 -560
- package/dist/src/prompt.js.map +1 -1
- package/dist/src/runtime/headless.d.ts +60 -0
- package/dist/src/runtime/headless.d.ts.map +1 -0
- package/dist/src/runtime/headless.js +197 -286
- package/dist/src/runtime/headless.js.map +1 -1
- package/dist/src/ruvector/agent-wasm.d.ts +182 -0
- package/dist/src/ruvector/agent-wasm.d.ts.map +1 -0
- package/dist/src/ruvector/agent-wasm.js +156 -351
- package/dist/src/ruvector/agent-wasm.js.map +1 -1
- package/dist/src/ruvector/ast-analyzer.d.ts +67 -0
- package/dist/src/ruvector/ast-analyzer.d.ts.map +1 -0
- package/dist/src/ruvector/ast-analyzer.js +145 -232
- package/dist/src/ruvector/ast-analyzer.js.map +1 -1
- package/dist/src/ruvector/coverage-router.d.ts +160 -0
- package/dist/src/ruvector/coverage-router.d.ts.map +1 -0
- package/dist/src/ruvector/coverage-router.js +287 -419
- package/dist/src/ruvector/coverage-router.js.map +1 -1
- package/dist/src/ruvector/coverage-tools.js +56 -101
- package/dist/src/ruvector/coverage-tools.js.map +1 -1
- package/dist/src/ruvector/diff-classifier.d.ts +175 -0
- package/dist/src/ruvector/diff-classifier.d.ts.map +1 -0
- package/dist/src/ruvector/diff-classifier.js +324 -451
- package/dist/src/ruvector/diff-classifier.js.map +1 -1
- package/dist/src/ruvector/enhanced-model-router.d.ts +146 -0
- package/dist/src/ruvector/enhanced-model-router.d.ts.map +1 -0
- package/dist/src/ruvector/enhanced-model-router.js +260 -336
- package/dist/src/ruvector/enhanced-model-router.js.map +1 -1
- package/dist/src/ruvector/flash-attention.d.ts +195 -0
- package/dist/src/ruvector/flash-attention.d.ts.map +1 -0
- package/dist/src/ruvector/flash-attention.js +223 -254
- package/dist/src/ruvector/flash-attention.js.map +1 -1
- package/dist/src/ruvector/graph-analyzer.d.ts +187 -0
- package/dist/src/ruvector/graph-analyzer.d.ts.map +1 -0
- package/dist/src/ruvector/graph-analyzer.js +486 -680
- package/dist/src/ruvector/graph-analyzer.js.map +1 -1
- package/dist/src/ruvector/index.d.ts +40 -0
- package/dist/src/ruvector/index.d.ts.map +1 -0
- package/dist/src/ruvector/index.js +36 -106
- package/dist/src/ruvector/index.js.map +1 -1
- package/dist/src/ruvector/lora-adapter.d.ts +218 -0
- package/dist/src/ruvector/lora-adapter.d.ts.map +1 -0
- package/dist/src/ruvector/lora-adapter.js +155 -248
- package/dist/src/ruvector/lora-adapter.js.map +1 -1
- package/dist/src/ruvector/model-router.d.ts +220 -0
- package/dist/src/ruvector/model-router.d.ts.map +1 -0
- package/dist/src/ruvector/model-router.js +175 -248
- package/dist/src/ruvector/model-router.js.map +1 -1
- package/dist/src/ruvector/moe-router.d.ts +206 -0
- package/dist/src/ruvector/moe-router.d.ts.map +1 -0
- package/dist/src/ruvector/moe-router.js +228 -286
- package/dist/src/ruvector/moe-router.js.map +1 -1
- package/dist/src/ruvector/q-learning-router.d.ts +211 -0
- package/dist/src/ruvector/q-learning-router.d.ts.map +1 -0
- package/dist/src/ruvector/q-learning-router.js +257 -338
- package/dist/src/ruvector/q-learning-router.js.map +1 -1
- package/dist/src/ruvector/ruvllm-wasm.d.ts +179 -0
- package/dist/src/ruvector/ruvllm-wasm.d.ts.map +1 -0
- package/dist/src/ruvector/ruvllm-wasm.js +270 -434
- package/dist/src/ruvector/ruvllm-wasm.js.map +1 -1
- package/dist/src/ruvector/semantic-router.d.ts +77 -0
- package/dist/src/ruvector/semantic-router.d.ts.map +1 -0
- package/dist/src/ruvector/semantic-router.js +60 -67
- package/dist/src/ruvector/semantic-router.js.map +1 -1
- package/dist/src/ruvector/vector-db.d.ts +69 -0
- package/dist/src/ruvector/vector-db.d.ts.map +1 -0
- package/dist/src/ruvector/vector-db.js +119 -205
- package/dist/src/ruvector/vector-db.js.map +1 -1
- package/dist/src/services/agentic-flow-bridge.d.ts +50 -0
- package/dist/src/services/agentic-flow-bridge.d.ts.map +1 -0
- package/dist/src/services/agentic-flow-bridge.js +32 -105
- package/dist/src/services/agentic-flow-bridge.js.map +1 -1
- package/dist/src/services/claim-service.d.ts +204 -0
- package/dist/src/services/claim-service.d.ts.map +1 -0
- package/dist/src/services/claim-service.js +615 -940
- package/dist/src/services/claim-service.js.map +1 -1
- package/dist/src/services/container-worker-pool.d.ts +197 -0
- package/dist/src/services/container-worker-pool.d.ts.map +1 -0
- package/dist/src/services/container-worker-pool.js +398 -666
- package/dist/src/services/container-worker-pool.js.map +1 -1
- package/dist/src/services/headless-worker-executor.d.ts +304 -0
- package/dist/src/services/headless-worker-executor.d.ts.map +1 -0
- package/dist/src/services/headless-worker-executor.js +441 -467
- package/dist/src/services/headless-worker-executor.js.map +1 -1
- package/dist/src/services/index.d.ts +4 -4
- package/dist/src/services/index.d.ts.map +1 -1
- package/dist/src/services/index.js +4 -4
- package/dist/src/services/index.js.map +1 -1
- package/dist/src/services/registry-api.d.ts +58 -0
- package/dist/src/services/registry-api.d.ts.map +1 -0
- package/dist/src/services/registry-api.js +92 -200
- package/dist/src/services/registry-api.js.map +1 -1
- package/dist/src/services/ruvector-training.d.ts +222 -0
- package/dist/src/services/ruvector-training.d.ts.map +1 -0
- package/dist/src/services/ruvector-training.js +257 -337
- package/dist/src/services/ruvector-training.js.map +1 -1
- package/dist/src/services/worker-daemon.d.ts +228 -0
- package/dist/src/services/worker-daemon.d.ts.map +1 -0
- package/dist/src/services/worker-daemon.js +591 -849
- package/dist/src/services/worker-daemon.js.map +1 -1
- package/dist/src/services/worker-queue.d.ts +194 -0
- package/dist/src/services/worker-queue.d.ts.map +1 -0
- package/dist/src/services/worker-queue.js +331 -548
- package/dist/src/services/worker-queue.js.map +1 -1
- package/dist/src/suggest.d.ts +53 -0
- package/dist/src/suggest.d.ts.map +1 -0
- package/dist/src/suggest.js +45 -55
- package/dist/src/suggest.js.map +1 -1
- package/dist/src/transfer/anonymization/index.js +29 -37
- package/dist/src/transfer/anonymization/index.js.map +1 -1
- package/dist/src/transfer/deploy-seraphine.js +128 -155
- package/dist/src/transfer/deploy-seraphine.js.map +1 -1
- package/dist/src/transfer/export.d.ts +25 -0
- package/dist/src/transfer/export.d.ts.map +1 -0
- package/dist/src/transfer/export.js +84 -142
- package/dist/src/transfer/export.js.map +1 -1
- package/dist/src/transfer/index.d.ts +1 -1
- package/dist/src/transfer/index.d.ts.map +1 -1
- package/dist/src/transfer/index.js +0 -2
- package/dist/src/transfer/index.js.map +1 -1
- package/dist/src/transfer/ipfs/client.d.ts +109 -0
- package/dist/src/transfer/ipfs/client.d.ts.map +1 -0
- package/dist/src/transfer/ipfs/client.js +187 -337
- package/dist/src/transfer/ipfs/client.js.map +1 -1
- package/dist/src/transfer/ipfs/upload.d.ts +95 -0
- package/dist/src/transfer/ipfs/upload.d.ts.map +1 -0
- package/dist/src/transfer/ipfs/upload.js +288 -434
- package/dist/src/transfer/ipfs/upload.js.map +1 -1
- package/dist/src/transfer/models/seraphine.d.ts +72 -0
- package/dist/src/transfer/models/seraphine.d.ts.map +1 -0
- package/dist/src/transfer/models/seraphine.js +55 -55
- package/dist/src/transfer/models/seraphine.js.map +1 -1
- package/dist/src/transfer/serialization/cfp.d.ts +49 -0
- package/dist/src/transfer/serialization/cfp.d.ts.map +1 -0
- package/dist/src/transfer/serialization/cfp.js +30 -31
- package/dist/src/transfer/serialization/cfp.js.map +1 -1
- package/dist/src/transfer/storage/gcs.d.ts +82 -0
- package/dist/src/transfer/storage/gcs.d.ts.map +1 -0
- package/dist/src/transfer/storage/gcs.js +165 -232
- package/dist/src/transfer/storage/gcs.js.map +1 -1
- package/dist/src/transfer/store/discovery.d.ts +84 -0
- package/dist/src/transfer/store/discovery.d.ts.map +1 -0
- package/dist/src/transfer/store/discovery.js +239 -349
- package/dist/src/transfer/store/discovery.js.map +1 -1
- package/dist/src/transfer/store/download.d.ts +70 -0
- package/dist/src/transfer/store/download.d.ts.map +1 -0
- package/dist/src/transfer/store/download.js +243 -365
- package/dist/src/transfer/store/download.js.map +1 -1
- package/dist/src/transfer/store/index.d.ts +84 -0
- package/dist/src/transfer/store/index.d.ts.map +1 -0
- package/dist/src/transfer/store/index.js +63 -130
- package/dist/src/transfer/store/index.js.map +1 -1
- package/dist/src/transfer/store/publish.d.ts +76 -0
- package/dist/src/transfer/store/publish.d.ts.map +1 -0
- package/dist/src/transfer/store/publish.js +184 -258
- package/dist/src/transfer/store/publish.js.map +1 -1
- package/dist/src/transfer/store/registry.js +50 -72
- package/dist/src/transfer/store/registry.js.map +1 -1
- package/dist/src/transfer/store/search.d.ts +54 -0
- package/dist/src/transfer/store/search.d.ts.map +1 -0
- package/dist/src/transfer/store/search.js +64 -96
- package/dist/src/transfer/store/search.js.map +1 -1
- package/dist/src/transfer/store/tests/standalone-test.js +174 -231
- package/dist/src/transfer/store/tests/standalone-test.js.map +1 -1
- package/dist/src/transfer/test-seraphine.js +95 -130
- package/dist/src/transfer/test-seraphine.js.map +1 -1
- package/dist/src/transfer/tests/test-store.js +194 -239
- package/dist/src/transfer/tests/test-store.js.map +1 -1
- package/dist/src/transfer/types.d.ts +245 -0
- package/dist/src/transfer/types.d.ts.map +1 -0
- package/dist/src/types.d.ts +198 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +26 -55
- package/dist/src/types.js.map +1 -1
- package/dist/src/update/checker.d.ts +34 -0
- package/dist/src/update/checker.d.ts.map +1 -0
- package/dist/src/update/checker.js +106 -183
- package/dist/src/update/checker.js.map +1 -1
- package/dist/src/update/executor.d.ts +32 -0
- package/dist/src/update/executor.d.ts.map +1 -0
- package/dist/src/update/executor.js +135 -198
- package/dist/src/update/executor.js.map +1 -1
- package/dist/src/update/index.d.ts +33 -0
- package/dist/src/update/index.d.ts.map +1 -0
- package/dist/src/update/index.js +38 -85
- package/dist/src/update/index.js.map +1 -1
- package/dist/src/update/rate-limiter.d.ts +20 -0
- package/dist/src/update/rate-limiter.d.ts.map +1 -0
- package/dist/src/update/rate-limiter.js +19 -31
- package/dist/src/update/rate-limiter.js.map +1 -1
- package/dist/src/update/validator.d.ts +17 -0
- package/dist/src/update/validator.d.ts.map +1 -0
- package/dist/src/update/validator.js +38 -64
- package/dist/src/update/validator.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -12,68 +12,6 @@
|
|
|
12
12
|
*
|
|
13
13
|
* @see /v3/implementation/adrs/ADR-016-collaborative-issue-claims.md
|
|
14
14
|
*/
|
|
15
|
-
var __extends = (this && this.__extends) || (function () {
|
|
16
|
-
var extendStatics = function (d, b) {
|
|
17
|
-
extendStatics = Object.setPrototypeOf ||
|
|
18
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
19
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
20
|
-
return extendStatics(d, b);
|
|
21
|
-
};
|
|
22
|
-
return function (d, b) {
|
|
23
|
-
if (typeof b !== "function" && b !== null)
|
|
24
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
25
|
-
extendStatics(d, b);
|
|
26
|
-
function __() { this.constructor = d; }
|
|
27
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
28
|
-
};
|
|
29
|
-
})();
|
|
30
|
-
var __assign = (this && this.__assign) || function () {
|
|
31
|
-
__assign = Object.assign || function(t) {
|
|
32
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
33
|
-
s = arguments[i];
|
|
34
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
35
|
-
t[p] = s[p];
|
|
36
|
-
}
|
|
37
|
-
return t;
|
|
38
|
-
};
|
|
39
|
-
return __assign.apply(this, arguments);
|
|
40
|
-
};
|
|
41
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
42
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
43
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
44
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
45
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
46
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
47
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
48
|
-
});
|
|
49
|
-
};
|
|
50
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
51
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
52
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
53
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
54
|
-
function step(op) {
|
|
55
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
56
|
-
while (_) try {
|
|
57
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
58
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
59
|
-
switch (op[0]) {
|
|
60
|
-
case 0: case 1: t = op; break;
|
|
61
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
62
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
63
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
64
|
-
default:
|
|
65
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
66
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
67
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
68
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
69
|
-
if (t[2]) _.ops.pop();
|
|
70
|
-
_.trys.pop(); continue;
|
|
71
|
-
}
|
|
72
|
-
op = body.call(thisArg, _);
|
|
73
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
74
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
15
|
import { EventEmitter } from 'events';
|
|
78
16
|
import * as fs from 'fs';
|
|
79
17
|
import * as path from 'path';
|
|
@@ -81,7 +19,7 @@ import { execFileSync } from 'child_process';
|
|
|
81
19
|
// ============================================================================
|
|
82
20
|
// Default Configuration
|
|
83
21
|
// ============================================================================
|
|
84
|
-
|
|
22
|
+
const DEFAULT_CONFIG = {
|
|
85
23
|
staleThresholdMinutes: 30,
|
|
86
24
|
blockedThresholdMinutes: 60,
|
|
87
25
|
overloadThreshold: 5,
|
|
@@ -92,647 +30,435 @@ var DEFAULT_CONFIG = {
|
|
|
92
30
|
allowCrossTypeSteal: [
|
|
93
31
|
['coder', 'debugger'],
|
|
94
32
|
['tester', 'reviewer'],
|
|
95
|
-
]
|
|
33
|
+
],
|
|
96
34
|
};
|
|
97
35
|
// ============================================================================
|
|
98
36
|
// Claim Service Implementation
|
|
99
37
|
// ============================================================================
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
38
|
+
export class ClaimService extends EventEmitter {
|
|
39
|
+
claims = new Map();
|
|
40
|
+
stealableInfo = new Map();
|
|
41
|
+
storagePath;
|
|
42
|
+
config;
|
|
43
|
+
eventLog = [];
|
|
44
|
+
constructor(projectRoot, config) {
|
|
45
|
+
super();
|
|
46
|
+
this.storagePath = path.join(projectRoot, '.claude-flow', 'claims');
|
|
47
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
110
48
|
}
|
|
111
49
|
// ==========================================================================
|
|
112
50
|
// Initialization
|
|
113
51
|
// ==========================================================================
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
ClaimService.prototype.loadClaims = function () {
|
|
134
|
-
return __awaiter(this, void 0, Promise, function () {
|
|
135
|
-
var claimsFile, data, _i, _a, claim;
|
|
136
|
-
return __generator(this, function (_b) {
|
|
137
|
-
claimsFile = path.join(this.storagePath, 'claims.json');
|
|
138
|
-
if (fs.existsSync(claimsFile)) {
|
|
139
|
-
try {
|
|
140
|
-
data = JSON.parse(fs.readFileSync(claimsFile, 'utf-8'));
|
|
141
|
-
for (_i = 0, _a = data.claims || []; _i < _a.length; _i++) {
|
|
142
|
-
claim = _a[_i];
|
|
143
|
-
claim.claimedAt = new Date(claim.claimedAt);
|
|
144
|
-
claim.statusChangedAt = new Date(claim.statusChangedAt);
|
|
145
|
-
if (claim.expiresAt)
|
|
146
|
-
claim.expiresAt = new Date(claim.expiresAt);
|
|
147
|
-
this.claims.set(claim.issueId, claim);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
catch (_c) {
|
|
151
|
-
// Start fresh if file is corrupted
|
|
152
|
-
}
|
|
52
|
+
async initialize() {
|
|
53
|
+
// Ensure storage directory exists
|
|
54
|
+
if (!fs.existsSync(this.storagePath)) {
|
|
55
|
+
fs.mkdirSync(this.storagePath, { recursive: true });
|
|
56
|
+
}
|
|
57
|
+
// Load existing claims
|
|
58
|
+
await this.loadClaims();
|
|
59
|
+
}
|
|
60
|
+
async loadClaims() {
|
|
61
|
+
const claimsFile = path.join(this.storagePath, 'claims.json');
|
|
62
|
+
if (fs.existsSync(claimsFile)) {
|
|
63
|
+
try {
|
|
64
|
+
const data = JSON.parse(fs.readFileSync(claimsFile, 'utf-8'));
|
|
65
|
+
for (const claim of data.claims || []) {
|
|
66
|
+
claim.claimedAt = new Date(claim.claimedAt);
|
|
67
|
+
claim.statusChangedAt = new Date(claim.statusChangedAt);
|
|
68
|
+
if (claim.expiresAt)
|
|
69
|
+
claim.expiresAt = new Date(claim.expiresAt);
|
|
70
|
+
this.claims.set(claim.issueId, claim);
|
|
153
71
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
return [2 /*return*/];
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
};
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Start fresh if file is corrupted
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async saveClaims() {
|
|
79
|
+
const claimsFile = path.join(this.storagePath, 'claims.json');
|
|
80
|
+
const data = {
|
|
81
|
+
claims: Array.from(this.claims.values()),
|
|
82
|
+
savedAt: new Date().toISOString(),
|
|
83
|
+
};
|
|
84
|
+
fs.writeFileSync(claimsFile, JSON.stringify(data, null, 2));
|
|
85
|
+
}
|
|
172
86
|
// ==========================================================================
|
|
173
87
|
// Core Claiming
|
|
174
88
|
// ==========================================================================
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
this.emitEvent({
|
|
202
|
-
type: 'issue:claimed',
|
|
203
|
-
timestamp: now,
|
|
204
|
-
issueId: issueId,
|
|
205
|
-
claimant: claimant,
|
|
206
|
-
previousClaimant: existing === null || existing === void 0 ? void 0 : existing.claimant
|
|
207
|
-
});
|
|
208
|
-
return [2 /*return*/, { success: true, claim: claim }];
|
|
209
|
-
}
|
|
210
|
-
});
|
|
89
|
+
async claim(issueId, claimant) {
|
|
90
|
+
// Check if already claimed
|
|
91
|
+
const existing = this.claims.get(issueId);
|
|
92
|
+
if (existing && existing.status !== 'stealable') {
|
|
93
|
+
return {
|
|
94
|
+
success: false,
|
|
95
|
+
error: `Issue ${issueId} is already claimed by ${this.formatClaimant(existing.claimant)}`,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const now = new Date();
|
|
99
|
+
const claim = {
|
|
100
|
+
issueId,
|
|
101
|
+
claimant,
|
|
102
|
+
claimedAt: now,
|
|
103
|
+
status: 'active',
|
|
104
|
+
statusChangedAt: now,
|
|
105
|
+
progress: 0,
|
|
106
|
+
};
|
|
107
|
+
this.claims.set(issueId, claim);
|
|
108
|
+
await this.saveClaims();
|
|
109
|
+
this.emitEvent({
|
|
110
|
+
type: 'issue:claimed',
|
|
111
|
+
timestamp: now,
|
|
112
|
+
issueId,
|
|
113
|
+
claimant,
|
|
114
|
+
previousClaimant: existing?.claimant,
|
|
211
115
|
});
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
_a.sent();
|
|
231
|
-
this.emitEvent({
|
|
232
|
-
type: 'issue:released',
|
|
233
|
-
timestamp: new Date(),
|
|
234
|
-
issueId: issueId,
|
|
235
|
-
claimant: claimant
|
|
236
|
-
});
|
|
237
|
-
return [2 /*return*/];
|
|
238
|
-
}
|
|
239
|
-
});
|
|
116
|
+
return { success: true, claim };
|
|
117
|
+
}
|
|
118
|
+
async release(issueId, claimant) {
|
|
119
|
+
const claim = this.claims.get(issueId);
|
|
120
|
+
if (!claim) {
|
|
121
|
+
throw new Error(`Issue ${issueId} is not claimed`);
|
|
122
|
+
}
|
|
123
|
+
if (!this.isSameClaimant(claim.claimant, claimant)) {
|
|
124
|
+
throw new Error(`Issue ${issueId} is not claimed by ${this.formatClaimant(claimant)}`);
|
|
125
|
+
}
|
|
126
|
+
this.claims.delete(issueId);
|
|
127
|
+
this.stealableInfo.delete(issueId);
|
|
128
|
+
await this.saveClaims();
|
|
129
|
+
this.emitEvent({
|
|
130
|
+
type: 'issue:released',
|
|
131
|
+
timestamp: new Date(),
|
|
132
|
+
issueId,
|
|
133
|
+
claimant,
|
|
240
134
|
});
|
|
241
|
-
}
|
|
135
|
+
}
|
|
242
136
|
// ==========================================================================
|
|
243
137
|
// Handoffs
|
|
244
138
|
// ==========================================================================
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
_a.sent();
|
|
265
|
-
this.emitEvent({
|
|
266
|
-
type: 'issue:handoff:requested',
|
|
267
|
-
timestamp: new Date(),
|
|
268
|
-
issueId: issueId,
|
|
269
|
-
claimant: from,
|
|
270
|
-
data: { to: to, reason: reason }
|
|
271
|
-
});
|
|
272
|
-
return [2 /*return*/];
|
|
273
|
-
}
|
|
274
|
-
});
|
|
139
|
+
async requestHandoff(issueId, from, to, reason) {
|
|
140
|
+
const claim = this.claims.get(issueId);
|
|
141
|
+
if (!claim) {
|
|
142
|
+
throw new Error(`Issue ${issueId} is not claimed`);
|
|
143
|
+
}
|
|
144
|
+
if (!this.isSameClaimant(claim.claimant, from)) {
|
|
145
|
+
throw new Error(`Issue ${issueId} is not claimed by ${this.formatClaimant(from)}`);
|
|
146
|
+
}
|
|
147
|
+
claim.status = 'handoff-pending';
|
|
148
|
+
claim.statusChangedAt = new Date();
|
|
149
|
+
claim.handoffTo = to;
|
|
150
|
+
claim.handoffReason = reason;
|
|
151
|
+
await this.saveClaims();
|
|
152
|
+
this.emitEvent({
|
|
153
|
+
type: 'issue:handoff:requested',
|
|
154
|
+
timestamp: new Date(),
|
|
155
|
+
issueId,
|
|
156
|
+
claimant: from,
|
|
157
|
+
data: { to, reason },
|
|
275
158
|
});
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
_a.sent();
|
|
299
|
-
this.emitEvent({
|
|
300
|
-
type: 'issue:handoff:accepted',
|
|
301
|
-
timestamp: new Date(),
|
|
302
|
-
issueId: issueId,
|
|
303
|
-
claimant: claimant,
|
|
304
|
-
previousClaimant: previousClaimant
|
|
305
|
-
});
|
|
306
|
-
return [2 /*return*/];
|
|
307
|
-
}
|
|
308
|
-
});
|
|
159
|
+
}
|
|
160
|
+
async acceptHandoff(issueId, claimant) {
|
|
161
|
+
const claim = this.claims.get(issueId);
|
|
162
|
+
if (!claim || claim.status !== 'handoff-pending') {
|
|
163
|
+
throw new Error(`No pending handoff for issue ${issueId}`);
|
|
164
|
+
}
|
|
165
|
+
if (!claim.handoffTo || !this.isSameClaimant(claim.handoffTo, claimant)) {
|
|
166
|
+
throw new Error(`Handoff not addressed to ${this.formatClaimant(claimant)}`);
|
|
167
|
+
}
|
|
168
|
+
const previousClaimant = claim.claimant;
|
|
169
|
+
claim.claimant = claimant;
|
|
170
|
+
claim.status = 'active';
|
|
171
|
+
claim.statusChangedAt = new Date();
|
|
172
|
+
delete claim.handoffTo;
|
|
173
|
+
delete claim.handoffReason;
|
|
174
|
+
await this.saveClaims();
|
|
175
|
+
this.emitEvent({
|
|
176
|
+
type: 'issue:handoff:accepted',
|
|
177
|
+
timestamp: new Date(),
|
|
178
|
+
issueId,
|
|
179
|
+
claimant,
|
|
180
|
+
previousClaimant,
|
|
309
181
|
});
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
_a.sent();
|
|
331
|
-
this.emitEvent({
|
|
332
|
-
type: 'issue:handoff:rejected',
|
|
333
|
-
timestamp: new Date(),
|
|
334
|
-
issueId: issueId,
|
|
335
|
-
claimant: claimant,
|
|
336
|
-
data: { reason: reason }
|
|
337
|
-
});
|
|
338
|
-
return [2 /*return*/];
|
|
339
|
-
}
|
|
340
|
-
});
|
|
182
|
+
}
|
|
183
|
+
async rejectHandoff(issueId, claimant, reason) {
|
|
184
|
+
const claim = this.claims.get(issueId);
|
|
185
|
+
if (!claim || claim.status !== 'handoff-pending') {
|
|
186
|
+
throw new Error(`No pending handoff for issue ${issueId}`);
|
|
187
|
+
}
|
|
188
|
+
if (!claim.handoffTo || !this.isSameClaimant(claim.handoffTo, claimant)) {
|
|
189
|
+
throw new Error(`Handoff not addressed to ${this.formatClaimant(claimant)}`);
|
|
190
|
+
}
|
|
191
|
+
claim.status = 'active';
|
|
192
|
+
claim.statusChangedAt = new Date();
|
|
193
|
+
delete claim.handoffTo;
|
|
194
|
+
delete claim.handoffReason;
|
|
195
|
+
await this.saveClaims();
|
|
196
|
+
this.emitEvent({
|
|
197
|
+
type: 'issue:handoff:rejected',
|
|
198
|
+
timestamp: new Date(),
|
|
199
|
+
issueId,
|
|
200
|
+
claimant,
|
|
201
|
+
data: { reason },
|
|
341
202
|
});
|
|
342
|
-
}
|
|
203
|
+
}
|
|
343
204
|
// ==========================================================================
|
|
344
205
|
// Status Updates
|
|
345
206
|
// ==========================================================================
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
case 1:
|
|
367
|
-
_a.sent();
|
|
368
|
-
this.emitEvent({
|
|
369
|
-
type: 'issue:status:changed',
|
|
370
|
-
timestamp: new Date(),
|
|
371
|
-
issueId: issueId,
|
|
372
|
-
data: { previousStatus: previousStatus, newStatus: status, note: note }
|
|
373
|
-
});
|
|
374
|
-
return [2 /*return*/];
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
});
|
|
378
|
-
};
|
|
379
|
-
ClaimService.prototype.updateProgress = function (issueId, progress) {
|
|
380
|
-
return __awaiter(this, void 0, Promise, function () {
|
|
381
|
-
var claim;
|
|
382
|
-
return __generator(this, function (_a) {
|
|
383
|
-
switch (_a.label) {
|
|
384
|
-
case 0:
|
|
385
|
-
claim = this.claims.get(issueId);
|
|
386
|
-
if (!claim) {
|
|
387
|
-
throw new Error("Issue " + issueId + " is not claimed");
|
|
388
|
-
}
|
|
389
|
-
claim.progress = Math.min(100, Math.max(0, progress));
|
|
390
|
-
return [4 /*yield*/, this.saveClaims()];
|
|
391
|
-
case 1:
|
|
392
|
-
_a.sent();
|
|
393
|
-
return [2 /*return*/];
|
|
394
|
-
}
|
|
395
|
-
});
|
|
207
|
+
async updateStatus(issueId, status, note) {
|
|
208
|
+
const claim = this.claims.get(issueId);
|
|
209
|
+
if (!claim) {
|
|
210
|
+
throw new Error(`Issue ${issueId} is not claimed`);
|
|
211
|
+
}
|
|
212
|
+
const previousStatus = claim.status;
|
|
213
|
+
claim.status = status;
|
|
214
|
+
claim.statusChangedAt = new Date();
|
|
215
|
+
if (status === 'blocked' && note) {
|
|
216
|
+
claim.blockReason = note;
|
|
217
|
+
}
|
|
218
|
+
if (status === 'completed') {
|
|
219
|
+
claim.progress = 100;
|
|
220
|
+
}
|
|
221
|
+
await this.saveClaims();
|
|
222
|
+
this.emitEvent({
|
|
223
|
+
type: 'issue:status:changed',
|
|
224
|
+
timestamp: new Date(),
|
|
225
|
+
issueId,
|
|
226
|
+
data: { previousStatus, newStatus: status, note },
|
|
396
227
|
});
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
return [2 /*return*/];
|
|
421
|
-
}
|
|
422
|
-
});
|
|
228
|
+
}
|
|
229
|
+
async updateProgress(issueId, progress) {
|
|
230
|
+
const claim = this.claims.get(issueId);
|
|
231
|
+
if (!claim) {
|
|
232
|
+
throw new Error(`Issue ${issueId} is not claimed`);
|
|
233
|
+
}
|
|
234
|
+
claim.progress = Math.min(100, Math.max(0, progress));
|
|
235
|
+
await this.saveClaims();
|
|
236
|
+
}
|
|
237
|
+
async requestReview(issueId, reviewers) {
|
|
238
|
+
const claim = this.claims.get(issueId);
|
|
239
|
+
if (!claim) {
|
|
240
|
+
throw new Error(`Issue ${issueId} is not claimed`);
|
|
241
|
+
}
|
|
242
|
+
claim.status = 'review-requested';
|
|
243
|
+
claim.statusChangedAt = new Date();
|
|
244
|
+
await this.saveClaims();
|
|
245
|
+
this.emitEvent({
|
|
246
|
+
type: 'issue:review:requested',
|
|
247
|
+
timestamp: new Date(),
|
|
248
|
+
issueId,
|
|
249
|
+
claimant: claim.claimant,
|
|
250
|
+
data: { reviewers },
|
|
423
251
|
});
|
|
424
|
-
}
|
|
252
|
+
}
|
|
425
253
|
// ==========================================================================
|
|
426
254
|
// Work Stealing
|
|
427
255
|
// ==========================================================================
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
_a.sent();
|
|
446
|
-
this.emitEvent({
|
|
447
|
-
type: 'issue:stealable',
|
|
448
|
-
timestamp: new Date(),
|
|
449
|
-
issueId: issueId,
|
|
450
|
-
claimant: claim.claimant,
|
|
451
|
-
data: { info: info }
|
|
452
|
-
});
|
|
453
|
-
return [2 /*return*/];
|
|
454
|
-
}
|
|
455
|
-
});
|
|
456
|
-
});
|
|
457
|
-
};
|
|
458
|
-
ClaimService.prototype.steal = function (issueId, stealer) {
|
|
459
|
-
return __awaiter(this, void 0, Promise, function () {
|
|
460
|
-
var claim, info, previousOwner, allowed;
|
|
461
|
-
return __generator(this, function (_a) {
|
|
462
|
-
switch (_a.label) {
|
|
463
|
-
case 0:
|
|
464
|
-
claim = this.claims.get(issueId);
|
|
465
|
-
if (!claim) {
|
|
466
|
-
return [2 /*return*/, { success: false, error: "Issue " + issueId + " is not claimed" }];
|
|
467
|
-
}
|
|
468
|
-
if (claim.status !== 'stealable') {
|
|
469
|
-
return [2 /*return*/, { success: false, error: "Issue " + issueId + " is not stealable" }];
|
|
470
|
-
}
|
|
471
|
-
info = this.stealableInfo.get(issueId);
|
|
472
|
-
previousOwner = claim.claimant;
|
|
473
|
-
// Check if steal is allowed
|
|
474
|
-
if (this.config.requireSameType && stealer.type === 'agent' && previousOwner.type === 'agent') {
|
|
475
|
-
if (stealer.agentType !== previousOwner.agentType) {
|
|
476
|
-
allowed = this.config.allowCrossTypeSteal.some(function (pair) { return pair.includes(stealer.agentType) && pair.includes(previousOwner.agentType); });
|
|
477
|
-
if (!allowed) {
|
|
478
|
-
return [2 /*return*/, { success: false, error: "Cross-type steal not allowed" }];
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
// Execute steal
|
|
483
|
-
claim.claimant = stealer;
|
|
484
|
-
claim.status = 'active';
|
|
485
|
-
claim.statusChangedAt = new Date();
|
|
486
|
-
claim.claimedAt = new Date();
|
|
487
|
-
this.stealableInfo["delete"](issueId);
|
|
488
|
-
return [4 /*yield*/, this.saveClaims()];
|
|
489
|
-
case 1:
|
|
490
|
-
_a.sent();
|
|
491
|
-
this.emitEvent({
|
|
492
|
-
type: 'issue:stolen',
|
|
493
|
-
timestamp: new Date(),
|
|
494
|
-
issueId: issueId,
|
|
495
|
-
claimant: stealer,
|
|
496
|
-
previousClaimant: previousOwner,
|
|
497
|
-
data: { context: info }
|
|
498
|
-
});
|
|
499
|
-
return [2 /*return*/, { success: true, claim: claim, previousOwner: previousOwner, context: info }];
|
|
500
|
-
}
|
|
501
|
-
});
|
|
256
|
+
async markStealable(issueId, info) {
|
|
257
|
+
const claim = this.claims.get(issueId);
|
|
258
|
+
if (!claim) {
|
|
259
|
+
throw new Error(`Issue ${issueId} is not claimed`);
|
|
260
|
+
}
|
|
261
|
+
claim.status = 'stealable';
|
|
262
|
+
claim.statusChangedAt = new Date();
|
|
263
|
+
claim.context = info.context;
|
|
264
|
+
claim.progress = info.progress;
|
|
265
|
+
this.stealableInfo.set(issueId, info);
|
|
266
|
+
await this.saveClaims();
|
|
267
|
+
this.emitEvent({
|
|
268
|
+
type: 'issue:stealable',
|
|
269
|
+
timestamp: new Date(),
|
|
270
|
+
issueId,
|
|
271
|
+
claimant: claim.claimant,
|
|
272
|
+
data: { info },
|
|
502
273
|
});
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
274
|
+
}
|
|
275
|
+
async steal(issueId, stealer) {
|
|
276
|
+
const claim = this.claims.get(issueId);
|
|
277
|
+
if (!claim) {
|
|
278
|
+
return { success: false, error: `Issue ${issueId} is not claimed` };
|
|
279
|
+
}
|
|
280
|
+
if (claim.status !== 'stealable') {
|
|
281
|
+
return { success: false, error: `Issue ${issueId} is not stealable` };
|
|
282
|
+
}
|
|
283
|
+
const info = this.stealableInfo.get(issueId);
|
|
284
|
+
const previousOwner = claim.claimant;
|
|
285
|
+
// Check if steal is allowed
|
|
286
|
+
if (this.config.requireSameType && stealer.type === 'agent' && previousOwner.type === 'agent') {
|
|
287
|
+
if (stealer.agentType !== previousOwner.agentType) {
|
|
288
|
+
const allowed = this.config.allowCrossTypeSteal.some(pair => pair.includes(stealer.agentType) && pair.includes(previousOwner.agentType));
|
|
289
|
+
if (!allowed) {
|
|
290
|
+
return { success: false, error: `Cross-type steal not allowed` };
|
|
520
291
|
}
|
|
521
|
-
|
|
522
|
-
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// Execute steal
|
|
295
|
+
claim.claimant = stealer;
|
|
296
|
+
claim.status = 'active';
|
|
297
|
+
claim.statusChangedAt = new Date();
|
|
298
|
+
claim.claimedAt = new Date();
|
|
299
|
+
this.stealableInfo.delete(issueId);
|
|
300
|
+
await this.saveClaims();
|
|
301
|
+
this.emitEvent({
|
|
302
|
+
type: 'issue:stolen',
|
|
303
|
+
timestamp: new Date(),
|
|
304
|
+
issueId,
|
|
305
|
+
claimant: stealer,
|
|
306
|
+
previousClaimant: previousOwner,
|
|
307
|
+
data: { context: info },
|
|
523
308
|
});
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
309
|
+
return { success: true, claim, previousOwner, context: info };
|
|
310
|
+
}
|
|
311
|
+
async getStealable(agentType) {
|
|
312
|
+
const stealable = [];
|
|
313
|
+
for (const claim of this.claims.values()) {
|
|
314
|
+
if (claim.status !== 'stealable')
|
|
315
|
+
continue;
|
|
316
|
+
const info = this.stealableInfo.get(claim.issueId);
|
|
317
|
+
if (agentType && info?.preferredTypes?.length) {
|
|
318
|
+
if (!info.preferredTypes.includes(agentType))
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
stealable.push(claim);
|
|
322
|
+
}
|
|
323
|
+
return stealable;
|
|
324
|
+
}
|
|
325
|
+
async contestSteal(issueId, originalClaimant, reason) {
|
|
326
|
+
const claim = this.claims.get(issueId);
|
|
327
|
+
if (!claim) {
|
|
328
|
+
throw new Error(`Issue ${issueId} is not claimed`);
|
|
329
|
+
}
|
|
330
|
+
this.emitEvent({
|
|
331
|
+
type: 'issue:steal:contested',
|
|
332
|
+
timestamp: new Date(),
|
|
333
|
+
issueId,
|
|
334
|
+
claimant: originalClaimant,
|
|
335
|
+
data: { reason, currentOwner: claim.claimant },
|
|
542
336
|
});
|
|
543
|
-
|
|
337
|
+
// Contest resolution would typically be handled by a coordinator or human
|
|
338
|
+
}
|
|
544
339
|
// ==========================================================================
|
|
545
340
|
// Load Balancing
|
|
546
341
|
// ==========================================================================
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
claims
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
342
|
+
async getAgentLoad(agentId) {
|
|
343
|
+
const claims = [];
|
|
344
|
+
let blockedCount = 0;
|
|
345
|
+
for (const claim of this.claims.values()) {
|
|
346
|
+
if (claim.claimant.type === 'agent' && claim.claimant.agentId === agentId) {
|
|
347
|
+
claims.push(claim);
|
|
348
|
+
if (claim.status === 'blocked')
|
|
349
|
+
blockedCount++;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
const agentType = claims[0]?.claimant.type === 'agent' ? claims[0].claimant.agentType : 'unknown';
|
|
353
|
+
return {
|
|
354
|
+
agentId,
|
|
355
|
+
agentType,
|
|
356
|
+
claimCount: claims.length,
|
|
357
|
+
maxClaims: this.config.overloadThreshold,
|
|
358
|
+
utilization: claims.length / this.config.overloadThreshold,
|
|
359
|
+
claims,
|
|
360
|
+
avgCompletionTime: 0, // Would need historical data
|
|
361
|
+
currentBlockedCount: blockedCount,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
async rebalance(swarmId) {
|
|
365
|
+
const result = { moved: [], suggested: [] };
|
|
366
|
+
// Get all agent loads
|
|
367
|
+
const agentLoads = new Map();
|
|
368
|
+
const agentTypes = new Set();
|
|
369
|
+
for (const claim of this.claims.values()) {
|
|
370
|
+
if (claim.claimant.type !== 'agent')
|
|
371
|
+
continue;
|
|
372
|
+
const agentId = claim.claimant.agentId;
|
|
373
|
+
if (!agentLoads.has(agentId)) {
|
|
374
|
+
const load = await this.getAgentLoad(agentId);
|
|
375
|
+
agentLoads.set(agentId, load);
|
|
376
|
+
agentTypes.add(load.agentType);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
// For each agent type, calculate average load
|
|
380
|
+
for (const agentType of agentTypes) {
|
|
381
|
+
const typeLoads = Array.from(agentLoads.values()).filter(l => l.agentType === agentType);
|
|
382
|
+
const avgLoad = typeLoads.reduce((sum, l) => sum + l.utilization, 0) / typeLoads.length;
|
|
383
|
+
const overloaded = typeLoads.filter(l => l.utilization > avgLoad * 1.5);
|
|
384
|
+
const underloaded = typeLoads.filter(l => l.utilization < avgLoad * 0.5);
|
|
385
|
+
// Generate suggestions
|
|
386
|
+
for (const over of overloaded) {
|
|
387
|
+
const lowProgressClaims = over.claims
|
|
388
|
+
.filter(c => c.progress < 25)
|
|
389
|
+
.sort((a, b) => a.progress - b.progress);
|
|
390
|
+
for (const claim of lowProgressClaims) {
|
|
391
|
+
const target = underloaded.find(u => u.claimCount < u.maxClaims);
|
|
392
|
+
if (target) {
|
|
393
|
+
result.suggested.push({
|
|
394
|
+
issueId: claim.issueId,
|
|
395
|
+
currentOwner: claim.claimant,
|
|
396
|
+
suggestedOwner: {
|
|
397
|
+
type: 'agent',
|
|
398
|
+
agentId: target.agentId,
|
|
399
|
+
agentType: target.agentType,
|
|
400
|
+
},
|
|
401
|
+
reason: 'Load balancing: redistributing work across swarm',
|
|
402
|
+
});
|
|
560
403
|
}
|
|
561
404
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
claimCount: claims.length,
|
|
567
|
-
maxClaims: this.config.overloadThreshold,
|
|
568
|
-
utilization: claims.length / this.config.overloadThreshold,
|
|
569
|
-
claims: claims,
|
|
570
|
-
avgCompletionTime: 0,
|
|
571
|
-
currentBlockedCount: blockedCount
|
|
572
|
-
}];
|
|
573
|
-
});
|
|
574
|
-
});
|
|
575
|
-
};
|
|
576
|
-
ClaimService.prototype.rebalance = function (swarmId) {
|
|
577
|
-
return __awaiter(this, void 0, Promise, function () {
|
|
578
|
-
var result, agentLoads, agentTypes, _i, _a, claim, agentId, load, _loop_1, _b, agentTypes_1, agentType;
|
|
579
|
-
return __generator(this, function (_c) {
|
|
580
|
-
switch (_c.label) {
|
|
581
|
-
case 0:
|
|
582
|
-
result = { moved: [], suggested: [] };
|
|
583
|
-
agentLoads = new Map();
|
|
584
|
-
agentTypes = new Set();
|
|
585
|
-
_i = 0, _a = this.claims.values();
|
|
586
|
-
_c.label = 1;
|
|
587
|
-
case 1:
|
|
588
|
-
if (!(_i < _a.length)) return [3 /*break*/, 4];
|
|
589
|
-
claim = _a[_i];
|
|
590
|
-
if (claim.claimant.type !== 'agent')
|
|
591
|
-
return [3 /*break*/, 3];
|
|
592
|
-
agentId = claim.claimant.agentId;
|
|
593
|
-
if (!!agentLoads.has(agentId)) return [3 /*break*/, 3];
|
|
594
|
-
return [4 /*yield*/, this.getAgentLoad(agentId)];
|
|
595
|
-
case 2:
|
|
596
|
-
load = _c.sent();
|
|
597
|
-
agentLoads.set(agentId, load);
|
|
598
|
-
agentTypes.add(load.agentType);
|
|
599
|
-
_c.label = 3;
|
|
600
|
-
case 3:
|
|
601
|
-
_i++;
|
|
602
|
-
return [3 /*break*/, 1];
|
|
603
|
-
case 4:
|
|
604
|
-
_loop_1 = function (agentType) {
|
|
605
|
-
var typeLoads = Array.from(agentLoads.values()).filter(function (l) { return l.agentType === agentType; });
|
|
606
|
-
var avgLoad = typeLoads.reduce(function (sum, l) { return sum + l.utilization; }, 0) / typeLoads.length;
|
|
607
|
-
var overloaded = typeLoads.filter(function (l) { return l.utilization > avgLoad * 1.5; });
|
|
608
|
-
var underloaded = typeLoads.filter(function (l) { return l.utilization < avgLoad * 0.5; });
|
|
609
|
-
// Generate suggestions
|
|
610
|
-
for (var _d = 0, overloaded_1 = overloaded; _d < overloaded_1.length; _d++) {
|
|
611
|
-
var over = overloaded_1[_d];
|
|
612
|
-
var lowProgressClaims = over.claims
|
|
613
|
-
.filter(function (c) { return c.progress < 25; })
|
|
614
|
-
.sort(function (a, b) { return a.progress - b.progress; });
|
|
615
|
-
for (var _e = 0, lowProgressClaims_1 = lowProgressClaims; _e < lowProgressClaims_1.length; _e++) {
|
|
616
|
-
var claim = lowProgressClaims_1[_e];
|
|
617
|
-
var target = underloaded.find(function (u) { return u.claimCount < u.maxClaims; });
|
|
618
|
-
if (target) {
|
|
619
|
-
result.suggested.push({
|
|
620
|
-
issueId: claim.issueId,
|
|
621
|
-
currentOwner: claim.claimant,
|
|
622
|
-
suggestedOwner: {
|
|
623
|
-
type: 'agent',
|
|
624
|
-
agentId: target.agentId,
|
|
625
|
-
agentType: target.agentType
|
|
626
|
-
},
|
|
627
|
-
reason: 'Load balancing: redistributing work across swarm'
|
|
628
|
-
});
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
};
|
|
633
|
-
// For each agent type, calculate average load
|
|
634
|
-
for (_b = 0, agentTypes_1 = agentTypes; _b < agentTypes_1.length; _b++) {
|
|
635
|
-
agentType = agentTypes_1[_b];
|
|
636
|
-
_loop_1(agentType);
|
|
637
|
-
}
|
|
638
|
-
return [2 /*return*/, result];
|
|
639
|
-
}
|
|
640
|
-
});
|
|
641
|
-
});
|
|
642
|
-
};
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return result;
|
|
408
|
+
}
|
|
643
409
|
// ==========================================================================
|
|
644
410
|
// Queries
|
|
645
411
|
// ==========================================================================
|
|
646
|
-
|
|
647
|
-
return
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
});
|
|
664
|
-
};
|
|
665
|
-
ClaimService.prototype.getIssueStatus = function (issueId) {
|
|
666
|
-
return __awaiter(this, void 0, Promise, function () {
|
|
667
|
-
return __generator(this, function (_a) {
|
|
668
|
-
return [2 /*return*/, this.claims.get(issueId) || null];
|
|
669
|
-
});
|
|
670
|
-
});
|
|
671
|
-
};
|
|
672
|
-
ClaimService.prototype.getAllClaims = function () {
|
|
673
|
-
return __awaiter(this, void 0, Promise, function () {
|
|
674
|
-
return __generator(this, function (_a) {
|
|
675
|
-
return [2 /*return*/, Array.from(this.claims.values())];
|
|
676
|
-
});
|
|
677
|
-
});
|
|
678
|
-
};
|
|
679
|
-
ClaimService.prototype.getByStatus = function (status) {
|
|
680
|
-
return __awaiter(this, void 0, Promise, function () {
|
|
681
|
-
return __generator(this, function (_a) {
|
|
682
|
-
return [2 /*return*/, Array.from(this.claims.values()).filter(function (c) { return c.status === status; })];
|
|
683
|
-
});
|
|
684
|
-
});
|
|
685
|
-
};
|
|
412
|
+
async getClaimedBy(claimant) {
|
|
413
|
+
return Array.from(this.claims.values()).filter(c => this.isSameClaimant(c.claimant, claimant));
|
|
414
|
+
}
|
|
415
|
+
async getAvailableIssues(_filters) {
|
|
416
|
+
// This would integrate with GitHub API
|
|
417
|
+
// For now, return issues that are not claimed
|
|
418
|
+
return [];
|
|
419
|
+
}
|
|
420
|
+
async getIssueStatus(issueId) {
|
|
421
|
+
return this.claims.get(issueId) || null;
|
|
422
|
+
}
|
|
423
|
+
async getAllClaims() {
|
|
424
|
+
return Array.from(this.claims.values());
|
|
425
|
+
}
|
|
426
|
+
async getByStatus(status) {
|
|
427
|
+
return Array.from(this.claims.values()).filter(c => c.status === status);
|
|
428
|
+
}
|
|
686
429
|
// ==========================================================================
|
|
687
430
|
// Auto-Management
|
|
688
431
|
// ==========================================================================
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
stealableAt: new Date(),
|
|
711
|
-
progress: claim.progress,
|
|
712
|
-
context: "Stale: No activity for " + Math.round(age) + " minutes"
|
|
713
|
-
})];
|
|
714
|
-
case 2:
|
|
715
|
-
// Mark as stealable
|
|
716
|
-
_b.sent();
|
|
717
|
-
expired.push(claim);
|
|
718
|
-
_b.label = 3;
|
|
719
|
-
case 3:
|
|
720
|
-
_i++;
|
|
721
|
-
return [3 /*break*/, 1];
|
|
722
|
-
case 4: return [2 /*return*/, expired];
|
|
723
|
-
}
|
|
724
|
-
});
|
|
725
|
-
});
|
|
726
|
-
};
|
|
432
|
+
async expireStale(maxAgeMinutes) {
|
|
433
|
+
const threshold = maxAgeMinutes ?? this.config.staleThresholdMinutes;
|
|
434
|
+
const now = Date.now();
|
|
435
|
+
const expired = [];
|
|
436
|
+
for (const claim of this.claims.values()) {
|
|
437
|
+
if (claim.status === 'stealable' || claim.status === 'completed')
|
|
438
|
+
continue;
|
|
439
|
+
const age = (now - claim.statusChangedAt.getTime()) / 60000;
|
|
440
|
+
if (age > threshold) {
|
|
441
|
+
// Mark as stealable
|
|
442
|
+
await this.markStealable(claim.issueId, {
|
|
443
|
+
reason: 'stale',
|
|
444
|
+
stealableAt: new Date(),
|
|
445
|
+
progress: claim.progress,
|
|
446
|
+
context: `Stale: No activity for ${Math.round(age)} minutes`,
|
|
447
|
+
});
|
|
448
|
+
expired.push(claim);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return expired;
|
|
452
|
+
}
|
|
727
453
|
// ==========================================================================
|
|
728
454
|
// Helpers
|
|
729
455
|
// ==========================================================================
|
|
730
|
-
|
|
456
|
+
formatClaimant(claimant) {
|
|
731
457
|
return claimant.type === 'human'
|
|
732
|
-
?
|
|
733
|
-
:
|
|
734
|
-
}
|
|
735
|
-
|
|
458
|
+
? `human:${claimant.name}`
|
|
459
|
+
: `agent:${claimant.agentType}:${claimant.agentId}`;
|
|
460
|
+
}
|
|
461
|
+
isSameClaimant(a, b) {
|
|
736
462
|
if (a.type !== b.type)
|
|
737
463
|
return false;
|
|
738
464
|
if (a.type === 'human' && b.type === 'human') {
|
|
@@ -742,31 +468,28 @@ var ClaimService = /** @class */ (function (_super) {
|
|
|
742
468
|
return a.agentId === b.agentId;
|
|
743
469
|
}
|
|
744
470
|
return false;
|
|
745
|
-
}
|
|
746
|
-
|
|
471
|
+
}
|
|
472
|
+
emitEvent(event) {
|
|
747
473
|
this.eventLog.push(event);
|
|
748
474
|
if (this.eventLog.length > 1000) {
|
|
749
475
|
this.eventLog = this.eventLog.slice(-500);
|
|
750
476
|
}
|
|
751
477
|
this.emit(event.type, event);
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
if (limit === void 0) { limit = 100; }
|
|
478
|
+
}
|
|
479
|
+
getEventLog(limit = 100) {
|
|
755
480
|
return this.eventLog.slice(-limit);
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
}(EventEmitter));
|
|
759
|
-
export { ClaimService };
|
|
481
|
+
}
|
|
482
|
+
}
|
|
760
483
|
// ============================================================================
|
|
761
484
|
// GitHub Sync Implementation
|
|
762
485
|
// ============================================================================
|
|
763
|
-
|
|
486
|
+
const DEFAULT_GITHUB_CONFIG = {
|
|
764
487
|
enabled: false,
|
|
765
488
|
syncLabels: true,
|
|
766
489
|
claimLabel: 'claimed',
|
|
767
490
|
autoAssign: true,
|
|
768
491
|
commentOnClaim: true,
|
|
769
|
-
commentOnRelease: true
|
|
492
|
+
commentOnRelease: true,
|
|
770
493
|
};
|
|
771
494
|
// ============================================================================
|
|
772
495
|
// Input Validation (Security)
|
|
@@ -805,331 +528,283 @@ function isValidLabel(label) {
|
|
|
805
528
|
* Sanitize error messages to prevent information disclosure
|
|
806
529
|
*/
|
|
807
530
|
function sanitizeError(error) {
|
|
808
|
-
|
|
531
|
+
const msg = error.message || 'Unknown error';
|
|
809
532
|
// Remove paths and sensitive details
|
|
810
533
|
return msg.replace(/\/[\w./-]+/g, '[path]').substring(0, 200);
|
|
811
534
|
}
|
|
812
|
-
|
|
813
|
-
|
|
535
|
+
export class GitHubSync {
|
|
536
|
+
config;
|
|
537
|
+
claimService;
|
|
538
|
+
constructor(claimService, config) {
|
|
814
539
|
this.claimService = claimService;
|
|
815
|
-
this.config =
|
|
540
|
+
this.config = { ...DEFAULT_GITHUB_CONFIG, ...config };
|
|
816
541
|
}
|
|
817
542
|
/**
|
|
818
543
|
* Check if GitHub CLI is available
|
|
819
544
|
*/
|
|
820
|
-
|
|
545
|
+
isGhAvailable() {
|
|
821
546
|
try {
|
|
822
547
|
execFileSync('gh', ['--version'], { stdio: 'ignore' });
|
|
823
548
|
return true;
|
|
824
549
|
}
|
|
825
|
-
catch
|
|
550
|
+
catch {
|
|
826
551
|
return false;
|
|
827
552
|
}
|
|
828
|
-
}
|
|
553
|
+
}
|
|
829
554
|
/**
|
|
830
555
|
* Get the current repository from git remote
|
|
831
556
|
*/
|
|
832
|
-
|
|
557
|
+
getRepo() {
|
|
833
558
|
if (this.config.repo) {
|
|
834
559
|
return isValidRepo(this.config.repo) ? this.config.repo : null;
|
|
835
560
|
}
|
|
836
561
|
try {
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
562
|
+
const remote = execFileSync('git', ['remote', 'get-url', 'origin'], { encoding: 'utf-8' }).trim();
|
|
563
|
+
const match = remote.match(/github\.com[/:]([\w.-]+\/[\w.-]+)/);
|
|
564
|
+
const repo = match ? match[1].replace('.git', '') : null;
|
|
840
565
|
return repo && isValidRepo(repo) ? repo : null;
|
|
841
566
|
}
|
|
842
|
-
catch
|
|
567
|
+
catch {
|
|
843
568
|
return null;
|
|
844
569
|
}
|
|
845
|
-
}
|
|
570
|
+
}
|
|
846
571
|
/**
|
|
847
572
|
* Sync issues from GitHub
|
|
848
573
|
*/
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
catch (error) {
|
|
894
|
-
errors.push("Failed to fetch issues: " + sanitizeError(error));
|
|
895
|
-
return [2 /*return*/, { success: false, synced: 0, errors: errors }];
|
|
896
|
-
}
|
|
897
|
-
return [2 /*return*/];
|
|
898
|
-
});
|
|
899
|
-
});
|
|
900
|
-
};
|
|
574
|
+
async syncIssues(state = 'open') {
|
|
575
|
+
const errors = [];
|
|
576
|
+
const issues = [];
|
|
577
|
+
if (!this.isGhAvailable()) {
|
|
578
|
+
return { success: false, synced: 0, errors: ['GitHub CLI (gh) not installed'] };
|
|
579
|
+
}
|
|
580
|
+
const repo = this.getRepo();
|
|
581
|
+
if (!repo) {
|
|
582
|
+
return { success: false, synced: 0, errors: ['Could not determine GitHub repository'] };
|
|
583
|
+
}
|
|
584
|
+
// Validate state parameter (whitelist)
|
|
585
|
+
const validStates = ['open', 'closed', 'all'];
|
|
586
|
+
if (!validStates.includes(state)) {
|
|
587
|
+
return { success: false, synced: 0, errors: ['Invalid state parameter'] };
|
|
588
|
+
}
|
|
589
|
+
try {
|
|
590
|
+
const issuesJson = execFileSync('gh', [
|
|
591
|
+
'issue', 'list',
|
|
592
|
+
'--repo', repo,
|
|
593
|
+
'--state', state,
|
|
594
|
+
'--json', 'number,title,body,state,labels,assignees,url,createdAt,updatedAt',
|
|
595
|
+
'--limit', '100'
|
|
596
|
+
], { encoding: 'utf-8' });
|
|
597
|
+
const rawIssues = JSON.parse(issuesJson);
|
|
598
|
+
for (const raw of rawIssues) {
|
|
599
|
+
issues.push({
|
|
600
|
+
number: raw.number,
|
|
601
|
+
title: raw.title,
|
|
602
|
+
body: raw.body || '',
|
|
603
|
+
state: raw.state === 'OPEN' ? 'open' : 'closed',
|
|
604
|
+
labels: raw.labels?.map((l) => l.name) || [],
|
|
605
|
+
assignees: raw.assignees?.map((a) => a.login) || [],
|
|
606
|
+
url: raw.url,
|
|
607
|
+
createdAt: new Date(raw.createdAt),
|
|
608
|
+
updatedAt: new Date(raw.updatedAt),
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
return { success: true, synced: issues.length, errors, issues };
|
|
612
|
+
}
|
|
613
|
+
catch (error) {
|
|
614
|
+
errors.push(`Failed to fetch issues: ${sanitizeError(error)}`);
|
|
615
|
+
return { success: false, synced: 0, errors };
|
|
616
|
+
}
|
|
617
|
+
}
|
|
901
618
|
/**
|
|
902
619
|
* Sync a local claim to GitHub (add label/assignee/comment)
|
|
903
620
|
*/
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
return
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
621
|
+
async claimOnGitHub(issueNumber, claimant) {
|
|
622
|
+
const errors = [];
|
|
623
|
+
if (!this.config.enabled) {
|
|
624
|
+
return { success: true, synced: 0, errors: ['GitHub sync not enabled'] };
|
|
625
|
+
}
|
|
626
|
+
if (!this.isGhAvailable()) {
|
|
627
|
+
return { success: false, synced: 0, errors: ['GitHub CLI (gh) not installed'] };
|
|
628
|
+
}
|
|
629
|
+
// Validate issue number
|
|
630
|
+
if (!isValidIssueNumber(issueNumber)) {
|
|
631
|
+
return { success: false, synced: 0, errors: ['Invalid issue number'] };
|
|
632
|
+
}
|
|
633
|
+
const repo = this.getRepo();
|
|
634
|
+
if (!repo) {
|
|
635
|
+
return { success: false, synced: 0, errors: ['Could not determine repository'] };
|
|
636
|
+
}
|
|
637
|
+
// Validate claim label
|
|
638
|
+
if (!isValidLabel(this.config.claimLabel)) {
|
|
639
|
+
return { success: false, synced: 0, errors: ['Invalid claim label configuration'] };
|
|
640
|
+
}
|
|
641
|
+
try {
|
|
642
|
+
// Add claim label
|
|
643
|
+
if (this.config.syncLabels) {
|
|
644
|
+
try {
|
|
645
|
+
execFileSync('gh', [
|
|
646
|
+
'issue', 'edit', String(issueNumber),
|
|
647
|
+
'--repo', repo,
|
|
648
|
+
'--add-label', this.config.claimLabel
|
|
649
|
+
], { stdio: 'ignore' });
|
|
918
650
|
}
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
return [2 /*return*/, { success: false, synced: 0, errors: ['Could not determine repository'] }];
|
|
651
|
+
catch {
|
|
652
|
+
errors.push('Failed to add claim label (label may not exist)');
|
|
922
653
|
}
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
654
|
+
}
|
|
655
|
+
// Auto-assign if human claimant
|
|
656
|
+
if (this.config.autoAssign && claimant.type === 'human') {
|
|
657
|
+
if (!isValidClaimantName(claimant.name)) {
|
|
658
|
+
errors.push('Invalid claimant name format');
|
|
926
659
|
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
'--add-label', this.config.claimLabel
|
|
935
|
-
], { stdio: 'ignore' });
|
|
936
|
-
}
|
|
937
|
-
catch (_b) {
|
|
938
|
-
errors.push('Failed to add claim label (label may not exist)');
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
// Auto-assign if human claimant
|
|
942
|
-
if (this.config.autoAssign && claimant.type === 'human') {
|
|
943
|
-
if (!isValidClaimantName(claimant.name)) {
|
|
944
|
-
errors.push('Invalid claimant name format');
|
|
945
|
-
}
|
|
946
|
-
else {
|
|
947
|
-
try {
|
|
948
|
-
execFileSync('gh', [
|
|
949
|
-
'issue', 'edit', String(issueNumber),
|
|
950
|
-
'--repo', repo,
|
|
951
|
-
'--add-assignee', claimant.name
|
|
952
|
-
], { stdio: 'ignore' });
|
|
953
|
-
}
|
|
954
|
-
catch (_c) {
|
|
955
|
-
errors.push('Failed to assign issue');
|
|
956
|
-
}
|
|
957
|
-
}
|
|
660
|
+
else {
|
|
661
|
+
try {
|
|
662
|
+
execFileSync('gh', [
|
|
663
|
+
'issue', 'edit', String(issueNumber),
|
|
664
|
+
'--repo', repo,
|
|
665
|
+
'--add-assignee', claimant.name
|
|
666
|
+
], { stdio: 'ignore' });
|
|
958
667
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
claimantStr = claimant.type === 'human'
|
|
962
|
-
? "@" + claimant.name.replace(/[^a-zA-Z0-9_-]/g, '')
|
|
963
|
-
: "Agent: " + (claimant.agentType || 'unknown').replace(/[^a-zA-Z0-9_-]/g, '');
|
|
964
|
-
comment = "\uD83E\uDD16 **Issue claimed** by " + claimantStr + "\n\n_Coordinated by RuFlo V3_";
|
|
965
|
-
try {
|
|
966
|
-
execFileSync('gh', [
|
|
967
|
-
'issue', 'comment', String(issueNumber),
|
|
968
|
-
'--repo', repo,
|
|
969
|
-
'--body', comment
|
|
970
|
-
], { stdio: 'ignore' });
|
|
971
|
-
}
|
|
972
|
-
catch (_d) {
|
|
973
|
-
errors.push('Failed to add comment');
|
|
974
|
-
}
|
|
668
|
+
catch {
|
|
669
|
+
errors.push('Failed to assign issue');
|
|
975
670
|
}
|
|
976
|
-
return [2 /*return*/, { success: errors.length === 0, synced: 1, errors: errors }];
|
|
977
671
|
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
672
|
+
}
|
|
673
|
+
// Add comment
|
|
674
|
+
if (this.config.commentOnClaim) {
|
|
675
|
+
const claimantStr = claimant.type === 'human'
|
|
676
|
+
? `@${claimant.name.replace(/[^a-zA-Z0-9_-]/g, '')}`
|
|
677
|
+
: `Agent: ${(claimant.agentType || 'unknown').replace(/[^a-zA-Z0-9_-]/g, '')}`;
|
|
678
|
+
const comment = `🤖 **Issue claimed** by ${claimantStr}\n\n_Coordinated by RuFlo V3_`;
|
|
679
|
+
try {
|
|
680
|
+
execFileSync('gh', [
|
|
681
|
+
'issue', 'comment', String(issueNumber),
|
|
682
|
+
'--repo', repo,
|
|
683
|
+
'--body', comment
|
|
684
|
+
], { stdio: 'ignore' });
|
|
685
|
+
}
|
|
686
|
+
catch {
|
|
687
|
+
errors.push('Failed to add comment');
|
|
981
688
|
}
|
|
982
|
-
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
|
|
689
|
+
}
|
|
690
|
+
return { success: errors.length === 0, synced: 1, errors };
|
|
691
|
+
}
|
|
692
|
+
catch (error) {
|
|
693
|
+
errors.push(`GitHub sync failed: ${sanitizeError(error)}`);
|
|
694
|
+
return { success: false, synced: 0, errors };
|
|
695
|
+
}
|
|
696
|
+
}
|
|
986
697
|
/**
|
|
987
698
|
* Release claim on GitHub (remove label/assignee/comment)
|
|
988
699
|
*/
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
return
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
700
|
+
async releaseOnGitHub(issueNumber, claimant) {
|
|
701
|
+
const errors = [];
|
|
702
|
+
if (!this.config.enabled) {
|
|
703
|
+
return { success: true, synced: 0, errors: ['GitHub sync not enabled'] };
|
|
704
|
+
}
|
|
705
|
+
if (!this.isGhAvailable()) {
|
|
706
|
+
return { success: false, synced: 0, errors: ['GitHub CLI (gh) not installed'] };
|
|
707
|
+
}
|
|
708
|
+
// Validate issue number
|
|
709
|
+
if (!isValidIssueNumber(issueNumber)) {
|
|
710
|
+
return { success: false, synced: 0, errors: ['Invalid issue number'] };
|
|
711
|
+
}
|
|
712
|
+
const repo = this.getRepo();
|
|
713
|
+
if (!repo) {
|
|
714
|
+
return { success: false, synced: 0, errors: ['Could not determine repository'] };
|
|
715
|
+
}
|
|
716
|
+
// Validate claim label
|
|
717
|
+
if (!isValidLabel(this.config.claimLabel)) {
|
|
718
|
+
return { success: false, synced: 0, errors: ['Invalid claim label configuration'] };
|
|
719
|
+
}
|
|
720
|
+
try {
|
|
721
|
+
// Remove claim label
|
|
722
|
+
if (this.config.syncLabels) {
|
|
723
|
+
try {
|
|
724
|
+
execFileSync('gh', [
|
|
725
|
+
'issue', 'edit', String(issueNumber),
|
|
726
|
+
'--repo', repo,
|
|
727
|
+
'--remove-label', this.config.claimLabel
|
|
728
|
+
], { stdio: 'ignore' });
|
|
1007
729
|
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
return [2 /*return*/, { success: false, synced: 0, errors: ['Invalid claim label configuration'] }];
|
|
730
|
+
catch {
|
|
731
|
+
// Label might not exist
|
|
1011
732
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
}
|
|
1022
|
-
catch (_b) {
|
|
1023
|
-
// Label might not exist
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
// Remove assignee if human claimant
|
|
1027
|
-
if (this.config.autoAssign && claimant.type === 'human') {
|
|
1028
|
-
if (isValidClaimantName(claimant.name)) {
|
|
1029
|
-
try {
|
|
1030
|
-
execFileSync('gh', [
|
|
1031
|
-
'issue', 'edit', String(issueNumber),
|
|
1032
|
-
'--repo', repo,
|
|
1033
|
-
'--remove-assignee', claimant.name
|
|
1034
|
-
], { stdio: 'ignore' });
|
|
1035
|
-
}
|
|
1036
|
-
catch (_c) {
|
|
1037
|
-
errors.push('Failed to remove assignee');
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
733
|
+
}
|
|
734
|
+
// Remove assignee if human claimant
|
|
735
|
+
if (this.config.autoAssign && claimant.type === 'human') {
|
|
736
|
+
if (isValidClaimantName(claimant.name)) {
|
|
737
|
+
try {
|
|
738
|
+
execFileSync('gh', [
|
|
739
|
+
'issue', 'edit', String(issueNumber),
|
|
740
|
+
'--repo', repo,
|
|
741
|
+
'--remove-assignee', claimant.name
|
|
742
|
+
], { stdio: 'ignore' });
|
|
1040
743
|
}
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
claimantStr = claimant.type === 'human'
|
|
1044
|
-
? "@" + claimant.name.replace(/[^a-zA-Z0-9_-]/g, '')
|
|
1045
|
-
: "Agent: " + (claimant.agentType || 'unknown').replace(/[^a-zA-Z0-9_-]/g, '');
|
|
1046
|
-
comment = "\uD83D\uDD13 **Issue released** by " + claimantStr + "\n\n_This issue is now available for others to claim._";
|
|
1047
|
-
try {
|
|
1048
|
-
execFileSync('gh', [
|
|
1049
|
-
'issue', 'comment', String(issueNumber),
|
|
1050
|
-
'--repo', repo,
|
|
1051
|
-
'--body', comment
|
|
1052
|
-
], { stdio: 'ignore' });
|
|
1053
|
-
}
|
|
1054
|
-
catch (_d) {
|
|
1055
|
-
errors.push('Failed to add release comment');
|
|
1056
|
-
}
|
|
744
|
+
catch {
|
|
745
|
+
errors.push('Failed to remove assignee');
|
|
1057
746
|
}
|
|
1058
|
-
return [2 /*return*/, { success: errors.length === 0, synced: 1, errors: errors }];
|
|
1059
747
|
}
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
748
|
+
}
|
|
749
|
+
// Add release comment
|
|
750
|
+
if (this.config.commentOnRelease) {
|
|
751
|
+
const claimantStr = claimant.type === 'human'
|
|
752
|
+
? `@${claimant.name.replace(/[^a-zA-Z0-9_-]/g, '')}`
|
|
753
|
+
: `Agent: ${(claimant.agentType || 'unknown').replace(/[^a-zA-Z0-9_-]/g, '')}`;
|
|
754
|
+
const comment = `🔓 **Issue released** by ${claimantStr}\n\n_This issue is now available for others to claim._`;
|
|
755
|
+
try {
|
|
756
|
+
execFileSync('gh', [
|
|
757
|
+
'issue', 'comment', String(issueNumber),
|
|
758
|
+
'--repo', repo,
|
|
759
|
+
'--body', comment
|
|
760
|
+
], { stdio: 'ignore' });
|
|
761
|
+
}
|
|
762
|
+
catch {
|
|
763
|
+
errors.push('Failed to add release comment');
|
|
1063
764
|
}
|
|
1064
|
-
|
|
1065
|
-
}
|
|
1066
|
-
}
|
|
1067
|
-
|
|
765
|
+
}
|
|
766
|
+
return { success: errors.length === 0, synced: 1, errors };
|
|
767
|
+
}
|
|
768
|
+
catch (error) {
|
|
769
|
+
errors.push(`GitHub release sync failed: ${sanitizeError(error)}`);
|
|
770
|
+
return { success: false, synced: 0, errors };
|
|
771
|
+
}
|
|
772
|
+
}
|
|
1068
773
|
/**
|
|
1069
774
|
* Bulk sync all local claims to GitHub
|
|
1070
775
|
*/
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
if (!issueMatch) return [3 /*break*/, 4];
|
|
1089
|
-
return [4 /*yield*/, this.claimOnGitHub(parseInt(issueMatch[1], 10), claim.claimant)];
|
|
1090
|
-
case 3:
|
|
1091
|
-
result = _a.sent();
|
|
1092
|
-
if (result.success)
|
|
1093
|
-
synced++;
|
|
1094
|
-
else
|
|
1095
|
-
errors.push.apply(errors, result.errors);
|
|
1096
|
-
_a.label = 4;
|
|
1097
|
-
case 4:
|
|
1098
|
-
_i++;
|
|
1099
|
-
return [3 /*break*/, 2];
|
|
1100
|
-
case 5: return [2 /*return*/, { success: errors.length === 0, synced: synced, errors: errors }];
|
|
1101
|
-
}
|
|
1102
|
-
});
|
|
1103
|
-
});
|
|
1104
|
-
};
|
|
776
|
+
async syncAllClaimsToGitHub() {
|
|
777
|
+
const errors = [];
|
|
778
|
+
let synced = 0;
|
|
779
|
+
const claims = await this.claimService.getAllClaims();
|
|
780
|
+
for (const claim of claims) {
|
|
781
|
+
// Extract issue number from issueId (assumes format like "123" or "issue-123")
|
|
782
|
+
const issueMatch = claim.issueId.match(/(\d+)/);
|
|
783
|
+
if (issueMatch) {
|
|
784
|
+
const result = await this.claimOnGitHub(parseInt(issueMatch[1], 10), claim.claimant);
|
|
785
|
+
if (result.success)
|
|
786
|
+
synced++;
|
|
787
|
+
else
|
|
788
|
+
errors.push(...result.errors);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
return { success: errors.length === 0, synced, errors };
|
|
792
|
+
}
|
|
1105
793
|
/**
|
|
1106
794
|
* Get GitHub issues that are claimed locally
|
|
1107
795
|
*/
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
return
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
localClaims = _a.sent();
|
|
1121
|
-
claimedIds = new Set(localClaims.map(function (c) {
|
|
1122
|
-
var match = c.issueId.match(/(\d+)/);
|
|
1123
|
-
return match ? parseInt(match[1], 10) : null;
|
|
1124
|
-
}).filter(Boolean));
|
|
1125
|
-
return [2 /*return*/, syncResult.issues.filter(function (issue) { return claimedIds.has(issue.number); })];
|
|
1126
|
-
}
|
|
1127
|
-
});
|
|
1128
|
-
});
|
|
1129
|
-
};
|
|
1130
|
-
return GitHubSync;
|
|
1131
|
-
}());
|
|
1132
|
-
export { GitHubSync };
|
|
796
|
+
async getClaimedGitHubIssues() {
|
|
797
|
+
const syncResult = await this.syncIssues('open');
|
|
798
|
+
if (!syncResult.success || !syncResult.issues)
|
|
799
|
+
return [];
|
|
800
|
+
const localClaims = await this.claimService.getAllClaims();
|
|
801
|
+
const claimedIds = new Set(localClaims.map(c => {
|
|
802
|
+
const match = c.issueId.match(/(\d+)/);
|
|
803
|
+
return match ? parseInt(match[1], 10) : null;
|
|
804
|
+
}).filter(Boolean));
|
|
805
|
+
return syncResult.issues.filter(issue => claimedIds.has(issue.number));
|
|
806
|
+
}
|
|
807
|
+
}
|
|
1133
808
|
// ============================================================================
|
|
1134
809
|
// Factory
|
|
1135
810
|
// ============================================================================
|