macro-agent 0.1.8 → 0.1.10
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.md +166 -33
- package/README.md +781 -131
- package/dist/acp/claude-code-replay.d.ts +11 -0
- package/dist/acp/claude-code-replay.d.ts.map +1 -0
- package/dist/acp/claude-code-replay.js +190 -0
- package/dist/acp/claude-code-replay.js.map +1 -0
- package/dist/acp/macro-agent.d.ts.map +1 -1
- package/dist/acp/macro-agent.js +155 -6
- package/dist/acp/macro-agent.js.map +1 -1
- package/dist/acp/types.d.ts +9 -0
- package/dist/acp/types.d.ts.map +1 -1
- package/dist/acp/types.js.map +1 -1
- package/dist/agent/agent-manager-v2.d.ts +21 -0
- package/dist/agent/agent-manager-v2.d.ts.map +1 -1
- package/dist/agent/agent-manager-v2.js +234 -43
- package/dist/agent/agent-manager-v2.js.map +1 -1
- package/dist/agent/agent-manager.d.ts +12 -0
- package/dist/agent/agent-manager.d.ts.map +1 -1
- package/dist/agent/agent-manager.js.map +1 -1
- package/dist/agent/types.d.ts +15 -2
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/boot-v2.d.ts +41 -0
- package/dist/boot-v2.d.ts.map +1 -1
- package/dist/boot-v2.js +16 -1
- package/dist/boot-v2.js.map +1 -1
- package/dist/cli/index.js +56 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cognitive/macro-agent-backend.d.ts.map +1 -1
- package/dist/cognitive/macro-agent-backend.js +40 -22
- package/dist/cognitive/macro-agent-backend.js.map +1 -1
- package/dist/integrations/skilltree.d.ts.map +1 -1
- package/dist/integrations/skilltree.js +1 -0
- package/dist/integrations/skilltree.js.map +1 -1
- package/dist/lifecycle/cleanup.d.ts +33 -2
- package/dist/lifecycle/cleanup.d.ts.map +1 -1
- package/dist/lifecycle/cleanup.js +28 -6
- package/dist/lifecycle/cleanup.js.map +1 -1
- package/dist/lifecycle/handlers-v2.d.ts +7 -0
- package/dist/lifecycle/handlers-v2.d.ts.map +1 -1
- package/dist/lifecycle/handlers-v2.js +28 -2
- package/dist/lifecycle/handlers-v2.js.map +1 -1
- package/dist/lifecycle/types.d.ts +11 -0
- package/dist/lifecycle/types.d.ts.map +1 -1
- package/dist/lifecycle/types.js.map +1 -1
- package/dist/map/acp-bridge.d.ts +9 -0
- package/dist/map/acp-bridge.d.ts.map +1 -1
- package/dist/map/acp-bridge.js +15 -2
- package/dist/map/acp-bridge.js.map +1 -1
- package/dist/map/cascade-bridge.d.ts +44 -0
- package/dist/map/cascade-bridge.d.ts.map +1 -0
- package/dist/map/cascade-bridge.js +257 -0
- package/dist/map/cascade-bridge.js.map +1 -0
- package/dist/map/lifecycle-bridge.d.ts +1 -1
- package/dist/map/lifecycle-bridge.d.ts.map +1 -1
- package/dist/map/lifecycle-bridge.js +58 -23
- package/dist/map/lifecycle-bridge.js.map +1 -1
- package/dist/map/server.d.ts.map +1 -1
- package/dist/map/server.js +47 -6
- package/dist/map/server.js.map +1 -1
- package/dist/map/sidecar.d.ts.map +1 -1
- package/dist/map/sidecar.js +33 -2
- package/dist/map/sidecar.js.map +1 -1
- package/dist/map/types.d.ts +20 -0
- package/dist/map/types.d.ts.map +1 -1
- package/dist/mcp/tools/done-v2.d.ts.map +1 -1
- package/dist/mcp/tools/done-v2.js +8 -0
- package/dist/mcp/tools/done-v2.js.map +1 -1
- package/dist/teams/team-manager-v2.d.ts.map +1 -1
- package/dist/teams/team-manager-v2.js +26 -0
- package/dist/teams/team-manager-v2.js.map +1 -1
- package/dist/teams/team-runtime-v2.d.ts.map +1 -1
- package/dist/teams/team-runtime-v2.js +16 -3
- package/dist/teams/team-runtime-v2.js.map +1 -1
- package/dist/workspace/config.d.ts +10 -10
- package/dist/workspace/config.d.ts.map +1 -1
- package/dist/workspace/config.js +4 -4
- package/dist/workspace/config.js.map +1 -1
- package/dist/workspace/git-cascade-adapter.d.ts +510 -0
- package/dist/workspace/git-cascade-adapter.d.ts.map +1 -0
- package/dist/workspace/git-cascade-adapter.js +908 -0
- package/dist/workspace/git-cascade-adapter.js.map +1 -0
- package/dist/workspace/index.d.ts +3 -3
- package/dist/workspace/index.d.ts.map +1 -1
- package/dist/workspace/index.js +4 -4
- package/dist/workspace/index.js.map +1 -1
- package/dist/workspace/landing/direct-push.d.ts +20 -0
- package/dist/workspace/landing/direct-push.d.ts.map +1 -0
- package/dist/workspace/landing/direct-push.js +74 -0
- package/dist/workspace/landing/direct-push.js.map +1 -0
- package/dist/workspace/landing/index.d.ts +29 -0
- package/dist/workspace/landing/index.d.ts.map +1 -0
- package/dist/workspace/landing/index.js +37 -0
- package/dist/workspace/landing/index.js.map +1 -0
- package/dist/workspace/landing/merge-to-parent.d.ts +41 -0
- package/dist/workspace/landing/merge-to-parent.d.ts.map +1 -0
- package/dist/workspace/landing/merge-to-parent.js +185 -0
- package/dist/workspace/landing/merge-to-parent.js.map +1 -0
- package/dist/workspace/landing/optimistic-push.d.ts +16 -0
- package/dist/workspace/landing/optimistic-push.d.ts.map +1 -0
- package/dist/workspace/landing/optimistic-push.js +27 -0
- package/dist/workspace/landing/optimistic-push.js.map +1 -0
- package/dist/workspace/landing/queue-to-branch.d.ts +24 -0
- package/dist/workspace/landing/queue-to-branch.d.ts.map +1 -0
- package/dist/workspace/landing/queue-to-branch.js +79 -0
- package/dist/workspace/landing/queue-to-branch.js.map +1 -0
- package/dist/workspace/merge-queue/merge-queue.d.ts +10 -0
- package/dist/workspace/merge-queue/merge-queue.d.ts.map +1 -1
- package/dist/workspace/merge-queue/merge-queue.js +10 -0
- package/dist/workspace/merge-queue/merge-queue.js.map +1 -1
- package/dist/workspace/merge-queue/types.d.ts +16 -2
- package/dist/workspace/merge-queue/types.d.ts.map +1 -1
- package/dist/workspace/merge-queue/types.js +9 -0
- package/dist/workspace/merge-queue/types.js.map +1 -1
- package/dist/workspace/pool/types.d.ts +1 -0
- package/dist/workspace/pool/types.d.ts.map +1 -1
- package/dist/workspace/pool/worktree-pool.d.ts.map +1 -1
- package/dist/workspace/pool/worktree-pool.js +1 -0
- package/dist/workspace/pool/worktree-pool.js.map +1 -1
- package/dist/workspace/recovery/abandon.d.ts +15 -0
- package/dist/workspace/recovery/abandon.d.ts.map +1 -0
- package/dist/workspace/recovery/abandon.js +45 -0
- package/dist/workspace/recovery/abandon.js.map +1 -0
- package/dist/workspace/recovery/auto-resolve.d.ts +27 -0
- package/dist/workspace/recovery/auto-resolve.d.ts.map +1 -0
- package/dist/workspace/recovery/auto-resolve.js +99 -0
- package/dist/workspace/recovery/auto-resolve.js.map +1 -0
- package/dist/workspace/recovery/defer.d.ts +15 -0
- package/dist/workspace/recovery/defer.d.ts.map +1 -0
- package/dist/workspace/recovery/defer.js +16 -0
- package/dist/workspace/recovery/defer.js.map +1 -0
- package/dist/workspace/recovery/escalate.d.ts +16 -0
- package/dist/workspace/recovery/escalate.d.ts.map +1 -0
- package/dist/workspace/recovery/escalate.js +24 -0
- package/dist/workspace/recovery/escalate.js.map +1 -0
- package/dist/workspace/recovery/index.d.ts +32 -0
- package/dist/workspace/recovery/index.d.ts.map +1 -0
- package/dist/workspace/recovery/index.js +45 -0
- package/dist/workspace/recovery/index.js.map +1 -0
- package/dist/workspace/recovery/spawn-resolver.d.ts +45 -0
- package/dist/workspace/recovery/spawn-resolver.d.ts.map +1 -0
- package/dist/workspace/recovery/spawn-resolver.js +111 -0
- package/dist/workspace/recovery/spawn-resolver.js.map +1 -0
- package/dist/workspace/recovery/types.d.ts +63 -0
- package/dist/workspace/recovery/types.d.ts.map +1 -0
- package/dist/workspace/recovery/types.js +12 -0
- package/dist/workspace/recovery/types.js.map +1 -0
- package/dist/workspace/topology/index.d.ts +9 -0
- package/dist/workspace/topology/index.d.ts.map +1 -0
- package/dist/workspace/topology/index.js +8 -0
- package/dist/workspace/topology/index.js.map +1 -0
- package/dist/workspace/topology/no-workspace.d.ts +18 -0
- package/dist/workspace/topology/no-workspace.d.ts.map +1 -0
- package/dist/workspace/topology/no-workspace.js +25 -0
- package/dist/workspace/topology/no-workspace.js.map +1 -0
- package/dist/workspace/topology/types.d.ts +97 -0
- package/dist/workspace/topology/types.d.ts.map +1 -0
- package/dist/workspace/topology/types.js +20 -0
- package/dist/workspace/topology/types.js.map +1 -0
- package/dist/workspace/topology/yaml-driven.d.ts +69 -0
- package/dist/workspace/topology/yaml-driven.d.ts.map +1 -0
- package/dist/workspace/topology/yaml-driven.js +273 -0
- package/dist/workspace/topology/yaml-driven.js.map +1 -0
- package/dist/workspace/types-v3.d.ts +110 -0
- package/dist/workspace/types-v3.d.ts.map +1 -0
- package/dist/workspace/types-v3.js +20 -0
- package/dist/workspace/types-v3.js.map +1 -0
- package/dist/workspace/types.d.ts +145 -17
- package/dist/workspace/types.d.ts.map +1 -1
- package/dist/workspace/workspace-manager.d.ts +92 -13
- package/dist/workspace/workspace-manager.d.ts.map +1 -1
- package/dist/workspace/workspace-manager.js +373 -13
- package/dist/workspace/workspace-manager.js.map +1 -1
- package/dist/workspace/yaml-schema.d.ts +254 -0
- package/dist/workspace/yaml-schema.d.ts.map +1 -0
- package/dist/workspace/yaml-schema.js +170 -0
- package/dist/workspace/yaml-schema.js.map +1 -0
- package/docs/conflict-recovery.md +472 -0
- package/docs/git-cascade-integration-gaps.md +678 -0
- package/docs/workspace-interfaces.md +731 -0
- package/docs/workspace-redesign-plan.md +302 -0
- package/package.json +4 -4
- package/src/__tests__/e2e/auto-sync.e2e.test.ts +257 -0
- package/src/__tests__/e2e/cascade-rebase.e2e.test.ts +254 -0
- package/src/__tests__/e2e/cli-run.e2e.test.ts +167 -0
- package/src/__tests__/e2e/self-driving-v3.e2e.test.ts +197 -0
- package/src/__tests__/e2e/spawn-resolver.e2e.test.ts +200 -0
- package/src/__tests__/e2e/workspace-lifecycle.e2e.test.ts +30 -22
- package/src/__tests__/e2e/workspace-v3.e2e.test.ts +413 -0
- package/src/acp/__tests__/claude-code-replay.test.ts +225 -0
- package/src/acp/__tests__/macro-agent.test.ts +39 -1
- package/src/acp/claude-code-replay.ts +208 -0
- package/src/acp/macro-agent.ts +167 -9
- package/src/acp/types.ts +10 -0
- package/src/agent/__tests__/agent-manager-topology.test.ts +73 -0
- package/src/agent/__tests__/agent-manager-v2.test.ts +66 -0
- package/src/agent/__tests__/task-ref-resolution.test.ts +231 -0
- package/src/agent/agent-manager-v2.ts +293 -48
- package/src/agent/agent-manager.ts +14 -0
- package/src/agent/types.ts +16 -2
- package/src/boot-v2.ts +68 -1
- package/src/cli/index.ts +61 -0
- package/src/cognitive/macro-agent-backend.ts +45 -29
- package/src/integrations/skilltree.ts +1 -0
- package/src/lifecycle/cleanup.ts +52 -3
- package/src/lifecycle/handlers-v2.ts +40 -3
- package/src/lifecycle/types.ts +12 -0
- package/src/map/__tests__/cascade-bridge.test.ts +229 -0
- package/src/map/__tests__/lifecycle-bridge.test.ts +86 -10
- package/src/map/acp-bridge.ts +26 -3
- package/src/map/cascade-bridge.ts +301 -0
- package/src/map/lifecycle-bridge.ts +52 -17
- package/src/map/server.ts +47 -6
- package/src/map/sidecar.ts +31 -1
- package/src/map/types.ts +20 -0
- package/src/mcp/tools/done-v2.ts +9 -0
- package/src/teams/team-manager-v2.ts +37 -0
- package/src/teams/team-runtime-v2.ts +23 -3
- package/src/workspace/__tests__/{dataplane-adapter.test.ts → git-cascade-adapter.test.ts} +209 -14
- package/src/workspace/__tests__/self-driving-yaml.test.ts +114 -0
- package/src/workspace/__tests__/shared-worktree-refcount.test.ts +154 -0
- package/src/workspace/__tests__/standalone-mode.test.ts +118 -0
- package/src/workspace/__tests__/workspace-manager-v3.test.ts +245 -0
- package/src/workspace/__tests__/yaml-schema.test.ts +210 -0
- package/src/workspace/config.ts +11 -11
- package/src/workspace/git-cascade-adapter.ts +1186 -0
- package/src/workspace/index.ts +11 -11
- package/src/workspace/landing/__tests__/strategies.test.ts +142 -0
- package/src/workspace/landing/direct-push.ts +91 -0
- package/src/workspace/landing/index.ts +40 -0
- package/src/workspace/landing/merge-to-parent.ts +228 -0
- package/src/workspace/landing/optimistic-push.ts +36 -0
- package/src/workspace/landing/queue-to-branch.ts +108 -0
- package/src/workspace/merge-queue/merge-queue.ts +10 -0
- package/src/workspace/merge-queue/types.ts +16 -2
- package/src/workspace/pool/__tests__/worktree-pool.integration.test.ts +5 -5
- package/src/workspace/pool/types.ts +1 -0
- package/src/workspace/pool/worktree-pool.ts +1 -0
- package/src/workspace/recovery/__tests__/auto-resolve-integration.test.ts +127 -0
- package/src/workspace/recovery/__tests__/spawn-resolver.test.ts +139 -0
- package/src/workspace/recovery/__tests__/strategies.test.ts +145 -0
- package/src/workspace/recovery/abandon.ts +51 -0
- package/src/workspace/recovery/auto-resolve.ts +119 -0
- package/src/workspace/recovery/defer.ts +23 -0
- package/src/workspace/recovery/escalate.ts +30 -0
- package/src/workspace/recovery/index.ts +58 -0
- package/src/workspace/recovery/spawn-resolver.ts +145 -0
- package/src/workspace/recovery/types.ts +54 -0
- package/src/workspace/topology/__tests__/yaml-driven.test.ts +345 -0
- package/src/workspace/topology/index.ts +18 -0
- package/src/workspace/topology/no-workspace.ts +39 -0
- package/src/workspace/topology/types.ts +116 -0
- package/src/workspace/topology/yaml-driven.ts +316 -0
- package/src/workspace/types-v3.ts +155 -0
- package/src/workspace/types.ts +191 -20
- package/src/workspace/workspace-manager.ts +474 -19
- package/src/workspace/yaml-schema.ts +216 -0
- package/src/workspace/dataplane-adapter.ts +0 -546
|
@@ -131,6 +131,12 @@ export interface AgentManager {
|
|
|
131
131
|
*/
|
|
132
132
|
listHeadManagers(): Agent[];
|
|
133
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Look up the SpawnedAgent shape for any agent (any role) that's running
|
|
136
|
+
* AND has a live session in this process. Returns null otherwise.
|
|
137
|
+
*/
|
|
138
|
+
getActiveAgentSession(agentId: AgentId): SpawnedAgent | null;
|
|
139
|
+
|
|
134
140
|
// ── Session Interaction ────────────────────────────────────────
|
|
135
141
|
|
|
136
142
|
/**
|
|
@@ -296,6 +302,14 @@ export interface AgentManager {
|
|
|
296
302
|
*/
|
|
297
303
|
setSidecar(sidecar: { connected: boolean; reportCheckpoint(cp: any): Promise<any> } | null): void;
|
|
298
304
|
|
|
305
|
+
/**
|
|
306
|
+
* Set a TopologyPolicy for workspace allocation decisions.
|
|
307
|
+
* When set, AgentManagerV2 delegates `createWorkspaceForRole` to the policy
|
|
308
|
+
* before falling back to role-name dispatch. Set by boot-v2 when team YAML
|
|
309
|
+
* contains `macro_agent.workspace`.
|
|
310
|
+
*/
|
|
311
|
+
setTopologyPolicy(policy: import('../workspace/topology/types.js').TopologyPolicy | null): void;
|
|
312
|
+
|
|
299
313
|
// ── Cleanup ────────────────────────────────────────────────────
|
|
300
314
|
|
|
301
315
|
/**
|
package/src/agent/types.ts
CHANGED
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
StreamConfig,
|
|
16
16
|
Workspace,
|
|
17
17
|
} from "../workspace/types.js";
|
|
18
|
+
import type { TaskRef } from "git-cascade/events";
|
|
18
19
|
|
|
19
20
|
// ─────────────────────────────────────────────────────────────────
|
|
20
21
|
// Spawn Options
|
|
@@ -90,16 +91,29 @@ export interface SpawnAgentOptions {
|
|
|
90
91
|
streamConfig?: StreamConfig;
|
|
91
92
|
|
|
92
93
|
/**
|
|
93
|
-
*
|
|
94
|
+
* git-cascade task ID to claim (for workers).
|
|
94
95
|
* If provided, the worker will claim this task and work on it.
|
|
95
96
|
*/
|
|
96
|
-
|
|
97
|
+
gitCascadeTaskId?: string;
|
|
97
98
|
|
|
98
99
|
/**
|
|
99
100
|
* Resolved capabilities for this agent's role.
|
|
100
101
|
* Injected by TeamRuntime spawn interceptor for capability-based workspace dispatch.
|
|
101
102
|
*/
|
|
102
103
|
capabilities?: string[];
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Optional reference to an external task this agent is working on. When
|
|
107
|
+
* set, the reference is woven into cascade event metadata so OpenHive (or
|
|
108
|
+
* any other observer) can bind the agent's commits, merges, and streams
|
|
109
|
+
* to the OpenTasks node. Propagates through:
|
|
110
|
+
* - stream creation: `adapter.createStream({ metadata: { task_ref } })`
|
|
111
|
+
* - commits: `adapter.commitChanges({ metadata: { task_ref } })` (pass
|
|
112
|
+
* per-commit; each commit can carry a distinct sub-task binding)
|
|
113
|
+
* Can also arrive late via pull-mode `claim_task` — workers that claim a
|
|
114
|
+
* task mid-session should include the ref on subsequent commits.
|
|
115
|
+
*/
|
|
116
|
+
taskRef?: TaskRef;
|
|
103
117
|
}
|
|
104
118
|
|
|
105
119
|
/**
|
package/src/boot-v2.ts
CHANGED
|
@@ -121,6 +121,52 @@ export interface BootV2Config {
|
|
|
121
121
|
};
|
|
122
122
|
};
|
|
123
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Cascade event binding config. Controls how cascade events emitted by
|
|
126
|
+
* git-cascade-backed agents get tagged with external task references for
|
|
127
|
+
* hub projection (changelog, task↔stream binding). Independent of MAP
|
|
128
|
+
* transport: cascade events are data/identity, not transport.
|
|
129
|
+
*/
|
|
130
|
+
cascade?: {
|
|
131
|
+
/**
|
|
132
|
+
* Default OpenTasks resource ID for this swarm. When set, the agent
|
|
133
|
+
* manager auto-builds `taskRef = { resource_id, node_id: task_id }`
|
|
134
|
+
* for spawned agents so cascade events carry the binding without
|
|
135
|
+
* callers constructing refs by hand.
|
|
136
|
+
*
|
|
137
|
+
* Leave undefined if:
|
|
138
|
+
* - The swarm touches multiple opentasks graphs (use `resolveTaskRef`).
|
|
139
|
+
* - Every caller sets `SpawnAgentOptions.taskRef` explicitly.
|
|
140
|
+
* - You don't care about hub task↔stream binding.
|
|
141
|
+
*/
|
|
142
|
+
taskResourceId?: string;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Custom resolver for multi-graph deployments. Called at every spawn;
|
|
146
|
+
* return a `TaskRef` to set the binding or `undefined` to skip.
|
|
147
|
+
* Precedence: explicit `SpawnAgentOptions.taskRef` > `resolveTaskRef` >
|
|
148
|
+
* `taskResourceId` fallback (combined with `spawnOptions.task_id`).
|
|
149
|
+
*
|
|
150
|
+
* Keep implementations cheap — this runs on every spawn.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* resolveTaskRef: (opts) => {
|
|
154
|
+
* const graph = graphForCwd(opts.cwd ?? process.cwd());
|
|
155
|
+
* return graph ? { resource_id: graph.resourceId, node_id: String(opts.task_id) } : undefined;
|
|
156
|
+
* }
|
|
157
|
+
*/
|
|
158
|
+
resolveTaskRef?: (
|
|
159
|
+
spawnOptions: import("./agent/types.js").SpawnAgentOptions
|
|
160
|
+
) => import("git-cascade/events").TaskRef | undefined;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Override the default `x-cascade` event prefix. Useful for branded
|
|
164
|
+
* deployments or isolating cascade namespaces in testing. Affects all
|
|
165
|
+
* events emitted by the tracker embedded in this swarm.
|
|
166
|
+
*/
|
|
167
|
+
eventPrefix?: string;
|
|
168
|
+
};
|
|
169
|
+
|
|
124
170
|
/** minimem (agent memory) — registers as MCP server for all agents */
|
|
125
171
|
minimem?: {
|
|
126
172
|
enabled?: boolean;
|
|
@@ -270,6 +316,8 @@ export async function bootV2(
|
|
|
270
316
|
serverUrl: config.serverUrl,
|
|
271
317
|
serverToken: config.serverToken,
|
|
272
318
|
controlSocketPath,
|
|
319
|
+
taskResourceId: config.cascade?.taskResourceId,
|
|
320
|
+
resolveTaskRef: config.cascade?.resolveTaskRef,
|
|
273
321
|
}
|
|
274
322
|
);
|
|
275
323
|
|
|
@@ -450,8 +498,27 @@ export async function bootV2(
|
|
|
450
498
|
if (config.map?.enabled && config.map.server) {
|
|
451
499
|
try {
|
|
452
500
|
const { createMAPSidecar } = await import("./map/sidecar.js");
|
|
501
|
+
// If a workspace manager is present, pull out its GitCascadeAdapter
|
|
502
|
+
// so the sidecar can forward cascade events to the hub.
|
|
503
|
+
const wsMgr = config.workspaceManager as
|
|
504
|
+
| {
|
|
505
|
+
getGitCascadeAdapter?: () =>
|
|
506
|
+
| import("./workspace/git-cascade-adapter.js").GitCascadeAdapter
|
|
507
|
+
| undefined;
|
|
508
|
+
}
|
|
509
|
+
| undefined;
|
|
510
|
+
const gitCascadeAdapter = wsMgr?.getGitCascadeAdapter?.();
|
|
453
511
|
mapSidecar = createMAPSidecar(
|
|
454
|
-
{
|
|
512
|
+
{
|
|
513
|
+
agentManager,
|
|
514
|
+
agentStore,
|
|
515
|
+
inboxAdapter,
|
|
516
|
+
tasksAdapter,
|
|
517
|
+
getLocalMapId: mapServerInstance
|
|
518
|
+
? (id: string) => mapServerInstance!.getLocalMapId(id)
|
|
519
|
+
: undefined,
|
|
520
|
+
gitCascadeAdapter,
|
|
521
|
+
},
|
|
455
522
|
{
|
|
456
523
|
server: config.map.server,
|
|
457
524
|
token: config.map.token,
|
package/src/cli/index.ts
CHANGED
|
@@ -498,6 +498,67 @@ program
|
|
|
498
498
|
}
|
|
499
499
|
});
|
|
500
500
|
|
|
501
|
+
// ─────────────────────────────────────────────────────────────────
|
|
502
|
+
// Run Team Command (Phase 10)
|
|
503
|
+
// ─────────────────────────────────────────────────────────────────
|
|
504
|
+
|
|
505
|
+
program
|
|
506
|
+
.command("run <teamName>")
|
|
507
|
+
.description("Boot the system, start a team by name, and optionally prompt the root agent")
|
|
508
|
+
.option("--task <task>", "Task to prompt the root agent with")
|
|
509
|
+
.option("--cwd <path>", "Working directory for agents")
|
|
510
|
+
.option("--base-path <path>", "Base path for team YAML lookup (default: cwd)")
|
|
511
|
+
.action(async (teamName: string, options: { task?: string; cwd?: string; basePath?: string }) => {
|
|
512
|
+
const cwd = options.cwd ?? process.cwd();
|
|
513
|
+
console.log(chalk.blue(`Booting macro-agent and starting team: ${teamName}`));
|
|
514
|
+
|
|
515
|
+
let system: Awaited<ReturnType<typeof bootV2>> | null = null;
|
|
516
|
+
try {
|
|
517
|
+
system = await bootV2({ cwd });
|
|
518
|
+
console.log(chalk.green("System booted."));
|
|
519
|
+
|
|
520
|
+
// Construct & install a TeamManagerV2; start the requested team.
|
|
521
|
+
const { TeamManagerV2 } = await import("../teams/team-manager-v2.js");
|
|
522
|
+
const teamManager = new TeamManagerV2({
|
|
523
|
+
agentManager: system.agentManager,
|
|
524
|
+
inboxAdapter: system.inboxAdapter,
|
|
525
|
+
tasksAdapter: system.tasksAdapter,
|
|
526
|
+
});
|
|
527
|
+
teamManager.install();
|
|
528
|
+
|
|
529
|
+
const instanceId = await teamManager.startTeam(teamName, options.basePath ?? cwd);
|
|
530
|
+
console.log(chalk.green(`Team started: ${teamName} (instance ${instanceId})`));
|
|
531
|
+
|
|
532
|
+
// Find the root agent (first spawned agent in the instance)
|
|
533
|
+
const agents = system.agentStore.listAgents({ state: "running" });
|
|
534
|
+
const root = agents[0];
|
|
535
|
+
|
|
536
|
+
if (options.task && root) {
|
|
537
|
+
console.log(chalk.gray(`Prompting root agent (${root.id}) with task...`));
|
|
538
|
+
const iter = system.agentManager.prompt(root.id, options.task);
|
|
539
|
+
for await (const chunk of iter) {
|
|
540
|
+
process.stdout.write(typeof chunk === "string" ? chunk : JSON.stringify(chunk));
|
|
541
|
+
}
|
|
542
|
+
console.log();
|
|
543
|
+
} else if (!root) {
|
|
544
|
+
console.log(chalk.yellow("No root agent found to prompt."));
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
console.log(chalk.gray("Press Ctrl+C to shut down."));
|
|
548
|
+
|
|
549
|
+
// Graceful shutdown on SIGINT
|
|
550
|
+
process.on("SIGINT", async () => {
|
|
551
|
+
console.log(chalk.yellow("\nShutting down..."));
|
|
552
|
+
if (system) await system.shutdown();
|
|
553
|
+
process.exit(0);
|
|
554
|
+
});
|
|
555
|
+
} catch (error) {
|
|
556
|
+
console.error(chalk.red(`Failed to run team: ${error}`));
|
|
557
|
+
if (system) await system.shutdown();
|
|
558
|
+
process.exit(1);
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
|
|
501
562
|
// ─────────────────────────────────────────────────────────────────
|
|
502
563
|
// Parse and Run
|
|
503
564
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -240,6 +240,46 @@ export class MacroAgentBackend {
|
|
|
240
240
|
const timeout = config.timeout;
|
|
241
241
|
let softTimer: ReturnType<typeof setTimeout> | undefined;
|
|
242
242
|
let hardTimer: ReturnType<typeof setTimeout> | undefined;
|
|
243
|
+
let completionNotified = false;
|
|
244
|
+
|
|
245
|
+
// Helper: fire the completion callback + inbox notification exactly once.
|
|
246
|
+
// Called from both the hard-timer path and the finally block to avoid a
|
|
247
|
+
// race where waitForSession returns (state != "running") before finally
|
|
248
|
+
// runs and fires the callback.
|
|
249
|
+
const notifyCompletion = async (): Promise<void> => {
|
|
250
|
+
if (completionNotified) return;
|
|
251
|
+
if (session.state !== "completed" && session.state !== "failed") return;
|
|
252
|
+
completionNotified = true;
|
|
253
|
+
|
|
254
|
+
const completeEvent: SessionCompleteEvent = {
|
|
255
|
+
sessionId: session.id,
|
|
256
|
+
agentId: agentId as string,
|
|
257
|
+
state: session.state,
|
|
258
|
+
duration_ms: session.endTime
|
|
259
|
+
? session.endTime.getTime() - session.startTime.getTime()
|
|
260
|
+
: 0,
|
|
261
|
+
message_count: session.messages.length,
|
|
262
|
+
tool_call_count: session.toolCalls.length,
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
this.onSessionComplete?.(completeEvent);
|
|
266
|
+
|
|
267
|
+
if (this.inboxAdapter) {
|
|
268
|
+
try {
|
|
269
|
+
await this.inboxAdapter.send(
|
|
270
|
+
agentId as string,
|
|
271
|
+
agentId as string,
|
|
272
|
+
{
|
|
273
|
+
type: "session.complete",
|
|
274
|
+
sessionId: session.id,
|
|
275
|
+
state: session.state,
|
|
276
|
+
duration_ms: completeEvent.duration_ms,
|
|
277
|
+
outcome: session.state === "completed" ? "success" : "failure",
|
|
278
|
+
},
|
|
279
|
+
);
|
|
280
|
+
} catch { /* best-effort */ }
|
|
281
|
+
}
|
|
282
|
+
};
|
|
243
283
|
|
|
244
284
|
try {
|
|
245
285
|
if (timeout && timeout > 0) {
|
|
@@ -263,6 +303,9 @@ export class MacroAgentBackend {
|
|
|
263
303
|
session.state = "failed";
|
|
264
304
|
session.error = "Timeout exceeded";
|
|
265
305
|
session.endTime = new Date();
|
|
306
|
+
// Fire completion callback immediately — the finally block's
|
|
307
|
+
// deferred callback could race with waitForSession returning.
|
|
308
|
+
void notifyCompletion();
|
|
266
309
|
this.agentManager.terminate(agentId, "timeout").catch(() => {});
|
|
267
310
|
}, timeout);
|
|
268
311
|
}
|
|
@@ -307,35 +350,8 @@ export class MacroAgentBackend {
|
|
|
307
350
|
}
|
|
308
351
|
|
|
309
352
|
// Notify completion (no trajectory extraction — OpenHive handles that via sessionlog)
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
sessionId: session.id,
|
|
313
|
-
agentId: agentId as string,
|
|
314
|
-
state: session.state,
|
|
315
|
-
duration_ms: session.endTime
|
|
316
|
-
? session.endTime.getTime() - session.startTime.getTime()
|
|
317
|
-
: 0,
|
|
318
|
-
message_count: session.messages.length,
|
|
319
|
-
tool_call_count: session.toolCalls.length,
|
|
320
|
-
};
|
|
321
|
-
|
|
322
|
-
this.onSessionComplete?.(completeEvent);
|
|
323
|
-
|
|
324
|
-
if (this.inboxAdapter) {
|
|
325
|
-
await this.inboxAdapter.send(
|
|
326
|
-
agentId as string,
|
|
327
|
-
agentId as string,
|
|
328
|
-
{
|
|
329
|
-
type: "session.complete",
|
|
330
|
-
sessionId: session.id,
|
|
331
|
-
state: session.state,
|
|
332
|
-
duration_ms: completeEvent.duration_ms,
|
|
333
|
-
outcome: session.state === "completed" ? "success" : "failure",
|
|
334
|
-
},
|
|
335
|
-
{ subject: "session.complete" },
|
|
336
|
-
).catch(() => {});
|
|
337
|
-
}
|
|
338
|
-
}
|
|
353
|
+
// This is a no-op if the hard-timer path already fired it.
|
|
354
|
+
await notifyCompletion();
|
|
339
355
|
|
|
340
356
|
// Clean up agent process
|
|
341
357
|
if (session.state !== "running") {
|
package/src/lifecycle/cleanup.ts
CHANGED
|
@@ -124,15 +124,45 @@ export function detectCleanupStatus(
|
|
|
124
124
|
// =============================================================================
|
|
125
125
|
|
|
126
126
|
/**
|
|
127
|
-
*
|
|
127
|
+
* Optional handle for routing commits through git-cascade so the resulting
|
|
128
|
+
* commit gets a Change-Id trailer and emits an `x-cascade/stream.committed`
|
|
129
|
+
* event. When omitted, commits are made via raw git (no Change-Id, no
|
|
130
|
+
* cascade event) — used by legacy/null-workspace paths.
|
|
131
|
+
*/
|
|
132
|
+
export interface TrackedCommitHandle {
|
|
133
|
+
/** WorkspaceManager-style commitChanges signature */
|
|
134
|
+
commitChanges(opts: {
|
|
135
|
+
streamId: string;
|
|
136
|
+
agentId: string;
|
|
137
|
+
worktree: string;
|
|
138
|
+
message: string;
|
|
139
|
+
metadata?: Record<string, unknown>;
|
|
140
|
+
}): { commit: string; changeId: string };
|
|
141
|
+
/** Stream this commit belongs to */
|
|
142
|
+
streamId: string;
|
|
143
|
+
/** Agent making the commit */
|
|
144
|
+
agentId: string;
|
|
145
|
+
/** Optional metadata threaded into the cascade event (e.g. `{ task_ref }`) */
|
|
146
|
+
metadata?: Record<string, unknown>;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Commit all uncommitted changes in a workspace.
|
|
151
|
+
*
|
|
152
|
+
* When a `TrackedCommitHandle` is supplied, the commit goes through
|
|
153
|
+
* git-cascade's tracker — gaining a stable Change-Id trailer and emitting
|
|
154
|
+
* `x-cascade/stream.committed` so OpenHive sees the work. Without a handle,
|
|
155
|
+
* falls back to raw git (legacy behavior).
|
|
128
156
|
*
|
|
129
157
|
* @param workspacePath - Path to the workspace
|
|
130
158
|
* @param message - Commit message
|
|
159
|
+
* @param tracked - Optional handle to commit via the cascade tracker
|
|
131
160
|
* @returns Commit hash if successful, undefined if nothing to commit
|
|
132
161
|
*/
|
|
133
162
|
export function commitChanges(
|
|
134
163
|
workspacePath: string,
|
|
135
|
-
message: string
|
|
164
|
+
message: string,
|
|
165
|
+
tracked?: TrackedCommitHandle
|
|
136
166
|
): string | undefined {
|
|
137
167
|
try {
|
|
138
168
|
// Check if there are changes to commit
|
|
@@ -140,7 +170,26 @@ export function commitChanges(
|
|
|
140
170
|
return undefined;
|
|
141
171
|
}
|
|
142
172
|
|
|
143
|
-
//
|
|
173
|
+
// Tracked path: stage + commit through git-cascade so Change-Id +
|
|
174
|
+
// x-cascade events fire.
|
|
175
|
+
if (tracked) {
|
|
176
|
+
try {
|
|
177
|
+
const { commit } = tracked.commitChanges({
|
|
178
|
+
streamId: tracked.streamId,
|
|
179
|
+
agentId: tracked.agentId,
|
|
180
|
+
worktree: workspacePath,
|
|
181
|
+
message,
|
|
182
|
+
metadata: tracked.metadata,
|
|
183
|
+
});
|
|
184
|
+
return commit;
|
|
185
|
+
} catch {
|
|
186
|
+
// Fall through to raw-git path on tracker failure (e.g., stream
|
|
187
|
+
// conflicted) so callers still get a commit. Caveat: no Change-Id
|
|
188
|
+
// and no cascade event in this fallback.
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Raw-git path: stage all changes
|
|
144
193
|
execFileSync("git", ["add", "--all"], {
|
|
145
194
|
cwd: workspacePath,
|
|
146
195
|
encoding: "utf-8",
|
|
@@ -22,8 +22,9 @@ import type {
|
|
|
22
22
|
CleanupStatus,
|
|
23
23
|
DoneHandlerResult,
|
|
24
24
|
} from "./types.js";
|
|
25
|
-
import { commitChanges, attemptMerge, abortMerge } from "./cleanup.js";
|
|
25
|
+
import { commitChanges, attemptMerge, abortMerge, type TrackedCommitHandle } from "./cleanup.js";
|
|
26
26
|
import type { MergeQueueInterface } from "../workspace/merge-queue/types.js";
|
|
27
|
+
import type { WorkspaceManager } from "../workspace/types.js";
|
|
27
28
|
import {
|
|
28
29
|
getAllDescendants,
|
|
29
30
|
needsCascadeTermination,
|
|
@@ -40,6 +41,40 @@ export interface HandlerDepsV2 {
|
|
|
40
41
|
agentManager: AgentManager;
|
|
41
42
|
taskMode?: "push" | "pull";
|
|
42
43
|
mergeQueue?: MergeQueueInterface;
|
|
44
|
+
/**
|
|
45
|
+
* Optional workspace manager. When provided AND `context.streamId` is set,
|
|
46
|
+
* commits route through the cascade tracker (Change-Id + x-cascade events).
|
|
47
|
+
* Without it, commits use raw git (legacy / null-workspace path).
|
|
48
|
+
*/
|
|
49
|
+
workspaceManager?: WorkspaceManager;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// =============================================================================
|
|
53
|
+
// Tracked Commit Helper
|
|
54
|
+
// =============================================================================
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Build a TrackedCommitHandle when the agent has a streamId + workspaceManager.
|
|
58
|
+
* Returns undefined if either is missing — caller falls back to raw git.
|
|
59
|
+
*/
|
|
60
|
+
function buildTrackedHandle(
|
|
61
|
+
context: LifecycleContext,
|
|
62
|
+
deps: HandlerDepsV2
|
|
63
|
+
): TrackedCommitHandle | undefined {
|
|
64
|
+
if (!context.streamId || !deps.workspaceManager) return undefined;
|
|
65
|
+
const ws = deps.workspaceManager;
|
|
66
|
+
// Build metadata with task_ref if known. Empty object is fine — the hub
|
|
67
|
+
// ignores unknown fields, and back-fill kicks in if task_ref appears later.
|
|
68
|
+
const metadata: Record<string, unknown> = {};
|
|
69
|
+
if (context.taskRef) {
|
|
70
|
+
metadata.task_ref = context.taskRef;
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
streamId: context.streamId,
|
|
74
|
+
agentId: context.agentId,
|
|
75
|
+
metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
|
|
76
|
+
commitChanges: (opts) => ws.commitChanges(opts),
|
|
77
|
+
};
|
|
43
78
|
}
|
|
44
79
|
|
|
45
80
|
// =============================================================================
|
|
@@ -110,10 +145,12 @@ async function handleWorkerDone(
|
|
|
110
145
|
? `WIP: ${args.summary}`
|
|
111
146
|
: `WIP: Auto-commit from done() with ${uncommittedCount} uncommitted file(s)`;
|
|
112
147
|
|
|
113
|
-
const
|
|
148
|
+
const tracked = buildTrackedHandle(context, deps);
|
|
149
|
+
const commitHash = commitChanges(context.workspacePath, commitMessage, tracked);
|
|
114
150
|
if (commitHash) {
|
|
151
|
+
const via = tracked ? "tracker" : "raw-git";
|
|
115
152
|
cleanupActions.push(
|
|
116
|
-
`Committed ${uncommittedCount} file(s): ${commitHash.slice(0, 8)}`
|
|
153
|
+
`Committed ${uncommittedCount} file(s) via ${via}: ${commitHash.slice(0, 8)}`
|
|
117
154
|
);
|
|
118
155
|
} else {
|
|
119
156
|
warnings.push("Failed to auto-commit uncommitted changes");
|
package/src/lifecycle/types.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import type { AgentId, TaskId } from "../store/types/index.js";
|
|
12
|
+
import type { TaskRef } from "git-cascade/events";
|
|
12
13
|
|
|
13
14
|
// =============================================================================
|
|
14
15
|
// Done Status Types
|
|
@@ -120,6 +121,17 @@ export interface LifecycleContext {
|
|
|
120
121
|
|
|
121
122
|
/** Resolved capabilities for the agent's role (for capability-based handler dispatch) */
|
|
122
123
|
capabilities?: string[];
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Optional reference to an external task this agent is working on. When
|
|
127
|
+
* present, threaded into commit metadata so cascade events carry the
|
|
128
|
+
* binding (enabling task↔stream queries on the OpenHive hub).
|
|
129
|
+
*
|
|
130
|
+
* Sourced from `SpawnAgentOptions.taskRef` at spawn time and propagated
|
|
131
|
+
* via the agent manager. Late-binding (mid-session pull-mode claim) can
|
|
132
|
+
* mutate this on the live context.
|
|
133
|
+
*/
|
|
134
|
+
taskRef?: TaskRef;
|
|
123
135
|
}
|
|
124
136
|
|
|
125
137
|
/**
|