claude-code-swarm 0.3.26 → 0.4.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-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CLAUDE.md +95 -0
- package/LICENSE +21 -0
- package/hooks/hooks.json +9 -0
- package/package.json +14 -1
- package/renovate.json5 +6 -0
- package/scripts/map-hook.mjs +58 -2
- package/scripts/map-sidecar.mjs +178 -1
- package/src/__tests__/cascade-client.test.mjs +217 -0
- package/src/__tests__/cascade-diff-server.test.mjs +375 -0
- package/src/__tests__/cascade-watcher.test.mjs +475 -0
- package/src/__tests__/config.test.mjs +23 -0
- package/src/bootstrap.mjs +3 -0
- package/src/cascade-client.mjs +334 -0
- package/src/cascade-diff-server.mjs +326 -0
- package/src/cascade-events.mjs +285 -0
- package/src/cascade-watcher.mjs +694 -0
- package/src/config.mjs +7 -0
- package/src/map-connection.mjs +18 -1
- package/src/paths.mjs +12 -0
- package/src/sidecar-server.mjs +26 -0
package/src/config.mjs
CHANGED
|
@@ -105,6 +105,13 @@ export function readConfig(configPath = CONFIG_PATH, globalConfigPath = GLOBAL_C
|
|
|
105
105
|
trust: project.inbox?.federation?.trust ?? global.inbox?.federation?.trust ?? undefined,
|
|
106
106
|
},
|
|
107
107
|
},
|
|
108
|
+
// Cascade integration. Only meaningful when `map` is enabled — the
|
|
109
|
+
// sidecar emits x-cascade/* notifications over the MAP connection.
|
|
110
|
+
// When map is disabled there is no connection to emit on, so cascade
|
|
111
|
+
// becomes an inert no-op (no hard failure — mirrors opentasks/minimem).
|
|
112
|
+
cascade: {
|
|
113
|
+
enabled: envBool("SWARM_CASCADE_ENABLED") ?? Boolean(project.cascade?.enabled ?? global.cascade?.enabled),
|
|
114
|
+
},
|
|
108
115
|
minimem: {
|
|
109
116
|
enabled: envBool("SWARM_MINIMEM_ENABLED") ?? Boolean(project.minimem?.enabled ?? global.minimem?.enabled),
|
|
110
117
|
provider: envStr("SWARM_MINIMEM_PROVIDER") ?? project.minimem?.provider ?? global.minimem?.provider ?? "auto",
|
package/src/map-connection.mjs
CHANGED
|
@@ -24,7 +24,7 @@ const log = createLogger("map");
|
|
|
24
24
|
* authRequired challenge with the server's preferred method + this credential.
|
|
25
25
|
* When absent, uses the standard SDK connect() for open mode servers.
|
|
26
26
|
*/
|
|
27
|
-
export async function connectToMAP({ server, scope, systemId, onMessage, credential, projectContext, inboxEnabled }) {
|
|
27
|
+
export async function connectToMAP({ server, scope, systemId, onMessage, credential, projectContext, inboxEnabled, cascadeEnabled }) {
|
|
28
28
|
try {
|
|
29
29
|
const mapSdk = await resolvePackage("@multi-agent-protocol/sdk");
|
|
30
30
|
if (!mapSdk) throw new Error("@multi-agent-protocol/sdk not available");
|
|
@@ -49,6 +49,23 @@ export async function connectToMAP({ server, scope, systemId, onMessage, credent
|
|
|
49
49
|
...(projectContext?.task_graph ? {
|
|
50
50
|
opentasks: { canQuery: true, canLink: true, canAnnotate: true, canTask: true },
|
|
51
51
|
} : {}),
|
|
52
|
+
// Cascade capability (CascadeCapability, git-cascade >= 0.0.8) — gated
|
|
53
|
+
// on cascade.enabled. cc-swarm runs cascade in "observed git" mode: it
|
|
54
|
+
// watches git state and serves diffs. It now also probes in-progress
|
|
55
|
+
// *merge* conflict state on every poll tick and emits
|
|
56
|
+
// `x-cascade/stream.conflicted` / `stream.conflict_resolved` on the
|
|
57
|
+
// transitions — so `emitsConflicts: true` ships honestly. Action-layer
|
|
58
|
+
// remains observe-only (`canAct: false`); the watcher does not drive
|
|
59
|
+
// merges / rebases / pauses.
|
|
60
|
+
// canServeDiff: true — the diff server (src/cascade-diff-server.mjs) is wired
|
|
61
|
+
// canAct: false — no cascade action handler
|
|
62
|
+
// emitsConflicts: true — the watcher observes merge-conflict transitions
|
|
63
|
+
// TODO: rebase-conflict observation (`.git/rebase-merge/`,
|
|
64
|
+
// `.git/rebase-apply/`) is a known follow-up. v1 covers `git merge`
|
|
65
|
+
// conflicts only.
|
|
66
|
+
...(cascadeEnabled ? {
|
|
67
|
+
cascade: { canServeDiff: true, canAct: false, emitsConflicts: true },
|
|
68
|
+
} : {}),
|
|
52
69
|
},
|
|
53
70
|
metadata: {
|
|
54
71
|
systemId,
|
package/src/paths.mjs
CHANGED
|
@@ -102,6 +102,10 @@ export const LOGS_DIR = path.join(GLOBAL_CONFIG_DIR, "tmp", "logs");
|
|
|
102
102
|
export const OPENTASKS_DIR = path.join(_tmpDir, "opentasks");
|
|
103
103
|
export const OPENTASKS_SYNC_STATE_PATH = path.join(_tmpDir, "opentasks", "sync-state.json");
|
|
104
104
|
|
|
105
|
+
// cascade runtime state — git-cascade tracker DB (local-mode state store)
|
|
106
|
+
export const CASCADE_DIR = path.join(_tmpDir, "cascade");
|
|
107
|
+
export const CASCADE_DB_PATH = path.join(_tmpDir, "cascade", "tracker.db");
|
|
108
|
+
|
|
105
109
|
/**
|
|
106
110
|
* Whether paths resolved to global (~/.claude-swarm/tmp/) vs project-level.
|
|
107
111
|
*/
|
|
@@ -149,6 +153,14 @@ export function ensureOpentasksDir() {
|
|
|
149
153
|
fs.mkdirSync(OPENTASKS_DIR, { recursive: true });
|
|
150
154
|
}
|
|
151
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Ensure the cascade runtime directory exists.
|
|
158
|
+
* Holds the git-cascade tracker DB (local-mode state store).
|
|
159
|
+
*/
|
|
160
|
+
export function ensureCascadeDir() {
|
|
161
|
+
fs.mkdirSync(CASCADE_DIR, { recursive: true });
|
|
162
|
+
}
|
|
163
|
+
|
|
152
164
|
/**
|
|
153
165
|
* Resolve the plugin root directory.
|
|
154
166
|
* Works from any file in src/ or scripts/.
|
package/src/sidecar-server.mjs
CHANGED
|
@@ -104,6 +104,12 @@ export function createCommandHandler(connection, scope, registeredAgents, opts =
|
|
|
104
104
|
// Keyed by dispatch_id → { conversation_id, received_at }.
|
|
105
105
|
const _pendingNudges = new Map();
|
|
106
106
|
|
|
107
|
+
// Cascade attribution hint — the single most-recent { agentId, taskRef, ts }
|
|
108
|
+
// sent by the PostToolUse(Bash) hook via the cascade-attribution command.
|
|
109
|
+
// The cascade-watcher reads this (via getCascadeAttribution) to stamp
|
|
110
|
+
// agent_id / task_ref on observed-git events when the hint is fresh.
|
|
111
|
+
let _cascadeAttribution = null;
|
|
112
|
+
|
|
107
113
|
// Connection-ready gate: commands that need `conn` await this promise.
|
|
108
114
|
// If connection is already available, resolves immediately.
|
|
109
115
|
// When connection arrives later (via setConnection), resolves the pending promise.
|
|
@@ -510,6 +516,21 @@ export function createCommandHandler(connection, scope, registeredAgents, opts =
|
|
|
510
516
|
break;
|
|
511
517
|
}
|
|
512
518
|
|
|
519
|
+
// --- Cascade attribution hint ---
|
|
520
|
+
// Sent by the PostToolUse(Bash) hook. Stores the single most-recent
|
|
521
|
+
// attribution hint; the cascade-watcher reads it to attribute
|
|
522
|
+
// observed-git events. Attribution-only — no git detection here.
|
|
523
|
+
|
|
524
|
+
case "cascade-attribution": {
|
|
525
|
+
_cascadeAttribution = {
|
|
526
|
+
agentId: command.agentId || "",
|
|
527
|
+
taskRef: command.taskRef || null,
|
|
528
|
+
ts: typeof command.ts === "number" ? command.ts : Date.now(),
|
|
529
|
+
};
|
|
530
|
+
respond(client, { ok: true });
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
|
|
513
534
|
default:
|
|
514
535
|
respond(client, { ok: false, error: `Unknown action: ${action}` });
|
|
515
536
|
}
|
|
@@ -519,6 +540,11 @@ export function createCommandHandler(connection, scope, registeredAgents, opts =
|
|
|
519
540
|
}
|
|
520
541
|
};
|
|
521
542
|
|
|
543
|
+
// Expose the latest cascade attribution hint so the sidecar can pass a
|
|
544
|
+
// getter to startCascadeWatcher as `getAttribution`. Returns the single
|
|
545
|
+
// most-recent { agentId, taskRef, ts } hint, or null when none received.
|
|
546
|
+
handler.getCascadeAttribution = () => _cascadeAttribution;
|
|
547
|
+
|
|
522
548
|
// Allow updating the connection reference (also resolves any pending waitForConn)
|
|
523
549
|
handler.setConnection = (newConn) => {
|
|
524
550
|
conn = newConn;
|