@ai-setting/roy-agent-cli 1.0.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 +126 -0
- package/dist/bin/roy.js +127297 -0
- package/dist/roy-agent-darwin-arm64/bin/roy.js +127297 -0
- package/dist/roy-agent-darwin-x64/bin/roy.js +127297 -0
- package/dist/roy-agent-linux-arm64/bin/roy.js +127297 -0
- package/dist/roy-agent-linux-x64/bin/roy.js +127297 -0
- package/dist/roy-agent-windows-x64/bin/roy.js +127297 -0
- package/package.json +91 -0
- package/src/bin/roy.ts +12 -0
- package/src/cli.ts +101 -0
- package/src/commands/act.ts +480 -0
- package/src/commands/commands-add.ts +110 -0
- package/src/commands/commands-dirs.ts +70 -0
- package/src/commands/commands-info.ts +90 -0
- package/src/commands/commands-list.ts +161 -0
- package/src/commands/commands-remove.ts +147 -0
- package/src/commands/commands.ts +55 -0
- package/src/commands/config/config-service.test.ts +449 -0
- package/src/commands/config/config-service.ts +312 -0
- package/src/commands/config/deep-merge.test.ts +168 -0
- package/src/commands/config/deep-merge.ts +63 -0
- package/src/commands/config/export.ts +97 -0
- package/src/commands/config/filter-history-e2e.test.ts +141 -0
- package/src/commands/config/import-preserve-refs.test.ts +212 -0
- package/src/commands/config/import.ts +119 -0
- package/src/commands/config/index.ts +35 -0
- package/src/commands/config/list.ts +281 -0
- package/src/commands/config/roy-config-e2e.test.ts +297 -0
- package/src/commands/config/types.ts +54 -0
- package/src/commands/debug/index.ts +38 -0
- package/src/commands/debug/log.test.ts +233 -0
- package/src/commands/debug/log.ts +123 -0
- package/src/commands/debug/span.test.ts +297 -0
- package/src/commands/debug/span.ts +211 -0
- package/src/commands/debug/trace.test.ts +254 -0
- package/src/commands/debug/trace.ts +140 -0
- package/src/commands/eventsource/add.ts +133 -0
- package/src/commands/eventsource/index.ts +48 -0
- package/src/commands/eventsource/list.ts +194 -0
- package/src/commands/eventsource/remove.ts +95 -0
- package/src/commands/eventsource/start.ts +103 -0
- package/src/commands/eventsource/status.ts +185 -0
- package/src/commands/eventsource/stop.ts +89 -0
- package/src/commands/index.ts +22 -0
- package/src/commands/input-handler.test.ts +76 -0
- package/src/commands/input-handler.ts +43 -0
- package/src/commands/interactive-esc.test.ts +254 -0
- package/src/commands/interactive.shutdown.test.ts +122 -0
- package/src/commands/interactive.test.ts +221 -0
- package/src/commands/interactive.ts +1015 -0
- package/src/commands/lsp/check.ts +92 -0
- package/src/commands/lsp/index.ts +32 -0
- package/src/commands/lsp/install.ts +126 -0
- package/src/commands/lsp/list.ts +64 -0
- package/src/commands/mcp/index.ts +27 -0
- package/src/commands/mcp/list.ts +116 -0
- package/src/commands/mcp/reload.ts +70 -0
- package/src/commands/mcp/tools.ts +121 -0
- package/src/commands/memory/extract-e2e.test.ts +388 -0
- package/src/commands/memory/index.ts +11 -0
- package/src/commands/memory/memory-simplified.test.ts +58 -0
- package/src/commands/memory/memory.ts +25 -0
- package/src/commands/memory/organize.ts +300 -0
- package/src/commands/memory/recall.test.ts +120 -0
- package/src/commands/memory/recall.ts +88 -0
- package/src/commands/memory/record-extract-handle-query.test.ts +385 -0
- package/src/commands/memory/record-prompt-component.test.ts +343 -0
- package/src/commands/memory/record.test.ts +92 -0
- package/src/commands/memory/record.ts +332 -0
- package/src/commands/plugin.test.ts +292 -0
- package/src/commands/plugin.ts +267 -0
- package/src/commands/sessions/active.ts +96 -0
- package/src/commands/sessions/add-message.ts +96 -0
- package/src/commands/sessions/checkpoints.ts +154 -0
- package/src/commands/sessions/compact.test.ts +215 -0
- package/src/commands/sessions/compact.ts +269 -0
- package/src/commands/sessions/delete.ts +236 -0
- package/src/commands/sessions/get.ts +165 -0
- package/src/commands/sessions/grep.ts +233 -0
- package/src/commands/sessions/index.ts +95 -0
- package/src/commands/sessions/list.ts +210 -0
- package/src/commands/sessions/messages.test.ts +333 -0
- package/src/commands/sessions/messages.ts +248 -0
- package/src/commands/sessions/mock.ts +194 -0
- package/src/commands/sessions/new.ts +82 -0
- package/src/commands/sessions/rename.ts +98 -0
- package/src/commands/shared/event-handler.ts +213 -0
- package/src/commands/shared/event-message-formatter.ts +295 -0
- package/src/commands/shared/index.ts +11 -0
- package/src/commands/shared/query-executor.test.ts +434 -0
- package/src/commands/shared/query-executor.ts +324 -0
- package/src/commands/shared/repl-engine.test.ts +354 -0
- package/src/commands/shared/session-manager.test.ts +212 -0
- package/src/commands/shared/session-manager.ts +114 -0
- package/src/commands/skills/get.ts +90 -0
- package/src/commands/skills/index.ts +39 -0
- package/src/commands/skills/list.ts +129 -0
- package/src/commands/skills/reload.ts +59 -0
- package/src/commands/skills/search.ts +132 -0
- package/src/commands/skills/show-config.ts +93 -0
- package/src/commands/tasks/complete.ts +92 -0
- package/src/commands/tasks/create.ts +118 -0
- package/src/commands/tasks/delete.ts +86 -0
- package/src/commands/tasks/get.ts +116 -0
- package/src/commands/tasks/index.ts +53 -0
- package/src/commands/tasks/list.ts +140 -0
- package/src/commands/tasks/operations.ts +120 -0
- package/src/commands/tasks/update.ts +122 -0
- package/src/commands/tools/exec-tool.ts +128 -0
- package/src/commands/tools/get.ts +114 -0
- package/src/commands/tools/index.ts +35 -0
- package/src/commands/tools/list.ts +107 -0
- package/src/commands/tools/shared/index.ts +7 -0
- package/src/commands/tools/shared/schema-helper.ts +111 -0
- package/src/commands/workflow/commands/add.ts +315 -0
- package/src/commands/workflow/commands/get.ts +193 -0
- package/src/commands/workflow/commands/list.ts +137 -0
- package/src/commands/workflow/commands/nodes.ts +528 -0
- package/src/commands/workflow/commands/remove.ts +94 -0
- package/src/commands/workflow/commands/run.ts +398 -0
- package/src/commands/workflow/commands/status.ts +147 -0
- package/src/commands/workflow/commands/stop.ts +91 -0
- package/src/commands/workflow/commands/update.ts +130 -0
- package/src/commands/workflow/commands/validate.ts +139 -0
- package/src/commands/workflow/commands/workflow-cli.test.ts +196 -0
- package/src/commands/workflow/index.ts +65 -0
- package/src/commands/workflow/renderers.ts +358 -0
- package/src/commands/workflow/validators/index.ts +8 -0
- package/src/commands/workflow/validators/node-validator-factory.ts +40 -0
- package/src/commands/workflow/validators/node-validator.ts +125 -0
- package/src/commands/workflow/validators/nodes/agent-node-validator.ts +58 -0
- package/src/commands/workflow/validators/nodes/condition-node-validator.ts +34 -0
- package/src/commands/workflow/validators/nodes/decorator-node-validator.ts +45 -0
- package/src/commands/workflow/validators/nodes/merge-node-validator.ts +46 -0
- package/src/commands/workflow/validators/nodes/skill-node-validator.ts +33 -0
- package/src/commands/workflow/validators/nodes/tool-node-validator.ts +54 -0
- package/src/commands/workflow/validators/nodes/workflow-node-validator.ts +33 -0
- package/src/commands/workflow/validators/types.ts +78 -0
- package/src/commands/workflow/validators/workflow-validator.test.ts +273 -0
- package/src/commands/workflow/validators/workflow-validator.ts +320 -0
- package/src/index.ts +19 -0
- package/src/plugin/apply.ts +103 -0
- package/src/plugin/discover.ts +219 -0
- package/src/plugin/index.ts +45 -0
- package/src/plugin/registry.ts +272 -0
- package/src/plugin/types.ts +165 -0
- package/src/services/context-handler.service.test.ts +501 -0
- package/src/services/context-handler.service.ts +372 -0
- package/src/services/environment.service.commands-prompt.test.ts +167 -0
- package/src/services/environment.service.ts +656 -0
- package/src/services/output.service.test.ts +92 -0
- package/src/services/output.service.ts +122 -0
- package/src/services/quiet-mode.service.test.ts +114 -0
- package/src/services/quiet-mode.service.ts +81 -0
- package/src/services/stream-output.service.test.ts +214 -0
- package/src/services/stream-output.service.ts +323 -0
- package/src/util/which.test.ts +101 -0
- package/src/util/which.ts +55 -0
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview QueryExecutor Test
|
|
3
|
+
*
|
|
4
|
+
* TDD: 测试 QueryExecutor 的核心功能
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, test, expect, vi, beforeEach, afterEach } from "bun:test";
|
|
8
|
+
import { QueryExecutor } from "./query-executor";
|
|
9
|
+
import { OutputService } from "../../services/output.service";
|
|
10
|
+
import { StreamOutputService, resetStreamAbort } from "../../services/stream-output.service";
|
|
11
|
+
import { ContextHandlerService } from "../../services/context-handler.service";
|
|
12
|
+
|
|
13
|
+
// Mock types
|
|
14
|
+
interface MockEnvironment {
|
|
15
|
+
subscribeTo: ReturnType<typeof vi.fn>;
|
|
16
|
+
getComponent: ReturnType<typeof vi.fn>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface MockSessionComponent {
|
|
20
|
+
setSummaryComponents: ReturnType<typeof vi.fn>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe("QueryExecutor", () => {
|
|
24
|
+
let queryExecutor: QueryExecutor;
|
|
25
|
+
let mockEnv: MockEnvironment;
|
|
26
|
+
let mockSessionComponent: MockSessionComponent;
|
|
27
|
+
let mockOutput: OutputService;
|
|
28
|
+
let consoleLogSpy: ReturnType<typeof vi.spyOn>;
|
|
29
|
+
let consoleErrorSpy: ReturnType<typeof vi.spyOn>;
|
|
30
|
+
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
// 重置全局 abort 状态,避免被其他测试污染
|
|
33
|
+
resetStreamAbort();
|
|
34
|
+
|
|
35
|
+
// Create mock Environment
|
|
36
|
+
const mockUnsubscribe = vi.fn();
|
|
37
|
+
mockEnv = {
|
|
38
|
+
subscribeTo: vi.fn().mockReturnValue(mockUnsubscribe),
|
|
39
|
+
getComponent: vi.fn(),
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
mockSessionComponent = {
|
|
43
|
+
setSummaryComponents: vi.fn(),
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
mockOutput = new OutputService();
|
|
47
|
+
mockOutput.configure({ quiet: true });
|
|
48
|
+
|
|
49
|
+
// Spy on console
|
|
50
|
+
consoleLogSpy = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
51
|
+
consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
52
|
+
|
|
53
|
+
queryExecutor = new QueryExecutor({
|
|
54
|
+
env: mockEnv as any,
|
|
55
|
+
sessionComponent: mockSessionComponent as any,
|
|
56
|
+
output: mockOutput,
|
|
57
|
+
quiet: true,
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
afterEach(() => {
|
|
62
|
+
vi.restoreAllMocks();
|
|
63
|
+
queryExecutor.dispose();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe("constructor", () => {
|
|
67
|
+
test("should create instance with options", () => {
|
|
68
|
+
expect(queryExecutor).toBeDefined();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe("initSummaryAgent()", () => {
|
|
73
|
+
test("should call setSummaryComponents on sessionComponent", () => {
|
|
74
|
+
// Given
|
|
75
|
+
const mockLLMComponent = {};
|
|
76
|
+
const mockPromptComponent = {};
|
|
77
|
+
|
|
78
|
+
// When
|
|
79
|
+
queryExecutor.initSummaryAgent(
|
|
80
|
+
mockLLMComponent as any,
|
|
81
|
+
mockPromptComponent as any
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// Then
|
|
85
|
+
expect(mockSessionComponent.setSummaryComponents).toHaveBeenCalledWith(
|
|
86
|
+
mockPromptComponent,
|
|
87
|
+
mockLLMComponent
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe("subscribeToEvents()", () => {
|
|
93
|
+
test("should call env.subscribeTo with correct events", () => {
|
|
94
|
+
// Given
|
|
95
|
+
const options = {
|
|
96
|
+
showReasoning: true,
|
|
97
|
+
showToolCalls: false,
|
|
98
|
+
showToolResults: false,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// When
|
|
102
|
+
queryExecutor.subscribeToEvents(options);
|
|
103
|
+
|
|
104
|
+
// Then
|
|
105
|
+
expect(mockEnv.subscribeTo).toHaveBeenCalledWith(
|
|
106
|
+
expect.arrayContaining([
|
|
107
|
+
"llm.start",
|
|
108
|
+
"llm.text",
|
|
109
|
+
"llm.reasoning",
|
|
110
|
+
"llm.tool_call",
|
|
111
|
+
"llm.completed",
|
|
112
|
+
"llm.error",
|
|
113
|
+
"tool.result",
|
|
114
|
+
"tool.error",
|
|
115
|
+
"context.threshold_exceeded",
|
|
116
|
+
"context.compacting",
|
|
117
|
+
"context.compacted",
|
|
118
|
+
]),
|
|
119
|
+
expect.any(Function)
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test("should only subscribe once", () => {
|
|
124
|
+
// Given
|
|
125
|
+
const options = {
|
|
126
|
+
showReasoning: true,
|
|
127
|
+
showToolCalls: false,
|
|
128
|
+
showToolResults: false,
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// When
|
|
132
|
+
queryExecutor.subscribeToEvents(options);
|
|
133
|
+
queryExecutor.subscribeToEvents(options);
|
|
134
|
+
|
|
135
|
+
// Then
|
|
136
|
+
expect(mockEnv.subscribeTo).toHaveBeenCalledTimes(1);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
describe("dispose()", () => {
|
|
141
|
+
test("should call unsubscribe when disposed", () => {
|
|
142
|
+
// Given
|
|
143
|
+
const options = {
|
|
144
|
+
showReasoning: false,
|
|
145
|
+
showToolCalls: false,
|
|
146
|
+
showToolResults: false,
|
|
147
|
+
};
|
|
148
|
+
queryExecutor.subscribeToEvents(options);
|
|
149
|
+
|
|
150
|
+
// When
|
|
151
|
+
queryExecutor.dispose();
|
|
152
|
+
|
|
153
|
+
// Then
|
|
154
|
+
expect(mockEnv.subscribeTo).toHaveBeenCalled(); // unsubscribe was called via dispose
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test("should handle dispose when not subscribed", () => {
|
|
158
|
+
// When & Then - should not throw
|
|
159
|
+
expect(() => queryExecutor.dispose()).not.toThrow();
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
describe("getFullText()", () => {
|
|
164
|
+
test("should return empty string when no stream service", () => {
|
|
165
|
+
// When
|
|
166
|
+
const result = queryExecutor.getFullText();
|
|
167
|
+
|
|
168
|
+
// Then
|
|
169
|
+
expect(result).toBe("");
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
describe("QueryExecutor compact", () => {
|
|
175
|
+
let queryExecutor: QueryExecutor;
|
|
176
|
+
let mockEnv: {
|
|
177
|
+
subscribeTo: ReturnType<typeof vi.fn>;
|
|
178
|
+
getComponent: ReturnType<typeof vi.fn>;
|
|
179
|
+
};
|
|
180
|
+
let mockSessionComponent: {
|
|
181
|
+
setSummaryComponents: ReturnType<typeof vi.fn>;
|
|
182
|
+
compact: ReturnType<typeof vi.fn>;
|
|
183
|
+
};
|
|
184
|
+
let mockOutput: OutputService;
|
|
185
|
+
|
|
186
|
+
beforeEach(() => {
|
|
187
|
+
const mockUnsubscribe = vi.fn();
|
|
188
|
+
mockEnv = {
|
|
189
|
+
subscribeTo: vi.fn().mockReturnValue(mockUnsubscribe),
|
|
190
|
+
getComponent: vi.fn().mockReturnValue({
|
|
191
|
+
pushEnvEvent: vi.fn(),
|
|
192
|
+
}),
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
mockSessionComponent = {
|
|
196
|
+
setSummaryComponents: vi.fn(),
|
|
197
|
+
compact: vi.fn().mockResolvedValue({
|
|
198
|
+
checkpoint: {
|
|
199
|
+
id: "cp_test_123",
|
|
200
|
+
sessionId: "s_test",
|
|
201
|
+
summary: "Test summary",
|
|
202
|
+
createdAt: new Date().toISOString(),
|
|
203
|
+
},
|
|
204
|
+
deletedMessageCount: 5,
|
|
205
|
+
}),
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
mockOutput = new OutputService();
|
|
209
|
+
mockOutput.configure({ quiet: true });
|
|
210
|
+
|
|
211
|
+
queryExecutor = new QueryExecutor({
|
|
212
|
+
env: mockEnv as any,
|
|
213
|
+
sessionComponent: mockSessionComponent as any,
|
|
214
|
+
output: mockOutput,
|
|
215
|
+
quiet: true,
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
afterEach(() => {
|
|
220
|
+
vi.restoreAllMocks();
|
|
221
|
+
queryExecutor.dispose();
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
describe("compact()", () => {
|
|
225
|
+
test("should call sessionComponent.compact with sessionId", async () => {
|
|
226
|
+
// Given
|
|
227
|
+
const sessionId = "s_test_123";
|
|
228
|
+
|
|
229
|
+
// When
|
|
230
|
+
await queryExecutor.compact(sessionId);
|
|
231
|
+
|
|
232
|
+
// Then
|
|
233
|
+
expect(mockSessionComponent.compact).toHaveBeenCalledWith(
|
|
234
|
+
sessionId,
|
|
235
|
+
expect.objectContaining({
|
|
236
|
+
summary: expect.any(String),
|
|
237
|
+
})
|
|
238
|
+
);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test("should publish context.compacting event before compact", async () => {
|
|
242
|
+
// Given
|
|
243
|
+
const sessionId = "s_test_123";
|
|
244
|
+
const pushEnvEvent = vi.fn();
|
|
245
|
+
(mockEnv.getComponent as any).mockReturnValue({
|
|
246
|
+
pushEnvEvent,
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// When
|
|
250
|
+
await queryExecutor.compact(sessionId);
|
|
251
|
+
|
|
252
|
+
// Then
|
|
253
|
+
expect(pushEnvEvent).toHaveBeenCalledWith(
|
|
254
|
+
expect.objectContaining({
|
|
255
|
+
type: "context.compacting",
|
|
256
|
+
})
|
|
257
|
+
);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
test("should publish context.compacted event after compact", async () => {
|
|
261
|
+
// Given
|
|
262
|
+
const sessionId = "s_test_123";
|
|
263
|
+
const pushEnvEvent = vi.fn();
|
|
264
|
+
(mockEnv.getComponent as any).mockReturnValue({
|
|
265
|
+
pushEnvEvent,
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// When
|
|
269
|
+
await queryExecutor.compact(sessionId);
|
|
270
|
+
|
|
271
|
+
// Then
|
|
272
|
+
expect(pushEnvEvent).toHaveBeenCalledWith(
|
|
273
|
+
expect.objectContaining({
|
|
274
|
+
type: "context.compacted",
|
|
275
|
+
payload: expect.objectContaining({
|
|
276
|
+
checkpointId: "cp_test_123",
|
|
277
|
+
messagesCompacted: 5,
|
|
278
|
+
}),
|
|
279
|
+
})
|
|
280
|
+
);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
test("should return compact result", async () => {
|
|
284
|
+
// Given
|
|
285
|
+
const sessionId = "s_test_123";
|
|
286
|
+
|
|
287
|
+
// When
|
|
288
|
+
const result = await queryExecutor.compact(sessionId);
|
|
289
|
+
|
|
290
|
+
// Then
|
|
291
|
+
expect(result).toEqual({
|
|
292
|
+
success: true,
|
|
293
|
+
checkpoint: expect.objectContaining({
|
|
294
|
+
id: "cp_test_123",
|
|
295
|
+
}),
|
|
296
|
+
deletedMessageCount: 5,
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
test("should return error result when compact fails", async () => {
|
|
301
|
+
// Given
|
|
302
|
+
const sessionId = "s_test_123";
|
|
303
|
+
mockSessionComponent.compact = vi.fn().mockRejectedValue(
|
|
304
|
+
new Error("Compact failed")
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
// When
|
|
308
|
+
const result = await queryExecutor.compact(sessionId);
|
|
309
|
+
|
|
310
|
+
// Then
|
|
311
|
+
expect(result).toEqual({
|
|
312
|
+
success: false,
|
|
313
|
+
error: "Compact failed",
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
describe("QueryExecutor Event Handling", () => {
|
|
320
|
+
let queryExecutor: QueryExecutor;
|
|
321
|
+
let mockEnv: MockEnvironment;
|
|
322
|
+
let mockSessionComponent: MockSessionComponent;
|
|
323
|
+
let mockOutput: OutputService;
|
|
324
|
+
let eventHandler: (event: any) => void;
|
|
325
|
+
let mockUnsubscribe: ReturnType<typeof vi.fn>;
|
|
326
|
+
|
|
327
|
+
beforeEach(() => {
|
|
328
|
+
mockUnsubscribe = vi.fn();
|
|
329
|
+
mockEnv = {
|
|
330
|
+
subscribeTo: vi.fn().mockImplementation((events, handler) => {
|
|
331
|
+
eventHandler = handler;
|
|
332
|
+
return mockUnsubscribe;
|
|
333
|
+
}),
|
|
334
|
+
getComponent: vi.fn(),
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
mockSessionComponent = {
|
|
338
|
+
setSummaryComponents: vi.fn(),
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
mockOutput = new OutputService();
|
|
342
|
+
mockOutput.configure({ quiet: true });
|
|
343
|
+
|
|
344
|
+
vi.spyOn(console, "log").mockImplementation(() => {});
|
|
345
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
346
|
+
|
|
347
|
+
queryExecutor = new QueryExecutor({
|
|
348
|
+
env: mockEnv as any,
|
|
349
|
+
sessionComponent: mockSessionComponent as any,
|
|
350
|
+
output: mockOutput,
|
|
351
|
+
quiet: true,
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
afterEach(() => {
|
|
356
|
+
vi.restoreAllMocks();
|
|
357
|
+
queryExecutor.dispose();
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
describe("handleEvent", () => {
|
|
361
|
+
test("should handle llm.tool_call event when showToolCalls is true", () => {
|
|
362
|
+
// Given
|
|
363
|
+
queryExecutor.subscribeToEvents({
|
|
364
|
+
showReasoning: false,
|
|
365
|
+
showToolCalls: true,
|
|
366
|
+
showToolResults: false,
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
const event = {
|
|
370
|
+
type: "llm.tool_call",
|
|
371
|
+
payload: {
|
|
372
|
+
toolCall: {
|
|
373
|
+
name: "testTool",
|
|
374
|
+
arguments: '{"input": "test"}',
|
|
375
|
+
},
|
|
376
|
+
},
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
// When
|
|
380
|
+
eventHandler(event);
|
|
381
|
+
|
|
382
|
+
// Then
|
|
383
|
+
expect(console.log).toHaveBeenCalled();
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
test("should not log tool_call when showToolCalls is false", () => {
|
|
387
|
+
// Given
|
|
388
|
+
queryExecutor.subscribeToEvents({
|
|
389
|
+
showReasoning: false,
|
|
390
|
+
showToolCalls: false,
|
|
391
|
+
showToolResults: false,
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
const event = {
|
|
395
|
+
type: "llm.tool_call",
|
|
396
|
+
payload: {
|
|
397
|
+
toolCall: {
|
|
398
|
+
name: "testTool",
|
|
399
|
+
arguments: '{"input": "test"}',
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
// When
|
|
405
|
+
eventHandler(event);
|
|
406
|
+
|
|
407
|
+
// Then
|
|
408
|
+
expect(console.log).not.toHaveBeenCalled();
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
test("should handle tool.error event", () => {
|
|
412
|
+
// Given
|
|
413
|
+
queryExecutor.subscribeToEvents({
|
|
414
|
+
showReasoning: false,
|
|
415
|
+
showToolCalls: false,
|
|
416
|
+
showToolResults: false,
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
const event = {
|
|
420
|
+
type: "tool.error",
|
|
421
|
+
payload: {
|
|
422
|
+
toolName: "failingTool",
|
|
423
|
+
error: "Tool execution failed",
|
|
424
|
+
},
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
// When
|
|
428
|
+
eventHandler(event);
|
|
429
|
+
|
|
430
|
+
// Then
|
|
431
|
+
expect(console.error).toHaveBeenCalled();
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
});
|