swarmdo 1.4.8 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/helpers/statusline.cjs +7 -7
- package/README.md +9 -6
- package/package.json +5 -3
- package/v3/@swarmdo/cli/dist/src/commands/compact.d.ts +16 -0
- package/v3/@swarmdo/cli/dist/src/commands/compact.js +106 -0
- package/v3/@swarmdo/cli/dist/src/commands/hooks.js +26 -24
- package/v3/@swarmdo/cli/dist/src/commands/index.js +10 -3
- package/v3/@swarmdo/cli/dist/src/commands/integrations.d.ts +14 -0
- package/v3/@swarmdo/cli/dist/src/commands/integrations.js +158 -0
- package/v3/@swarmdo/cli/dist/src/commands/memory.js +50 -1
- package/v3/@swarmdo/cli/dist/src/commands/providers.js +3 -0
- package/v3/@swarmdo/cli/dist/src/commands/release.d.ts +15 -0
- package/v3/@swarmdo/cli/dist/src/commands/release.js +241 -0
- package/v3/@swarmdo/cli/dist/src/commands/security.js +14 -0
- package/v3/@swarmdo/cli/dist/src/commands/transcript.js +82 -1
- package/v3/@swarmdo/cli/dist/src/commands/usage.js +80 -1
- package/v3/@swarmdo/cli/dist/src/compact/compact.d.ts +60 -0
- package/v3/@swarmdo/cli/dist/src/compact/compact.js +170 -0
- package/v3/@swarmdo/cli/dist/src/config-lint/lint.js +11 -1
- package/v3/@swarmdo/cli/dist/src/index.js +4 -2
- package/v3/@swarmdo/cli/dist/src/init/statusline-generator.js +6 -6
- package/v3/@swarmdo/cli/dist/src/integrations/integrations.d.ts +54 -0
- package/v3/@swarmdo/cli/dist/src/integrations/integrations.js +162 -0
- package/v3/@swarmdo/cli/dist/src/mcp-tools/agent-execute-core.js +25 -3
- package/v3/@swarmdo/cli/dist/src/mcp-tools/agentdb-tools.js +8 -8
- package/v3/@swarmdo/cli/dist/src/memory/graph-edge-writer.d.ts +12 -0
- package/v3/@swarmdo/cli/dist/src/memory/graph-edge-writer.js +32 -1
- package/v3/@swarmdo/cli/dist/src/memory-vault/watch.d.ts +32 -0
- package/v3/@swarmdo/cli/dist/src/memory-vault/watch.js +66 -0
- package/v3/@swarmdo/cli/dist/src/providers/openrouter-config.d.ts +91 -0
- package/v3/@swarmdo/cli/dist/src/providers/openrouter-config.js +186 -0
- package/v3/@swarmdo/cli/dist/src/release/release.d.ts +72 -0
- package/v3/@swarmdo/cli/dist/src/release/release.js +86 -0
- package/v3/@swarmdo/cli/dist/src/resilience/backoff.d.ts +23 -0
- package/v3/@swarmdo/cli/dist/src/resilience/backoff.js +30 -0
- package/v3/@swarmdo/cli/dist/src/swarmvector/model-router.js +14 -0
- package/v3/@swarmdo/cli/dist/src/transcript/search.d.ts +39 -0
- package/v3/@swarmdo/cli/dist/src/transcript/search.js +67 -0
- package/v3/@swarmdo/cli/dist/src/usage/diff.d.ts +69 -0
- package/v3/@swarmdo/cli/dist/src/usage/diff.js +112 -0
- package/v3/@swarmdo/cli/package.json +4 -4
- package/v3/@swarmdo/cli-core/dist/src/index.js +1 -1
- package/v3/@swarmdo/codex/dist/cli.js +0 -0
- package/v3/@swarmdo/hooks/dist/cli/guidance-cli.js +0 -0
- package/v3/@swarmdo/hooks/dist/statusline/index.d.ts +3 -3
- package/v3/@swarmdo/hooks/dist/statusline/index.js +3 -3
- package/v3/@swarmdo/integration/dist/__tests__/agentic-flow-agent.test.js +4 -1
- package/v3/@swarmdo/neural/dist/flash-attention.d.ts +1 -1
- package/v3/@swarmdo/neural/dist/flash-attention.js +1 -1
- package/v3/@swarmdo/plugin-agent-federation/dist/plugin.js +1 -1
- package/v3/@swarmdo/plugin-agent-federation/dist/transport/midstream-aware-loader.js +2 -2
- package/v3/@swarmdo/providers/dist/swarmvector-provider.d.ts +1 -1
- package/v3/@swarmdo/providers/dist/swarmvector-provider.js +1 -1
- package/v3/@swarmdo/security/dist/input-validator.d.ts +6 -6
- package/v3/@swarmdo/shared/dist/hooks/safety/git-commit.js +1 -1
- package/v3/@swarmdo/shared/dist/mcp/transport/http.js +8 -1
- package/v3/vendor/agentdb/package.json +0 -1
- package/v3/vendor/agentic-flow/package.json +0 -1
- package/.claude/scheduled_tasks.lock +0 -1
- package/.claude/skills/sdo-caveman-compress/scripts/__pycache__/__init__.cpython-314.pyc +0 -0
- package/.claude/skills/sdo-caveman-compress/scripts/__pycache__/__main__.cpython-314.pyc +0 -0
- package/.claude/skills/sdo-caveman-compress/scripts/__pycache__/cli.cpython-314.pyc +0 -0
- package/.claude/skills/sdo-caveman-compress/scripts/__pycache__/compress.cpython-314.pyc +0 -0
- package/.claude/skills/sdo-caveman-compress/scripts/__pycache__/detect.cpython-314.pyc +0 -0
- package/.claude/skills/sdo-caveman-compress/scripts/__pycache__/validate.cpython-314.pyc +0 -0
- package/v3/@swarmdo/plugin-iot-cognitum/dist/application/index.d.ts +0 -2
- package/v3/@swarmdo/plugin-iot-cognitum/dist/application/index.js +0 -2
- package/v3/@swarmdo/plugin-iot-cognitum/dist/application/iot-coordinator.d.ts +0 -138
- package/v3/@swarmdo/plugin-iot-cognitum/dist/application/iot-coordinator.js +0 -418
- package/v3/@swarmdo/plugin-iot-cognitum/dist/bin.d.ts +0 -15
- package/v3/@swarmdo/plugin-iot-cognitum/dist/bin.js +0 -240
- package/v3/@swarmdo/plugin-iot-cognitum/dist/cli-commands.d.ts +0 -7
- package/v3/@swarmdo/plugin-iot-cognitum/dist/cli-commands.js +0 -508
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-agent.d.ts +0 -54
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-agent.js +0 -2
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-fleet.d.ts +0 -46
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-fleet.js +0 -2
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-trust-level.d.ts +0 -18
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/device-trust-level.js +0 -28
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/index.d.ts +0 -5
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/index.js +0 -2
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/telemetry.d.ts +0 -35
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/entities/telemetry.js +0 -2
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/device-repository.d.ts +0 -11
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/device-repository.js +0 -2
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/fleet-repository.d.ts +0 -9
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/fleet-repository.js +0 -2
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/index.d.ts +0 -5
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/index.js +0 -2
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/telemetry-repository.d.ts +0 -12
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/telemetry-repository.js +0 -2
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/trust-history-repository.d.ts +0 -19
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/repositories/trust-history-repository.js +0 -2
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/anomaly-detection-service.d.ts +0 -44
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/anomaly-detection-service.js +0 -117
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/device-lifecycle-service.d.ts +0 -70
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/device-lifecycle-service.js +0 -194
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/firmware-orchestration-service.d.ts +0 -69
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/firmware-orchestration-service.js +0 -139
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/fleet-topology-service.d.ts +0 -34
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/fleet-topology-service.js +0 -101
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/index.d.ts +0 -10
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/index.js +0 -10
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/mesh-service.d.ts +0 -64
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/mesh-service.js +0 -70
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/sona-integration-service.d.ts +0 -44
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/sona-integration-service.js +0 -79
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/telemetry-ingestion-service.d.ts +0 -37
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/telemetry-ingestion-service.js +0 -39
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/telemetry-service.d.ts +0 -67
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/telemetry-service.js +0 -58
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/witness-verification-service.d.ts +0 -45
- package/v3/@swarmdo/plugin-iot-cognitum/dist/domain/services/witness-verification-service.js +0 -63
- package/v3/@swarmdo/plugin-iot-cognitum/dist/index.d.ts +0 -26
- package/v3/@swarmdo/plugin-iot-cognitum/dist/index.js +0 -17
- package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/agentdb-telemetry-repository.d.ts +0 -51
- package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/agentdb-telemetry-repository.js +0 -110
- package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-device-repository.d.ts +0 -13
- package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-device-repository.js +0 -25
- package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-fleet-repository.d.ts +0 -11
- package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-fleet-repository.js +0 -19
- package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-trust-history-repository.d.ts +0 -11
- package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/in-memory-trust-history-repository.js +0 -27
- package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/index.d.ts +0 -6
- package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/index.js +0 -6
- package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/seed-client-factory.d.ts +0 -41
- package/v3/@swarmdo/plugin-iot-cognitum/dist/infrastructure/seed-client-factory.js +0 -64
- package/v3/@swarmdo/plugin-iot-cognitum/dist/mcp-tools.d.ts +0 -8
- package/v3/@swarmdo/plugin-iot-cognitum/dist/mcp-tools.js +0 -703
- package/v3/@swarmdo/plugin-iot-cognitum/dist/plugin.d.ts +0 -23
- package/v3/@swarmdo/plugin-iot-cognitum/dist/plugin.js +0 -239
- package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/anomaly-scan-worker.d.ts +0 -17
- package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/anomaly-scan-worker.js +0 -42
- package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/firmware-watch-worker.d.ts +0 -18
- package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/firmware-watch-worker.js +0 -45
- package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/health-probe-worker.d.ts +0 -19
- package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/health-probe-worker.js +0 -50
- package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/mesh-sync-worker.d.ts +0 -19
- package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/mesh-sync-worker.js +0 -47
- package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/telemetry-ingest-worker.d.ts +0 -17
- package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/telemetry-ingest-worker.js +0 -40
- package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/witness-audit-worker.d.ts +0 -18
- package/v3/@swarmdo/plugin-iot-cognitum/dist/workers/witness-audit-worker.js +0 -51
- package/v3/@swarmdo/testing/dist/fixtures/agent-fixtures.d.ts +0 -214
- package/v3/@swarmdo/testing/dist/fixtures/agent-fixtures.js +0 -595
- package/v3/@swarmdo/testing/dist/fixtures/agents.d.ts +0 -76
- package/v3/@swarmdo/testing/dist/fixtures/agents.js +0 -158
- package/v3/@swarmdo/testing/dist/fixtures/configurations.d.ts +0 -157
- package/v3/@swarmdo/testing/dist/fixtures/configurations.js +0 -337
- package/v3/@swarmdo/testing/dist/fixtures/index.d.ts +0 -10
- package/v3/@swarmdo/testing/dist/fixtures/index.js +0 -17
- package/v3/@swarmdo/testing/dist/fixtures/mcp-fixtures.d.ts +0 -329
- package/v3/@swarmdo/testing/dist/fixtures/mcp-fixtures.js +0 -714
- package/v3/@swarmdo/testing/dist/fixtures/memory-entries.d.ts +0 -159
- package/v3/@swarmdo/testing/dist/fixtures/memory-entries.js +0 -262
- package/v3/@swarmdo/testing/dist/fixtures/memory-fixtures.d.ts +0 -290
- package/v3/@swarmdo/testing/dist/fixtures/memory-fixtures.js +0 -547
- package/v3/@swarmdo/testing/dist/fixtures/swarm-fixtures.d.ts +0 -289
- package/v3/@swarmdo/testing/dist/fixtures/swarm-fixtures.js +0 -534
- package/v3/@swarmdo/testing/dist/fixtures/tasks.d.ts +0 -106
- package/v3/@swarmdo/testing/dist/fixtures/tasks.js +0 -229
- package/v3/@swarmdo/testing/dist/helpers/assertion-helpers.d.ts +0 -213
- package/v3/@swarmdo/testing/dist/helpers/assertion-helpers.js +0 -435
- package/v3/@swarmdo/testing/dist/helpers/assertions.d.ts +0 -135
- package/v3/@swarmdo/testing/dist/helpers/assertions.js +0 -217
- package/v3/@swarmdo/testing/dist/helpers/create-mock.d.ts +0 -96
- package/v3/@swarmdo/testing/dist/helpers/create-mock.js +0 -164
- package/v3/@swarmdo/testing/dist/helpers/index.d.ts +0 -14
- package/v3/@swarmdo/testing/dist/helpers/index.js +0 -22
- package/v3/@swarmdo/testing/dist/helpers/mock-factory.d.ts +0 -323
- package/v3/@swarmdo/testing/dist/helpers/mock-factory.js +0 -350
- package/v3/@swarmdo/testing/dist/helpers/setup-teardown.d.ts +0 -271
- package/v3/@swarmdo/testing/dist/helpers/setup-teardown.js +0 -446
- package/v3/@swarmdo/testing/dist/helpers/swarm-instance.d.ts +0 -142
- package/v3/@swarmdo/testing/dist/helpers/swarm-instance.js +0 -205
- package/v3/@swarmdo/testing/dist/helpers/test-application.d.ts +0 -190
- package/v3/@swarmdo/testing/dist/helpers/test-application.js +0 -138
- package/v3/@swarmdo/testing/dist/helpers/test-utils.d.ts +0 -274
- package/v3/@swarmdo/testing/dist/helpers/test-utils.js +0 -456
- package/v3/@swarmdo/testing/dist/index.d.ts +0 -42
- package/v3/@swarmdo/testing/dist/index.js +0 -66
- package/v3/@swarmdo/testing/dist/mocks/index.d.ts +0 -8
- package/v3/@swarmdo/testing/dist/mocks/index.js +0 -10
- package/v3/@swarmdo/testing/dist/mocks/mock-mcp-client.d.ts +0 -206
- package/v3/@swarmdo/testing/dist/mocks/mock-mcp-client.js +0 -575
- package/v3/@swarmdo/testing/dist/mocks/mock-services.d.ts +0 -287
- package/v3/@swarmdo/testing/dist/mocks/mock-services.js +0 -563
- package/v3/@swarmdo/testing/dist/regression/api-contract.d.ts +0 -109
- package/v3/@swarmdo/testing/dist/regression/api-contract.js +0 -374
- package/v3/@swarmdo/testing/dist/regression/index.d.ts +0 -18
- package/v3/@swarmdo/testing/dist/regression/index.js +0 -18
- package/v3/@swarmdo/testing/dist/regression/integration-regression.d.ts +0 -67
- package/v3/@swarmdo/testing/dist/regression/integration-regression.js +0 -334
- package/v3/@swarmdo/testing/dist/regression/performance-baseline.d.ts +0 -106
- package/v3/@swarmdo/testing/dist/regression/performance-baseline.js +0 -268
- package/v3/@swarmdo/testing/dist/regression/regression-runner.d.ts +0 -124
- package/v3/@swarmdo/testing/dist/regression/regression-runner.js +0 -227
- package/v3/@swarmdo/testing/dist/regression/security-regression.d.ts +0 -73
- package/v3/@swarmdo/testing/dist/regression/security-regression.js +0 -258
- package/v3/@swarmdo/testing/dist/setup.d.ts +0 -43
- package/v3/@swarmdo/testing/dist/setup.js +0 -91
- package/v3/@swarmdo/testing/dist/v2-compat/api-compat.test.d.ts +0 -10
- package/v3/@swarmdo/testing/dist/v2-compat/api-compat.test.js +0 -433
- package/v3/@swarmdo/testing/dist/v2-compat/cli-compat.test.d.ts +0 -10
- package/v3/@swarmdo/testing/dist/v2-compat/cli-compat.test.js +0 -352
- package/v3/@swarmdo/testing/dist/v2-compat/compatibility-validator.d.ts +0 -206
- package/v3/@swarmdo/testing/dist/v2-compat/compatibility-validator.js +0 -839
- package/v3/@swarmdo/testing/dist/v2-compat/hooks-compat.test.d.ts +0 -10
- package/v3/@swarmdo/testing/dist/v2-compat/hooks-compat.test.js +0 -428
- package/v3/@swarmdo/testing/dist/v2-compat/index.d.ts +0 -38
- package/v3/@swarmdo/testing/dist/v2-compat/index.js +0 -41
- package/v3/@swarmdo/testing/dist/v2-compat/mcp-compat.test.d.ts +0 -10
- package/v3/@swarmdo/testing/dist/v2-compat/mcp-compat.test.js +0 -419
- package/v3/@swarmdo/testing/dist/v2-compat/report-generator.d.ts +0 -34
- package/v3/@swarmdo/testing/dist/v2-compat/report-generator.js +0 -372
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* compact.ts — deterministic command-output compression.
|
|
3
|
+
*
|
|
4
|
+
* Noisy command output (test runners, builds, installers, `git log`) burns a
|
|
5
|
+
* large share of an agent's context window on repetition and formatting that
|
|
6
|
+
* carries no signal. This engine shrinks that output BEFORE it reaches an LLM,
|
|
7
|
+
* with no model call — every transform is a pure, signal-preserving rewrite:
|
|
8
|
+
*
|
|
9
|
+
* 1. strip ANSI escape sequences (colour, cursor moves)
|
|
10
|
+
* 2. resolve carriage-return progress spam to each line's final state
|
|
11
|
+
* 3. collapse runs of identical consecutive lines → `<line> … (×N)`
|
|
12
|
+
* 4. fold consecutive node_modules stack frames → `… N frames in node_modules`
|
|
13
|
+
* 5. collapse ≥3 blank lines to one; trim trailing whitespace
|
|
14
|
+
* 6. (opt-in) window very long output to head + tail with an elision marker
|
|
15
|
+
*
|
|
16
|
+
* Distinct from `swarmdo compress` (caveman, LLM-based, for memory FILES) —
|
|
17
|
+
* this is a zero-token STREAM filter. Pure: no I/O, fully testable.
|
|
18
|
+
*/
|
|
19
|
+
// SGR colour codes, cursor moves, and other CSI/OSC escapes. Intentionally
|
|
20
|
+
// broad within the ESC-[ / ESC-] families; does not touch ordinary text.
|
|
21
|
+
// eslint-disable-next-line no-control-regex
|
|
22
|
+
const ANSI_RE = /\x1b\[[0-9;?]*[ -/]*[@-~]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[@-Z\\-_]/g;
|
|
23
|
+
const NODE_FRAME_RE = /^\s*at\s.*[/\\]node_modules[/\\]/;
|
|
24
|
+
/** Remove ANSI escapes from a string. Exported for reuse/testing. */
|
|
25
|
+
export function stripAnsi(s) {
|
|
26
|
+
return s.replace(ANSI_RE, '');
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolve carriage-return progress updates: a terminal renders `a\rb\rc` as
|
|
30
|
+
* just `c` (each CR returns to column 0 and overwrites). Keep the final
|
|
31
|
+
* segment of each line so progress bars collapse to their last frame.
|
|
32
|
+
*/
|
|
33
|
+
function resolveCarriageReturns(line) {
|
|
34
|
+
if (!line.includes('\r'))
|
|
35
|
+
return line;
|
|
36
|
+
const segs = line.split('\r');
|
|
37
|
+
// Drop empty trailing segment from a line that ended with \r.
|
|
38
|
+
while (segs.length > 1 && segs[segs.length - 1] === '')
|
|
39
|
+
segs.pop();
|
|
40
|
+
return segs[segs.length - 1] ?? '';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Collapse runs of ≥ minRun identical consecutive lines into `<line> … (×N)`.
|
|
44
|
+
* Blank/whitespace-only runs are left untouched — those are the blank-line
|
|
45
|
+
* collapser's job, so the `(×N)` marker only ever tags repeated *content*.
|
|
46
|
+
*/
|
|
47
|
+
function collapseRepeats(lines, minRun) {
|
|
48
|
+
if (minRun <= 0)
|
|
49
|
+
return lines;
|
|
50
|
+
const out = [];
|
|
51
|
+
let i = 0;
|
|
52
|
+
while (i < lines.length) {
|
|
53
|
+
if (lines[i].trim() === '') {
|
|
54
|
+
out.push(lines[i]);
|
|
55
|
+
i++;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
let j = i + 1;
|
|
59
|
+
while (j < lines.length && lines[j] === lines[i])
|
|
60
|
+
j++;
|
|
61
|
+
const run = j - i;
|
|
62
|
+
out.push(lines[i]);
|
|
63
|
+
if (run >= minRun)
|
|
64
|
+
out.push(` … (×${run})`);
|
|
65
|
+
else
|
|
66
|
+
for (let k = 1; k < run; k++)
|
|
67
|
+
out.push(lines[i]);
|
|
68
|
+
i = j;
|
|
69
|
+
}
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
/** Fold consecutive node_modules stack frames into a single summary line. */
|
|
73
|
+
function foldNodeFrames(lines) {
|
|
74
|
+
const out = [];
|
|
75
|
+
let i = 0;
|
|
76
|
+
while (i < lines.length) {
|
|
77
|
+
if (NODE_FRAME_RE.test(lines[i])) {
|
|
78
|
+
let j = i + 1;
|
|
79
|
+
while (j < lines.length && NODE_FRAME_RE.test(lines[j]))
|
|
80
|
+
j++;
|
|
81
|
+
const run = j - i;
|
|
82
|
+
if (run >= 2) {
|
|
83
|
+
const indent = lines[i].match(/^\s*/)?.[0] ?? ' ';
|
|
84
|
+
out.push(`${indent}… ${run} frames in node_modules`);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
out.push(lines[i]);
|
|
88
|
+
}
|
|
89
|
+
i = j;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
out.push(lines[i]);
|
|
93
|
+
i++;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
/** Collapse ≥3 consecutive blank lines to a single blank. */
|
|
99
|
+
function collapseBlankLines(lines) {
|
|
100
|
+
const out = [];
|
|
101
|
+
let blanks = 0;
|
|
102
|
+
for (const line of lines) {
|
|
103
|
+
if (line.trim() === '') {
|
|
104
|
+
blanks++;
|
|
105
|
+
if (blanks <= 1)
|
|
106
|
+
out.push('');
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
blanks = 0;
|
|
110
|
+
out.push(line);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
/** Keep head + tail lines, eliding the middle with a marker. */
|
|
116
|
+
function windowLines(lines, head, tail) {
|
|
117
|
+
if (lines.length <= head + tail + 1)
|
|
118
|
+
return lines;
|
|
119
|
+
const elided = lines.length - head - tail;
|
|
120
|
+
return [
|
|
121
|
+
...lines.slice(0, head),
|
|
122
|
+
`… ${elided} lines elided …`,
|
|
123
|
+
...lines.slice(lines.length - tail),
|
|
124
|
+
];
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Compact command output. Pure — returns the rewritten text plus byte/line
|
|
128
|
+
* savings. The input's trailing newline (if any) is preserved.
|
|
129
|
+
*/
|
|
130
|
+
export function compactOutput(input, opts = {}) {
|
|
131
|
+
const { stripAnsi: doStrip = true, minRun = 3, foldNodeModules = true, collapseBlanks = true, window, } = opts;
|
|
132
|
+
const bytesIn = Buffer.byteLength(input, 'utf8');
|
|
133
|
+
const hadTrailingNewline = input.endsWith('\n');
|
|
134
|
+
let text = doStrip ? stripAnsi(input) : input;
|
|
135
|
+
// Split without the trailing empty element a final newline would create.
|
|
136
|
+
let lines = text.split('\n');
|
|
137
|
+
if (hadTrailingNewline)
|
|
138
|
+
lines.pop();
|
|
139
|
+
const linesIn = lines.length;
|
|
140
|
+
lines = lines.map(resolveCarriageReturns);
|
|
141
|
+
if (minRun > 0)
|
|
142
|
+
lines = collapseRepeats(lines, minRun);
|
|
143
|
+
if (foldNodeModules)
|
|
144
|
+
lines = foldNodeFrames(lines);
|
|
145
|
+
if (collapseBlanks)
|
|
146
|
+
lines = collapseBlankLines(lines);
|
|
147
|
+
if (window)
|
|
148
|
+
lines = windowLines(lines, window.head, window.tail);
|
|
149
|
+
const linesOut = lines.length;
|
|
150
|
+
text = lines.join('\n');
|
|
151
|
+
if (hadTrailingNewline && text !== '')
|
|
152
|
+
text += '\n';
|
|
153
|
+
const bytesOut = Buffer.byteLength(text, 'utf8');
|
|
154
|
+
const savedFraction = bytesIn === 0 ? 0 : Math.max(0, (bytesIn - bytesOut) / bytesIn);
|
|
155
|
+
return { text, stats: { linesIn, linesOut, bytesIn, bytesOut, savedFraction } };
|
|
156
|
+
}
|
|
157
|
+
/** Human-readable byte count (for the savings summary). */
|
|
158
|
+
export function formatBytes(n) {
|
|
159
|
+
if (n < 1024)
|
|
160
|
+
return `${n}B`;
|
|
161
|
+
if (n < 1024 * 1024)
|
|
162
|
+
return `${(n / 1024).toFixed(1)}KB`;
|
|
163
|
+
return `${(n / (1024 * 1024)).toFixed(1)}MB`;
|
|
164
|
+
}
|
|
165
|
+
/** One-line savings summary for stderr. */
|
|
166
|
+
export function formatSavings(stats) {
|
|
167
|
+
const pct = Math.round(stats.savedFraction * 100);
|
|
168
|
+
return `compacted: ${stats.linesIn}→${stats.linesOut} lines, ${formatBytes(stats.bytesIn)}→${formatBytes(stats.bytesOut)} (−${pct}%)`;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=compact.js.map
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
const f = (file, severity, rule, message) => ({ file, severity, rule, message });
|
|
12
12
|
export const TOPOLOGIES = ['hierarchical', 'mesh', 'hierarchical-mesh', 'ring', 'star', 'hybrid', 'adaptive'];
|
|
13
13
|
export const MEMORY_BACKENDS = ['agentdb', 'sqlite', 'hybrid', 'memory'];
|
|
14
|
-
|
|
14
|
+
import { parseOpenRouterConfig } from '../providers/openrouter-config.js';
|
|
15
|
+
export const KNOWN_CONFIG_KEYS = ['topology', 'maxAgents', 'strategy', 'consensus', 'memory', 'memoryBackend', 'hnsw', 'neural', 'embeddings', 'providers', 'mcp', 'logging', 'daemon', 'hooks', 'version', 'openrouter', '$schema'];
|
|
15
16
|
export const HOOK_EVENTS = [
|
|
16
17
|
'PreToolUse', 'PostToolUse', 'UserPromptSubmit', 'Notification', 'Stop', 'SubagentStop',
|
|
17
18
|
'SessionStart', 'SessionEnd', 'PreCompact', 'TeammateIdle', 'TaskCompleted', 'PermissionDecision',
|
|
@@ -39,6 +40,15 @@ export function lintSwarmdoConfig(file, obj) {
|
|
|
39
40
|
for (const key of Object.keys(c)) {
|
|
40
41
|
if (!KNOWN_CONFIG_KEYS.includes(key))
|
|
41
42
|
out.push(f(file, 'warn', 'unknown-key', `unknown key "${key}" (known: ${KNOWN_CONFIG_KEYS.filter(k => k !== '$schema').join(', ')})`));
|
|
43
|
+
if (key === 'openrouter') {
|
|
44
|
+
// reuse the runtime parser so lint findings and runtime behavior can't drift
|
|
45
|
+
const { config: orCfg, warnings } = parseOpenRouterConfig(c.openrouter);
|
|
46
|
+
for (const w of warnings)
|
|
47
|
+
out.push(f(file, 'warn', 'openrouter-config', w));
|
|
48
|
+
if (orCfg.enabled && orCfg.models.length === 0 && !orCfg.defaultModel) {
|
|
49
|
+
out.push(f(file, 'warn', 'openrouter-config', 'openrouter.enabled=true but no valid models[] or defaultModel — swarms have nothing to select from'));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
42
52
|
}
|
|
43
53
|
if (c.topology !== undefined && !TOPOLOGIES.includes(String(c.topology))) {
|
|
44
54
|
out.push(f(file, 'error', 'bad-topology', `topology "${String(c.topology)}" is not one of: ${TOPOLOGIES.join(', ')}`));
|
|
@@ -93,8 +93,10 @@ export class CLI {
|
|
|
93
93
|
// Parse arguments
|
|
94
94
|
const parseResult = this.parser.parse(args);
|
|
95
95
|
const { command: commandPath, flags, positional } = parseResult;
|
|
96
|
-
// Handle global flags
|
|
97
|
-
|
|
96
|
+
// Handle global flags. --version is only global when no command was
|
|
97
|
+
// resolved — commands may define their own `version` option (e.g.
|
|
98
|
+
// `changelog --version v1.5.0`), which this used to swallow.
|
|
99
|
+
if (!commandPath && (flags.version || flags.V)) {
|
|
98
100
|
this.showVersion();
|
|
99
101
|
return;
|
|
100
102
|
}
|
|
@@ -384,7 +384,7 @@ function buildLocalFallback() {
|
|
|
384
384
|
return applyLocalOverlays({
|
|
385
385
|
user: { name: 'user', gitBranch: '', modelName: 'Claude Code' },
|
|
386
386
|
v3Progress: { domainsCompleted: 0, totalDomains: 5, dddProgress: 0, patternsLearned: 0, sessionsCompleted: 0 },
|
|
387
|
-
security: { status: 'NONE',
|
|
387
|
+
security: { status: 'NONE', critical: 0, high: 0, total: 0 },
|
|
388
388
|
swarm: { activeAgents: 0, maxAgents: CONFIG.maxAgents, coordinationActive: false },
|
|
389
389
|
system: { memoryMB: memMB, contextPct: 0, intelligencePct: 0, subAgents: 0 },
|
|
390
390
|
lastUpdated: new Date().toISOString(),
|
|
@@ -652,9 +652,9 @@ function generateStatusline() {
|
|
|
652
652
|
const intelligencePct = system.intelligencePct || 0;
|
|
653
653
|
const memoryMB = system.memoryMB || 0;
|
|
654
654
|
const subAgents = system.subAgents || 0;
|
|
655
|
-
const
|
|
656
|
-
const totalCves = security.totalCves || 0;
|
|
655
|
+
const secCritHigh = (security.critical || 0) + (security.high || 0);
|
|
657
656
|
const secStatus = security.status || 'NONE';
|
|
657
|
+
const secLabel = secStatus === 'VULN' ? 'sec ' + secCritHigh + '!' : secStatus === 'CLEAN' ? 'sec ✓' : secStatus === 'STALE' ? 'sec stale' : 'sec —';
|
|
658
658
|
const adrCount = adrs.count || 0;
|
|
659
659
|
const adrImpl = adrs.implemented || 0;
|
|
660
660
|
const hooksEnabled = hooks.enabled || 0;
|
|
@@ -720,8 +720,8 @@ function generateStatusline() {
|
|
|
720
720
|
// Line 2: Swarm + Hooks + CVE + Memory + Intelligence
|
|
721
721
|
const swarmInd = coordinationActive ? c.brightGreen + '◉' + c.reset : c.dim + '○' + c.reset;
|
|
722
722
|
const agentsColor = activeAgents > 0 ? c.brightGreen : c.red;
|
|
723
|
-
const secIcon = secStatus === 'CLEAN' ? '🟢' :
|
|
724
|
-
const secColor = secStatus === 'CLEAN' ? c.brightGreen :
|
|
723
|
+
const secIcon = secStatus === 'CLEAN' ? '🟢' : secStatus === 'STALE' ? '🟡' : (secStatus === 'NONE' ? '⚪' : '🔴');
|
|
724
|
+
const secColor = secStatus === 'CLEAN' ? c.brightGreen : secStatus === 'STALE' ? c.brightYellow : (secStatus === 'NONE' ? c.dim : c.brightRed);
|
|
725
725
|
const hooksColor = hooksEnabled > 0 ? c.brightGreen : c.dim;
|
|
726
726
|
const intellColor = intelligencePct >= 80 ? c.brightGreen : intelligencePct >= 40 ? c.brightYellow : c.dim;
|
|
727
727
|
|
|
@@ -729,7 +729,7 @@ function generateStatusline() {
|
|
|
729
729
|
c.brightYellow + '🤖 Swarm' + c.reset + ' ' + swarmInd + ' [' + agentsColor + String(activeAgents).padStart(2) + c.reset + '/' + c.brightWhite + maxAgents + c.reset + '] ' +
|
|
730
730
|
c.brightPurple + '👥 ' + subAgents + c.reset + ' ' +
|
|
731
731
|
c.brightBlue + '🪝 ' + hooksColor + hooksEnabled + c.reset + '/' + c.brightWhite + hooksTotal + c.reset + ' ' +
|
|
732
|
-
secIcon + ' ' + secColor +
|
|
732
|
+
secIcon + ' ' + secColor + secLabel + c.reset + ' ' +
|
|
733
733
|
c.brightCyan + '💾 ' + memoryMB + 'MB' + c.reset + ' ' +
|
|
734
734
|
intellColor + '🧠 ' + String(intelligencePct).padStart(3) + '%' + c.reset
|
|
735
735
|
);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* integrations.ts — wire swarmdo into agent CLIs beyond Claude Code.
|
|
3
|
+
*
|
|
4
|
+
* Targets: OpenAI Codex CLI, GitHub Copilot CLI, pi. Two standards do the
|
|
5
|
+
* heavy lifting: AGENTS.md (the cross-agent instructions file all three
|
|
6
|
+
* read) and MCP (swarmdo already ships a stdio server — `swarmdo mcp
|
|
7
|
+
* start`). Each merge below is PURE (string/JSON in → out), additive, and
|
|
8
|
+
* idempotent, so the whole surface is unit-testable and re-running install
|
|
9
|
+
* never duplicates or clobbers.
|
|
10
|
+
*
|
|
11
|
+
* INVARIANT (do-not-break-Claude): nothing in this module produces content
|
|
12
|
+
* for `.claude/**`, `.mcp.json`, or `CLAUDE.md` — the Claude Code surfaces
|
|
13
|
+
* are owned by init/mcp-generator and are only ever READ for status here.
|
|
14
|
+
*/
|
|
15
|
+
export declare const MCP_COMMAND = "npx";
|
|
16
|
+
export declare const MCP_ARGS: string[];
|
|
17
|
+
/** Codex CLI (~/.codex/config.toml): add the marked [mcp_servers.swarmdo]
|
|
18
|
+
* block when absent. Existing content — including a user's own hand-written
|
|
19
|
+
* swarmdo server — is left untouched. */
|
|
20
|
+
export declare function mergeCodexToml(existing: string | null): {
|
|
21
|
+
content: string;
|
|
22
|
+
changed: boolean;
|
|
23
|
+
};
|
|
24
|
+
/** Copilot CLI (~/.copilot/mcp-config.json): same mcpServers schema Claude
|
|
25
|
+
* uses. Adds the swarmdo entry when absent; other servers preserved. */
|
|
26
|
+
export declare function mergeCopilotMcpJson(existing: string | null): {
|
|
27
|
+
content: string;
|
|
28
|
+
changed: boolean;
|
|
29
|
+
};
|
|
30
|
+
/** Cross-agent AGENTS.md for projects that don't have one. Existing files
|
|
31
|
+
* are never rewritten (report-only) — teams own their AGENTS.md. */
|
|
32
|
+
export declare function crossAgentAgentsMd(): string;
|
|
33
|
+
/** .github/copilot-instructions.md — Copilot reads this per-repo. Kept as a
|
|
34
|
+
* thin pointer so AGENTS.md stays the single source of truth. */
|
|
35
|
+
export declare function copilotInstructionsMd(): string;
|
|
36
|
+
export type IntegrationTarget = 'codex' | 'copilot' | 'pi' | 'claude';
|
|
37
|
+
export declare const INSTALLABLE: IntegrationTarget[];
|
|
38
|
+
export interface TargetStatus {
|
|
39
|
+
target: IntegrationTarget;
|
|
40
|
+
ok: boolean;
|
|
41
|
+
details: string[];
|
|
42
|
+
}
|
|
43
|
+
/** Pure status evaluation over pre-read file contents (null = absent). */
|
|
44
|
+
export declare function evaluateStatus(files: {
|
|
45
|
+
agentsMd: string | null;
|
|
46
|
+
codexToml: string | null;
|
|
47
|
+
copilotJson: string | null;
|
|
48
|
+
copilotInstructions: string | null;
|
|
49
|
+
claudeMcpJson: string | null;
|
|
50
|
+
/** ~/.claude.json — Claude Code's user-level config (claude mcp add) */
|
|
51
|
+
claudeUserJson?: string | null;
|
|
52
|
+
claudeDirExists: boolean;
|
|
53
|
+
}): TargetStatus[];
|
|
54
|
+
//# sourceMappingURL=integrations.d.ts.map
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* integrations.ts — wire swarmdo into agent CLIs beyond Claude Code.
|
|
3
|
+
*
|
|
4
|
+
* Targets: OpenAI Codex CLI, GitHub Copilot CLI, pi. Two standards do the
|
|
5
|
+
* heavy lifting: AGENTS.md (the cross-agent instructions file all three
|
|
6
|
+
* read) and MCP (swarmdo already ships a stdio server — `swarmdo mcp
|
|
7
|
+
* start`). Each merge below is PURE (string/JSON in → out), additive, and
|
|
8
|
+
* idempotent, so the whole surface is unit-testable and re-running install
|
|
9
|
+
* never duplicates or clobbers.
|
|
10
|
+
*
|
|
11
|
+
* INVARIANT (do-not-break-Claude): nothing in this module produces content
|
|
12
|
+
* for `.claude/**`, `.mcp.json`, or `CLAUDE.md` — the Claude Code surfaces
|
|
13
|
+
* are owned by init/mcp-generator and are only ever READ for status here.
|
|
14
|
+
*/
|
|
15
|
+
export const MCP_COMMAND = 'npx';
|
|
16
|
+
export const MCP_ARGS = ['-y', 'swarmdo@latest', 'mcp', 'start'];
|
|
17
|
+
const TOML_BEGIN = '# >>> swarmdo mcp (managed by `swarmdo integrations`) >>>';
|
|
18
|
+
const TOML_END = '# <<< swarmdo mcp <<<';
|
|
19
|
+
/** Codex CLI (~/.codex/config.toml): add the marked [mcp_servers.swarmdo]
|
|
20
|
+
* block when absent. Existing content — including a user's own hand-written
|
|
21
|
+
* swarmdo server — is left untouched. */
|
|
22
|
+
export function mergeCodexToml(existing) {
|
|
23
|
+
const base = existing ?? '';
|
|
24
|
+
if (base.includes(TOML_BEGIN) || /\[mcp_servers\.swarmdo\]/.test(base)) {
|
|
25
|
+
return { content: base, changed: false };
|
|
26
|
+
}
|
|
27
|
+
const block = [
|
|
28
|
+
TOML_BEGIN,
|
|
29
|
+
'[mcp_servers.swarmdo]',
|
|
30
|
+
`command = "${MCP_COMMAND}"`,
|
|
31
|
+
`args = [${MCP_ARGS.map((a) => `"${a}"`).join(', ')}]`,
|
|
32
|
+
TOML_END,
|
|
33
|
+
'',
|
|
34
|
+
].join('\n');
|
|
35
|
+
const sep = base.length > 0 && !base.endsWith('\n\n') ? (base.endsWith('\n') ? '\n' : '\n\n') : '';
|
|
36
|
+
return { content: base + sep + block, changed: true };
|
|
37
|
+
}
|
|
38
|
+
/** Copilot CLI (~/.copilot/mcp-config.json): same mcpServers schema Claude
|
|
39
|
+
* uses. Adds the swarmdo entry when absent; other servers preserved. */
|
|
40
|
+
export function mergeCopilotMcpJson(existing) {
|
|
41
|
+
let cfg;
|
|
42
|
+
try {
|
|
43
|
+
cfg = existing ? JSON.parse(existing) : {};
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// never clobber an unparseable user file
|
|
47
|
+
return { content: existing ?? '', changed: false };
|
|
48
|
+
}
|
|
49
|
+
if (cfg.mcpServers && Object.prototype.hasOwnProperty.call(cfg.mcpServers, 'swarmdo')) {
|
|
50
|
+
return { content: JSON.stringify(cfg, null, 2) + '\n', changed: false };
|
|
51
|
+
}
|
|
52
|
+
cfg.mcpServers = { ...(cfg.mcpServers ?? {}), swarmdo: { type: 'local', command: MCP_COMMAND, args: MCP_ARGS, tools: ['*'] } };
|
|
53
|
+
return { content: JSON.stringify(cfg, null, 2) + '\n', changed: true };
|
|
54
|
+
}
|
|
55
|
+
/** Cross-agent AGENTS.md for projects that don't have one. Existing files
|
|
56
|
+
* are never rewritten (report-only) — teams own their AGENTS.md. */
|
|
57
|
+
export function crossAgentAgentsMd() {
|
|
58
|
+
return `# AGENTS.md — swarmdo project
|
|
59
|
+
|
|
60
|
+
> Read by Codex CLI, GitHub Copilot CLI, pi, and other AGENTS.md-aware
|
|
61
|
+
> agents. Claude Code uses CLAUDE.md instead — both coexist in this repo.
|
|
62
|
+
|
|
63
|
+
## What swarmdo gives you
|
|
64
|
+
|
|
65
|
+
This project is wired to **swarmdo** — agent orchestration with persistent
|
|
66
|
+
vector memory, swarm coordination, and 300+ MCP tools.
|
|
67
|
+
|
|
68
|
+
- **MCP server**: \`swarmdo mcp start\` (stdio). If your CLI supports MCP,
|
|
69
|
+
\`swarmdo integrations install <your-cli>\` wires it; key tools:
|
|
70
|
+
\`memory_search\`, \`memory_store\`, \`swarm_init\`, \`agent_spawn\`.
|
|
71
|
+
- **CLI**: \`npx swarmdo@latest <command>\` — \`memory search -q "topic"\`,
|
|
72
|
+
\`usage\`, \`task\`, \`hud\`, \`security scan\`, \`config lint\`.
|
|
73
|
+
|
|
74
|
+
## Working agreement (any agent)
|
|
75
|
+
|
|
76
|
+
1. **Search memory BEFORE starting**: \`memory_search(query="task keywords")\`
|
|
77
|
+
— patterns with score > 0.7 are load-bearing precedent.
|
|
78
|
+
2. **You are the executor** — swarmdo coordinates and remembers; it never
|
|
79
|
+
writes your code for you.
|
|
80
|
+
3. **Store what worked AFTER success**:
|
|
81
|
+
\`memory_store(key="pattern-…", value="what worked", namespace="patterns")\`.
|
|
82
|
+
4. Claude Code users: the same surfaces are namespaced under \`/sDo:\`
|
|
83
|
+
commands and \`/sdo-\` skills.
|
|
84
|
+
|
|
85
|
+
## Do not
|
|
86
|
+
|
|
87
|
+
- Do not commit secrets or .env files.
|
|
88
|
+
- Do not edit \`.claude/\`, \`.mcp.json\`, or \`CLAUDE.md\` — those belong to
|
|
89
|
+
the Claude Code integration and are managed by \`swarmdo init\`.
|
|
90
|
+
`;
|
|
91
|
+
}
|
|
92
|
+
/** .github/copilot-instructions.md — Copilot reads this per-repo. Kept as a
|
|
93
|
+
* thin pointer so AGENTS.md stays the single source of truth. */
|
|
94
|
+
export function copilotInstructionsMd() {
|
|
95
|
+
return `# Copilot instructions
|
|
96
|
+
|
|
97
|
+
This repository uses **swarmdo** for agent orchestration and persistent
|
|
98
|
+
memory. Follow \`AGENTS.md\` at the repo root — it is the canonical
|
|
99
|
+
cross-agent working agreement (memory-first workflow, executor role, MCP
|
|
100
|
+
tools). The swarmdo MCP server (\`swarmdo mcp start\`) provides
|
|
101
|
+
memory_search / memory_store / swarm_init; wire it with
|
|
102
|
+
\`swarmdo integrations install copilot\`.
|
|
103
|
+
`;
|
|
104
|
+
}
|
|
105
|
+
export const INSTALLABLE = ['codex', 'copilot', 'pi'];
|
|
106
|
+
/** Pure status evaluation over pre-read file contents (null = absent). */
|
|
107
|
+
export function evaluateStatus(files) {
|
|
108
|
+
const agentsOk = files.agentsMd !== null;
|
|
109
|
+
const codexMcp = !!files.codexToml && /\[mcp_servers\.swarmdo\]/.test(files.codexToml);
|
|
110
|
+
const copilotMcp = (() => {
|
|
111
|
+
try {
|
|
112
|
+
return !!files.copilotJson && 'swarmdo' in (JSON.parse(files.copilotJson).mcpServers ?? {});
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
})();
|
|
118
|
+
const hasSwarmdoServer = (raw) => {
|
|
119
|
+
try {
|
|
120
|
+
return !!raw && 'swarmdo' in (JSON.parse(raw).mcpServers ?? {});
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
const claudeProject = hasSwarmdoServer(files.claudeMcpJson);
|
|
127
|
+
const claudeUser = hasSwarmdoServer(files.claudeUserJson);
|
|
128
|
+
const claudeMcp = claudeProject || claudeUser;
|
|
129
|
+
return [
|
|
130
|
+
{
|
|
131
|
+
target: 'claude', ok: files.claudeDirExists && claudeMcp,
|
|
132
|
+
details: [
|
|
133
|
+
`.claude/ ${files.claudeDirExists ? 'present' : 'MISSING'}`,
|
|
134
|
+
`swarmdo MCP server ${claudeMcp ? `wired (${claudeProject ? '.mcp.json' : '~/.claude.json'})` : 'missing from .mcp.json and ~/.claude.json'}`,
|
|
135
|
+
'(read-only here — managed by `swarmdo init`)',
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
target: 'codex', ok: agentsOk && codexMcp,
|
|
140
|
+
details: [
|
|
141
|
+
`AGENTS.md ${agentsOk ? 'present' : 'missing'}`,
|
|
142
|
+
`~/.codex/config.toml [mcp_servers.swarmdo] ${codexMcp ? 'wired' : 'missing'}`,
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
target: 'copilot', ok: agentsOk && copilotMcp && files.copilotInstructions !== null,
|
|
147
|
+
details: [
|
|
148
|
+
`AGENTS.md ${agentsOk ? 'present' : 'missing'}`,
|
|
149
|
+
`.github/copilot-instructions.md ${files.copilotInstructions !== null ? 'present' : 'missing'}`,
|
|
150
|
+
`~/.copilot/mcp-config.json swarmdo server ${copilotMcp ? 'wired' : 'missing'}`,
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
target: 'pi', ok: agentsOk,
|
|
155
|
+
details: [
|
|
156
|
+
`AGENTS.md ${agentsOk ? 'present (pi reads it natively)' : 'missing'}`,
|
|
157
|
+
'MCP: point pi at `npx -y swarmdo@latest mcp start` if your pi build supports MCP servers',
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
];
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=integrations.js.map
|
|
@@ -80,16 +80,34 @@ export async function callAnthropicMessages(input) {
|
|
|
80
80
|
const useOpenRouter = explicitProvider === 'openrouter' || (!anthropicKey && !!openrouterKey);
|
|
81
81
|
const useOllama = explicitProvider === 'ollama' || (!anthropicKey && !!ollamaKey && !openrouterKey);
|
|
82
82
|
if (useOpenRouter && openrouterKey) {
|
|
83
|
+
// Configurable model pool: swarmdo.config.json `openrouter` section lets
|
|
84
|
+
// the swarm draw from user-configured models (explicit slug > tier pick
|
|
85
|
+
// via Thompson sampling > config defaultModel). Env vars still win for
|
|
86
|
+
// base URL and as the final default for un-configured projects.
|
|
87
|
+
let configuredModel;
|
|
88
|
+
let configuredBaseUrl;
|
|
89
|
+
try {
|
|
90
|
+
const { loadOpenRouterConfig, resolveOpenRouterModel } = await import('../providers/openrouter-config.js');
|
|
91
|
+
const { config } = loadOpenRouterConfig();
|
|
92
|
+
if (config.enabled) {
|
|
93
|
+
configuredBaseUrl = config.baseUrl;
|
|
94
|
+
configuredModel = resolveOpenRouterModel({ requested: input.model, cfg: config })?.model;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch { /* config unreadable — env-only behavior */ }
|
|
83
98
|
return callOpenAICompat({
|
|
84
99
|
...input,
|
|
100
|
+
// a resolved pool pick replaces tier words / Anthropic ids; explicit
|
|
101
|
+
// slugs pass through resolveOpenRouterModel unchanged
|
|
102
|
+
model: configuredModel ?? input.model,
|
|
85
103
|
apiKey: openrouterKey,
|
|
86
|
-
baseUrl: process.env.OPENROUTER_BASE_URL || 'https://openrouter.ai/api',
|
|
104
|
+
baseUrl: process.env.OPENROUTER_BASE_URL || configuredBaseUrl || 'https://openrouter.ai/api',
|
|
87
105
|
providerLabel: 'openrouter',
|
|
88
106
|
// #2357 Finding C: anthropic/claude-3.5-sonnet was retired Oct 2025.
|
|
89
107
|
// Default to the same canonical family the rest of the resolver uses
|
|
90
108
|
// (MODEL_MAP). `OPENROUTER_DEFAULT_MODEL` still wins for callers who
|
|
91
109
|
// want to pin a specific OpenRouter slug.
|
|
92
|
-
defaultModel: process.env.OPENROUTER_DEFAULT_MODEL || 'anthropic/claude-sonnet-4-6',
|
|
110
|
+
defaultModel: process.env.OPENROUTER_DEFAULT_MODEL || configuredModel || 'anthropic/claude-sonnet-4-6',
|
|
93
111
|
});
|
|
94
112
|
}
|
|
95
113
|
if (useOllama && ollamaKey) {
|
|
@@ -445,7 +463,8 @@ export async function executeAgentTask(input) {
|
|
|
445
463
|
const fallbackBudget = Math.max(0, parseInt(process.env.SWARMDO_ROUTER_FALLBACK_MAX_RETRIES ?? '1', 10) || 1);
|
|
446
464
|
const fallbackHistory = [];
|
|
447
465
|
if (!result.success && agent.modelId && fallbackBudget > 0) {
|
|
448
|
-
const
|
|
466
|
+
const { isRetryableError, computeBackoffMs, sleep } = await import('../resilience/backoff.js');
|
|
467
|
+
const isRetryable = isRetryableError(result.error);
|
|
449
468
|
if (isRetryable) {
|
|
450
469
|
try {
|
|
451
470
|
const { nextCostOptimalAlternative } = await import('../swarmvector/neural-router.js');
|
|
@@ -459,6 +478,9 @@ export async function executeAgentTask(input) {
|
|
|
459
478
|
const excludeIds = [agent.modelId];
|
|
460
479
|
for (let attempt = 0; attempt < fallbackBudget && !result.success; attempt++) {
|
|
461
480
|
fallbackHistory.push({ modelId: excludeIds[excludeIds.length - 1], error: result.error ?? '' });
|
|
481
|
+
// full-jitter exponential backoff — a 429 is usually account-wide,
|
|
482
|
+
// so an instant re-call against the same provider burns the attempt
|
|
483
|
+
await sleep(computeBackoffMs(attempt));
|
|
462
484
|
const alt = await nextCostOptimalAlternative(embedding, excludeIds);
|
|
463
485
|
if (!alt || !alt.modelId)
|
|
464
486
|
break;
|
|
@@ -996,11 +996,11 @@ export const agentdbGraphQuery = {
|
|
|
996
996
|
catch { /* fall through to sql.js */ }
|
|
997
997
|
// SQL CTE fallback for k-hop up to depth 3
|
|
998
998
|
try {
|
|
999
|
-
const { getBridgeDb } = await import('../memory/graph-edge-writer.js');
|
|
999
|
+
const { getBridgeDb, execRows } = await import('../memory/graph-edge-writer.js');
|
|
1000
1000
|
const db = await getBridgeDb();
|
|
1001
1001
|
if (db) {
|
|
1002
1002
|
const cteSql = buildKHopCTE(nodeId, Math.min(depth, 3), relation, budget.maxNodesVisited);
|
|
1003
|
-
const result = db
|
|
1003
|
+
const result = execRows(db, cteSql);
|
|
1004
1004
|
const rows = result?.[0]?.values ?? [];
|
|
1005
1005
|
return {
|
|
1006
1006
|
success: true, mode, nodeId, depth,
|
|
@@ -1021,14 +1021,14 @@ export const agentdbGraphQuery = {
|
|
|
1021
1021
|
const queryEmb = await generateEmbedding(nodeId);
|
|
1022
1022
|
if (!queryEmb)
|
|
1023
1023
|
throw new Error('embedding failed');
|
|
1024
|
-
const { getBridgeDb } = await import('../memory/graph-edge-writer.js');
|
|
1024
|
+
const { getBridgeDb, execRows } = await import('../memory/graph-edge-writer.js');
|
|
1025
1025
|
// #2246 fix: lazy-create memory.db on first pathfinder call so
|
|
1026
1026
|
// fresh environments work without a pre-existing memory init.
|
|
1027
1027
|
const db = await getBridgeDb(undefined, { createIfMissing: true });
|
|
1028
1028
|
if (!db)
|
|
1029
1029
|
return { success: false, error: 'graph_edges DB unavailable (sql.js could not load)', hint: 'Check Node version + try `swarmdo memory init` to initialize manually.', mode, nodeId };
|
|
1030
1030
|
// Load all rows with embedding_ref and score by cosine
|
|
1031
|
-
const rowResult = db
|
|
1031
|
+
const rowResult = execRows(db, `SELECT id, source_id, target_id, relation, weight, embedding_ref FROM graph_edges WHERE embedding_ref IS NOT NULL LIMIT ?`, [budget.maxNodesVisited]);
|
|
1032
1032
|
const rows = rowResult?.[0]?.values ?? [];
|
|
1033
1033
|
const { decodeEmbedding } = await import('../memory/embedding-quantization.js');
|
|
1034
1034
|
const scored = [];
|
|
@@ -1061,13 +1061,13 @@ export const agentdbGraphQuery = {
|
|
|
1061
1061
|
// ── pagerank mode ────────────────────────────────────────────────────────
|
|
1062
1062
|
if (mode === 'pagerank') {
|
|
1063
1063
|
try {
|
|
1064
|
-
const { getBridgeDb } = await import('../memory/graph-edge-writer.js');
|
|
1064
|
+
const { getBridgeDb, execRows } = await import('../memory/graph-edge-writer.js');
|
|
1065
1065
|
// #2246 fix: lazy-create memory.db on first pathfinder call so
|
|
1066
1066
|
// fresh environments work without a pre-existing memory init.
|
|
1067
1067
|
const db = await getBridgeDb(undefined, { createIfMissing: true });
|
|
1068
1068
|
if (!db)
|
|
1069
1069
|
return { success: false, error: 'graph_edges DB unavailable (sql.js could not load)', hint: 'Check Node version + try `swarmdo memory init` to initialize manually.', mode, nodeId };
|
|
1070
|
-
const edgeResult = db
|
|
1070
|
+
const edgeResult = execRows(db, `SELECT source_id, target_id, weight FROM graph_edges LIMIT ?`, [budget.maxNodesVisited]);
|
|
1071
1071
|
const edges = edgeResult?.[0]?.values ?? [];
|
|
1072
1072
|
if (edges.length === 0) {
|
|
1073
1073
|
return { success: true, mode, nodeId, results: [], count: 0, message: 'graph_edges is empty', elapsedMs: Date.now() - t0 };
|
|
@@ -1248,7 +1248,7 @@ export const agentdbGraphPathfinder = {
|
|
|
1248
1248
|
return { success: false, error: `Unknown algorithm: ${algorithm}. Valid: ${validAlgorithms.join(', ')}` };
|
|
1249
1249
|
}
|
|
1250
1250
|
// Load edges from graph_edges
|
|
1251
|
-
const { getBridgeDb } = await import('../memory/graph-edge-writer.js');
|
|
1251
|
+
const { getBridgeDb, execRows } = await import('../memory/graph-edge-writer.js');
|
|
1252
1252
|
// #2246 fix: lazy-create memory.db on first pathfinder call.
|
|
1253
1253
|
const db = await getBridgeDb(undefined, { createIfMissing: true });
|
|
1254
1254
|
if (!db)
|
|
@@ -1258,7 +1258,7 @@ export const agentdbGraphPathfinder = {
|
|
|
1258
1258
|
: algorithm === 'temporal-centrality'
|
|
1259
1259
|
? 'source_id, target_id, weight, last_reinforced, confidence'
|
|
1260
1260
|
: 'source_id, target_id, weight';
|
|
1261
|
-
const edgeResult = db
|
|
1261
|
+
const edgeResult = execRows(db, `SELECT ${colsSql} FROM graph_edges LIMIT ?`, [budget.maxNodesVisited]);
|
|
1262
1262
|
const rawEdges = edgeResult?.[0]?.values ?? [];
|
|
1263
1263
|
if (rawEdges.length === 0) {
|
|
1264
1264
|
return { success: true, paths: [], count: 0, message: `no edges found from seedNodeId`, seedNodeId, algorithm, elapsedMs: Date.now() - t0 };
|
|
@@ -58,6 +58,18 @@ export interface GraphEdgeInput {
|
|
|
58
58
|
metadata?: Record<string, unknown>;
|
|
59
59
|
dbPath?: string;
|
|
60
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Engine-compat read: run a SELECT and return rows in sql.js exec() shape
|
|
63
|
+
* ([{columns, values}] or [] when no rows). getBridgeDb returned sql.js
|
|
64
|
+
* historically and better-sqlite3 since #2431 — readers written against the
|
|
65
|
+
* old shape (agentdb graph query/pathfinder) go through this shim so they
|
|
66
|
+
* work on either engine. better-sqlite3's own exec() neither binds params
|
|
67
|
+
* nor returns rows, which surfaced as "datatype mismatch" on every LIMIT ?.
|
|
68
|
+
*/
|
|
69
|
+
export declare function execRows(db: any, sql: string, params?: unknown[]): Array<{
|
|
70
|
+
columns: string[];
|
|
71
|
+
values: unknown[][];
|
|
72
|
+
}>;
|
|
61
73
|
/**
|
|
62
74
|
* Insert a single edge into graph_edges.
|
|
63
75
|
* Fire-and-forget — errors are suppressed.
|