@agentrq/acp-gateway 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,180 @@
1
+ # @agentrq/acp-gateway
2
+
3
+ ACP+MCP Bridge brings Experimentation Claude Notification Channels feature to all agents that supports Agent Client Protocol.
4
+
5
+ > [!WARNING]
6
+ > **Pre-Alpha**: This project is in early development. APIs, configurations, and behaviors are subject to change without notice.
7
+ >
8
+ > **Note**: `claude/notifications` is an experimental feature of Claude Code. `@agentrq/acp-gateway` extends this same capability to any `--acp` compatible agent (e.g., Gemini CLI).
9
+
10
+ ## Overview
11
+
12
+ `@agentrq/acp-gateway` bridges the [Agent Client Protocol (ACP)](https://agentclientprotocol.com) with the [Model Context Protocol (MCP)](https://modelcontextprotocol.io) to connect ACP-compatible AI agents (e.g., Gemini) to an agentrq MCP server.
13
+
14
+ It automates task execution by:
15
+
16
+ 1. Loading your workspace's `.mcp.json` configuration.
17
+ 2. Connecting to the agentrq MCP server.
18
+ 3. Spawning an ACP-compatible agent subprocess.
19
+ 4. Bridging MCP notifications (tasks, permission requests) to ACP prompts and vice versa.
20
+ 5. Providing file read/write capabilities through the ACP protocol.
21
+ 6. Auto-reconnecting the MCP transport on disconnection.
22
+
23
+ ## Prerequisites
24
+
25
+ - **Node.js** >= 24
26
+ - **npm** or **yarn**
27
+ - An [ACP-compatible agent](https://agentclientprotocol.com) (e.g., Gemini CLI)
28
+ - An [agentrq](https://github.com/agentrq/agentrq) workspace with an HTTP MCP server
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ cd acp-gateway
34
+ npm install
35
+ ```
36
+
37
+ To use globally:
38
+
39
+ ```bash
40
+ npm install -g @agentrq/acp-gateway
41
+ ```
42
+
43
+ ## Usage
44
+
45
+ ### Quick Start
46
+
47
+ Run `acp-gateway` from your agentrq workspace root (the directory containing `.mcp.json`):
48
+
49
+ ```bash
50
+ # From workspace root
51
+ acp-gateway -- gemini --acp
52
+ ```
53
+
54
+ Or with a custom command:
55
+
56
+ ```bash
57
+ acp-gateway -- your-acp-agent --flag1 --flag2
58
+ ```
59
+
60
+ ### Configuration
61
+
62
+ `acp-gateway` searches for `.mcp.json` starting in the current working directory and up to 3 parent directories.
63
+
64
+ Example `.mcp.json`:
65
+
66
+ ```json
67
+ {
68
+ "mcpServers": {
69
+ "agentrq": {
70
+ "type": "http",
71
+ "url": "http://localhost:3000/mcp"
72
+ }
73
+ }
74
+ }
75
+ ```
76
+
77
+ `acp-gateway` prefers servers with `agentrq` in the name; it falls back to the first HTTP server with a `url`.
78
+
79
+ ## How It Works
80
+
81
+ ```
82
+ ┌─────────────┐ ACP (JSON-RPC) ┌──────────────────┐
83
+ │ ACP Agent │ ◄─────────────────────────► │ │
84
+ │ (Gemini) │ │ acp-gateway │
85
+ └─────────────┘ │ │
86
+ │ MCP Bridge │
87
+ │ │
88
+ ┌─────────────────────────────────────────────┤ │
89
+ │ │ │
90
+ │ │ │
91
+ │ ▼ │
92
+ │ ┌──────────────────────────┐ │
93
+ │ │ agentrq MCP Server │ │
94
+ │ │ (HTTP / StreamableHTTP) │ │
95
+ │ └──────────────────────────┘ │
96
+ └────────────────────────────────────────────────────────────────┘
97
+ ```
98
+
99
+ ### Flow
100
+
101
+ 1. **Config Loading** — Reads `.mcp.json` to find the agentrq MCP server.
102
+ 2. **MCP Connection** — Establishes a `StreamableHTTPClientTransport` to the MCP server with automatic retry and reconnection.
103
+ 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.
106
+ 6. **Permission Bridge** — Permission requests from the ACP agent are forwarded to the MCP server; verdicts are sent back.
107
+ 7. **Recursive Execution** — After each task completes, `acp-gateway` checks for the next pending task automatically.
108
+
109
+ ### Key Components
110
+
111
+ | File | Description |
112
+ |---|---|
113
+ | `src/index.ts` | Entry point; orchestrates config loading, MCP connection, agent spawning, and ACP session lifecycle. |
114
+ | `src/acpClient.ts` | Implements the ACP `Client` interface — routes permission requests, handles session updates, and provides file operations. |
115
+ | `src/mcpClient.ts` | `EventEmitter`-based MCP client with auto-reconnection, notification handling, and tool call dispatch. |
116
+ | `src/config.ts` | Parses `.mcp.json` from the current directory tree up to 3 levels deep. |
117
+
118
+ ## Development
119
+
120
+ ### Scripts
121
+
122
+ ```bash
123
+ # Run in development mode
124
+ npm run dev
125
+
126
+ # Type-check
127
+ npm run typecheck
128
+
129
+ # Run tests
130
+ npm test
131
+ ```
132
+
133
+ ### Project Structure
134
+
135
+ ```
136
+ acp-gateway/
137
+ ├── src/
138
+ │ ├── acpClient.ts # ACP Client implementation
139
+ │ ├── config.ts # .mcp.json loader
140
+ │ ├── index.ts # Entry point & orchestrator
141
+ │ ├── mcpClient.ts # MCP Bridge with auto-reconnect
142
+ │ └── __tests__/ # Unit tests
143
+ ├── package.json
144
+ └── tsconfig.json
145
+ ```
146
+
147
+ ### Architecture Notes
148
+
149
+ - **Auto-reconnection**: The MCP transport auto-reconnects on disconnection with exponential backoff (1s → 30s max).
150
+ - **Notification-driven tasks**: The MCP server pushes task content via `notifications/claude/channel`; `acp-gateway` reacts immediately.
151
+ - **Permission flow**: ACP agent requests permission → `acp-gateway` forwards to MCP server → waits for verdict → resolves the ACP permission.
152
+ - **File I/O**: `readTextFile` / `writeTextFile` are proxied directly to the filesystem; paths are resolved relative to `process.cwd()`.
153
+
154
+ ## Contributing
155
+
156
+ Contributions are welcome! Please feel free to submit pull requests or open issues.
157
+
158
+ 1. Fork the repository
159
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
160
+ 3. Commit your changes (`git commit -m 'Add: amazing feature'`)
161
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
162
+ 5. Open a Pull Request
163
+
164
+ ## Contributing License
165
+
166
+ By contributing to this project, you agree that your contributions will be licensed under the project's Apache License 2.0.
167
+
168
+ ---
169
+
170
+ ## License
171
+
172
+ Apache License 2.0
173
+
174
+ Copyright (c) 2026 Contextual, Inc.
175
+
176
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
177
+
178
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
179
+
180
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,258 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { AgentRQACPClient } from "../acpClient.js";
3
+ import * as fs from "node:fs/promises";
4
+ import * as path from "node:path";
5
+ // Mock dependencies
6
+ vi.mock("node:fs/promises");
7
+ vi.mock("node:path");
8
+ describe("AgentRQACPClient", () => {
9
+ let mcpBridge;
10
+ let client;
11
+ beforeEach(() => {
12
+ vi.clearAllMocks();
13
+ mcpBridge = {
14
+ getSessionId: vi.fn().mockReturnValue("test-session"),
15
+ sendNotification: vi.fn().mockResolvedValue(undefined),
16
+ on: vi.fn(),
17
+ off: vi.fn(),
18
+ };
19
+ client = new AgentRQACPClient(mcpBridge);
20
+ });
21
+ describe("requestPermission", () => {
22
+ it("should send a notification and wait for a verdict", async () => {
23
+ const params = {
24
+ toolCall: {
25
+ toolCallId: "req-123",
26
+ title: "Test Tool",
27
+ rawInput: { foo: "bar" },
28
+ },
29
+ options: [
30
+ { optionId: "opt-1", kind: "allow", name: "Allow Once" },
31
+ { optionId: "opt-2", kind: "deny", name: "Deny" },
32
+ ],
33
+ };
34
+ mcpBridge.on.mockImplementation((event, handler) => {
35
+ if (event === "verdict") {
36
+ setTimeout(() => handler({ requestId: "req-123", behavior: "allow" }), 10);
37
+ }
38
+ });
39
+ const response = await client.requestPermission(params);
40
+ expect(response.outcome.optionId).toBe("opt-1");
41
+ });
42
+ it("should auto-allow tools matching agentrq-<11 chars> pattern in title", async () => {
43
+ const params = {
44
+ toolCall: {
45
+ toolCallId: "req-123",
46
+ title: "updateTaskStatus (agentrq-0aleR6CbZBp MCP Server)",
47
+ },
48
+ options: [
49
+ { optionId: "opt-1", kind: "allow", name: "Allow" },
50
+ { optionId: "opt-2", kind: "deny", name: "Deny" },
51
+ ],
52
+ };
53
+ const response = await client.requestPermission(params);
54
+ expect(mcpBridge.sendNotification).not.toHaveBeenCalled();
55
+ expect(response.outcome.outcome).toBe("selected");
56
+ expect(response.outcome.optionId).toBe("opt-1");
57
+ });
58
+ it("should handle missing tool title", async () => {
59
+ const consoleSpy = vi
60
+ .spyOn(console, "error")
61
+ .mockImplementation(() => { });
62
+ const params = {
63
+ toolCall: { toolCallId: "req-123" },
64
+ options: [{ optionId: "opt-1", kind: "allow", name: "Allow" }],
65
+ };
66
+ mcpBridge.on.mockImplementation((event, handler) => {
67
+ if (event === "verdict") {
68
+ setTimeout(() => handler({ requestId: "req-123", behavior: "allow" }), 10);
69
+ }
70
+ });
71
+ const response = await client.requestPermission(params);
72
+ // Permission matching still works based on behavior, independent of title presence
73
+ expect(response.outcome.optionId).toBe("opt-1");
74
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Unknown Tool"));
75
+ consoleSpy.mockRestore();
76
+ });
77
+ it("should handle missing rawInput and missing session ID", async () => {
78
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
79
+ mcpBridge.getSessionId.mockReturnValue(undefined);
80
+ const params = {
81
+ toolCall: { toolCallId: "req-123", title: "Test Tool" },
82
+ options: [{ optionId: "opt-1", kind: "allow", name: "Allow" }],
83
+ };
84
+ mcpBridge.on.mockImplementation((event, handler) => {
85
+ if (event === "verdict") {
86
+ setTimeout(() => handler({ requestId: "req-123", behavior: "allow" }), 10);
87
+ }
88
+ });
89
+ const response = await client.requestPermission(params);
90
+ expect(response.outcome.optionId).toBe("opt-1");
91
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Bridge Session ID: unknown"));
92
+ // Verify payload had empty object for rawInput
93
+ expect(mcpBridge.sendNotification).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({ input_preview: "{}" }));
94
+ consoleSpy.mockRestore();
95
+ });
96
+ it("should match options with 'yes' or 'approve'", async () => {
97
+ const params = {
98
+ toolCall: { toolCallId: "req-123" },
99
+ options: [
100
+ { optionId: "opt-1", kind: "other", name: "Yes, proceed" },
101
+ { optionId: "opt-2", kind: "other", name: "No" },
102
+ ],
103
+ };
104
+ mcpBridge.on.mockImplementation((event, handler) => {
105
+ if (event === "verdict") {
106
+ setTimeout(() => handler({ requestId: "req-123", behavior: "allow" }), 10);
107
+ }
108
+ });
109
+ const response = await client.requestPermission(params);
110
+ expect(response.outcome.optionId).toBe("opt-1");
111
+ });
112
+ it("should match options with 'deny' in the name", async () => {
113
+ const params = {
114
+ toolCall: { toolCallId: "req-123" },
115
+ options: [
116
+ { optionId: "opt-1", kind: "allow", name: "Allow" },
117
+ { optionId: "opt-2", kind: "other", name: "Deny this" },
118
+ ],
119
+ };
120
+ mcpBridge.on.mockImplementation((event, handler) => {
121
+ if (event === "verdict") {
122
+ setTimeout(() => handler({ requestId: "req-123", behavior: "deny" }), 10);
123
+ }
124
+ });
125
+ const response = await client.requestPermission(params);
126
+ expect(response.outcome.optionId).toBe("opt-2");
127
+ });
128
+ it("should fall back to first option if 'deny' verdict has no specific match", async () => {
129
+ const params = {
130
+ toolCall: { toolCallId: "req-123" },
131
+ options: [
132
+ { optionId: "opt-1", kind: "other", name: "Other 1" },
133
+ { optionId: "opt-2", kind: "other", name: "Other 2" },
134
+ ],
135
+ };
136
+ mcpBridge.on.mockImplementation((event, handler) => {
137
+ if (event === "verdict") {
138
+ setTimeout(() => handler({ requestId: "req-123", behavior: "deny" }), 10);
139
+ }
140
+ });
141
+ const response = await client.requestPermission(params);
142
+ expect(response.outcome.optionId).toBe("opt-1");
143
+ });
144
+ it("should fall back to first option if no match", async () => {
145
+ const params = {
146
+ toolCall: { toolCallId: "req-123" },
147
+ options: [{ optionId: "opt-default", kind: "other", name: "Maybe" }],
148
+ };
149
+ mcpBridge.on.mockImplementation((event, handler) => {
150
+ if (event === "verdict") {
151
+ setTimeout(() => handler({ requestId: "req-123", behavior: "allow" }), 10);
152
+ }
153
+ });
154
+ const response = await client.requestPermission(params);
155
+ expect(response.outcome.optionId).toBe("opt-default");
156
+ });
157
+ });
158
+ describe("sessionUpdate", () => {
159
+ it("should write text chunks to stdout", async () => {
160
+ const writeSpy = vi
161
+ .spyOn(process.stdout, "write")
162
+ .mockImplementation(() => true);
163
+ const params = {
164
+ update: {
165
+ sessionUpdate: "agent_message_chunk",
166
+ content: { type: "text", text: "hello" },
167
+ },
168
+ };
169
+ await client.sessionUpdate(params);
170
+ expect(writeSpy).toHaveBeenCalledWith("hello");
171
+ writeSpy.mockRestore();
172
+ });
173
+ it("should ignore non-text chunks", async () => {
174
+ const writeSpy = vi
175
+ .spyOn(process.stdout, "write")
176
+ .mockImplementation(() => true);
177
+ const params = {
178
+ update: {
179
+ sessionUpdate: "agent_message_chunk",
180
+ content: { type: "other", text: "ignored" },
181
+ },
182
+ };
183
+ await client.sessionUpdate(params);
184
+ expect(writeSpy).not.toHaveBeenCalled();
185
+ writeSpy.mockRestore();
186
+ });
187
+ it("should log tool calls", async () => {
188
+ const consoleSpy = vi
189
+ .spyOn(console, "error")
190
+ .mockImplementation(() => { });
191
+ const params = {
192
+ update: {
193
+ sessionUpdate: "tool_call",
194
+ title: "test-tool",
195
+ status: "pending",
196
+ },
197
+ };
198
+ await client.sessionUpdate(params);
199
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Tool call: test-tool (pending)"));
200
+ consoleSpy.mockRestore();
201
+ });
202
+ it("should skip logging for auto-allowed tool calls", async () => {
203
+ const consoleSpy = vi
204
+ .spyOn(console, "error")
205
+ .mockImplementation(() => { });
206
+ const params = {
207
+ update: {
208
+ sessionUpdate: "tool_call",
209
+ title: "updateTaskStatus (agentrq-0aleR6CbZBp MCP Server)",
210
+ status: "pending",
211
+ },
212
+ };
213
+ await client.sessionUpdate(params);
214
+ expect(consoleSpy).not.toHaveBeenCalled();
215
+ consoleSpy.mockRestore();
216
+ });
217
+ it("should handle unknown update types", async () => {
218
+ const params = { update: { sessionUpdate: "unknown" } };
219
+ await expect(client.sessionUpdate(params)).resolves.toBeUndefined();
220
+ });
221
+ });
222
+ describe("file operations", () => {
223
+ it("should read text files", async () => {
224
+ vi.mocked(path.resolve).mockReturnValue("/mock/path/file.txt");
225
+ vi.mocked(fs.readFile).mockResolvedValue("file content");
226
+ const response = await client.readTextFile({
227
+ path: "file.txt",
228
+ sessionId: "test-session",
229
+ });
230
+ expect(response.content).toBe("file content");
231
+ });
232
+ it("should throw error when reading file fails", async () => {
233
+ vi.mocked(fs.readFile).mockRejectedValue(new Error("read failed"));
234
+ await expect(client.readTextFile({ path: "fail.txt", sessionId: "test-session" })).rejects.toThrow("read failed");
235
+ });
236
+ it("should write text files", async () => {
237
+ vi.mocked(path.resolve).mockReturnValue("/mock/path/file.txt");
238
+ vi.mocked(path.dirname).mockReturnValue("/mock/path");
239
+ vi.mocked(fs.mkdir).mockResolvedValue(undefined);
240
+ vi.mocked(fs.writeFile).mockResolvedValue(undefined);
241
+ await client.writeTextFile({
242
+ path: "file.txt",
243
+ content: "new content",
244
+ sessionId: "test-session",
245
+ });
246
+ expect(fs.writeFile).toHaveBeenCalledWith("/mock/path/file.txt", "new content", "utf8");
247
+ });
248
+ it("should throw error when writing file fails", async () => {
249
+ vi.mocked(fs.writeFile).mockRejectedValue(new Error("write failed"));
250
+ await expect(client.writeTextFile({
251
+ path: "fail.txt",
252
+ content: "content",
253
+ sessionId: "test-session",
254
+ })).rejects.toThrow("write failed");
255
+ });
256
+ });
257
+ });
258
+ //# sourceMappingURL=acpClient.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acpClient.test.js","sourceRoot":"","sources":["../../src/__tests__/acpClient.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { loadMcpConfig, pickAgentrqServer } from "../config.js";
3
+ import { readFileSync } from "node:fs";
4
+ import { resolve } from "node:path";
5
+ vi.mock("node:fs");
6
+ vi.mock("node:path");
7
+ describe("config", () => {
8
+ beforeEach(() => {
9
+ vi.clearAllMocks();
10
+ });
11
+ describe("loadMcpConfig", () => {
12
+ it("should parse .mcp.json and return server configs", () => {
13
+ vi.mocked(resolve).mockImplementation((...args) => args.join("/"));
14
+ vi.mocked(readFileSync).mockReturnValue(JSON.stringify({
15
+ mcpServers: {
16
+ "agentrq": {
17
+ type: "http",
18
+ url: "http://localhost:8080"
19
+ }
20
+ }
21
+ }));
22
+ const configs = loadMcpConfig("/dummy");
23
+ expect(configs).toHaveLength(1);
24
+ expect(configs[0]).toEqual({
25
+ name: "agentrq",
26
+ type: "http",
27
+ url: "http://localhost:8080",
28
+ args: undefined,
29
+ command: undefined,
30
+ env: undefined,
31
+ });
32
+ });
33
+ it("should handle missing mcpServers in JSON", () => {
34
+ vi.mocked(resolve).mockImplementation((...args) => args.join("/"));
35
+ vi.mocked(readFileSync).mockReturnValue(JSON.stringify({}));
36
+ expect(() => loadMcpConfig("/dummy")).toThrow("Could not find .mcp.json");
37
+ });
38
+ it("should infer type based on url presence", () => {
39
+ vi.mocked(resolve).mockImplementation((...args) => args.join("/"));
40
+ vi.mocked(readFileSync).mockReturnValue(JSON.stringify({
41
+ mcpServers: {
42
+ "http-server": { url: "http://example.com" },
43
+ "stdio-server": { command: "node", args: ["server.js"] }
44
+ }
45
+ }));
46
+ const configs = loadMcpConfig("/dummy");
47
+ expect(configs).toHaveLength(2);
48
+ expect(configs[0].type).toBe("http");
49
+ expect(configs[1].type).toBe("stdio");
50
+ });
51
+ it("should throw error if no .mcp.json is found", () => {
52
+ vi.mocked(readFileSync).mockImplementation(() => { throw new Error("not found"); });
53
+ expect(() => loadMcpConfig("/dummy")).toThrow("Could not find .mcp.json");
54
+ });
55
+ });
56
+ describe("pickAgentrqServer", () => {
57
+ it("should prefer server with agentrq in its name", () => {
58
+ const servers = [
59
+ { name: "other", type: "http", url: "http://other" },
60
+ { name: "my-agentrq-server", type: "http", url: "http://agentrq" }
61
+ ];
62
+ const picked = pickAgentrqServer(servers);
63
+ expect(picked.name).toBe("my-agentrq-server");
64
+ });
65
+ it("should fall back to first HTTP server", () => {
66
+ const servers = [
67
+ { name: "other", type: "http", url: "http://other" }
68
+ ];
69
+ const picked = pickAgentrqServer(servers);
70
+ expect(picked.name).toBe("other");
71
+ });
72
+ it("should throw error if no HTTP server found", () => {
73
+ const servers = [
74
+ { name: "stdio-server", type: "stdio", command: "ls" }
75
+ ];
76
+ expect(() => pickAgentrqServer(servers)).toThrow("No HTTP MCP server found");
77
+ });
78
+ });
79
+ });
80
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/__tests__/config.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
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.
4
+ 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);
8
+ });
9
+ });
10
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +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"}