mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-24 09:01:27 +08:00
71d22d0a77
Finishes the steer/transmit loop — advisories now reach the agents' sessions. - message-sink.js: createEccMessageSink() delivers via the canonical writer 'ecc-tui messages send' (maps steer/hold -> conflict kind, transmit -> query), resolving the binary from override/env/built target/PATH. Injectable runner; best-effort (a missing binary/failed send is counted skipped, never blocks). - proximity.js: createProximityDispatcher() adds per-trigger cooldown so a persistent collision fires once then stays quiet (agents get steered, not spammed); runProximityTick() builds the snapshot and dispatches. - scripts/proximity-tick.js: thin CLI — one-shot, --dry-run, --watch <sec>. Messages are internal ECC agent-to-agent coordination, not any external channel. - 14 new tests (sink argv/kind mapping, cooldown dedup, tick dispatch/dry-run, CLI parse). Full suite 2891/2891; lint green.
71 lines
2.5 KiB
JavaScript
71 lines
2.5 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* Concrete message sink for proximity triggers: delivers a session-to-session
|
|
* message through the canonical writer, the `ecc-tui messages send` CLI. The CLI
|
|
* owns the ecc2 session DB (the `messages` table the control pane reads), so we
|
|
* shell out to it rather than writing the SQLite directly and racing the daemon.
|
|
*
|
|
* Best-effort: if the binary is not found / the command fails, the call throws,
|
|
* and the dispatcher counts it as skipped — proximity never blocks on delivery.
|
|
* The command runner and binary path are injectable for tests.
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const { execFileSync } = require('child_process');
|
|
|
|
// Proximity trigger type → ecc-tui message kind (value_enum on `--kind`).
|
|
// A steer/hold is a collision warning; a transmit is a "what are you doing" query.
|
|
const KIND_BY_TYPE = {
|
|
proximity_steer: 'conflict',
|
|
proximity_hold: 'conflict',
|
|
proximity_transmit: 'query'
|
|
};
|
|
|
|
/**
|
|
* Resolve the ecc-tui binary: explicit override, env var, a built target in the
|
|
* repo, then the bare name (hope it's on PATH).
|
|
*/
|
|
function resolveEccBin(deps = {}) {
|
|
if (deps.binPath) return deps.binPath;
|
|
if (process.env.ECC_TUI_BIN && process.env.ECC_TUI_BIN.trim()) return process.env.ECC_TUI_BIN.trim();
|
|
const repoRoot = deps.repoRoot || path.join(__dirname, '..', '..', '..');
|
|
for (const rel of ['ecc2/target/release/ecc-tui', 'ecc2/target/debug/ecc-tui']) {
|
|
const candidate = path.join(repoRoot, rel);
|
|
try {
|
|
if (fs.existsSync(candidate)) return candidate;
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
}
|
|
return 'ecc-tui';
|
|
}
|
|
|
|
/**
|
|
* Build the `messages send` argv for a proximity message.
|
|
*/
|
|
function buildSendArgs({ fromSession, toSession, content, msgType }) {
|
|
const kind = KIND_BY_TYPE[msgType] || 'query';
|
|
return ['messages', 'send', '--from', String(fromSession), '--to', String(toSession), '--kind', kind, '--text', String(content)];
|
|
}
|
|
|
|
/**
|
|
* Create a `sendMessage({ fromSession, toSession, content, msgType })` sink that
|
|
* delivers via `ecc-tui messages send`. Inject `runCommand(bin, args)` for tests.
|
|
*/
|
|
function createEccMessageSink(deps = {}) {
|
|
const run = deps.runCommand || ((bin, args) => execFileSync(bin, args, { encoding: 'utf8', timeout: 5000, stdio: ['ignore', 'pipe', 'pipe'] }));
|
|
const bin = resolveEccBin(deps);
|
|
return function sendMessage(message) {
|
|
run(bin, buildSendArgs(message));
|
|
};
|
|
}
|
|
|
|
module.exports = {
|
|
KIND_BY_TYPE,
|
|
resolveEccBin,
|
|
buildSendArgs,
|
|
createEccMessageSink
|
|
};
|