macro-agent 0.0.14 → 0.0.16
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/settings.local.json +59 -0
- package/dist/acp/index.d.ts +1 -1
- package/dist/acp/index.d.ts.map +1 -1
- package/dist/acp/index.js.map +1 -1
- package/dist/acp/macro-agent.d.ts +21 -0
- package/dist/acp/macro-agent.d.ts.map +1 -1
- package/dist/acp/macro-agent.js +182 -0
- package/dist/acp/macro-agent.js.map +1 -1
- package/dist/acp/types.d.ts +31 -2
- package/dist/acp/types.d.ts.map +1 -1
- package/dist/acp/types.js.map +1 -1
- package/dist/agent/agent-manager.d.ts.map +1 -1
- package/dist/agent/agent-manager.js +10 -4
- package/dist/agent/agent-manager.js.map +1 -1
- package/dist/cli/acp.d.ts +6 -0
- package/dist/cli/acp.d.ts.map +1 -1
- package/dist/cli/acp.js +16 -2
- package/dist/cli/acp.js.map +1 -1
- package/dist/map/adapter/acp-over-map.d.ts +5 -0
- package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
- package/dist/map/adapter/acp-over-map.js +47 -4
- package/dist/map/adapter/acp-over-map.js.map +1 -1
- package/dist/map/utils/address-translation.d.ts +99 -0
- package/dist/map/utils/address-translation.d.ts.map +1 -0
- package/dist/map/utils/address-translation.js +285 -0
- package/dist/map/utils/address-translation.js.map +1 -0
- package/dist/map/utils/index.d.ts +7 -0
- package/dist/map/utils/index.d.ts.map +1 -0
- package/dist/map/utils/index.js +7 -0
- package/dist/map/utils/index.js.map +1 -0
- package/dist/store/event-store.js +9 -2
- package/dist/store/event-store.js.map +1 -1
- package/dist/store/types/agents.d.ts +2 -0
- package/dist/store/types/agents.d.ts.map +1 -1
- package/package.json +4 -4
- package/references/acp-factory-ref/CHANGELOG.md +33 -0
- package/references/acp-factory-ref/LICENSE +21 -0
- package/references/acp-factory-ref/README.md +341 -0
- package/references/acp-factory-ref/package-lock.json +3102 -0
- package/references/acp-factory-ref/package.json +96 -0
- package/references/acp-factory-ref/python/CHANGELOG.md +33 -0
- package/references/acp-factory-ref/python/LICENSE +21 -0
- package/references/acp-factory-ref/python/Makefile +57 -0
- package/references/acp-factory-ref/python/README.md +253 -0
- package/references/acp-factory-ref/python/pyproject.toml +73 -0
- package/references/acp-factory-ref/python/tests/__init__.py +0 -0
- package/references/acp-factory-ref/python/tests/e2e/__init__.py +1 -0
- package/references/acp-factory-ref/python/tests/e2e/test_codex_e2e.py +349 -0
- package/references/acp-factory-ref/python/tests/e2e/test_gemini_e2e.py +165 -0
- package/references/acp-factory-ref/python/tests/e2e/test_opencode_e2e.py +296 -0
- package/references/acp-factory-ref/python/tests/test_client_handler.py +543 -0
- package/references/acp-factory-ref/python/tests/test_pushable.py +199 -0
- package/references/claude-code-acp/.github/workflows/ci.yml +45 -0
- package/references/claude-code-acp/.github/workflows/publish.yml +34 -0
- package/references/claude-code-acp/.prettierrc.json +4 -0
- package/references/claude-code-acp/CHANGELOG.md +249 -0
- package/references/claude-code-acp/LICENSE +222 -0
- package/references/claude-code-acp/README.md +53 -0
- package/references/claude-code-acp/docs/RELEASES.md +24 -0
- package/references/claude-code-acp/eslint.config.js +48 -0
- package/references/claude-code-acp/package-lock.json +4570 -0
- package/references/claude-code-acp/package.json +88 -0
- package/references/claude-code-acp/scripts/release.sh +119 -0
- package/references/claude-code-acp/src/acp-agent.ts +2079 -0
- package/references/claude-code-acp/src/index.ts +26 -0
- package/references/claude-code-acp/src/lib.ts +38 -0
- package/references/claude-code-acp/src/mcp-server.ts +911 -0
- package/references/claude-code-acp/src/settings.ts +522 -0
- package/references/claude-code-acp/src/tests/.claude/commands/quick-math.md +5 -0
- package/references/claude-code-acp/src/tests/.claude/commands/say-hello.md +6 -0
- package/references/claude-code-acp/src/tests/acp-agent-fork.test.ts +479 -0
- package/references/claude-code-acp/src/tests/acp-agent.test.ts +1502 -0
- package/references/claude-code-acp/src/tests/extract-lines.test.ts +103 -0
- package/references/claude-code-acp/src/tests/fork-session.test.ts +335 -0
- package/references/claude-code-acp/src/tests/replace-and-calculate-location.test.ts +334 -0
- package/references/claude-code-acp/src/tests/settings.test.ts +617 -0
- package/references/claude-code-acp/src/tests/skills-options.test.ts +187 -0
- package/references/claude-code-acp/src/tests/tools.test.ts +318 -0
- package/references/claude-code-acp/src/tests/typescript-declarations.test.ts +558 -0
- package/references/claude-code-acp/src/tools.ts +819 -0
- package/references/claude-code-acp/src/utils.ts +171 -0
- package/references/claude-code-acp/tsconfig.json +18 -0
- package/references/claude-code-acp/vitest.config.ts +19 -0
- package/references/multi-agent-protocol/.sudocode/issues.jsonl +111 -0
- package/references/multi-agent-protocol/.sudocode/specs.jsonl +13 -0
- package/references/multi-agent-protocol/LICENSE +21 -0
- package/references/multi-agent-protocol/README.md +113 -0
- package/references/multi-agent-protocol/docs/00-design-specification.md +496 -0
- package/references/multi-agent-protocol/docs/01-open-questions.md +1050 -0
- package/references/multi-agent-protocol/docs/02-wire-protocol.md +296 -0
- package/references/multi-agent-protocol/docs/03-streaming-semantics.md +252 -0
- package/references/multi-agent-protocol/docs/04-error-handling.md +231 -0
- package/references/multi-agent-protocol/docs/05-connection-model.md +244 -0
- package/references/multi-agent-protocol/docs/06-visibility-permissions.md +243 -0
- package/references/multi-agent-protocol/docs/07-federation.md +259 -0
- package/references/multi-agent-protocol/docs/08-macro-agent-migration.md +253 -0
- package/references/multi-agent-protocol/docs/09-authentication.md +680 -0
- package/references/multi-agent-protocol/docs/10-mail-protocol.md +553 -0
- package/references/multi-agent-protocol/docs/agent-iam-integration.md +877 -0
- package/references/multi-agent-protocol/docs/agentic-mesh-integration-draft.md +459 -0
- package/references/multi-agent-protocol/docs/git-transport-draft.md +251 -0
- package/references/multi-agent-protocol/docs-site/Gemfile +22 -0
- package/references/multi-agent-protocol/docs-site/README.md +82 -0
- package/references/multi-agent-protocol/docs-site/_config.yml +91 -0
- package/references/multi-agent-protocol/docs-site/_includes/head_custom.html +20 -0
- package/references/multi-agent-protocol/docs-site/_sass/color_schemes/map.scss +42 -0
- package/references/multi-agent-protocol/docs-site/_sass/custom/custom.scss +34 -0
- package/references/multi-agent-protocol/docs-site/examples/full-integration.md +510 -0
- package/references/multi-agent-protocol/docs-site/examples/index.md +138 -0
- package/references/multi-agent-protocol/docs-site/examples/simple-chat.md +282 -0
- package/references/multi-agent-protocol/docs-site/examples/task-queue.md +399 -0
- package/references/multi-agent-protocol/docs-site/getting-started/index.md +98 -0
- package/references/multi-agent-protocol/docs-site/getting-started/installation.md +219 -0
- package/references/multi-agent-protocol/docs-site/getting-started/overview.md +172 -0
- package/references/multi-agent-protocol/docs-site/getting-started/quickstart.md +237 -0
- package/references/multi-agent-protocol/docs-site/index.md +136 -0
- package/references/multi-agent-protocol/docs-site/protocol/authentication.md +391 -0
- package/references/multi-agent-protocol/docs-site/protocol/connection-model.md +376 -0
- package/references/multi-agent-protocol/docs-site/protocol/design.md +284 -0
- package/references/multi-agent-protocol/docs-site/protocol/error-handling.md +312 -0
- package/references/multi-agent-protocol/docs-site/protocol/federation.md +449 -0
- package/references/multi-agent-protocol/docs-site/protocol/index.md +129 -0
- package/references/multi-agent-protocol/docs-site/protocol/permissions.md +398 -0
- package/references/multi-agent-protocol/docs-site/protocol/streaming.md +353 -0
- package/references/multi-agent-protocol/docs-site/protocol/wire-protocol.md +369 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/agent.md +357 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/client.md +380 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/index.md +62 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/server.md +453 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/types.md +468 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/agent.md +375 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/authentication.md +405 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/client.md +352 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/index.md +89 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/server.md +360 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/testing.md +446 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/transports.md +363 -0
- package/references/multi-agent-protocol/docs-site/sdk/index.md +206 -0
- package/references/multi-agent-protocol/package-lock.json +3886 -0
- package/references/multi-agent-protocol/package.json +56 -0
- package/references/multi-agent-protocol/schema/meta.json +467 -0
- package/references/multi-agent-protocol/schema/schema.json +2558 -0
- package/src/acp/__tests__/history.test.ts +526 -0
- package/src/acp/__tests__/integration.test.ts +2 -1
- package/src/acp/index.ts +4 -0
- package/src/acp/macro-agent.ts +329 -85
- package/src/acp/types.ts +39 -2
- package/src/agent/__tests__/agent-manager.test.ts +67 -1
- package/src/agent/agent-manager.ts +10 -4
- package/src/cli/__tests__/stable-instance-id.test.ts +57 -0
- package/src/cli/acp.ts +17 -2
- package/src/map/adapter/acp-over-map.ts +57 -2
- package/src/store/event-store.ts +10 -3
- package/src/store/types/agents.ts +2 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { extractLinesWithByteLimit } from "../utils.js";
|
|
3
|
+
|
|
4
|
+
describe("extractLinesWithByteLimit", () => {
|
|
5
|
+
const simpleContent = "Line 1\nLine 2\nLine 3\nLine 4\nLine 5";
|
|
6
|
+
|
|
7
|
+
it("should extract all lines when under byte limit", () => {
|
|
8
|
+
const result = extractLinesWithByteLimit(simpleContent, 1000);
|
|
9
|
+
|
|
10
|
+
expect(result.content).toBe(simpleContent);
|
|
11
|
+
expect(result.wasLimited).toBe(false);
|
|
12
|
+
expect(result.linesRead).toBe(5);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("should limit output when exceeding byte limit", () => {
|
|
16
|
+
// Create content that will exceed byte limit
|
|
17
|
+
const longLine = "x".repeat(100);
|
|
18
|
+
const manyLines = Array(10).fill(longLine).join("\n");
|
|
19
|
+
|
|
20
|
+
const result = extractLinesWithByteLimit(manyLines, 250);
|
|
21
|
+
|
|
22
|
+
expect(result.wasLimited).toBe(true);
|
|
23
|
+
expect(result.linesRead).toBe(2);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("should handle empty content", () => {
|
|
27
|
+
const result = extractLinesWithByteLimit("", 1000);
|
|
28
|
+
|
|
29
|
+
expect(result.content).toBe("");
|
|
30
|
+
expect(result.wasLimited).toBe(false);
|
|
31
|
+
expect(result.linesRead).toBe(1); // We read the one empty line
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("should handle single line file", () => {
|
|
35
|
+
const singleLine = "This is a single line without newline";
|
|
36
|
+
const result = extractLinesWithByteLimit(singleLine, 1000);
|
|
37
|
+
|
|
38
|
+
expect(result.content).toBe(singleLine);
|
|
39
|
+
expect(result.wasLimited).toBe(false);
|
|
40
|
+
expect(result.linesRead).toBe(1);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should correctly count bytes with multi-byte characters", () => {
|
|
44
|
+
const unicodeContent = "Hello 世界\n你好 World\nEmoji: 🌍\nNormal line";
|
|
45
|
+
const result = extractLinesWithByteLimit(unicodeContent, 1000);
|
|
46
|
+
|
|
47
|
+
expect(result.content).toBe(unicodeContent);
|
|
48
|
+
expect(result.linesRead).toBe(4);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("should stop at byte limit even with one more line available", () => {
|
|
52
|
+
// Create lines where adding one more would exceed limit
|
|
53
|
+
const line1 = "a".repeat(40);
|
|
54
|
+
const line2 = "b".repeat(40);
|
|
55
|
+
const line3 = "c".repeat(40);
|
|
56
|
+
const content = `${line1}\n${line2}\n${line3}`;
|
|
57
|
+
|
|
58
|
+
const result = extractLinesWithByteLimit(content, 85);
|
|
59
|
+
|
|
60
|
+
expect(result.content).toBe(`${line1}\n${line2}\n`);
|
|
61
|
+
expect(result.wasLimited).toBe(true);
|
|
62
|
+
expect(result.linesRead).toBe(2);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should read exactly to limit when possible", () => {
|
|
66
|
+
const exactContent = "12345\n67890\n12345"; // 17 bytes total
|
|
67
|
+
const result = extractLinesWithByteLimit(exactContent, 17);
|
|
68
|
+
|
|
69
|
+
expect(result.content).toBe(exactContent);
|
|
70
|
+
expect(result.wasLimited).toBe(false);
|
|
71
|
+
expect(result.linesRead).toBe(3);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("should handle Windows-style line endings", () => {
|
|
75
|
+
const windowsContent = "Line 1\r\nLine 2\r\nLine 3";
|
|
76
|
+
const result = extractLinesWithByteLimit(windowsContent, 1000);
|
|
77
|
+
|
|
78
|
+
// Note: split("\n") will keep the \r characters
|
|
79
|
+
expect(result.content).toBe("Line 1\r\nLine 2\r\nLine 3");
|
|
80
|
+
expect(result.linesRead).toBe(3);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("should handle very large files efficiently", () => {
|
|
84
|
+
// Create a 100KB file
|
|
85
|
+
const largeLine = "x".repeat(1000);
|
|
86
|
+
const largeContent = Array(110).fill(largeLine).join("\n");
|
|
87
|
+
|
|
88
|
+
const result = extractLinesWithByteLimit(largeContent, 50000);
|
|
89
|
+
|
|
90
|
+
expect(result.wasLimited).toBe(true);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("should allow at least one line even if it exceeds byte limit", () => {
|
|
94
|
+
const veryLongLine = "x".repeat(100000); // 100KB line
|
|
95
|
+
const result = extractLinesWithByteLimit(veryLongLine, 50000);
|
|
96
|
+
|
|
97
|
+
// Should return the line even though it exceeds the byte limit
|
|
98
|
+
// because we always allow at least one line if no lines have been added yet
|
|
99
|
+
expect(result.content).toBe(veryLongLine);
|
|
100
|
+
expect(result.linesRead).toBe(1);
|
|
101
|
+
expect(result.wasLimited).toBe(false);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for session management functionality (fork and load).
|
|
3
|
+
*
|
|
4
|
+
* Run with: npx vitest run src/tests/fork-session.test.ts
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, beforeEach } from "vitest";
|
|
7
|
+
import type { ClaudeAcpAgent } from "../acp-agent.js";
|
|
8
|
+
|
|
9
|
+
// Mock client for testing
|
|
10
|
+
const mockClient = {} as any;
|
|
11
|
+
|
|
12
|
+
describe("session management", () => {
|
|
13
|
+
let agent: ClaudeAcpAgent;
|
|
14
|
+
|
|
15
|
+
beforeEach(async () => {
|
|
16
|
+
const { ClaudeAcpAgent } = await import("../acp-agent.js");
|
|
17
|
+
agent = new ClaudeAcpAgent(mockClient);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("capability advertisement", () => {
|
|
21
|
+
it("advertises sessionCapabilities.fork", async () => {
|
|
22
|
+
const response = await agent.initialize({
|
|
23
|
+
protocolVersion: 1,
|
|
24
|
+
clientInfo: { name: "test-client", version: "1.0.0" },
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
expect(response.agentCapabilities?.sessionCapabilities?.fork).toEqual({});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("advertises loadSession capability", async () => {
|
|
31
|
+
const response = await agent.initialize({
|
|
32
|
+
protocolVersion: 1,
|
|
33
|
+
clientInfo: { name: "test-client", version: "1.0.0" },
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(response.agentCapabilities?.loadSession).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("includes all expected agent capabilities", async () => {
|
|
40
|
+
const response = await agent.initialize({
|
|
41
|
+
protocolVersion: 1,
|
|
42
|
+
clientInfo: { name: "test-client", version: "1.0.0" },
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
expect(response.agentCapabilities).toMatchObject({
|
|
46
|
+
promptCapabilities: {
|
|
47
|
+
image: true,
|
|
48
|
+
embeddedContext: true,
|
|
49
|
+
},
|
|
50
|
+
mcpCapabilities: {
|
|
51
|
+
http: true,
|
|
52
|
+
sse: true,
|
|
53
|
+
},
|
|
54
|
+
sessionCapabilities: {
|
|
55
|
+
fork: {},
|
|
56
|
+
resume: {},
|
|
57
|
+
},
|
|
58
|
+
loadSession: true,
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe("forkSession", () => {
|
|
64
|
+
it("method exists on ClaudeAcpAgent", () => {
|
|
65
|
+
expect(typeof agent.forkSession).toBe("function");
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("accepts ForkSessionRequest params with sessionId", () => {
|
|
69
|
+
// Verify method signature accepts minimal params
|
|
70
|
+
expect(agent.forkSession).toBeInstanceOf(Function);
|
|
71
|
+
expect(agent.forkSession.length).toBeGreaterThanOrEqual(1);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("accepts optional _meta with cwd and mcpServers", () => {
|
|
75
|
+
// Verify method can handle extended params via _meta
|
|
76
|
+
expect(agent.forkSession).toBeInstanceOf(Function);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe("loadSession", () => {
|
|
81
|
+
it("method exists on ClaudeAcpAgent", () => {
|
|
82
|
+
expect(typeof agent.loadSession).toBe("function");
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("accepts LoadSessionRequest params", () => {
|
|
86
|
+
// Verify method signature accepts params (sessionId, cwd, mcpServers)
|
|
87
|
+
expect(agent.loadSession).toBeInstanceOf(Function);
|
|
88
|
+
expect(agent.loadSession.length).toBeGreaterThanOrEqual(1);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe("deprecated methods", () => {
|
|
93
|
+
it("unstable_forkSession delegates to forkSession", () => {
|
|
94
|
+
expect(typeof agent.unstable_forkSession).toBe("function");
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("unstable_resumeSession delegates to loadSession", () => {
|
|
98
|
+
expect(typeof agent.unstable_resumeSession).toBe("function");
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe("extMethod _session/inject", () => {
|
|
103
|
+
it("extMethod exists on ClaudeAcpAgent", () => {
|
|
104
|
+
expect(typeof agent.extMethod).toBe("function");
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("returns error for non-existent session", async () => {
|
|
108
|
+
const result = await agent.extMethod("_session/inject", {
|
|
109
|
+
sessionId: "non-existent-session",
|
|
110
|
+
message: "test message",
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
expect(result).toEqual({
|
|
114
|
+
success: false,
|
|
115
|
+
error: "Session non-existent-session not found",
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("throws for unknown extension methods", async () => {
|
|
120
|
+
await expect(
|
|
121
|
+
agent.extMethod("_unknown/method", {}),
|
|
122
|
+
).rejects.toThrow();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("accepts string messages", async () => {
|
|
126
|
+
// Mock a session in the agent's sessions map
|
|
127
|
+
const mockSession = {
|
|
128
|
+
query: {} as any,
|
|
129
|
+
input: {
|
|
130
|
+
push: () => {},
|
|
131
|
+
end: () => {},
|
|
132
|
+
},
|
|
133
|
+
cancelled: false,
|
|
134
|
+
permissionMode: "default" as const,
|
|
135
|
+
settingsManager: {} as any,
|
|
136
|
+
abortController: new AbortController(),
|
|
137
|
+
cwd: "/tmp",
|
|
138
|
+
};
|
|
139
|
+
(agent as any).sessions["test-session"] = mockSession;
|
|
140
|
+
|
|
141
|
+
const result = await agent.extMethod("_session/inject", {
|
|
142
|
+
sessionId: "test-session",
|
|
143
|
+
message: "test message",
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
expect(result).toEqual({ success: true });
|
|
147
|
+
|
|
148
|
+
// Cleanup
|
|
149
|
+
delete (agent as any).sessions["test-session"];
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("accepts ContentBlock array messages", async () => {
|
|
153
|
+
// Mock a session
|
|
154
|
+
const mockSession = {
|
|
155
|
+
query: {} as any,
|
|
156
|
+
input: {
|
|
157
|
+
push: () => {},
|
|
158
|
+
end: () => {},
|
|
159
|
+
},
|
|
160
|
+
cancelled: false,
|
|
161
|
+
permissionMode: "default" as const,
|
|
162
|
+
settingsManager: {} as any,
|
|
163
|
+
abortController: new AbortController(),
|
|
164
|
+
cwd: "/tmp",
|
|
165
|
+
};
|
|
166
|
+
(agent as any).sessions["test-session"] = mockSession;
|
|
167
|
+
|
|
168
|
+
const result = await agent.extMethod("_session/inject", {
|
|
169
|
+
sessionId: "test-session",
|
|
170
|
+
message: [
|
|
171
|
+
{ type: "text", text: "first part" },
|
|
172
|
+
{ type: "text", text: "second part" },
|
|
173
|
+
],
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
expect(result).toEqual({ success: true });
|
|
177
|
+
|
|
178
|
+
// Cleanup
|
|
179
|
+
delete (agent as any).sessions["test-session"];
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("returns error for cancelled session", async () => {
|
|
183
|
+
// Mock a cancelled session
|
|
184
|
+
const mockSession = {
|
|
185
|
+
query: {} as any,
|
|
186
|
+
input: {
|
|
187
|
+
push: () => {},
|
|
188
|
+
end: () => {},
|
|
189
|
+
},
|
|
190
|
+
cancelled: true, // Session is cancelled
|
|
191
|
+
permissionMode: "default" as const,
|
|
192
|
+
settingsManager: {} as any,
|
|
193
|
+
abortController: new AbortController(),
|
|
194
|
+
cwd: "/tmp",
|
|
195
|
+
};
|
|
196
|
+
(agent as any).sessions["cancelled-session"] = mockSession;
|
|
197
|
+
|
|
198
|
+
const result = await agent.extMethod("_session/inject", {
|
|
199
|
+
sessionId: "cancelled-session",
|
|
200
|
+
message: "test message",
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
expect(result).toEqual({
|
|
204
|
+
success: false,
|
|
205
|
+
error: "Session cancelled-session is cancelled",
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Cleanup
|
|
209
|
+
delete (agent as any).sessions["cancelled-session"];
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it("actually pushes message to session input", async () => {
|
|
213
|
+
// Track what was pushed
|
|
214
|
+
const pushedMessages: any[] = [];
|
|
215
|
+
const mockSession = {
|
|
216
|
+
query: {} as any,
|
|
217
|
+
input: {
|
|
218
|
+
push: (msg: any) => pushedMessages.push(msg),
|
|
219
|
+
end: () => {},
|
|
220
|
+
},
|
|
221
|
+
cancelled: false,
|
|
222
|
+
permissionMode: "default" as const,
|
|
223
|
+
settingsManager: {} as any,
|
|
224
|
+
abortController: new AbortController(),
|
|
225
|
+
cwd: "/tmp",
|
|
226
|
+
};
|
|
227
|
+
(agent as any).sessions["push-test-session"] = mockSession;
|
|
228
|
+
|
|
229
|
+
await agent.extMethod("_session/inject", {
|
|
230
|
+
sessionId: "push-test-session",
|
|
231
|
+
message: "hello world",
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
expect(pushedMessages.length).toBe(1);
|
|
235
|
+
expect(pushedMessages[0].type).toBe("user");
|
|
236
|
+
expect(pushedMessages[0].message.role).toBe("user");
|
|
237
|
+
expect(pushedMessages[0].message.content).toContainEqual({
|
|
238
|
+
type: "text",
|
|
239
|
+
text: "hello world",
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Cleanup
|
|
243
|
+
delete (agent as any).sessions["push-test-session"];
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
describe("extMethod _session/listSkills", () => {
|
|
248
|
+
it("returns error for non-existent session", async () => {
|
|
249
|
+
const result = await agent.extMethod("_session/listSkills", {
|
|
250
|
+
sessionId: "non-existent-session",
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
expect(result).toEqual({
|
|
254
|
+
success: false,
|
|
255
|
+
error: "Session non-existent-session not found",
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it("returns empty skills array when session has no skills", async () => {
|
|
260
|
+
// Mock a session without skills
|
|
261
|
+
const mockSession = {
|
|
262
|
+
query: {} as any,
|
|
263
|
+
input: {
|
|
264
|
+
push: () => {},
|
|
265
|
+
end: () => {},
|
|
266
|
+
},
|
|
267
|
+
cancelled: false,
|
|
268
|
+
permissionMode: "default" as const,
|
|
269
|
+
settingsManager: {} as any,
|
|
270
|
+
abortController: new AbortController(),
|
|
271
|
+
cwd: "/tmp",
|
|
272
|
+
compaction: {
|
|
273
|
+
enabled: false,
|
|
274
|
+
threshold: 100000,
|
|
275
|
+
currentTokens: 0,
|
|
276
|
+
isCompacting: false,
|
|
277
|
+
},
|
|
278
|
+
// No skills field
|
|
279
|
+
};
|
|
280
|
+
(agent as any).sessions["test-session"] = mockSession;
|
|
281
|
+
|
|
282
|
+
const result = await agent.extMethod("_session/listSkills", {
|
|
283
|
+
sessionId: "test-session",
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
expect(result).toEqual({
|
|
287
|
+
success: true,
|
|
288
|
+
skills: [],
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
// Cleanup
|
|
292
|
+
delete (agent as any).sessions["test-session"];
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it("returns skills array when session has skills", async () => {
|
|
296
|
+
// Mock a session with skills
|
|
297
|
+
const mockSkills = [
|
|
298
|
+
{ name: "pdf-processor", description: "Process PDF files", source: "project" },
|
|
299
|
+
{ name: "code-reviewer", description: "Review code changes", source: "user" },
|
|
300
|
+
];
|
|
301
|
+
const mockSession = {
|
|
302
|
+
query: {} as any,
|
|
303
|
+
input: {
|
|
304
|
+
push: () => {},
|
|
305
|
+
end: () => {},
|
|
306
|
+
},
|
|
307
|
+
cancelled: false,
|
|
308
|
+
permissionMode: "default" as const,
|
|
309
|
+
settingsManager: {} as any,
|
|
310
|
+
abortController: new AbortController(),
|
|
311
|
+
cwd: "/tmp",
|
|
312
|
+
compaction: {
|
|
313
|
+
enabled: false,
|
|
314
|
+
threshold: 100000,
|
|
315
|
+
currentTokens: 0,
|
|
316
|
+
isCompacting: false,
|
|
317
|
+
},
|
|
318
|
+
skills: mockSkills,
|
|
319
|
+
};
|
|
320
|
+
(agent as any).sessions["skills-session"] = mockSession;
|
|
321
|
+
|
|
322
|
+
const result = await agent.extMethod("_session/listSkills", {
|
|
323
|
+
sessionId: "skills-session",
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
expect(result).toEqual({
|
|
327
|
+
success: true,
|
|
328
|
+
skills: mockSkills,
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
// Cleanup
|
|
332
|
+
delete (agent as any).sessions["skills-session"];
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
});
|