@agentrq/acp-gateway 0.1.4 → 0.1.8

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/README.md CHANGED
@@ -40,6 +40,10 @@ To use globally:
40
40
  npm install -g @agentrq/acp-gateway
41
41
  ```
42
42
 
43
+ ## Current Version
44
+
45
+ `0.1.8`
46
+
43
47
  ## Usage
44
48
 
45
49
  ### Quick Start
@@ -101,8 +105,11 @@ Example `.mcp.json`:
101
105
  1. **Config Loading** — Reads `.mcp.json` to find the agentrq MCP server.
102
106
  2. **MCP Connection** — Establishes a `StreamableHTTPClientTransport` to the MCP server with automatic retry and reconnection.
103
107
  3. **Agent Spawning** — Launches the specified ACP agent as a subprocess with stdio piping.
104
- 4. **ACP Handshake** — Initializes the ACP connection and creates a new session with the MCP server reference.
105
- 5. **Task Bridge** The MCP server sends `notifications/claude/channel` for new tasks; `acp-gateway` forwards them to the ACP agent.
108
+ 4. **ACP Handshake** — Initializes the ACP connection.
109
+ 5. **Task Bridge & Multi-Session Isolation** When a task is received from the MCP server:
110
+ - `acp-gateway` extracts the `chat_id` (Task ID).
111
+ - It ensures a dedicated ACP session for that specific task.
112
+ - If the task belongs to a different session than the current one, a new ACP session is initialized, providing clean state isolation between concurrent or sequential tasks.
106
113
  6. **Permission Bridge** — Permission requests from the ACP agent are forwarded to the MCP server; verdicts are sent back.
107
114
  7. **Recursive Execution** — After each task completes, `acp-gateway` checks for the next pending task automatically.
108
115
 
@@ -1,10 +1,108 @@
1
- import { describe, it, expect } from "vitest";
2
- // This is a minimal test for logic found in index.ts, if any can be exported.
3
- // Since index.ts is mostly procedural, we'll just check if it's there for now.
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { createAcpSessionSwitcher, checkForNextTask } from "../index.js";
4
3
  describe("index", () => {
5
- it("should have bridge logic", () => {
6
- // This is more of a placeholder as index.ts is the main entry point
7
- expect(true).toBe(true);
4
+ describe("createAcpSessionSwitcher", () => {
5
+ let mockConnection;
6
+ let params;
7
+ beforeEach(() => {
8
+ mockConnection = {
9
+ newSession: vi.fn().mockResolvedValue({ sessionId: "new-session-id" }),
10
+ };
11
+ params = { cwd: "/test", mcpServers: [{ name: "s1", url: "http://s1", headers: [] }] };
12
+ });
13
+ it("should return initial session ID", () => {
14
+ const switcher = createAcpSessionSwitcher(mockConnection, params, "initial-id");
15
+ expect(switcher.getSessionId()).toBe("initial-id");
16
+ });
17
+ it("should return current session ID if taskId is undefined", async () => {
18
+ const switcher = createAcpSessionSwitcher(mockConnection, params, "initial-id");
19
+ const id = await switcher.ensureForTask(undefined);
20
+ expect(id).toBe("initial-id");
21
+ expect(mockConnection.newSession).not.toHaveBeenCalled();
22
+ });
23
+ it("should create a new session on first call with taskId", async () => {
24
+ const switcher = createAcpSessionSwitcher(mockConnection, params, "initial-id");
25
+ const id = await switcher.ensureForTask("task-1");
26
+ expect(id).toBe("new-session-id");
27
+ expect(mockConnection.newSession).toHaveBeenCalled();
28
+ // Second call with same taskId should still return same ID
29
+ const id2 = await switcher.ensureForTask("task-1");
30
+ expect(id2).toBe("new-session-id");
31
+ expect(mockConnection.newSession).toHaveBeenCalledTimes(1);
32
+ });
33
+ it("should create a new session when taskId changes", async () => {
34
+ params = { cwd: "/test", mcpServers: [{ name: "s1", url: "http://s1", headers: [] }] };
35
+ const switcher = createAcpSessionSwitcher(mockConnection, params, "initial-id");
36
+ // Set initial task
37
+ await switcher.ensureForTask("task-1");
38
+ // Change task
39
+ const id = await switcher.ensureForTask("task-2");
40
+ expect(id).toBe("new-session-id");
41
+ expect(mockConnection.newSession).toHaveBeenCalledTimes(2);
42
+ expect(switcher.getSessionId()).toBe("new-session-id");
43
+ });
44
+ });
45
+ describe("checkForNextTask", () => {
46
+ let mockMcpBridge;
47
+ let mockConnection;
48
+ let mockSessionSwitcher;
49
+ beforeEach(() => {
50
+ vi.clearAllMocks();
51
+ mockMcpBridge = {
52
+ callTool: vi.fn(),
53
+ };
54
+ mockConnection = {
55
+ prompt: vi.fn().mockResolvedValue({ stopReason: "complete" }),
56
+ };
57
+ mockSessionSwitcher = {
58
+ getSessionId: vi.fn().mockReturnValue("current-session"),
59
+ ensureForTask: vi.fn().mockResolvedValue("current-session"),
60
+ };
61
+ // Mock console.error to avoid cluttering test output
62
+ vi.spyOn(console, "error").mockImplementation(() => { });
63
+ });
64
+ it("should do nothing if no tasks are found", async () => {
65
+ mockMcpBridge.callTool.mockResolvedValue({
66
+ isError: false,
67
+ content: [{ type: "text", text: "no pending tasks exist" }],
68
+ });
69
+ await checkForNextTask(mockMcpBridge, mockConnection, mockSessionSwitcher);
70
+ expect(mockMcpBridge.callTool).toHaveBeenCalledWith("getNextTask");
71
+ expect(mockConnection.prompt).not.toHaveBeenCalled();
72
+ });
73
+ it("should handle error from MCP bridge", async () => {
74
+ mockMcpBridge.callTool.mockResolvedValue({
75
+ isError: true,
76
+ content: "some error",
77
+ });
78
+ await checkForNextTask(mockMcpBridge, mockConnection, mockSessionSwitcher);
79
+ expect(mockMcpBridge.callTool).toHaveBeenCalledWith("getNextTask");
80
+ expect(mockConnection.prompt).not.toHaveBeenCalled();
81
+ });
82
+ it("should process task and recurse if task is found", async () => {
83
+ // First call returns a task with ID in text, second call returns no task
84
+ mockMcpBridge.callTool
85
+ .mockResolvedValueOnce({
86
+ isError: false,
87
+ content: [{ type: "text", text: "Task ID: T1\ndo something" }],
88
+ })
89
+ .mockResolvedValueOnce({
90
+ isError: false,
91
+ content: [{ type: "text", text: "no pending tasks exist" }],
92
+ });
93
+ await checkForNextTask(mockMcpBridge, mockConnection, mockSessionSwitcher);
94
+ expect(mockMcpBridge.callTool).toHaveBeenCalledTimes(2);
95
+ expect(mockSessionSwitcher.ensureForTask).toHaveBeenCalledWith("T1");
96
+ expect(mockConnection.prompt).toHaveBeenCalledWith({
97
+ sessionId: "current-session",
98
+ prompt: [{ type: "text", text: "Task ID: T1\ndo something" }],
99
+ });
100
+ });
101
+ it("should handle exceptions during execution", async () => {
102
+ mockMcpBridge.callTool.mockRejectedValue(new Error("network error"));
103
+ await checkForNextTask(mockMcpBridge, mockConnection, mockSessionSwitcher);
104
+ expect(console.error).toHaveBeenCalledWith(expect.stringContaining("Failed to check for next task"), expect.any(Error));
105
+ });
8
106
  });
9
107
  });
10
108
  //# sourceMappingURL=index.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAkB,MAAM,QAAQ,CAAC;AAG9D,8EAA8E;AAC9E,+EAA+E;AAE/E,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;IACrB,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,oEAAoE;QACpE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { extractTaskIdFromMeta, extractTaskIdFromText, } from "../taskIdentity.js";
3
+ describe("extractTaskIdFromMeta", () => {
4
+ it("returns undefined for non-objects", () => {
5
+ expect(extractTaskIdFromMeta(undefined)).toBeUndefined();
6
+ expect(extractTaskIdFromMeta(null)).toBeUndefined();
7
+ expect(extractTaskIdFromMeta("x")).toBeUndefined();
8
+ });
9
+ it("reads only chat_id", () => {
10
+ expect(extractTaskIdFromMeta({ chat_id: "chat-1" })).toBe("chat-1");
11
+ expect(extractTaskIdFromMeta({ taskId: "a" })).toBeUndefined();
12
+ expect(extractTaskIdFromMeta({ task_id: "b" })).toBeUndefined();
13
+ expect(extractTaskIdFromMeta({ id: "c" })).toBeUndefined();
14
+ });
15
+ it("ignores empty chat_id", () => {
16
+ expect(extractTaskIdFromMeta({ chat_id: "" })).toBeUndefined();
17
+ });
18
+ });
19
+ describe("extractTaskIdFromText", () => {
20
+ it("extracts from Task ID", () => {
21
+ expect(extractTaskIdFromText("Task ID: 0amnlepEi1J")).toBe("0amnlepEi1J");
22
+ expect(extractTaskIdFromText("task ID 0amnlepEi1J")).toBe("0amnlepEi1J");
23
+ expect(extractTaskIdFromText("TASK ID: abc-123")).toBe("abc-123");
24
+ });
25
+ it("extracts from Response to task", () => {
26
+ expect(extractTaskIdFromText("Response to task 0amnlepEi1J")).toBe("0amnlepEi1J");
27
+ expect(extractTaskIdFromText("response to task: xyz_789")).toBe("xyz_789");
28
+ });
29
+ it("extracts from task keyword", () => {
30
+ expect(extractTaskIdFromText("task 0amnlepEi1J")).toBe("0amnlepEi1J");
31
+ expect(extractTaskIdFromText("Working on task abc")).toBe("abc");
32
+ });
33
+ it("returns undefined if no match", () => {
34
+ expect(extractTaskIdFromText("Hello world")).toBeUndefined();
35
+ expect(extractTaskIdFromText("")).toBeUndefined();
36
+ });
37
+ });
38
+ //# sourceMappingURL=taskIdentity.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taskIdentity.test.js","sourceRoot":"","sources":["../../src/__tests__/taskIdentity.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACzD,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACpD,MAAM,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,qBAAqB,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpE,MAAM,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAC/D,MAAM,CAAC,qBAAqB,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAChE,MAAM,CAAC,qBAAqB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,CAAC,qBAAqB,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,CAAC,qBAAqB,CAAC,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC1E,MAAM,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACzE,MAAM,CAAC,qBAAqB,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,qBAAqB,CAAC,8BAA8B,CAAC,CAAC,CAAC,IAAI,CAChE,aAAa,CACd,CAAC;QACF,MAAM,CAAC,qBAAqB,CAAC,2BAA2B,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,qBAAqB,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACtE,MAAM,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,qBAAqB,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAC7D,MAAM,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACpD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/dist/index.js CHANGED
@@ -7,18 +7,41 @@
7
7
  */
8
8
  import { spawn } from "node:child_process";
9
9
  import { Writable, Readable } from "node:stream";
10
+ import { readFileSync } from "node:fs";
10
11
  import * as acp from "@agentclientprotocol/sdk";
12
+ const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
11
13
  import { loadMcpConfig, pickAgentrqServer } from "./config.js";
12
14
  import { MCPBridge } from "./mcpClient.js";
13
15
  import { AgentRQACPClient } from "./acpClient.js";
16
+ import { extractTaskIdFromMeta, extractTaskIdFromText, } from "./taskIdentity.js";
17
+ export function createAcpSessionSwitcher(connection, params, initialSessionId) {
18
+ let sessionId = initialSessionId;
19
+ let activeTaskId = undefined;
20
+ return {
21
+ getSessionId() {
22
+ return sessionId;
23
+ },
24
+ async ensureForTask(taskId) {
25
+ if (taskId === activeTaskId) {
26
+ return sessionId;
27
+ }
28
+ const next = await connection.newSession(params);
29
+ sessionId = next.sessionId;
30
+ activeTaskId = taskId;
31
+ console.error(`[acp] New ACP session for task ${taskId ?? "anonymous"} (MCP connection unchanged): ${sessionId}`);
32
+ return sessionId;
33
+ },
34
+ };
35
+ }
14
36
  async function main() {
37
+ console.log(`Starting [acp-gateway] ${pkg.name} v${pkg.version}`);
15
38
  const args = process.argv.slice(2);
16
39
  // Find where the command starts (after -- if provided, or just all args)
17
40
  const cmdStartIndex = args.indexOf("--");
18
41
  const acpCmdArgs = cmdStartIndex !== -1 ? args.slice(cmdStartIndex + 1) : args;
19
42
  if (acpCmdArgs.length === 0) {
20
- console.error("Usage: acp-gateway -- <acp-server-command> [args...]");
21
- console.error("Example: acp-gateway -- gemini --acp");
43
+ console.log("Usage: acp-gateway -- <acp-server-command> [args...]");
44
+ console.log("Example: acp-gateway -- gemini --acp");
22
45
  process.exit(1);
23
46
  }
24
47
  // 1. Load MCP Config
@@ -55,7 +78,7 @@ async function main() {
55
78
  // 6. Create ACP Session
56
79
  // We pass our agentrq MCP server to the agent so it can use our tools directly.
57
80
  // The McpServer object must follow the ACP protocol schema (type, name, url, headers).
58
- const sessionResult = await connection.newSession({
81
+ const newSessionParams = {
59
82
  cwd: process.cwd(),
60
83
  mcpServers: [
61
84
  {
@@ -65,15 +88,18 @@ async function main() {
65
88
  headers: [],
66
89
  },
67
90
  ],
68
- });
69
- const sessionId = sessionResult.sessionId;
70
- console.error(`[acp] Created session: ${sessionId}`);
91
+ };
92
+ const sessionResult = await connection.newSession(newSessionParams);
93
+ const sessionSwitcher = createAcpSessionSwitcher(connection, newSessionParams, sessionResult.sessionId);
94
+ console.error(`[acp] Created session: ${sessionSwitcher.getSessionId()}`);
71
95
  // Bridge: MCP -> ACP
72
96
  // When the MCP server sends a notification to 'notifications/claude/channel',
73
97
  // it contains a new task content.
74
- mcpBridge.on("task", async ({ content }) => {
98
+ mcpBridge.on("task", async ({ content, meta }) => {
75
99
  console.error("\n[bridge] Incoming task from MCP server. Forwarding to ACP agent...");
76
100
  try {
101
+ const taskId = extractTaskIdFromMeta(meta);
102
+ const sessionId = await sessionSwitcher.ensureForTask(taskId);
77
103
  const result = await connection.prompt({
78
104
  sessionId,
79
105
  prompt: [{ type: "text", text: content }],
@@ -85,7 +111,7 @@ async function main() {
85
111
  }
86
112
  });
87
113
  // Initial check for a pending task
88
- await checkForNextTask(mcpBridge, connection, sessionId);
114
+ await checkForNextTask(mcpBridge, connection, sessionSwitcher);
89
115
  // Keep the process alive
90
116
  await new Promise(() => { });
91
117
  }
@@ -102,7 +128,7 @@ async function main() {
102
128
  * Checks for the next pending task using the 'getNextTask' tool on the MCP server.
103
129
  * If found, sends it to the ACP agent.
104
130
  */
105
- async function checkForNextTask(mcpBridge, connection, sessionId) {
131
+ export async function checkForNextTask(mcpBridge, connection, sessionSwitcher) {
106
132
  console.error("[bridge] Checking for next task via MCP server...");
107
133
  try {
108
134
  const result = await mcpBridge.callTool("getNextTask");
@@ -115,14 +141,17 @@ async function checkForNextTask(mcpBridge, connection, sessionId) {
115
141
  if (content &&
116
142
  content.text &&
117
143
  !content.text.includes("no pending tasks exist")) {
118
- console.error(`[bridge] Found task: "${content.text.slice(0, 50).replace(/\n/g, " ")}..."`);
144
+ const text = content.text;
145
+ console.error(`[bridge] Found task: "${text.slice(0, 50).replace(/\n/g, " ")}..."`);
146
+ const taskId = extractTaskIdFromText(text);
147
+ const sessionId = await sessionSwitcher.ensureForTask(taskId);
119
148
  const promptResult = await connection.prompt({
120
149
  sessionId,
121
- prompt: [{ type: "text", text: content.text }],
150
+ prompt: [{ type: "text", text }],
122
151
  });
123
152
  console.error(`\n[acp] Agent completed with: ${promptResult.stopReason}`);
124
153
  // Recursively check for next task
125
- await checkForNextTask(mcpBridge, connection, sessionId);
154
+ await checkForNextTask(mcpBridge, connection, sessionSwitcher);
126
155
  }
127
156
  else {
128
157
  console.error("[bridge] No pending tasks available.");
@@ -132,8 +161,10 @@ async function checkForNextTask(mcpBridge, connection, sessionId) {
132
161
  console.error("[bridge] Failed to check for next task:", err);
133
162
  }
134
163
  }
135
- main().catch((err) => {
136
- console.error("[fatal]", err);
137
- process.exit(1);
138
- });
164
+ if (process.env.NODE_ENV !== "test") {
165
+ main().catch((err) => {
166
+ console.error("[fatal]", err);
167
+ process.exit(1);
168
+ });
169
+ }
139
170
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,yEAAyE;IACzE,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,UAAU,GACd,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE9D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;QACtE,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,qBAAqB;IACrB,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAChC,MAAM,aAAa,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAEjD,2BAA2B;IAC3B,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,aAAa,CAAC,CAAC;IAC/C,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC;IAE1B,gCAAgC;IAChC,MAAM,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,UAAU,CAAC;IACrC,OAAO,CAAC,KAAK,CAAC,yBAAyB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEnE,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE;QACvC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;QAClC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,aAAa,CAAC,GAAG,EAAE;KAC9C,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,KAAM,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAC3B,YAAY,CAAC,MAAO,CACS,CAAC;IAEhC,2BAA2B;IAC3B,MAAM,SAAS,GAAG,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,oBAAoB,CAC7C,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,EACrB,MAAM,CACP,CAAC;IAEF,IAAI,CAAC;QACH,+BAA+B;QAC/B,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC;YAC7C,eAAe,EAAE,GAAG,CAAC,gBAAgB;YACrC,kBAAkB,EAAE;gBAClB,EAAE,EAAE;oBACF,YAAY,EAAE,IAAI;oBAClB,aAAa,EAAE,IAAI;iBACpB;aACF;SACF,CAAC,CAAC;QAEH,OAAO,CAAC,KAAK,CACX,uCAAuC,UAAU,CAAC,eAAe,GAAG,CACrE,CAAC;QAEF,wBAAwB;QACxB,gFAAgF;QAChF,uFAAuF;QACvF,MAAM,aAAa,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC;YAChD,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;YAClB,UAAU,EAAE;gBACV;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,aAAa,CAAC,IAAI;oBACxB,GAAG,EAAE,aAAa,CAAC,GAAI;oBACvB,OAAO,EAAE,EAAE;iBACZ;aACF;SACF,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC;QAC1C,OAAO,CAAC,KAAK,CAAC,0BAA0B,SAAS,EAAE,CAAC,CAAC;QAErD,qBAAqB;QACrB,8EAA8E;QAC9E,kCAAkC;QAClC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;YACzC,OAAO,CAAC,KAAK,CACX,sEAAsE,CACvE,CAAC;YACF,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC;oBACrC,SAAS;oBACT,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;iBAC1C,CAAC,CAAC;gBAEH,OAAO,CAAC,KAAK,CACX,yCAAyC,MAAM,CAAC,UAAU,EAAE,CAC7D,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,GAAG,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,mCAAmC;QACnC,MAAM,gBAAgB,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;QAEzD,yBAAyB;QACzB,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,IAAI,EAAE,CAAC;QACpB,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,gBAAgB,CAC7B,SAAoB,EACpB,UAAoC,EACpC,SAAiB;IAEjB,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACnE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAEvD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YAChE,OAAO;QACT,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,CAAC,OAG1B,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAmC,CAAC;QAClE,IACE,OAAO;YACP,OAAO,CAAC,IAAI;YACZ,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAChD,CAAC;YACD,OAAO,CAAC,KAAK,CACX,yBAAyB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAC7E,CAAC;YAEF,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC;gBAC3C,SAAS;gBACT,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;aAC/C,CAAC,CAAC;YAEH,OAAO,CAAC,KAAK,CAAC,iCAAiC,YAAY,CAAC,UAAU,EAAE,CAAC,CAAC;YAE1E,kCAAkC;YAClC,MAAM,gBAAgB,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;QAC3D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,GAAG,CAAC,CAAC;IAChE,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC9B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Task identity from MCP channel `meta` for ACP session switching (agentrq `chat_id`).
3
+ */
4
+ /** Task identity from `notifications/claude/channel` `meta` (agentrq uses `chat_id`). */
5
+ export function extractTaskIdFromMeta(meta) {
6
+ if (!meta || typeof meta !== "object")
7
+ return undefined;
8
+ const m = meta;
9
+ if (typeof m.chat_id === "string" && m.chat_id.length > 0)
10
+ return m.chat_id;
11
+ return undefined;
12
+ }
13
+ /** Try to extract taskId from text content as a fallback. */
14
+ export function extractTaskIdFromText(text) {
15
+ // Try to match "Task ID: <id>" or "Response to task <id>" or just "task <id>"
16
+ const patterns = [
17
+ /Task ID[:\s]+([a-zA-Z0-9_-]+)/i,
18
+ /Response to task[:\s]+([a-zA-Z0-9_-]+)/i,
19
+ /task[:\s]+([a-zA-Z0-9_-]+)/i,
20
+ ];
21
+ for (const pattern of patterns) {
22
+ const match = text.match(pattern);
23
+ if (match && match[1])
24
+ return match[1];
25
+ }
26
+ return undefined;
27
+ }
28
+ //# sourceMappingURL=taskIdentity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taskIdentity.js","sourceRoot":"","sources":["../src/taskIdentity.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,yFAAyF;AACzF,MAAM,UAAU,qBAAqB,CAAC,IAAa;IACjD,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACxD,MAAM,CAAC,GAAG,IAA+B,CAAC;IAC1C,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC,OAAO,CAAC;IAC5E,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,8EAA8E;IAC9E,MAAM,QAAQ,GAAG;QACf,gCAAgC;QAChC,yCAAyC;QACzC,6BAA6B;KAC9B,CAAC;IACF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentrq/acp-gateway",
3
- "version": "0.1.4",
3
+ "version": "0.1.8",
4
4
  "description": "ACP+MCP bridge CLI for agentrq workspaces",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -15,6 +15,7 @@
15
15
  "dev": "tsx src/index.ts",
16
16
  "typecheck": "tsc --noEmit",
17
17
  "test": "vitest run",
18
+ "test:coverage": "vitest run --coverage",
18
19
  "prepare": "npm run build",
19
20
  "prepublishOnly": "npm run build"
20
21
  },