kynjal-cli 3.1.4 → 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/.claude/agents/core/coder.md +1 -1
- package/.claude/agents/core/planner.md +2 -2
- package/.claude/agents/core/researcher.md +1 -1
- package/.claude/agents/core/reviewer.md +1 -1
- package/.claude/agents/core/tester.md +1 -1
- package/.claude/agents/data/data-ml-model.md +4 -4
- package/.claude/agents/development/dev-backend-api.md +4 -4
- package/.claude/agents/documentation/docs-api-openapi.md +4 -4
- package/.claude/agents/github/code-review-swarm.md +2 -2
- package/.claude/agents/github/issue-tracker.md +2 -2
- package/.claude/agents/github/pr-manager.md +2 -2
- package/.claude/agents/github/release-manager.md +2 -2
- package/.claude/agents/github/workflow-automation.md +2 -2
- package/.claude/agents/sparc/architecture.md +3 -3
- package/.claude/agents/sparc/pseudocode.md +2 -2
- package/.claude/agents/sparc/refinement.md +3 -3
- package/.claude/agents/sparc/specification.md +2 -2
- package/.claude/agents/swarm/adaptive-coordinator.md +1 -1
- package/.claude/agents/swarm/hierarchical-coordinator.md +1 -1
- package/.claude/agents/swarm/mesh-coordinator.md +1 -1
- package/.claude/agents/templates/base-template-generator.md +25 -4
- package/.claude/agents/templates/sparc-coordinator.md +3 -3
- package/.claude/helpers/auto-commit.sh +1 -1
- package/.claude/helpers/auto-memory-hook.mjs +27 -9
- package/.claude/helpers/hook-handler.cjs +58 -18
- package/.claude/helpers/statusline.cjs +420 -613
- package/.claude/helpers/statusline.js +3 -3
- package/.claude/settings.json +9 -9
- package/.claude/skills/reasoningbank-intelligence/SKILL.md +2 -2
- package/.claude/skills/swarm-orchestration/SKILL.md +1 -1
- package/README.md +383 -170
- package/bin/cli.js +6 -6
- package/bin/mcp-server.js +1 -1
- package/bin/preinstall.cjs +2 -0
- 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 +425 -0
- package/dist/src/appliance/gguf-engine.js.map +1 -0
- 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 +292 -0
- package/dist/src/appliance/ruvllm-bridge.js.map +1 -0
- 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 +329 -0
- package/dist/src/appliance/rvfa-builder.js.map +1 -0
- 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 +370 -0
- package/dist/src/appliance/rvfa-distribution.js.map +1 -0
- 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 +393 -0
- package/dist/src/appliance/rvfa-format.js.map +1 -0
- 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 +237 -0
- package/dist/src/appliance/rvfa-runner.js.map +1 -0
- 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 +347 -0
- package/dist/src/appliance/rvfa-signing.js.map +1 -0
- package/dist/src/commands/agent.d.ts.map +1 -1
- package/dist/src/commands/agent.js +121 -21
- package/dist/src/commands/agent.js.map +1 -1
- package/dist/src/commands/appliance-advanced.d.ts +9 -0
- package/dist/src/commands/appliance-advanced.d.ts.map +1 -0
- package/dist/src/commands/appliance-advanced.js +215 -0
- package/dist/src/commands/appliance-advanced.js.map +1 -0
- package/dist/src/commands/appliance.d.ts +8 -0
- package/dist/src/commands/appliance.d.ts.map +1 -0
- package/dist/src/commands/appliance.js +406 -0
- package/dist/src/commands/appliance.js.map +1 -0
- package/dist/src/commands/benchmark.js +2 -2
- package/dist/src/commands/benchmark.js.map +1 -1
- package/dist/src/commands/claims.js +1 -1
- package/dist/src/commands/claims.js.map +1 -1
- package/dist/src/commands/cleanup.d.ts +13 -0
- package/dist/src/commands/cleanup.d.ts.map +1 -0
- package/dist/src/commands/cleanup.js +218 -0
- package/dist/src/commands/cleanup.js.map +1 -0
- package/dist/src/commands/config.js +1 -1
- package/dist/src/commands/config.js.map +1 -1
- package/dist/src/commands/daemon.d.ts.map +1 -1
- package/dist/src/commands/daemon.js +81 -18
- package/dist/src/commands/daemon.js.map +1 -1
- package/dist/src/commands/deployment.js +1 -1
- package/dist/src/commands/deployment.js.map +1 -1
- package/dist/src/commands/doctor.d.ts.map +1 -1
- package/dist/src/commands/doctor.js +99 -51
- package/dist/src/commands/doctor.js.map +1 -1
- package/dist/src/commands/embeddings.js +1 -1
- package/dist/src/commands/embeddings.js.map +1 -1
- package/dist/src/commands/hive-mind.js +26 -26
- package/dist/src/commands/hive-mind.js.map +1 -1
- package/dist/src/commands/hooks.d.ts.map +1 -1
- package/dist/src/commands/hooks.js +800 -100
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/commands/index.d.ts +9 -2
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +20 -2
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/init.d.ts +1 -1
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +22 -18
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/mcp.d.ts.map +1 -1
- package/dist/src/commands/mcp.js +23 -5
- package/dist/src/commands/mcp.js.map +1 -1
- package/dist/src/commands/memory.d.ts.map +1 -1
- package/dist/src/commands/memory.js +24 -0
- package/dist/src/commands/memory.js.map +1 -1
- package/dist/src/commands/neural.d.ts.map +1 -1
- package/dist/src/commands/neural.js +13 -7
- package/dist/src/commands/neural.js.map +1 -1
- package/dist/src/commands/performance.js +1 -1
- package/dist/src/commands/performance.js.map +1 -1
- package/dist/src/commands/plugins.js +1 -1
- package/dist/src/commands/plugins.js.map +1 -1
- package/dist/src/commands/providers.js +1 -1
- package/dist/src/commands/providers.js.map +1 -1
- package/dist/src/commands/ruvector/import.js +2 -2
- package/dist/src/commands/ruvector/import.js.map +1 -1
- package/dist/src/commands/ruvector/index.js +1 -1
- package/dist/src/commands/ruvector/index.js.map +1 -1
- package/dist/src/commands/ruvector/setup.js +6 -6
- package/dist/src/commands/security.d.ts.map +1 -1
- package/dist/src/commands/security.js +47 -16
- package/dist/src/commands/security.js.map +1 -1
- package/dist/src/commands/session.d.ts +1 -1
- package/dist/src/commands/session.js +1 -1
- package/dist/src/commands/start.d.ts +1 -1
- package/dist/src/commands/start.js +12 -12
- package/dist/src/commands/start.js.map +1 -1
- package/dist/src/commands/status.d.ts +1 -1
- package/dist/src/commands/status.d.ts.map +1 -1
- package/dist/src/commands/status.js +13 -6
- package/dist/src/commands/status.js.map +1 -1
- package/dist/src/commands/swarm.js +2 -2
- package/dist/src/commands/swarm.js.map +1 -1
- package/dist/src/commands/task.d.ts +1 -1
- package/dist/src/commands/task.js +1 -1
- package/dist/src/commands/transfer-store.js +1 -1
- package/dist/src/commands/transfer-store.js.map +1 -1
- package/dist/src/config-adapter.js +1 -1
- package/dist/src/config-adapter.js.map +1 -1
- package/dist/src/index.d.ts +4 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/init/claudemd-generator.js +30 -30
- package/dist/src/init/claudemd-generator.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +86 -101
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/helpers-generator.d.ts.map +1 -1
- package/dist/src/init/helpers-generator.js +96 -26
- package/dist/src/init/helpers-generator.js.map +1 -1
- package/dist/src/init/mcp-generator.d.ts +0 -1
- package/dist/src/init/mcp-generator.d.ts.map +1 -1
- package/dist/src/init/mcp-generator.js +34 -18
- package/dist/src/init/mcp-generator.js.map +1 -1
- package/dist/src/init/settings-generator.d.ts.map +1 -1
- package/dist/src/init/settings-generator.js +107 -41
- package/dist/src/init/settings-generator.js.map +1 -1
- package/dist/src/init/statusline-generator.d.ts +16 -8
- package/dist/src/init/statusline-generator.d.ts.map +1 -1
- package/dist/src/init/statusline-generator.js +537 -1019
- package/dist/src/init/statusline-generator.js.map +1 -1
- package/dist/src/init/types.d.ts +14 -4
- package/dist/src/init/types.d.ts.map +1 -1
- package/dist/src/init/types.js +9 -2
- package/dist/src/init/types.js.map +1 -1
- package/dist/src/mcp-client.d.ts.map +1 -1
- package/dist/src/mcp-client.js +10 -0
- package/dist/src/mcp-client.js.map +1 -1
- package/dist/src/mcp-server.d.ts.map +1 -1
- package/dist/src/mcp-server.js +30 -4
- package/dist/src/mcp-server.js.map +1 -1
- package/dist/src/mcp-tools/agentdb-tools.d.ts +30 -0
- package/dist/src/mcp-tools/agentdb-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/agentdb-tools.js +557 -0
- package/dist/src/mcp-tools/agentdb-tools.js.map +1 -0
- package/dist/src/mcp-tools/browser-tools.js +2 -2
- package/dist/src/mcp-tools/browser-tools.js.map +1 -1
- package/dist/src/mcp-tools/config-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/config-tools.js +21 -2
- package/dist/src/mcp-tools/config-tools.js.map +1 -1
- package/dist/src/mcp-tools/coordination-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/coordination-tools.js +192 -13
- package/dist/src/mcp-tools/coordination-tools.js.map +1 -1
- package/dist/src/mcp-tools/daa-tools.js +5 -5
- package/dist/src/mcp-tools/daa-tools.js.map +1 -1
- package/dist/src/mcp-tools/github-tools.js +2 -2
- package/dist/src/mcp-tools/github-tools.js.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.js +263 -35
- package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.js +355 -40
- package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
- package/dist/src/mcp-tools/index.d.ts +2 -0
- package/dist/src/mcp-tools/index.d.ts.map +1 -1
- package/dist/src/mcp-tools/index.js +2 -0
- package/dist/src/mcp-tools/index.js.map +1 -1
- package/dist/src/mcp-tools/memory-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/memory-tools.js +31 -1
- package/dist/src/mcp-tools/memory-tools.js.map +1 -1
- package/dist/src/mcp-tools/neural-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/neural-tools.js +32 -27
- package/dist/src/mcp-tools/neural-tools.js.map +1 -1
- package/dist/src/mcp-tools/performance-tools.js +1 -1
- package/dist/src/mcp-tools/performance-tools.js.map +1 -1
- package/dist/src/mcp-tools/ruvllm-tools.d.ts +9 -0
- package/dist/src/mcp-tools/ruvllm-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/ruvllm-tools.js +283 -0
- package/dist/src/mcp-tools/ruvllm-tools.js.map +1 -0
- package/dist/src/mcp-tools/swarm-tools.d.ts +2 -1
- package/dist/src/mcp-tools/swarm-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/swarm-tools.js +216 -30
- package/dist/src/mcp-tools/swarm-tools.js.map +1 -1
- package/dist/src/mcp-tools/system-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/system-tools.js +109 -6
- package/dist/src/mcp-tools/system-tools.js.map +1 -1
- package/dist/src/mcp-tools/task-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/task-tools.js +102 -0
- package/dist/src/mcp-tools/task-tools.js.map +1 -1
- package/dist/src/mcp-tools/wasm-agent-tools.d.ts +9 -0
- package/dist/src/mcp-tools/wasm-agent-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/wasm-agent-tools.js +230 -0
- package/dist/src/mcp-tools/wasm-agent-tools.js.map +1 -0
- package/dist/src/mcp-tools/workflow-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/workflow-tools.js +91 -0
- package/dist/src/mcp-tools/workflow-tools.js.map +1 -1
- package/dist/src/memory/ewc-consolidation.d.ts +24 -0
- package/dist/src/memory/ewc-consolidation.d.ts.map +1 -1
- package/dist/src/memory/ewc-consolidation.js +59 -0
- package/dist/src/memory/ewc-consolidation.js.map +1 -1
- package/dist/src/memory/intelligence.d.ts +53 -0
- package/dist/src/memory/intelligence.d.ts.map +1 -1
- package/dist/src/memory/intelligence.js +264 -7
- 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 +1494 -0
- package/dist/src/memory/memory-bridge.js.map +1 -0
- package/dist/src/memory/memory-initializer.d.ts +17 -1
- package/dist/src/memory/memory-initializer.d.ts.map +1 -1
- package/dist/src/memory/memory-initializer.js +320 -42
- package/dist/src/memory/memory-initializer.js.map +1 -1
- package/dist/src/output.d.ts.map +1 -1
- package/dist/src/output.js +1 -0
- package/dist/src/output.js.map +1 -1
- package/dist/src/parser.d.ts +10 -0
- package/dist/src/parser.d.ts.map +1 -1
- package/dist/src/parser.js +49 -3
- package/dist/src/parser.js.map +1 -1
- package/dist/src/plugins/manager.d.ts.map +1 -1
- package/dist/src/plugins/manager.js +31 -14
- package/dist/src/plugins/manager.js.map +1 -1
- package/dist/src/plugins/store/discovery.js +5 -5
- package/dist/src/plugins/store/discovery.js.map +1 -1
- package/dist/src/plugins/tests/standalone-test.js +4 -4
- package/dist/src/plugins/tests/standalone-test.js.map +1 -1
- package/dist/src/production/error-handler.js +1 -1
- package/dist/src/production/error-handler.js.map +1 -1
- package/dist/src/runtime/headless.d.ts +3 -3
- package/dist/src/runtime/headless.js +6 -6
- 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 +316 -0
- package/dist/src/ruvector/agent-wasm.js.map +1 -0
- package/dist/src/ruvector/enhanced-model-router.d.ts.map +1 -1
- package/dist/src/ruvector/enhanced-model-router.js +25 -15
- package/dist/src/ruvector/enhanced-model-router.js.map +1 -1
- package/dist/src/ruvector/index.d.ts +7 -1
- package/dist/src/ruvector/index.d.ts.map +1 -1
- package/dist/src/ruvector/index.js +17 -1
- package/dist/src/ruvector/index.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 +363 -0
- package/dist/src/ruvector/ruvllm-wasm.js.map +1 -0
- 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 +95 -0
- package/dist/src/services/agentic-flow-bridge.js.map +1 -0
- package/dist/src/services/claim-service.js +1 -1
- package/dist/src/services/claim-service.js.map +1 -1
- package/dist/src/services/container-worker-pool.d.ts.map +1 -1
- package/dist/src/services/container-worker-pool.js +3 -1
- package/dist/src/services/container-worker-pool.js.map +1 -1
- package/dist/src/services/index.d.ts +1 -1
- package/dist/src/services/index.d.ts.map +1 -1
- package/dist/src/services/registry-api.d.ts +1 -1
- package/dist/src/services/registry-api.js +1 -1
- package/dist/src/services/ruvector-training.d.ts +11 -2
- package/dist/src/services/ruvector-training.d.ts.map +1 -1
- package/dist/src/services/ruvector-training.js +233 -43
- package/dist/src/services/ruvector-training.js.map +1 -1
- package/dist/src/services/worker-daemon.d.ts +28 -3
- package/dist/src/services/worker-daemon.d.ts.map +1 -1
- package/dist/src/services/worker-daemon.js +156 -17
- package/dist/src/services/worker-daemon.js.map +1 -1
- package/dist/src/services/worker-queue.d.ts.map +1 -1
- package/dist/src/services/worker-queue.js +2 -0
- package/dist/src/services/worker-queue.js.map +1 -1
- package/dist/src/transfer/deploy-seraphine.d.ts +1 -1
- package/dist/src/transfer/deploy-seraphine.js +4 -4
- package/dist/src/transfer/deploy-seraphine.js.map +1 -1
- package/dist/src/transfer/ipfs/client.d.ts.map +1 -1
- package/dist/src/transfer/ipfs/client.js +8 -0
- package/dist/src/transfer/ipfs/client.js.map +1 -1
- package/dist/src/transfer/ipfs/upload.d.ts.map +1 -1
- package/dist/src/transfer/ipfs/upload.js +0 -2
- package/dist/src/transfer/ipfs/upload.js.map +1 -1
- package/dist/src/transfer/models/seraphine.d.ts +1 -1
- package/dist/src/transfer/models/seraphine.js +5 -5
- package/dist/src/transfer/models/seraphine.js.map +1 -1
- package/dist/src/transfer/serialization/cfp.d.ts +1 -1
- package/dist/src/transfer/serialization/cfp.d.ts.map +1 -1
- package/dist/src/transfer/serialization/cfp.js +9 -6
- package/dist/src/transfer/serialization/cfp.js.map +1 -1
- package/dist/src/transfer/storage/gcs.d.ts.map +1 -1
- package/dist/src/transfer/storage/gcs.js +71 -29
- package/dist/src/transfer/storage/gcs.js.map +1 -1
- package/dist/src/transfer/store/discovery.js +4 -4
- package/dist/src/transfer/store/discovery.js.map +1 -1
- package/dist/src/transfer/store/registry.js +1 -1
- package/dist/src/transfer/store/registry.js.map +1 -1
- package/dist/src/transfer/store/tests/standalone-test.js +4 -4
- package/dist/src/transfer/store/tests/standalone-test.js.map +1 -1
- package/dist/src/transfer/types.d.ts +1 -1
- package/dist/src/types.d.ts +1 -1
- package/dist/src/types.js +1 -1
- package/dist/src/update/validator.js +1 -1
- package/dist/src/update/validator.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -10
- package/.claude/agents/custom/accessibility-auditor.yaml +0 -56
- package/.claude/agents/custom/design-architect.yaml +0 -48
- package/.claude/agents/custom/ui-developer.yaml +0 -46
- package/.claude/agents/custom/ux-researcher.yaml +0 -60
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RVFA Ed25519 Code Signing -- Digital signatures for RVFA appliance files.
|
|
3
|
+
*
|
|
4
|
+
* Provides tamper detection and publisher identity verification using
|
|
5
|
+
* Ed25519 (RFC 8032) via Node.js native crypto. Zero external dependencies.
|
|
6
|
+
*
|
|
7
|
+
* @module @claude-flow/cli/appliance/rvfa-signing
|
|
8
|
+
*/
|
|
9
|
+
import { generateKeyPairSync, createHash, sign, verify, createPublicKey, createPrivateKey, } from 'node:crypto';
|
|
10
|
+
import { readFile, writeFile, stat, chmod, mkdir } from 'node:fs/promises';
|
|
11
|
+
// ── Constants ────────────────────────────────────────────────
|
|
12
|
+
const PREAMBLE_SIZE = 12; // 4B magic + 4B version + 4B header_len
|
|
13
|
+
const SHA256_SIZE = 32;
|
|
14
|
+
const KEY_FILE_MODE = 0o600;
|
|
15
|
+
// ── Key Management ───────────────────────────────────────────
|
|
16
|
+
/** Compute the fingerprint of a public key: first 16 hex chars of its SHA256. */
|
|
17
|
+
function computeFingerprint(publicKeyPem) {
|
|
18
|
+
return createHash('sha256')
|
|
19
|
+
.update(publicKeyPem, 'utf-8')
|
|
20
|
+
.digest('hex')
|
|
21
|
+
.slice(0, 16);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Generate a new Ed25519 key pair for RVFA signing.
|
|
25
|
+
*/
|
|
26
|
+
export async function generateKeyPair() {
|
|
27
|
+
const { publicKey, privateKey } = generateKeyPairSync('ed25519', {
|
|
28
|
+
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
29
|
+
privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
|
|
30
|
+
});
|
|
31
|
+
const pubBuf = Buffer.from(publicKey, 'utf-8');
|
|
32
|
+
const privBuf = Buffer.from(privateKey, 'utf-8');
|
|
33
|
+
const fingerprint = computeFingerprint(publicKey);
|
|
34
|
+
return { publicKey: pubBuf, privateKey: privBuf, fingerprint };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Save a key pair to disk as PEM files.
|
|
38
|
+
*
|
|
39
|
+
* @param keyPair The key pair to persist.
|
|
40
|
+
* @param dir Directory to write files into.
|
|
41
|
+
* @param name Base name for the key files (default: 'rvfa-signing').
|
|
42
|
+
* @returns Paths to the written public and private key files.
|
|
43
|
+
*/
|
|
44
|
+
export async function saveKeyPair(keyPair, dir, name = 'rvfa-signing') {
|
|
45
|
+
await mkdir(dir, { recursive: true });
|
|
46
|
+
const pubPath = `${dir}/${name}.pub`;
|
|
47
|
+
const privPath = `${dir}/${name}.key`;
|
|
48
|
+
await writeFile(pubPath, keyPair.publicKey);
|
|
49
|
+
await writeFile(privPath, keyPair.privateKey, { mode: KEY_FILE_MODE });
|
|
50
|
+
// Ensure private key has restrictive permissions even on existing files
|
|
51
|
+
await chmod(privPath, KEY_FILE_MODE);
|
|
52
|
+
return { publicKeyPath: pubPath, privateKeyPath: privPath };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Load a key pair from PEM files on disk.
|
|
56
|
+
*
|
|
57
|
+
* @param dir Directory containing the key files.
|
|
58
|
+
* @param name Base name for the key files (default: 'rvfa-signing').
|
|
59
|
+
*/
|
|
60
|
+
export async function loadKeyPair(dir, name = 'rvfa-signing') {
|
|
61
|
+
const pubPath = `${dir}/${name}.pub`;
|
|
62
|
+
const privPath = `${dir}/${name}.key`;
|
|
63
|
+
const publicKey = await readFile(pubPath);
|
|
64
|
+
const privateKey = await readFile(privPath);
|
|
65
|
+
// Warn if private key permissions are too open
|
|
66
|
+
const privStat = await stat(privPath);
|
|
67
|
+
const mode = privStat.mode & 0o777;
|
|
68
|
+
if (mode & 0o077) {
|
|
69
|
+
console.warn(`[rvfa-signing] WARNING: Private key ${privPath} has open permissions ` +
|
|
70
|
+
`(${mode.toString(8)}). Consider running: chmod 600 ${privPath}`);
|
|
71
|
+
}
|
|
72
|
+
const fingerprint = computeFingerprint(publicKey.toString('utf-8'));
|
|
73
|
+
return { publicKey, privateKey, fingerprint };
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Load a public key from a single PEM file.
|
|
77
|
+
*/
|
|
78
|
+
export async function loadPublicKey(path) {
|
|
79
|
+
return readFile(path);
|
|
80
|
+
}
|
|
81
|
+
// ── Internal Helpers ─────────────────────────────────────────
|
|
82
|
+
/**
|
|
83
|
+
* Recursively sort object keys for canonical JSON serialization.
|
|
84
|
+
* Produces deterministic output regardless of insertion order.
|
|
85
|
+
*/
|
|
86
|
+
function canonicalJson(value) {
|
|
87
|
+
return JSON.stringify(value, (_key, val) => {
|
|
88
|
+
if (val !== null && typeof val === 'object' && !Array.isArray(val) && !Buffer.isBuffer(val)) {
|
|
89
|
+
const sorted = {};
|
|
90
|
+
for (const k of Object.keys(val).sort()) {
|
|
91
|
+
sorted[k] = val[k];
|
|
92
|
+
}
|
|
93
|
+
return sorted;
|
|
94
|
+
}
|
|
95
|
+
return val;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Parse an RVFA binary into its components without full validation.
|
|
100
|
+
* Returns the header object, header JSON bytes, section data region, and footer.
|
|
101
|
+
*/
|
|
102
|
+
function parseRvfaBinary(buf) {
|
|
103
|
+
if (buf.length < PREAMBLE_SIZE + SHA256_SIZE) {
|
|
104
|
+
throw new Error('Buffer too small to be a valid RVFA file');
|
|
105
|
+
}
|
|
106
|
+
const magic = buf.subarray(0, 4).toString('ascii');
|
|
107
|
+
if (magic !== 'RVFA') {
|
|
108
|
+
throw new Error(`Invalid RVFA magic: expected "RVFA", got "${magic}"`);
|
|
109
|
+
}
|
|
110
|
+
const headerLen = buf.readUInt32LE(8);
|
|
111
|
+
const headerStart = PREAMBLE_SIZE;
|
|
112
|
+
const headerEnd = headerStart + headerLen;
|
|
113
|
+
if (headerEnd > buf.length - SHA256_SIZE) {
|
|
114
|
+
throw new Error('Header length extends beyond buffer');
|
|
115
|
+
}
|
|
116
|
+
const headerJson = buf.subarray(headerStart, headerEnd).toString('utf-8');
|
|
117
|
+
let header;
|
|
118
|
+
try {
|
|
119
|
+
header = JSON.parse(headerJson);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
throw new Error('Failed to parse RVFA header JSON');
|
|
123
|
+
}
|
|
124
|
+
const footer = buf.subarray(buf.length - SHA256_SIZE);
|
|
125
|
+
const sectionData = buf.subarray(headerEnd, buf.length - SHA256_SIZE);
|
|
126
|
+
return { header, headerStart, headerEnd, sectionData, footer };
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Compute the signing digest for an RVFA file.
|
|
130
|
+
*
|
|
131
|
+
* The digest is SHA256 of: canonical_header_json (without signature field)
|
|
132
|
+
* + section_data_bytes
|
|
133
|
+
* + footer_32_bytes
|
|
134
|
+
*/
|
|
135
|
+
function computeSigningDigest(header, sectionData, footer) {
|
|
136
|
+
// Strip signature field from header for digest computation
|
|
137
|
+
const stripped = { ...header };
|
|
138
|
+
delete stripped.signature;
|
|
139
|
+
const canonical = Buffer.from(canonicalJson(stripped), 'utf-8');
|
|
140
|
+
return createHash('sha256')
|
|
141
|
+
.update(canonical)
|
|
142
|
+
.update(sectionData)
|
|
143
|
+
.update(footer)
|
|
144
|
+
.digest();
|
|
145
|
+
}
|
|
146
|
+
/** Convert a Buffer or PEM string into a KeyObject. */
|
|
147
|
+
function toPrivateKeyObject(key) {
|
|
148
|
+
const pem = Buffer.isBuffer(key) ? key.toString('utf-8') : key;
|
|
149
|
+
return createPrivateKey(pem);
|
|
150
|
+
}
|
|
151
|
+
/** Convert a Buffer or PEM string into a KeyObject. */
|
|
152
|
+
function toPublicKeyObject(key) {
|
|
153
|
+
const pem = Buffer.isBuffer(key) ? key.toString('utf-8') : key;
|
|
154
|
+
return createPublicKey(pem);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Rebuild the RVFA binary with an updated header.
|
|
158
|
+
*
|
|
159
|
+
* Preserves the original preamble version, recalculates header length,
|
|
160
|
+
* and keeps section data and footer intact.
|
|
161
|
+
*/
|
|
162
|
+
function rebuildRvfa(originalBuf, newHeader, sectionData, footer) {
|
|
163
|
+
const headerJson = Buffer.from(JSON.stringify(newHeader), 'utf-8');
|
|
164
|
+
// Preamble: magic + version + new header length
|
|
165
|
+
const preamble = Buffer.alloc(PREAMBLE_SIZE);
|
|
166
|
+
originalBuf.copy(preamble, 0, 0, 8); // magic + version unchanged
|
|
167
|
+
preamble.writeUInt32LE(headerJson.length, 8);
|
|
168
|
+
return Buffer.concat([preamble, headerJson, sectionData, footer]);
|
|
169
|
+
}
|
|
170
|
+
// ── RvfaSigner ───────────────────────────────────────────────
|
|
171
|
+
/**
|
|
172
|
+
* Signs RVFA appliance files and data with Ed25519.
|
|
173
|
+
*/
|
|
174
|
+
export class RvfaSigner {
|
|
175
|
+
keyObj;
|
|
176
|
+
fingerprint;
|
|
177
|
+
constructor(privateKey) {
|
|
178
|
+
this.keyObj = toPrivateKeyObject(privateKey);
|
|
179
|
+
// Derive public key to compute fingerprint
|
|
180
|
+
const pubPem = createPublicKey(this.keyObj)
|
|
181
|
+
.export({ type: 'spki', format: 'pem' });
|
|
182
|
+
this.fingerprint = computeFingerprint(pubPem);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Sign an RVFA appliance file in-place.
|
|
186
|
+
*
|
|
187
|
+
* Algorithm:
|
|
188
|
+
* 1. Read and parse the RVFA binary
|
|
189
|
+
* 2. Strip any existing signature from the header
|
|
190
|
+
* 3. Compute SHA256 of [canonical_header + section_data + footer]
|
|
191
|
+
* 4. Sign the digest with Ed25519
|
|
192
|
+
* 5. Embed signature metadata into the header
|
|
193
|
+
* 6. Write the updated binary back to the file
|
|
194
|
+
*
|
|
195
|
+
* @param rvfaPath Path to the .rvf appliance file.
|
|
196
|
+
* @param signedBy Optional publisher name.
|
|
197
|
+
* @returns The signature metadata that was embedded.
|
|
198
|
+
*/
|
|
199
|
+
async signAppliance(rvfaPath, signedBy) {
|
|
200
|
+
const buf = await readFile(rvfaPath);
|
|
201
|
+
const { header, sectionData, footer } = parseRvfaBinary(buf);
|
|
202
|
+
// Compute digest over header (without signature) + sections + footer
|
|
203
|
+
const digest = computeSigningDigest(header, sectionData, footer);
|
|
204
|
+
// Ed25519 sign
|
|
205
|
+
const sig = sign(null, digest, this.keyObj);
|
|
206
|
+
const metadata = {
|
|
207
|
+
algorithm: 'ed25519',
|
|
208
|
+
publicKeyFingerprint: this.fingerprint,
|
|
209
|
+
signature: sig.toString('hex'),
|
|
210
|
+
signedAt: new Date().toISOString(),
|
|
211
|
+
signedBy,
|
|
212
|
+
scope: 'full',
|
|
213
|
+
};
|
|
214
|
+
// Embed signature in header and rebuild
|
|
215
|
+
header.signature = metadata;
|
|
216
|
+
const rebuilt = rebuildRvfa(buf, header, sectionData, footer);
|
|
217
|
+
await writeFile(rvfaPath, rebuilt);
|
|
218
|
+
return metadata;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Sign a section footer hash (detached signature).
|
|
222
|
+
*
|
|
223
|
+
* @param footerHash The 32-byte SHA256 footer hash from an RVFA file.
|
|
224
|
+
* @returns Hex-encoded Ed25519 signature.
|
|
225
|
+
*/
|
|
226
|
+
async signSections(footerHash) {
|
|
227
|
+
if (footerHash.length !== SHA256_SIZE) {
|
|
228
|
+
throw new Error(`Footer hash must be ${SHA256_SIZE} bytes, got ${footerHash.length}`);
|
|
229
|
+
}
|
|
230
|
+
const sig = sign(null, footerHash, this.keyObj);
|
|
231
|
+
return sig.toString('hex');
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Sign an RVFP patch file (detached signature).
|
|
235
|
+
*
|
|
236
|
+
* @param patchData The raw patch binary data.
|
|
237
|
+
* @returns Hex-encoded Ed25519 signature.
|
|
238
|
+
*/
|
|
239
|
+
async signPatch(patchData) {
|
|
240
|
+
const digest = createHash('sha256').update(patchData).digest();
|
|
241
|
+
const sig = sign(null, digest, this.keyObj);
|
|
242
|
+
return sig.toString('hex');
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// ── RvfaVerifier ─────────────────────────────────────────────
|
|
246
|
+
/**
|
|
247
|
+
* Verifies Ed25519 signatures on RVFA appliance files and data.
|
|
248
|
+
*/
|
|
249
|
+
export class RvfaVerifier {
|
|
250
|
+
keyObj;
|
|
251
|
+
fingerprint;
|
|
252
|
+
constructor(publicKey) {
|
|
253
|
+
this.keyObj = toPublicKeyObject(publicKey);
|
|
254
|
+
const pem = Buffer.isBuffer(publicKey) ? publicKey.toString('utf-8') : publicKey;
|
|
255
|
+
this.fingerprint = computeFingerprint(pem);
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Verify the Ed25519 signature embedded in an RVFA appliance file.
|
|
259
|
+
*
|
|
260
|
+
* @param rvfaPath Path to the .rvf appliance file.
|
|
261
|
+
* @returns Verification result with details and any errors.
|
|
262
|
+
*/
|
|
263
|
+
async verifyAppliance(rvfaPath) {
|
|
264
|
+
const errors = [];
|
|
265
|
+
let buf;
|
|
266
|
+
try {
|
|
267
|
+
buf = await readFile(rvfaPath);
|
|
268
|
+
}
|
|
269
|
+
catch (err) {
|
|
270
|
+
return { valid: false, errors: [`Failed to read file: ${err.message}`] };
|
|
271
|
+
}
|
|
272
|
+
let parsed;
|
|
273
|
+
try {
|
|
274
|
+
parsed = parseRvfaBinary(buf);
|
|
275
|
+
}
|
|
276
|
+
catch (err) {
|
|
277
|
+
return { valid: false, errors: [`Invalid RVFA file: ${err.message}`] };
|
|
278
|
+
}
|
|
279
|
+
const { header, sectionData, footer } = parsed;
|
|
280
|
+
// Extract signature metadata from header
|
|
281
|
+
const sigRaw = header.signature;
|
|
282
|
+
if (!sigRaw || typeof sigRaw !== 'object') {
|
|
283
|
+
return { valid: false, errors: ['No signature found in RVFA header'] };
|
|
284
|
+
}
|
|
285
|
+
const sigMeta = sigRaw;
|
|
286
|
+
if (sigMeta.algorithm !== 'ed25519') {
|
|
287
|
+
errors.push(`Unsupported algorithm: ${String(sigMeta.algorithm)}`);
|
|
288
|
+
return { valid: false, errors };
|
|
289
|
+
}
|
|
290
|
+
if (typeof sigMeta.signature !== 'string' || !sigMeta.signature) {
|
|
291
|
+
errors.push('Signature field is missing or empty');
|
|
292
|
+
return { valid: false, errors };
|
|
293
|
+
}
|
|
294
|
+
// Recompute the digest the same way the signer did
|
|
295
|
+
const digest = computeSigningDigest(header, sectionData, footer);
|
|
296
|
+
// Verify
|
|
297
|
+
let sigBuf;
|
|
298
|
+
try {
|
|
299
|
+
sigBuf = Buffer.from(sigMeta.signature, 'hex');
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
errors.push('Signature is not valid hex');
|
|
303
|
+
return { valid: false, errors };
|
|
304
|
+
}
|
|
305
|
+
let valid;
|
|
306
|
+
try {
|
|
307
|
+
valid = verify(null, digest, this.keyObj, sigBuf);
|
|
308
|
+
}
|
|
309
|
+
catch (err) {
|
|
310
|
+
errors.push(`Verification error: ${err.message}`);
|
|
311
|
+
return { valid: false, errors };
|
|
312
|
+
}
|
|
313
|
+
if (!valid) {
|
|
314
|
+
errors.push('Ed25519 signature verification failed: data may be tampered');
|
|
315
|
+
}
|
|
316
|
+
return {
|
|
317
|
+
valid,
|
|
318
|
+
signerFingerprint: sigMeta.publicKeyFingerprint,
|
|
319
|
+
signedAt: sigMeta.signedAt,
|
|
320
|
+
signedBy: sigMeta.signedBy,
|
|
321
|
+
errors,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Verify a detached Ed25519 signature over arbitrary data.
|
|
326
|
+
*
|
|
327
|
+
* @param data The data that was signed.
|
|
328
|
+
* @param signature Hex-encoded Ed25519 signature.
|
|
329
|
+
*/
|
|
330
|
+
async verifyDetached(data, signature) {
|
|
331
|
+
const digest = createHash('sha256').update(data).digest();
|
|
332
|
+
const sigBuf = Buffer.from(signature, 'hex');
|
|
333
|
+
return verify(null, digest, this.keyObj, sigBuf);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Verify an RVFP patch file signature.
|
|
337
|
+
*
|
|
338
|
+
* @param patchData The raw patch binary data.
|
|
339
|
+
* @param signature Hex-encoded Ed25519 signature.
|
|
340
|
+
*/
|
|
341
|
+
async verifyPatch(patchData, signature) {
|
|
342
|
+
const digest = createHash('sha256').update(patchData).digest();
|
|
343
|
+
const sigBuf = Buffer.from(signature, 'hex');
|
|
344
|
+
return verify(null, digest, this.keyObj, sigBuf);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
//# sourceMappingURL=rvfa-signing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rvfa-signing.js","sourceRoot":"","sources":["../../../src/appliance/rvfa-signing.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/commands/agent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAiC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/commands/agent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAiC,MAAM,aAAa,CAAC;AA49B1E,eAAO,MAAM,YAAY,EAAE,OA8B1B,CAAC;AAoCF,eAAe,YAAY,CAAC"}
|
|
@@ -5,6 +5,40 @@
|
|
|
5
5
|
import { output } from '../output.js';
|
|
6
6
|
import { select, confirm, input } from '../prompt.js';
|
|
7
7
|
import { callMCPTool, MCPClientError } from '../mcp-client.js';
|
|
8
|
+
import * as fs from 'fs';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
/**
|
|
11
|
+
* Update swarm-activity.json metrics after agent count changes.
|
|
12
|
+
* The statusline reads this file to display the swarm agent count.
|
|
13
|
+
*/
|
|
14
|
+
function updateSwarmActivityMetrics(agentCountDelta) {
|
|
15
|
+
try {
|
|
16
|
+
const metricsDir = path.join(process.cwd(), '.claude-flow', 'metrics');
|
|
17
|
+
const activityPath = path.join(metricsDir, 'swarm-activity.json');
|
|
18
|
+
let data = {
|
|
19
|
+
timestamp: new Date().toISOString(),
|
|
20
|
+
swarm: { active: false, agent_count: 0, coordination_active: false },
|
|
21
|
+
};
|
|
22
|
+
if (fs.existsSync(activityPath)) {
|
|
23
|
+
data = JSON.parse(fs.readFileSync(activityPath, 'utf-8'));
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
fs.mkdirSync(metricsDir, { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
const swarm = data.swarm ?? {};
|
|
29
|
+
const currentCount = Math.max(0, swarm.agent_count || 0);
|
|
30
|
+
const newCount = Math.max(0, currentCount + agentCountDelta);
|
|
31
|
+
swarm.agent_count = newCount;
|
|
32
|
+
swarm.active = newCount > 0;
|
|
33
|
+
swarm.coordination_active = newCount > 0;
|
|
34
|
+
data.swarm = swarm;
|
|
35
|
+
data.timestamp = new Date().toISOString();
|
|
36
|
+
fs.writeFileSync(activityPath, JSON.stringify(data, null, 2));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Non-critical — don't fail the command if metrics update fails
|
|
40
|
+
}
|
|
41
|
+
}
|
|
8
42
|
// Available agent types with descriptions
|
|
9
43
|
const AGENT_TYPES = [
|
|
10
44
|
{ value: 'coder', label: 'Coder', hint: 'Code development with neural patterns' },
|
|
@@ -130,6 +164,8 @@ const spawnCommand = {
|
|
|
130
164
|
});
|
|
131
165
|
output.writeln();
|
|
132
166
|
output.printSuccess(`Agent ${agentName} spawned successfully`);
|
|
167
|
+
// Update swarm-activity.json so statusline reflects the new agent count
|
|
168
|
+
updateSwarmActivityMetrics(1);
|
|
133
169
|
if (ctx.flags.format === 'json') {
|
|
134
170
|
output.printJson(result);
|
|
135
171
|
}
|
|
@@ -350,6 +386,8 @@ const stopCommand = {
|
|
|
350
386
|
output.writeln(output.dim(' Releasing resources...'));
|
|
351
387
|
}
|
|
352
388
|
output.printSuccess(`Agent ${agentId} stopped successfully`);
|
|
389
|
+
// Update swarm-activity.json so statusline reflects the reduced agent count
|
|
390
|
+
updateSwarmActivityMetrics(-1);
|
|
353
391
|
if (ctx.flags.format === 'json') {
|
|
354
392
|
output.printJson(result);
|
|
355
393
|
}
|
|
@@ -382,26 +420,86 @@ const metricsCommand = {
|
|
|
382
420
|
action: async (ctx) => {
|
|
383
421
|
const agentId = ctx.args[0];
|
|
384
422
|
const period = ctx.flags.period;
|
|
385
|
-
//
|
|
423
|
+
// Collect real metrics from .swarm/ state
|
|
424
|
+
const { existsSync, readFileSync, readdirSync, statSync } = await import('fs');
|
|
425
|
+
const { join } = await import('path');
|
|
426
|
+
let totalAgents = 0;
|
|
427
|
+
let activeAgents = 0;
|
|
428
|
+
let tasksCompleted = 0;
|
|
429
|
+
const typeCounts = {};
|
|
430
|
+
// Read swarm agent state
|
|
431
|
+
const swarmDir = join(process.cwd(), '.swarm');
|
|
432
|
+
const agentsDir = join(swarmDir, 'agents');
|
|
433
|
+
if (existsSync(agentsDir)) {
|
|
434
|
+
try {
|
|
435
|
+
const files = readdirSync(agentsDir).filter(f => f.endsWith('.json'));
|
|
436
|
+
for (const file of files) {
|
|
437
|
+
try {
|
|
438
|
+
const data = JSON.parse(readFileSync(join(agentsDir, file), 'utf-8'));
|
|
439
|
+
totalAgents++;
|
|
440
|
+
const agType = data.type || 'unknown';
|
|
441
|
+
if (!typeCounts[agType])
|
|
442
|
+
typeCounts[agType] = { count: 0, tasks: 0, success: 0 };
|
|
443
|
+
typeCounts[agType].count++;
|
|
444
|
+
if (data.status === 'active' || data.status === 'running')
|
|
445
|
+
activeAgents++;
|
|
446
|
+
if (data.tasksCompleted) {
|
|
447
|
+
typeCounts[agType].tasks += data.tasksCompleted;
|
|
448
|
+
tasksCompleted += data.tasksCompleted;
|
|
449
|
+
}
|
|
450
|
+
if (data.successCount)
|
|
451
|
+
typeCounts[agType].success += data.successCount;
|
|
452
|
+
}
|
|
453
|
+
catch { /* skip malformed */ }
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
catch { /* no agents dir */ }
|
|
457
|
+
}
|
|
458
|
+
// Read swarm activity for additional state
|
|
459
|
+
const activityFile = join(swarmDir, 'swarm-activity.json');
|
|
460
|
+
if (existsSync(activityFile)) {
|
|
461
|
+
try {
|
|
462
|
+
const activity = JSON.parse(readFileSync(activityFile, 'utf-8'));
|
|
463
|
+
if (activity.totalAgents && totalAgents === 0)
|
|
464
|
+
totalAgents = activity.totalAgents;
|
|
465
|
+
if (activity.activeAgents && activeAgents === 0)
|
|
466
|
+
activeAgents = activity.activeAgents;
|
|
467
|
+
}
|
|
468
|
+
catch { /* ignore */ }
|
|
469
|
+
}
|
|
470
|
+
// Read memory.db stats
|
|
471
|
+
let vectorCount = 0;
|
|
472
|
+
const dbPath = join(swarmDir, 'memory.db');
|
|
473
|
+
if (existsSync(dbPath)) {
|
|
474
|
+
try {
|
|
475
|
+
const dbSize = statSync(dbPath).size;
|
|
476
|
+
vectorCount = Math.floor(dbSize / 2048);
|
|
477
|
+
}
|
|
478
|
+
catch { /* ignore */ }
|
|
479
|
+
}
|
|
480
|
+
const byType = Object.entries(typeCounts).map(([type, data]) => ({
|
|
481
|
+
type,
|
|
482
|
+
count: data.count,
|
|
483
|
+
tasks: data.tasks,
|
|
484
|
+
successRate: data.tasks > 0 ? `${Math.round((data.success / data.tasks) * 100)}%` : 'N/A'
|
|
485
|
+
}));
|
|
486
|
+
const avgSuccessRate = tasksCompleted > 0
|
|
487
|
+
? `${Math.round(Object.values(typeCounts).reduce((a, d) => a + d.success, 0) / tasksCompleted * 100)}%`
|
|
488
|
+
: 'N/A';
|
|
386
489
|
const metrics = {
|
|
387
490
|
period,
|
|
388
491
|
summary: {
|
|
389
|
-
totalAgents
|
|
390
|
-
activeAgents
|
|
391
|
-
tasksCompleted
|
|
392
|
-
avgSuccessRate
|
|
393
|
-
|
|
394
|
-
|
|
492
|
+
totalAgents,
|
|
493
|
+
activeAgents,
|
|
494
|
+
tasksCompleted,
|
|
495
|
+
avgSuccessRate,
|
|
496
|
+
vectorCount,
|
|
497
|
+
note: totalAgents === 0 ? 'No agents spawned yet. Use: agent spawn -t coder' : undefined
|
|
395
498
|
},
|
|
396
|
-
byType
|
|
397
|
-
{ type: 'coder', count: 2, tasks: 45, successRate: '97%' },
|
|
398
|
-
{ type: 'researcher', count: 1, tasks: 32, successRate: '95%' },
|
|
399
|
-
{ type: 'tester', count: 1, tasks: 50, successRate: '98%' }
|
|
400
|
-
],
|
|
499
|
+
byType,
|
|
401
500
|
performance: {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
searchImprovement: '150x faster'
|
|
501
|
+
memoryVectors: `${vectorCount} vectors`,
|
|
502
|
+
searchBackend: vectorCount > 0 ? 'HNSW-indexed' : 'none'
|
|
405
503
|
}
|
|
406
504
|
};
|
|
407
505
|
if (ctx.flags.format === 'json') {
|
|
@@ -421,8 +519,7 @@ const metricsCommand = {
|
|
|
421
519
|
{ metric: 'Active Agents', value: metrics.summary.activeAgents },
|
|
422
520
|
{ metric: 'Tasks Completed', value: metrics.summary.tasksCompleted },
|
|
423
521
|
{ metric: 'Success Rate', value: metrics.summary.avgSuccessRate },
|
|
424
|
-
{ metric: '
|
|
425
|
-
{ metric: 'Avg Response Time', value: metrics.summary.avgResponseTime }
|
|
522
|
+
{ metric: 'Memory Vectors', value: metrics.summary.vectorCount }
|
|
426
523
|
]
|
|
427
524
|
});
|
|
428
525
|
output.writeln();
|
|
@@ -436,12 +533,15 @@ const metricsCommand = {
|
|
|
436
533
|
],
|
|
437
534
|
data: metrics.byType
|
|
438
535
|
});
|
|
536
|
+
if (metrics.summary.note) {
|
|
537
|
+
output.writeln();
|
|
538
|
+
output.writeln(output.dim(metrics.summary.note));
|
|
539
|
+
}
|
|
439
540
|
output.writeln();
|
|
440
|
-
output.writeln(output.bold('
|
|
541
|
+
output.writeln(output.bold('Memory'));
|
|
441
542
|
output.printList([
|
|
442
|
-
`
|
|
443
|
-
`
|
|
444
|
-
`Search: ${output.success(metrics.performance.searchImprovement)}`
|
|
543
|
+
`Vectors: ${output.success(metrics.performance.memoryVectors)}`,
|
|
544
|
+
`Backend: ${output.success(metrics.performance.searchBackend)}`
|
|
445
545
|
]);
|
|
446
546
|
return { success: true, data: metrics };
|
|
447
547
|
}
|