mastracode 0.25.0-alpha.0 → 0.25.0-alpha.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # mastracode
2
2
 
3
+ ## 0.25.0-alpha.2
4
+
5
+ ### Minor Changes
6
+
7
+ - Added ACP server mode for `mastracode`. ([#18231](https://github.com/mastra-ai/mastra/pull/18231))
8
+
9
+ You can now connect ACP-compatible editors and clients to `mastracode` over stdio. This lets clients start sessions, send prompts, and receive streamed responses.
10
+
11
+ **Example**
12
+
13
+ ```bash
14
+ mastracode --acp
15
+ ```
16
+
17
+ ### Patch Changes
18
+
19
+ - Fixed Mastra Code steering display so messages wait for runtime acceptance, blocked inputs are shown as blocked instead of chat, abort cleanup removes pending steering without duplicating output, and plan approvals continue correctly in same-mode and cross-mode flows. ([#18183](https://github.com/mastra-ai/mastra/pull/18183))
20
+
21
+ - Fixed thread loading in worktrees to only show threads explicitly tagged for the current worktree path, preventing threads from other worktrees or the main repo from being incorrectly loaded on startup ([#18332](https://github.com/mastra-ai/mastra/pull/18332))
22
+
23
+ - Updated dependencies [[`6a1428a`](https://github.com/mastra-ai/mastra/commit/6a1428a23133fc070fc6c1caa08d28f3ba4fe5ff), [`7f51548`](https://github.com/mastra-ai/mastra/commit/7f515481213780be7047cef00640b9d35f3d545c)]:
24
+ - @mastra/core@1.46.0-alpha.2
25
+
26
+ ## 0.25.0-alpha.1
27
+
28
+ ### Patch Changes
29
+
30
+ - Updated dependencies [[`7794d71`](https://github.com/mastra-ai/mastra/commit/7794d71872c68733a30e028dfb7b1705daf6c5d2)]:
31
+ - @mastra/core@1.46.0-alpha.1
32
+
3
33
  ## 0.25.0-alpha.0
4
34
 
5
35
  ### Minor Changes
@@ -0,0 +1,32 @@
1
+ import type { Agent, AgentSideConnection, InitializeRequest, InitializeResponse, NewSessionRequest, NewSessionResponse, PromptRequest, PromptResponse, CancelNotification, ContentBlock } from '@agentclientprotocol/sdk';
2
+ import type { Harness, HarnessMode } from '@mastra/core/harness';
3
+ /**
4
+ * ACP Agent implementation that wraps a mastracode Harness.
5
+ * Each instance represents one ACP connection from a client.
6
+ */
7
+ export declare class MastraCodeAcpAgent implements Agent {
8
+ private readonly connection;
9
+ private readonly harness;
10
+ private readonly modes;
11
+ private readonly sessionMap;
12
+ private currentPromptState;
13
+ private promptMutex;
14
+ private getThreadIdOrThrow;
15
+ constructor(connection: AgentSideConnection, harness: Harness, modes: HarnessMode[]);
16
+ initialize(_request: InitializeRequest): Promise<InitializeResponse>;
17
+ authenticate(): Promise<void>;
18
+ newSession(_request: NewSessionRequest): Promise<NewSessionResponse>;
19
+ prompt(request: PromptRequest): Promise<PromptResponse>;
20
+ cancel(_notification: CancelNotification): Promise<void>;
21
+ setSessionMode(params: {
22
+ sessionId: string;
23
+ modeId: string;
24
+ }): Promise<void>;
25
+ unstable_setSessionModel(params: {
26
+ sessionId: string;
27
+ modelId: string;
28
+ }): Promise<void>;
29
+ }
30
+ export declare function extractTextFromContentBlocks(blocks: ContentBlock[]): string;
31
+ export declare function mapStopReason(reason: 'complete' | 'aborted' | 'error' | 'suspended'): 'end_turn' | 'cancelled' | 'max_tokens' | 'max_turn_requests' | 'refusal';
32
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/acp/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,YAAY,EACb,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIjE;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,KAAK;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IACxD,OAAO,CAAC,kBAAkB,CAA4B;IACtD,OAAO,CAAC,WAAW,CAAoC;IAEvD,OAAO,CAAC,kBAAkB;gBAQd,UAAU,EAAE,mBAAmB,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE;IAW7E,UAAU,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAcpE,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,UAAU,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA0CpE,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAqEvD,MAAM,CAAC,aAAa,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxD,cAAc,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5E,wBAAwB,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAK9F;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,CAY3E;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,GACrD,UAAU,GAAG,WAAW,GAAG,YAAY,GAAG,mBAAmB,GAAG,SAAS,CAW3E"}
@@ -0,0 +1,22 @@
1
+ import type { AgentSideConnection } from '@agentclientprotocol/sdk';
2
+ import type { Harness, HarnessEvent, TokenUsage } from '@mastra/core/harness';
3
+ /**
4
+ * Enable or disable automatic tool approval (set via --dangerous-auto-approve CLI flag).
5
+ */
6
+ export declare function setAutoApprove(value: boolean): void;
7
+ /**
8
+ * Accumulated state for an active prompt turn.
9
+ */
10
+ export interface PromptState {
11
+ sessionId: string;
12
+ lastTextLength: number;
13
+ usage: TokenUsage;
14
+ resolve: (reason: 'complete' | 'aborted' | 'error' | 'suspended') => void;
15
+ }
16
+ /**
17
+ * Translate a HarnessEvent into an ACP SessionNotification and send it
18
+ * via the provided connection. Returns null for events that don't produce
19
+ * a session update.
20
+ */
21
+ export declare function handleHarnessEvent(event: HarnessEvent, state: PromptState | null, connection: AgentSideConnection, harness: Harness): void;
22
+ //# sourceMappingURL=event-mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-mapper.d.ts","sourceRoot":"","sources":["../../src/acp/event-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiD,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACnH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAI9E;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAEnD;AA4BD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,KAAK,IAAI,CAAC;CAC3E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,WAAW,GAAG,IAAI,EACzB,UAAU,EAAE,mBAAmB,EAC/B,OAAO,EAAE,OAAO,GACf,IAAI,CAyEN"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Entry point for ACP server mode.
3
+ * Initializes mastracode and runs the ACP protocol over stdio.
4
+ */
5
+ export declare function acpMain(options?: {
6
+ dangerousAutoApprove?: boolean;
7
+ }): Promise<void>;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/acp/index.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,wBAAsB,OAAO,CAAC,OAAO,CAAC,EAAE;IAAE,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA8DzF"}
@@ -0,0 +1,7 @@
1
+ import type { Harness, HarnessMode } from '@mastra/core/harness';
2
+ /**
3
+ * Run the ACP server over stdio.
4
+ * This sets up the JSON-RPC stream and keeps the process alive until the client disconnects.
5
+ */
6
+ export declare function runAcpServer(harness: Harness, modes: HarnessMode[], cleanup?: () => Promise<void>): Promise<void>;
7
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/acp/server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGjE;;;GAGG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,WAAW,EAAE,EACpB,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC,CAiBf"}
@@ -0,0 +1,390 @@
1
+ import { createMastraCode } from './chunk-TZBT6UPD.js';
2
+ import { releaseAllThreadLocks } from './chunk-ONKJTRKR.js';
3
+ import { Readable, Writable } from 'stream';
4
+ import { ndJsonStream, AgentSideConnection, PROTOCOL_VERSION } from '@agentclientprotocol/sdk';
5
+
6
+ // src/acp/event-mapper.ts
7
+ var autoApprove = false;
8
+ function setAutoApprove(value) {
9
+ autoApprove = value;
10
+ }
11
+ function mapToolKind(toolName) {
12
+ const name = toolName.toLowerCase();
13
+ if (name.includes("edit") || name.includes("write") || name.includes("replace") || name.includes("patch"))
14
+ return "edit";
15
+ if (name.includes("read") || name.includes("view") || name.includes("list") || name.includes("find")) return "read";
16
+ if (name.includes("delete") || name.includes("remove")) return "delete";
17
+ if (name.includes("search") || name.includes("grep") || name.includes("query")) return "search";
18
+ if (name.includes("execute") || name.includes("run") || name.includes("command") || name.includes("shell"))
19
+ return "execute";
20
+ if (name.includes("fetch") || name.includes("curl") || name.includes("http") || name.includes("browse") || name.includes("navigate"))
21
+ return "fetch";
22
+ if (name.includes("think") || name.includes("reason")) return "think";
23
+ return "other";
24
+ }
25
+ function handleHarnessEvent(event, state, connection, harness) {
26
+ if (!state) return;
27
+ switch (event.type) {
28
+ case "agent_start":
29
+ state.lastTextLength = 0;
30
+ break;
31
+ case "message_update": {
32
+ if (event.message.role !== "assistant") break;
33
+ const fullText = event.message.content.filter((c) => c.type === "text").map((p) => p.text).join("");
34
+ if (fullText.length > state.lastTextLength) {
35
+ const delta = fullText.slice(state.lastTextLength);
36
+ state.lastTextLength = fullText.length;
37
+ sendUpdate(connection, state.sessionId, {
38
+ sessionUpdate: "agent_message_chunk",
39
+ content: { type: "text", text: delta }
40
+ });
41
+ }
42
+ break;
43
+ }
44
+ case "message_end":
45
+ state.lastTextLength = 0;
46
+ break;
47
+ case "tool_start":
48
+ sendUpdate(connection, state.sessionId, {
49
+ sessionUpdate: "tool_call",
50
+ toolCallId: event.toolCallId,
51
+ title: event.toolName,
52
+ kind: mapToolKind(event.toolName),
53
+ status: "in_progress",
54
+ rawInput: JSON.stringify(event.args)
55
+ });
56
+ break;
57
+ case "tool_end":
58
+ sendUpdate(connection, state.sessionId, {
59
+ sessionUpdate: "tool_call_update",
60
+ toolCallId: event.toolCallId,
61
+ status: event.isError ? "failed" : "completed",
62
+ rawOutput: typeof event.result === "string" ? event.result : JSON.stringify(event.result)
63
+ });
64
+ break;
65
+ case "tool_approval_required":
66
+ void handleToolApproval(state, connection, harness, event).catch((err) => {
67
+ process.stderr.write(`[acp] handleToolApproval error: ${err}
68
+ `);
69
+ });
70
+ break;
71
+ case "tool_suspended":
72
+ void handleToolSuspended(state, connection, harness, event).catch((err) => {
73
+ process.stderr.write(`[acp] handleToolSuspended error: ${err}
74
+ `);
75
+ });
76
+ break;
77
+ case "usage_update":
78
+ accumulateUsage(state.usage, event.usage);
79
+ break;
80
+ case "agent_end":
81
+ state.resolve(event.reason ?? "complete");
82
+ break;
83
+ }
84
+ }
85
+ function sendUpdate(connection, sessionId, update) {
86
+ connection.sessionUpdate({ sessionId, update }).catch((err) => {
87
+ process.stderr.write(`[acp] sessionUpdate error: ${err}
88
+ `);
89
+ });
90
+ }
91
+ async function handleToolApproval(state, connection, harness, event) {
92
+ if (autoApprove) {
93
+ harness.session.respondToToolApproval({ decision: "approve" });
94
+ return;
95
+ }
96
+ const req = {
97
+ sessionId: state.sessionId,
98
+ toolCall: {
99
+ toolCallId: event.toolCallId,
100
+ title: event.toolName,
101
+ rawInput: JSON.stringify(event.args)
102
+ },
103
+ options: [
104
+ { optionId: "approve", name: "Allow", kind: "allow_once" },
105
+ { optionId: "reject", name: "Reject", kind: "reject_once" }
106
+ ]
107
+ };
108
+ try {
109
+ const resp = await connection.requestPermission(req);
110
+ if (resp.outcome.outcome === "selected") {
111
+ const decision = resp.outcome.optionId === "approve" ? "approve" : "decline";
112
+ harness.session.respondToToolApproval({ decision });
113
+ } else {
114
+ harness.session.respondToToolApproval({ decision: "decline" });
115
+ }
116
+ } catch (err) {
117
+ process.stderr.write(`[acp] requestPermission error: ${err}
118
+ `);
119
+ harness.session.respondToToolApproval({ decision: "decline" });
120
+ }
121
+ }
122
+ async function handleToolSuspended(state, connection, harness, event) {
123
+ const { toolCallId, toolName, args, suspendPayload } = event;
124
+ if (toolName === "request_access" || suspendPayload?.kind === "sandbox_access_request") {
125
+ harness.respondToToolSuspension({ toolCallId, resumeData: "Yes" });
126
+ return;
127
+ }
128
+ if (toolName === "submit_plan") {
129
+ const req = {
130
+ sessionId: state.sessionId,
131
+ toolCall: {
132
+ toolCallId,
133
+ title: toolName,
134
+ rawInput: JSON.stringify(args)
135
+ },
136
+ options: [
137
+ { optionId: "approve", name: "Approve Plan", kind: "allow_once" },
138
+ { optionId: "reject", name: "Reject Plan", kind: "reject_once" }
139
+ ]
140
+ };
141
+ try {
142
+ const resp = await connection.requestPermission(req);
143
+ const action = resp.outcome.outcome === "selected" && resp.outcome.optionId === "approve" ? "approved" : "rejected";
144
+ harness.respondToToolSuspension({ toolCallId, resumeData: { action } });
145
+ } catch {
146
+ harness.respondToToolSuspension({ toolCallId, resumeData: { action: "rejected" } });
147
+ }
148
+ return;
149
+ }
150
+ harness.respondToToolSuspension({
151
+ toolCallId,
152
+ resumeData: "Proceed with your best judgment. Do not ask further questions."
153
+ });
154
+ }
155
+ function accumulateUsage(target, usage) {
156
+ target.promptTokens += usage.promptTokens;
157
+ target.completionTokens += usage.completionTokens;
158
+ target.totalTokens += usage.totalTokens;
159
+ if (usage.reasoningTokens) target.reasoningTokens = (target.reasoningTokens ?? 0) + usage.reasoningTokens;
160
+ if (usage.cachedInputTokens) target.cachedInputTokens = (target.cachedInputTokens ?? 0) + usage.cachedInputTokens;
161
+ if (usage.cacheCreationInputTokens) {
162
+ target.cacheCreationInputTokens = (target.cacheCreationInputTokens ?? 0) + usage.cacheCreationInputTokens;
163
+ }
164
+ }
165
+ var MastraCodeAcpAgent = class {
166
+ connection;
167
+ harness;
168
+ modes;
169
+ sessionMap = /* @__PURE__ */ new Map();
170
+ // sessionId -> threadId
171
+ currentPromptState = null;
172
+ promptMutex = Promise.resolve();
173
+ getThreadIdOrThrow(sessionId) {
174
+ const threadId = this.sessionMap.get(sessionId);
175
+ if (!threadId) {
176
+ throw new Error(`Unknown ACP sessionId: ${sessionId}`);
177
+ }
178
+ return threadId;
179
+ }
180
+ constructor(connection, harness, modes) {
181
+ this.connection = connection;
182
+ this.harness = harness;
183
+ this.modes = modes;
184
+ this.harness.subscribe((event) => {
185
+ handleHarnessEvent(event, this.currentPromptState, this.connection, this.harness);
186
+ });
187
+ }
188
+ async initialize(_request) {
189
+ return {
190
+ protocolVersion: PROTOCOL_VERSION,
191
+ agentInfo: {
192
+ name: "mastracode",
193
+ title: "Mastra Code",
194
+ version: "0.1.0"
195
+ },
196
+ agentCapabilities: {
197
+ loadSession: false
198
+ }
199
+ };
200
+ }
201
+ async authenticate() {
202
+ }
203
+ async newSession(_request) {
204
+ const thread = await this.harness.createThread();
205
+ const sessionId = thread.id;
206
+ this.sessionMap.set(sessionId, thread.id);
207
+ await this.harness.switchThread({ threadId: thread.id });
208
+ const availableModes = this.modes.map((m) => ({
209
+ id: m.id,
210
+ name: m.name ?? m.id
211
+ }));
212
+ const currentModeId = this.harness.session.mode.get();
213
+ let models;
214
+ try {
215
+ const availableModels = await this.harness.listAvailableModels();
216
+ const currentModelId = this.harness.session.model.get();
217
+ models = {
218
+ currentModelId: currentModelId ?? "",
219
+ availableModels: availableModels.map((m) => ({
220
+ modelId: m.id,
221
+ name: m.modelName
222
+ }))
223
+ };
224
+ } catch {
225
+ }
226
+ return {
227
+ sessionId,
228
+ modes: {
229
+ currentModeId,
230
+ availableModes
231
+ },
232
+ models
233
+ };
234
+ }
235
+ async prompt(request) {
236
+ const { sessionId, prompt: contentBlocks } = request;
237
+ const text = extractTextFromContentBlocks(contentBlocks);
238
+ const threadId = this.getThreadIdOrThrow(sessionId);
239
+ await this.harness.switchThread({ threadId });
240
+ const prevMutex = this.promptMutex;
241
+ let resolveMutex;
242
+ this.promptMutex = new Promise((resolve) => {
243
+ resolveMutex = resolve;
244
+ });
245
+ await prevMutex;
246
+ try {
247
+ const result = new Promise((resolve) => {
248
+ const usage2 = {
249
+ promptTokens: 0,
250
+ completionTokens: 0,
251
+ totalTokens: 0
252
+ };
253
+ this.currentPromptState = {
254
+ sessionId,
255
+ lastTextLength: 0,
256
+ usage: usage2,
257
+ resolve: (reason2) => {
258
+ resolve({ reason: reason2, usage: usage2 });
259
+ this.currentPromptState = null;
260
+ }
261
+ };
262
+ });
263
+ try {
264
+ await this.harness.sendMessage({ content: text });
265
+ } catch (error) {
266
+ this.currentPromptState = null;
267
+ throw error;
268
+ }
269
+ const { reason, usage } = await result;
270
+ return {
271
+ stopReason: mapStopReason(reason),
272
+ usage: {
273
+ inputTokens: usage.promptTokens,
274
+ outputTokens: usage.completionTokens,
275
+ totalTokens: usage.totalTokens,
276
+ thoughtTokens: usage.reasoningTokens,
277
+ cachedReadTokens: usage.cachedInputTokens,
278
+ cachedWriteTokens: usage.cacheCreationInputTokens
279
+ }
280
+ };
281
+ } finally {
282
+ resolveMutex();
283
+ }
284
+ }
285
+ async cancel(_notification) {
286
+ this.harness.abort();
287
+ }
288
+ async setSessionMode(params) {
289
+ const threadId = this.getThreadIdOrThrow(params.sessionId);
290
+ await this.harness.switchThread({ threadId });
291
+ this.harness.session.mode.set({ modeId: params.modeId });
292
+ }
293
+ async unstable_setSessionModel(params) {
294
+ const threadId = this.getThreadIdOrThrow(params.sessionId);
295
+ await this.harness.switchThread({ threadId });
296
+ this.harness.session.model.set({ modelId: params.modelId });
297
+ }
298
+ };
299
+ function extractTextFromContentBlocks(blocks) {
300
+ const parts = [];
301
+ for (const block of blocks) {
302
+ if (block.type === "text") {
303
+ parts.push(block.text);
304
+ } else if (block.type === "resource_link") {
305
+ parts.push(`[resource: ${block.uri}]`);
306
+ } else if (block.type === "resource") {
307
+ parts.push(`[resource: ${block.resource.uri}]`);
308
+ }
309
+ }
310
+ return parts.join("\n");
311
+ }
312
+ function mapStopReason(reason) {
313
+ switch (reason) {
314
+ case "complete":
315
+ return "end_turn";
316
+ case "aborted":
317
+ return "cancelled";
318
+ case "error":
319
+ return "end_turn";
320
+ case "suspended":
321
+ return "end_turn";
322
+ }
323
+ }
324
+
325
+ // src/acp/server.ts
326
+ async function runAcpServer(harness, modes, cleanup) {
327
+ const input = Readable.toWeb(process.stdin);
328
+ const output = Writable.toWeb(process.stdout);
329
+ const stream = ndJsonStream(output, input);
330
+ const connection = new AgentSideConnection((conn) => new MastraCodeAcpAgent(conn, harness, modes), stream);
331
+ try {
332
+ await connection.closed;
333
+ } finally {
334
+ if (cleanup) {
335
+ await cleanup();
336
+ }
337
+ }
338
+ }
339
+
340
+ // src/acp/index.ts
341
+ async function acpMain(options) {
342
+ if (options?.dangerousAutoApprove) {
343
+ setAutoApprove(true);
344
+ }
345
+ const originalConsoleLog = console.log;
346
+ console.log = (...args) => {
347
+ process.stderr.write(args.map(String).join(" ") + "\n");
348
+ };
349
+ let result;
350
+ try {
351
+ result = await createMastraCode({
352
+ unixSocketPubSub: false,
353
+ disableMcp: false,
354
+ disableHooks: false
355
+ });
356
+ const { harness, mcpManager, signalsPubSub } = result;
357
+ const modes = [
358
+ { id: "build", name: "Build" },
359
+ { id: "plan", name: "Plan" },
360
+ { id: "fast", name: "Fast" }
361
+ ];
362
+ const cleanup = async () => {
363
+ releaseAllThreadLocks();
364
+ const closeSignalsPubSub = signalsPubSub?.close;
365
+ await Promise.allSettled([
366
+ mcpManager?.disconnect(),
367
+ harness?.getMastra()?.stopWorkers(),
368
+ harness?.stopHeartbeats(),
369
+ closeSignalsPubSub?.()
370
+ ]);
371
+ console.log = originalConsoleLog;
372
+ };
373
+ const handleSignal = async () => {
374
+ await cleanup();
375
+ process.exit(0);
376
+ };
377
+ process.on("SIGINT", handleSignal);
378
+ process.on("SIGTERM", handleSignal);
379
+ await runAcpServer(harness, modes, cleanup);
380
+ } catch (error) {
381
+ process.stderr.write(`[acp] Fatal error: ${error}
382
+ `);
383
+ console.log = originalConsoleLog;
384
+ process.exit(1);
385
+ }
386
+ }
387
+
388
+ export { acpMain };
389
+ //# sourceMappingURL=acp-4JBFAGKY.js.map
390
+ //# sourceMappingURL=acp-4JBFAGKY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/acp/event-mapper.ts","../src/acp/agent.ts","../src/acp/server.ts","../src/acp/index.ts"],"names":["usage","reason"],"mappings":"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","file":"acp-4JBFAGKY.js","sourcesContent":["import type { SessionNotification, RequestPermissionRequest, AgentSideConnection } from '@agentclientprotocol/sdk';\nimport type { Harness, HarnessEvent, TokenUsage } from '@mastra/core/harness';\n\nlet autoApprove = false;\n\n/**\n * Enable or disable automatic tool approval (set via --dangerous-auto-approve CLI flag).\n */\nexport function setAutoApprove(value: boolean): void {\n autoApprove = value;\n}\n\n/**\n * Map a mastracode tool name to an ACP ToolKind.\n */\nfunction mapToolKind(\n toolName: string,\n): 'read' | 'edit' | 'delete' | 'move' | 'search' | 'execute' | 'think' | 'fetch' | 'other' {\n const name = toolName.toLowerCase();\n if (name.includes('edit') || name.includes('write') || name.includes('replace') || name.includes('patch'))\n return 'edit';\n if (name.includes('read') || name.includes('view') || name.includes('list') || name.includes('find')) return 'read';\n if (name.includes('delete') || name.includes('remove')) return 'delete';\n if (name.includes('search') || name.includes('grep') || name.includes('query')) return 'search';\n if (name.includes('execute') || name.includes('run') || name.includes('command') || name.includes('shell'))\n return 'execute';\n if (\n name.includes('fetch') ||\n name.includes('curl') ||\n name.includes('http') ||\n name.includes('browse') ||\n name.includes('navigate')\n )\n return 'fetch';\n if (name.includes('think') || name.includes('reason')) return 'think';\n return 'other';\n}\n\n/**\n * Accumulated state for an active prompt turn.\n */\nexport interface PromptState {\n sessionId: string;\n lastTextLength: number;\n usage: TokenUsage;\n resolve: (reason: 'complete' | 'aborted' | 'error' | 'suspended') => void;\n}\n\n/**\n * Translate a HarnessEvent into an ACP SessionNotification and send it\n * via the provided connection. Returns null for events that don't produce\n * a session update.\n */\nexport function handleHarnessEvent(\n event: HarnessEvent,\n state: PromptState | null,\n connection: AgentSideConnection,\n harness: Harness,\n): void {\n if (!state) return;\n\n switch (event.type) {\n case 'agent_start':\n state.lastTextLength = 0;\n break;\n\n case 'message_update': {\n if (event.message.role !== 'assistant') break;\n const fullText = event.message.content\n .filter((c): c is { type: 'text'; text: string } => c.type === 'text')\n .map(p => p.text)\n .join('');\n if (fullText.length > state.lastTextLength) {\n const delta = fullText.slice(state.lastTextLength);\n state.lastTextLength = fullText.length;\n sendUpdate(connection, state.sessionId, {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: delta },\n });\n }\n break;\n }\n\n case 'message_end':\n state.lastTextLength = 0;\n break;\n\n case 'tool_start':\n sendUpdate(connection, state.sessionId, {\n sessionUpdate: 'tool_call',\n toolCallId: event.toolCallId,\n title: event.toolName,\n kind: mapToolKind(event.toolName),\n status: 'in_progress',\n rawInput: JSON.stringify(event.args),\n });\n break;\n\n case 'tool_end':\n sendUpdate(connection, state.sessionId, {\n sessionUpdate: 'tool_call_update',\n toolCallId: event.toolCallId,\n status: event.isError ? 'failed' : 'completed',\n rawOutput: typeof event.result === 'string' ? event.result : JSON.stringify(event.result),\n });\n break;\n\n case 'tool_approval_required':\n void handleToolApproval(state, connection, harness, event).catch(err => {\n process.stderr.write(`[acp] handleToolApproval error: ${err}\\n`);\n });\n break;\n\n case 'tool_suspended':\n void handleToolSuspended(state, connection, harness, event).catch(err => {\n process.stderr.write(`[acp] handleToolSuspended error: ${err}\\n`);\n });\n break;\n\n case 'usage_update':\n accumulateUsage(state.usage, event.usage);\n break;\n\n case 'agent_end':\n state.resolve(event.reason ?? 'complete');\n break;\n\n // Ignored in v1: om_*, subagent_*, workspace_*, task_updated, etc.\n default:\n break;\n }\n}\n\nfunction sendUpdate(connection: AgentSideConnection, sessionId: string, update: SessionNotification['update']): void {\n connection.sessionUpdate({ sessionId, update }).catch(err => {\n process.stderr.write(`[acp] sessionUpdate error: ${err}\\n`);\n });\n}\n\nasync function handleToolApproval(\n state: PromptState,\n connection: AgentSideConnection,\n harness: Harness,\n event: Extract<HarnessEvent, { type: 'tool_approval_required' }>,\n): Promise<void> {\n // Auto-approve if --dangerous-auto-approve flag is set\n if (autoApprove) {\n harness.session.respondToToolApproval({ decision: 'approve' });\n return;\n }\n\n const req: RequestPermissionRequest = {\n sessionId: state.sessionId,\n toolCall: {\n toolCallId: event.toolCallId,\n title: event.toolName,\n rawInput: JSON.stringify(event.args),\n },\n options: [\n { optionId: 'approve', name: 'Allow', kind: 'allow_once' },\n { optionId: 'reject', name: 'Reject', kind: 'reject_once' },\n ],\n };\n\n try {\n const resp = await connection.requestPermission(req);\n if (resp.outcome.outcome === 'selected') {\n const decision = resp.outcome.optionId === 'approve' ? 'approve' : 'decline';\n harness.session.respondToToolApproval({ decision });\n } else {\n harness.session.respondToToolApproval({ decision: 'decline' });\n }\n } catch (err) {\n process.stderr.write(`[acp] requestPermission error: ${err}\\n`);\n harness.session.respondToToolApproval({ decision: 'decline' });\n }\n}\n\nasync function handleToolSuspended(\n state: PromptState,\n connection: AgentSideConnection,\n harness: Harness,\n event: Extract<HarnessEvent, { type: 'tool_suspended' }>,\n): Promise<void> {\n const { toolCallId, toolName, args, suspendPayload } = event;\n\n // Auto-resolve certain suspensions (mirrors headless.ts autoResolve)\n if (toolName === 'request_access' || (suspendPayload as any)?.kind === 'sandbox_access_request') {\n harness.respondToToolSuspension({ toolCallId, resumeData: 'Yes' });\n return;\n }\n\n if (toolName === 'submit_plan') {\n // Request permission for plan approval\n const req: RequestPermissionRequest = {\n sessionId: state.sessionId,\n toolCall: {\n toolCallId,\n title: toolName,\n rawInput: JSON.stringify(args),\n },\n options: [\n { optionId: 'approve', name: 'Approve Plan', kind: 'allow_once' },\n { optionId: 'reject', name: 'Reject Plan', kind: 'reject_once' },\n ],\n };\n\n try {\n const resp = await connection.requestPermission(req);\n const action =\n resp.outcome.outcome === 'selected' && resp.outcome.optionId === 'approve' ? 'approved' : 'rejected';\n harness.respondToToolSuspension({ toolCallId, resumeData: { action } });\n } catch {\n harness.respondToToolSuspension({ toolCallId, resumeData: { action: 'rejected' } });\n }\n return;\n }\n\n // For ask_user and other suspensions, auto-resolve\n harness.respondToToolSuspension({\n toolCallId,\n resumeData: 'Proceed with your best judgment. Do not ask further questions.',\n });\n}\n\nfunction accumulateUsage(target: TokenUsage, usage: TokenUsage): void {\n target.promptTokens += usage.promptTokens;\n target.completionTokens += usage.completionTokens;\n target.totalTokens += usage.totalTokens;\n if (usage.reasoningTokens) target.reasoningTokens = (target.reasoningTokens ?? 0) + usage.reasoningTokens;\n if (usage.cachedInputTokens) target.cachedInputTokens = (target.cachedInputTokens ?? 0) + usage.cachedInputTokens;\n if (usage.cacheCreationInputTokens) {\n target.cacheCreationInputTokens = (target.cacheCreationInputTokens ?? 0) + usage.cacheCreationInputTokens;\n }\n}\n","import type {\n Agent,\n AgentSideConnection,\n InitializeRequest,\n InitializeResponse,\n NewSessionRequest,\n NewSessionResponse,\n PromptRequest,\n PromptResponse,\n CancelNotification,\n ContentBlock,\n} from '@agentclientprotocol/sdk';\nimport { PROTOCOL_VERSION } from '@agentclientprotocol/sdk';\nimport type { Harness, HarnessMode } from '@mastra/core/harness';\nimport { handleHarnessEvent } from './event-mapper.js';\nimport type { PromptState } from './event-mapper.js';\n\n/**\n * ACP Agent implementation that wraps a mastracode Harness.\n * Each instance represents one ACP connection from a client.\n */\nexport class MastraCodeAcpAgent implements Agent {\n private readonly connection: AgentSideConnection;\n private readonly harness: Harness;\n private readonly modes: HarnessMode[];\n private readonly sessionMap = new Map<string, string>(); // sessionId -> threadId\n private currentPromptState: PromptState | null = null;\n private promptMutex: Promise<void> = Promise.resolve();\n\n private getThreadIdOrThrow(sessionId: string): string {\n const threadId = this.sessionMap.get(sessionId);\n if (!threadId) {\n throw new Error(`Unknown ACP sessionId: ${sessionId}`);\n }\n return threadId;\n }\n\n constructor(connection: AgentSideConnection, harness: Harness, modes: HarnessMode[]) {\n this.connection = connection;\n this.harness = harness;\n this.modes = modes;\n\n // Register persistent event listener\n this.harness.subscribe(event => {\n handleHarnessEvent(event, this.currentPromptState, this.connection, this.harness);\n });\n }\n\n async initialize(_request: InitializeRequest): Promise<InitializeResponse> {\n return {\n protocolVersion: PROTOCOL_VERSION,\n agentInfo: {\n name: 'mastracode',\n title: 'Mastra Code',\n version: '0.1.0',\n },\n agentCapabilities: {\n loadSession: false,\n },\n };\n }\n\n async authenticate(): Promise<void> {\n // No-op: mastracode handles its own auth\n }\n\n async newSession(_request: NewSessionRequest): Promise<NewSessionResponse> {\n const thread = await this.harness.createThread();\n const sessionId = thread.id;\n this.sessionMap.set(sessionId, thread.id);\n\n // Switch to the new thread\n await this.harness.switchThread({ threadId: thread.id });\n\n // Build modes list from constructor param\n const availableModes = this.modes.map((m: HarnessMode) => ({\n id: m.id,\n name: m.name ?? m.id,\n }));\n\n const currentModeId = this.harness.session.mode.get();\n\n // Build models list (best-effort)\n let models: NewSessionResponse['models'];\n try {\n const availableModels = await this.harness.listAvailableModels();\n const currentModelId = this.harness.session.model.get();\n models = {\n currentModelId: currentModelId ?? '',\n availableModels: availableModels.map(m => ({\n modelId: m.id,\n name: m.modelName,\n })),\n };\n } catch {\n // Model listing may fail if no providers are configured\n }\n\n return {\n sessionId,\n modes: {\n currentModeId,\n availableModes,\n },\n models,\n };\n }\n\n async prompt(request: PromptRequest): Promise<PromptResponse> {\n const { sessionId, prompt: contentBlocks } = request;\n\n // Extract text from content blocks\n const text = extractTextFromContentBlocks(contentBlocks);\n\n // Ensure we're on the right thread\n const threadId = this.getThreadIdOrThrow(sessionId);\n await this.harness.switchThread({ threadId });\n\n // Serialize prompts via mutex\n const prevMutex = this.promptMutex;\n let resolveMutex: () => void;\n this.promptMutex = new Promise<void>(resolve => {\n resolveMutex = resolve;\n });\n\n await prevMutex;\n\n try {\n // Create prompt state that will be resolved when agent_end fires\n const result = new Promise<{\n reason: 'complete' | 'aborted' | 'error' | 'suspended';\n usage: PromptState['usage'];\n }>(resolve => {\n const usage: PromptState['usage'] = {\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n };\n\n this.currentPromptState = {\n sessionId,\n lastTextLength: 0,\n usage,\n resolve: reason => {\n resolve({ reason, usage });\n this.currentPromptState = null;\n },\n };\n });\n\n // Send the message to the harness\n try {\n await this.harness.sendMessage({ content: text });\n } catch (error) {\n this.currentPromptState = null;\n throw error;\n }\n\n // Wait for agent_end to resolve\n const { reason, usage } = await result;\n\n return {\n stopReason: mapStopReason(reason),\n usage: {\n inputTokens: usage.promptTokens,\n outputTokens: usage.completionTokens,\n totalTokens: usage.totalTokens,\n thoughtTokens: usage.reasoningTokens,\n cachedReadTokens: usage.cachedInputTokens,\n cachedWriteTokens: usage.cacheCreationInputTokens,\n },\n };\n } finally {\n resolveMutex!();\n }\n }\n\n async cancel(_notification: CancelNotification): Promise<void> {\n this.harness.abort();\n }\n\n async setSessionMode(params: { sessionId: string; modeId: string }): Promise<void> {\n const threadId = this.getThreadIdOrThrow(params.sessionId);\n await this.harness.switchThread({ threadId });\n this.harness.session.mode.set({ modeId: params.modeId });\n }\n\n async unstable_setSessionModel(params: { sessionId: string; modelId: string }): Promise<void> {\n const threadId = this.getThreadIdOrThrow(params.sessionId);\n await this.harness.switchThread({ threadId });\n this.harness.session.model.set({ modelId: params.modelId });\n }\n}\n\nexport function extractTextFromContentBlocks(blocks: ContentBlock[]): string {\n const parts: string[] = [];\n for (const block of blocks) {\n if (block.type === 'text') {\n parts.push(block.text);\n } else if (block.type === 'resource_link') {\n parts.push(`[resource: ${block.uri}]`);\n } else if (block.type === 'resource') {\n parts.push(`[resource: ${block.resource.uri}]`);\n }\n }\n return parts.join('\\n');\n}\n\nexport function mapStopReason(\n reason: 'complete' | 'aborted' | 'error' | 'suspended',\n): 'end_turn' | 'cancelled' | 'max_tokens' | 'max_turn_requests' | 'refusal' {\n switch (reason) {\n case 'complete':\n return 'end_turn';\n case 'aborted':\n return 'cancelled';\n case 'error':\n return 'end_turn';\n case 'suspended':\n return 'end_turn';\n }\n}\n","import { Readable, Writable } from 'node:stream';\nimport { AgentSideConnection, ndJsonStream } from '@agentclientprotocol/sdk';\nimport type { Harness, HarnessMode } from '@mastra/core/harness';\nimport { MastraCodeAcpAgent } from './agent.js';\n\n/**\n * Run the ACP server over stdio.\n * This sets up the JSON-RPC stream and keeps the process alive until the client disconnects.\n */\nexport async function runAcpServer(\n harness: Harness,\n modes: HarnessMode[],\n cleanup?: () => Promise<void>,\n): Promise<void> {\n // Create the ndJSON stream from stdin/stdout\n const input = Readable.toWeb(process.stdin) as ReadableStream<Uint8Array>;\n const output = Writable.toWeb(process.stdout) as WritableStream<Uint8Array>;\n const stream = ndJsonStream(output, input);\n\n // Create the agent-side connection\n const connection = new AgentSideConnection(conn => new MastraCodeAcpAgent(conn, harness, modes), stream);\n\n // Handle cleanup on disconnect (success or error)\n try {\n await connection.closed;\n } finally {\n if (cleanup) {\n await cleanup();\n }\n }\n}\n","import type { HarnessMode } from '@mastra/core/harness';\n\nimport { createMastraCode } from '../index.js';\nimport { releaseAllThreadLocks } from '../utils/thread-lock.js';\nimport { setAutoApprove } from './event-mapper.js';\nimport { runAcpServer } from './server.js';\n\n/**\n * Entry point for ACP server mode.\n * Initializes mastracode and runs the ACP protocol over stdio.\n */\nexport async function acpMain(options?: { dangerousAutoApprove?: boolean }): Promise<void> {\n if (options?.dangerousAutoApprove) {\n setAutoApprove(true);\n }\n // Redirect console.log to stderr to avoid polluting the JSON-RPC stream on stdout.\n // eslint-disable-next-line no-console\n const originalConsoleLog = console.log;\n // eslint-disable-next-line no-console\n console.log = (...args: unknown[]) => {\n process.stderr.write(args.map(String).join(' ') + '\\n');\n };\n\n let result: Awaited<ReturnType<typeof createMastraCode>> | undefined;\n\n try {\n result = await createMastraCode({\n unixSocketPubSub: false,\n disableMcp: false,\n disableHooks: false,\n });\n\n const { harness, mcpManager, signalsPubSub } = result;\n\n // Default modes (same as createMastraCode defaults)\n const modes: HarnessMode[] = [\n { id: 'build', name: 'Build' },\n { id: 'plan', name: 'Plan' },\n { id: 'fast', name: 'Fast' },\n ];\n\n // Cleanup function (mirrors main.ts asyncCleanup)\n const cleanup = async () => {\n releaseAllThreadLocks();\n const closeSignalsPubSub = (signalsPubSub as { close?: () => Promise<void> | void } | undefined)?.close;\n await Promise.allSettled([\n mcpManager?.disconnect(),\n harness?.getMastra()?.stopWorkers(),\n harness?.stopHeartbeats(),\n closeSignalsPubSub?.(),\n ]);\n\n // Restore console.log\n // eslint-disable-next-line no-console\n console.log = originalConsoleLog;\n };\n\n // Handle signals\n const handleSignal = async () => {\n await cleanup();\n process.exit(0);\n };\n\n process.on('SIGINT', handleSignal);\n process.on('SIGTERM', handleSignal);\n\n await runAcpServer(harness, modes, cleanup);\n } catch (error) {\n process.stderr.write(`[acp] Fatal error: ${error}\\n`);\n // eslint-disable-next-line no-console\n console.log = originalConsoleLog;\n process.exit(1);\n }\n}\n"]}