@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,388 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview End-to-End Test for Memory Extract Mode
|
|
3
|
+
*
|
|
4
|
+
* 完整测试 record --extract 命令的集成流程
|
|
5
|
+
*
|
|
6
|
+
* 注意:runExtractMode 是内部函数,直接测试其逻辑而非导入
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, expect, test, vi, beforeEach, afterEach } from "vitest";
|
|
10
|
+
|
|
11
|
+
// Mock chalk
|
|
12
|
+
vi.mock("chalk", () => ({
|
|
13
|
+
default: {
|
|
14
|
+
blue: (str: string) => str,
|
|
15
|
+
gray: (str: string) => str,
|
|
16
|
+
green: (str: string) => str,
|
|
17
|
+
red: (str: string) => str,
|
|
18
|
+
},
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
// Mock dependencies
|
|
22
|
+
const mockSessionComponent = {
|
|
23
|
+
searchSessions: vi.fn().mockResolvedValue([
|
|
24
|
+
{ sessionId: "test-1", title: "Test Session", preview: "Hello world" }
|
|
25
|
+
]),
|
|
26
|
+
getSession: vi.fn().mockResolvedValue({
|
|
27
|
+
sessionId: "test-1",
|
|
28
|
+
messages: [
|
|
29
|
+
{ role: "user", content: "Hello" },
|
|
30
|
+
{ role: "assistant", content: "Hi there!" },
|
|
31
|
+
],
|
|
32
|
+
}),
|
|
33
|
+
getContext: vi.fn().mockResolvedValue({
|
|
34
|
+
messages: [
|
|
35
|
+
{ id: "1", role: "user", content: "What's the weather?" },
|
|
36
|
+
{ id: "2", role: "assistant", content: "It's sunny today." },
|
|
37
|
+
],
|
|
38
|
+
}),
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const mockMemoryComponent = {
|
|
42
|
+
recallMemory: vi.fn().mockResolvedValue("# 项目记忆\n\n暂无内容"),
|
|
43
|
+
recordMemory: vi.fn().mockResolvedValue({ path: "/test/memory.md", action: "overwrite" }),
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const mockAgentInstance = {
|
|
47
|
+
name: "memory-extract-project",
|
|
48
|
+
config: {
|
|
49
|
+
type: "sub",
|
|
50
|
+
systemPrompt: "",
|
|
51
|
+
allowedTools: ["search_sessions", "get_session", "write_memory"],
|
|
52
|
+
deniedTools: [],
|
|
53
|
+
},
|
|
54
|
+
status: "idle",
|
|
55
|
+
plugins: new Map(),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const mockAgentComponent = {
|
|
59
|
+
registerAgent: vi.fn().mockReturnValue(mockAgentInstance),
|
|
60
|
+
unregisterAgent: vi.fn(),
|
|
61
|
+
setDefaultTools: vi.fn(),
|
|
62
|
+
run: vi.fn().mockResolvedValue({
|
|
63
|
+
finalText: "Memory extracted successfully",
|
|
64
|
+
iterations: 1,
|
|
65
|
+
toolCalls: [],
|
|
66
|
+
}),
|
|
67
|
+
getAgent: vi.fn().mockReturnValue(mockAgentInstance),
|
|
68
|
+
getAvailableTools: vi.fn().mockReturnValue([
|
|
69
|
+
{ name: "search_sessions", execute: vi.fn() },
|
|
70
|
+
{ name: "get_session", execute: vi.fn() },
|
|
71
|
+
{ name: "write_memory", execute: vi.fn() },
|
|
72
|
+
]),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// Replicate runExtractMode logic for testing
|
|
76
|
+
async function testableRunExtractMode(
|
|
77
|
+
output: any,
|
|
78
|
+
memoryComponent: any,
|
|
79
|
+
agentComponent: any,
|
|
80
|
+
sessionComponent: any,
|
|
81
|
+
options: {
|
|
82
|
+
scope: "project" | "global";
|
|
83
|
+
sessionId?: string;
|
|
84
|
+
require?: string;
|
|
85
|
+
}
|
|
86
|
+
): Promise<void> {
|
|
87
|
+
const { scope, sessionId, require: userRequirement } = options;
|
|
88
|
+
|
|
89
|
+
// Get current memory
|
|
90
|
+
const currentMemory = await memoryComponent.recallMemory(scope) || "(无现有记忆)";
|
|
91
|
+
|
|
92
|
+
// Import getBuiltInPrompt and createMemoryAgentTools
|
|
93
|
+
const { getBuiltInPrompt, createMemoryAgentTools } = await import("@ai-setting/roy-agent-core");
|
|
94
|
+
|
|
95
|
+
// Build prompt
|
|
96
|
+
const promptTemplate = scope === "project"
|
|
97
|
+
? getBuiltInPrompt("project-memory")
|
|
98
|
+
: getBuiltInPrompt("global-memory");
|
|
99
|
+
|
|
100
|
+
if (!promptTemplate) {
|
|
101
|
+
throw new Error(`Prompt not found for scope: ${scope}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const systemPrompt = promptTemplate
|
|
105
|
+
.replace("{USER_REQUIREMENT}", userRequirement || "请从会话历史中提炼关键知识。")
|
|
106
|
+
.replace("{SCOPE}", scope)
|
|
107
|
+
.replace("{CURRENT_MEMORY}", currentMemory);
|
|
108
|
+
|
|
109
|
+
// Create tools
|
|
110
|
+
const memoryTools = createMemoryAgentTools({
|
|
111
|
+
sessionComponent,
|
|
112
|
+
memoryComponent,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Register agent
|
|
116
|
+
const agentName = `memory-extract-${scope}`;
|
|
117
|
+
agentComponent.registerAgent(agentName, {
|
|
118
|
+
type: "sub",
|
|
119
|
+
systemPrompt,
|
|
120
|
+
allowedTools: ["search_sessions", "get_session", "write_memory"],
|
|
121
|
+
deniedTools: [],
|
|
122
|
+
});
|
|
123
|
+
agentComponent.setDefaultTools([
|
|
124
|
+
memoryTools.searchSessions,
|
|
125
|
+
memoryTools.getSession,
|
|
126
|
+
memoryTools.writeMemory,
|
|
127
|
+
]);
|
|
128
|
+
|
|
129
|
+
// Run agent
|
|
130
|
+
const query = `请分析会话历史,提炼${scope === "project" ? "项目" : "全局"}记忆并写入记忆文件。`;
|
|
131
|
+
const result = await agentComponent.run(agentName, query, {
|
|
132
|
+
sessionId,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Handle result
|
|
136
|
+
if (result.error) {
|
|
137
|
+
output.error(`提取失败: ${result.error}`);
|
|
138
|
+
} else if (result.finalText) {
|
|
139
|
+
output.log(chalk.green("\n✅ 记忆提取完成"));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Cleanup
|
|
143
|
+
agentComponent.unregisterAgent(agentName);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Mock chalk after importing
|
|
147
|
+
import chalk from "chalk";
|
|
148
|
+
|
|
149
|
+
// Helper to create mock output
|
|
150
|
+
function createMockOutput() {
|
|
151
|
+
return {
|
|
152
|
+
log: vi.fn(),
|
|
153
|
+
info: vi.fn(),
|
|
154
|
+
warn: vi.fn(),
|
|
155
|
+
error: vi.fn(),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
describe("runExtractMode - E2E Test (replicated logic)", () => {
|
|
160
|
+
beforeEach(() => {
|
|
161
|
+
vi.clearAllMocks();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
afterEach(() => {
|
|
165
|
+
vi.restoreAllMocks();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test("should complete full extract flow with project scope", async () => {
|
|
169
|
+
const mockOutput = createMockOutput();
|
|
170
|
+
|
|
171
|
+
await testableRunExtractMode(
|
|
172
|
+
mockOutput,
|
|
173
|
+
mockMemoryComponent,
|
|
174
|
+
mockAgentComponent,
|
|
175
|
+
mockSessionComponent,
|
|
176
|
+
{
|
|
177
|
+
scope: "project",
|
|
178
|
+
sessionId: "test-session-123",
|
|
179
|
+
require: "重点关注配置信息",
|
|
180
|
+
}
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
// 1. Verify memory recall was called
|
|
184
|
+
expect(mockMemoryComponent.recallMemory).toHaveBeenCalledWith("project");
|
|
185
|
+
|
|
186
|
+
// 2. Verify agent registration
|
|
187
|
+
expect(mockAgentComponent.registerAgent).toHaveBeenCalledWith(
|
|
188
|
+
"memory-extract-project",
|
|
189
|
+
expect.objectContaining({
|
|
190
|
+
type: "sub",
|
|
191
|
+
allowedTools: expect.arrayContaining(["search_sessions", "get_session", "write_memory"]),
|
|
192
|
+
})
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
// 3. Verify default tools were set
|
|
196
|
+
expect(mockAgentComponent.setDefaultTools).toHaveBeenCalled();
|
|
197
|
+
|
|
198
|
+
// 4. Verify agent run was called with correct params
|
|
199
|
+
expect(mockAgentComponent.run).toHaveBeenCalledWith(
|
|
200
|
+
"memory-extract-project",
|
|
201
|
+
expect.stringContaining("分析会话历史"),
|
|
202
|
+
expect.objectContaining({
|
|
203
|
+
sessionId: "test-session-123",
|
|
204
|
+
})
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
// 5. Verify cleanup
|
|
208
|
+
expect(mockAgentComponent.unregisterAgent).toHaveBeenCalledWith("memory-extract-project");
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test("should complete full extract flow with global scope", async () => {
|
|
212
|
+
const mockOutput = createMockOutput();
|
|
213
|
+
|
|
214
|
+
await testableRunExtractMode(
|
|
215
|
+
mockOutput,
|
|
216
|
+
mockMemoryComponent,
|
|
217
|
+
mockAgentComponent,
|
|
218
|
+
mockSessionComponent,
|
|
219
|
+
{
|
|
220
|
+
scope: "global",
|
|
221
|
+
sessionId: "test-session-456",
|
|
222
|
+
require: "提取通用知识",
|
|
223
|
+
}
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
// Verify agent registration with global scope
|
|
227
|
+
expect(mockAgentComponent.registerAgent).toHaveBeenCalledWith(
|
|
228
|
+
"memory-extract-global",
|
|
229
|
+
expect.objectContaining({
|
|
230
|
+
type: "sub",
|
|
231
|
+
})
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
// Verify agent run with global scope
|
|
235
|
+
expect(mockAgentComponent.run).toHaveBeenCalledWith(
|
|
236
|
+
"memory-extract-global",
|
|
237
|
+
expect.stringContaining("全局"),
|
|
238
|
+
expect.objectContaining({
|
|
239
|
+
sessionId: "test-session-456",
|
|
240
|
+
})
|
|
241
|
+
);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
test("should use default requirement when not provided", async () => {
|
|
245
|
+
const mockOutput = createMockOutput();
|
|
246
|
+
|
|
247
|
+
await testableRunExtractMode(
|
|
248
|
+
mockOutput,
|
|
249
|
+
mockMemoryComponent,
|
|
250
|
+
mockAgentComponent,
|
|
251
|
+
mockSessionComponent,
|
|
252
|
+
{
|
|
253
|
+
scope: "project",
|
|
254
|
+
sessionId: "test-session",
|
|
255
|
+
}
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
// Verify agent was registered (requirement uses default)
|
|
259
|
+
expect(mockAgentComponent.registerAgent).toHaveBeenCalled();
|
|
260
|
+
expect(mockAgentComponent.run).toHaveBeenCalled();
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("should handle agent execution error", async () => {
|
|
264
|
+
const mockOutput = createMockOutput();
|
|
265
|
+
|
|
266
|
+
// Setup error scenario
|
|
267
|
+
mockAgentComponent.run.mockResolvedValueOnce({
|
|
268
|
+
finalText: undefined,
|
|
269
|
+
iterations: 1,
|
|
270
|
+
toolCalls: [],
|
|
271
|
+
error: "LLM invocation failed",
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
await testableRunExtractMode(
|
|
275
|
+
mockOutput,
|
|
276
|
+
mockMemoryComponent,
|
|
277
|
+
mockAgentComponent,
|
|
278
|
+
mockSessionComponent,
|
|
279
|
+
{
|
|
280
|
+
scope: "project",
|
|
281
|
+
sessionId: "test-session",
|
|
282
|
+
}
|
|
283
|
+
);
|
|
284
|
+
|
|
285
|
+
// Verify error was reported
|
|
286
|
+
expect(mockOutput.error).toHaveBeenCalledWith(expect.stringContaining("提取失败"));
|
|
287
|
+
|
|
288
|
+
// Verify cleanup still happened
|
|
289
|
+
expect(mockAgentComponent.unregisterAgent).toHaveBeenCalledWith("memory-extract-project");
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
test("should work without session ID", async () => {
|
|
293
|
+
const mockOutput = createMockOutput();
|
|
294
|
+
|
|
295
|
+
await testableRunExtractMode(
|
|
296
|
+
mockOutput,
|
|
297
|
+
mockMemoryComponent,
|
|
298
|
+
mockAgentComponent,
|
|
299
|
+
mockSessionComponent,
|
|
300
|
+
{
|
|
301
|
+
scope: "project",
|
|
302
|
+
sessionId: undefined,
|
|
303
|
+
}
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
// Verify agent run was called without sessionId
|
|
307
|
+
expect(mockAgentComponent.run).toHaveBeenCalledWith(
|
|
308
|
+
"memory-extract-project",
|
|
309
|
+
expect.any(String),
|
|
310
|
+
expect.not.objectContaining({ sessionId: expect.anything() })
|
|
311
|
+
);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
test("should verify tool names match between allowedTools and created tools", async () => {
|
|
315
|
+
const { createMemoryAgentTools } = await import("@ai-setting/roy-agent-core");
|
|
316
|
+
|
|
317
|
+
const tools = createMemoryAgentTools({
|
|
318
|
+
sessionComponent: mockSessionComponent,
|
|
319
|
+
memoryComponent: mockMemoryComponent,
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
// These are the allowedTools in the agent config
|
|
323
|
+
const allowedTools = ["search_sessions", "get_session", "write_memory"];
|
|
324
|
+
|
|
325
|
+
// Verify each allowed tool exists with matching name
|
|
326
|
+
expect(tools.searchSessions.name).toBe("search_sessions");
|
|
327
|
+
expect(tools.getSession.name).toBe("get_session");
|
|
328
|
+
expect(tools.writeMemory.name).toBe("write_memory");
|
|
329
|
+
|
|
330
|
+
// Verify all allowed tools are present
|
|
331
|
+
expect(allowedTools).toContain(tools.searchSessions.name);
|
|
332
|
+
expect(allowedTools).toContain(tools.getSession.name);
|
|
333
|
+
expect(allowedTools).toContain(tools.writeMemory.name);
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
describe("CLI parameter integration", () => {
|
|
338
|
+
test("should accept extract option", () => {
|
|
339
|
+
const options = {
|
|
340
|
+
mode: "append" as const,
|
|
341
|
+
extract: true,
|
|
342
|
+
scope: "project" as const,
|
|
343
|
+
"session-id": "sid:abc123",
|
|
344
|
+
require: "提取项目配置",
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
expect(options.extract).toBe(true);
|
|
348
|
+
expect(options.scope).toBe("project");
|
|
349
|
+
expect(options["session-id"]).toBe("sid:abc123");
|
|
350
|
+
expect(options.require).toBe("提取项目配置");
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
test("should accept global scope", () => {
|
|
354
|
+
const options = {
|
|
355
|
+
extract: true,
|
|
356
|
+
scope: "global" as const,
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
expect(options.scope).toBe("global");
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
test("should not require content when extract is true", () => {
|
|
363
|
+
const options = {
|
|
364
|
+
extract: true,
|
|
365
|
+
mode: "append" as const,
|
|
366
|
+
// content is intentionally omitted
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
// This is valid - extract mode doesn't need content
|
|
370
|
+
expect(options.extract).toBe(true);
|
|
371
|
+
expect((options as any).content).toBeUndefined();
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
test("should validate extract mode doesn't require content", () => {
|
|
375
|
+
// Simulate yargs check logic
|
|
376
|
+
const argv = {
|
|
377
|
+
mode: "append",
|
|
378
|
+
extract: true,
|
|
379
|
+
content: undefined,
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
// extract mode should pass validation
|
|
383
|
+
if (argv.extract) {
|
|
384
|
+
// Should pass without content
|
|
385
|
+
expect(true).toBe(true);
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Memory Commands Index - Simplified
|
|
3
|
+
*
|
|
4
|
+
* 导出所有 memory 子命令
|
|
5
|
+
*
|
|
6
|
+
* Simplified 设计:只保留 record 和 recall 两个核心命令
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export { MemoryCommand } from "./memory";
|
|
10
|
+
export { RecordCommand } from "./record";
|
|
11
|
+
export { RecallCommand } from "./recall";
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Memory Command Simplified Tests (TDD)
|
|
3
|
+
*
|
|
4
|
+
* 测试目标:验证简化后的 memory 命令设计
|
|
5
|
+
*
|
|
6
|
+
* Simplified 设计:只保留核心命令 record 和 recall
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, expect, test } from "vitest";
|
|
10
|
+
import { MemoryCommand } from "./memory";
|
|
11
|
+
|
|
12
|
+
describe("MemoryCommand - Simplified Design", () => {
|
|
13
|
+
describe("command configuration", () => {
|
|
14
|
+
test("should have correct command name", () => {
|
|
15
|
+
expect(MemoryCommand.command).toBe("memory");
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("should have simplified describe text", () => {
|
|
19
|
+
// 描述应该只列出核心命令:record 和 recall
|
|
20
|
+
expect(MemoryCommand.describe).toContain("record");
|
|
21
|
+
expect(MemoryCommand.describe).toContain("recall");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("should NOT mention old commands that were removed", () => {
|
|
25
|
+
// list, read, write, grep 已被移除
|
|
26
|
+
expect(MemoryCommand.describe).not.toContain("list");
|
|
27
|
+
expect(MemoryCommand.describe).not.toContain("read");
|
|
28
|
+
expect(MemoryCommand.describe).not.toContain("write");
|
|
29
|
+
expect(MemoryCommand.describe).not.toContain("grep");
|
|
30
|
+
expect(MemoryCommand.describe).not.toContain("paths");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("should NOT mention draft or organize commands", () => {
|
|
34
|
+
// draft 和 organize 已被移除
|
|
35
|
+
expect(MemoryCommand.describe).not.toContain("draft");
|
|
36
|
+
expect(MemoryCommand.describe).not.toContain("organize");
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe("should have essential subcommands", () => {
|
|
41
|
+
test("should register record command", () => {
|
|
42
|
+
expect(MemoryCommand.describe).toContain("record");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("should register recall command", () => {
|
|
46
|
+
expect(MemoryCommand.describe).toContain("recall");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("should NOT register removed commands", () => {
|
|
50
|
+
// 以下命令已被移除
|
|
51
|
+
expect(MemoryCommand.describe).not.toContain("list");
|
|
52
|
+
expect(MemoryCommand.describe).not.toContain("read");
|
|
53
|
+
expect(MemoryCommand.describe).not.toContain("write");
|
|
54
|
+
expect(MemoryCommand.describe).not.toContain("grep");
|
|
55
|
+
expect(MemoryCommand.describe).not.toContain("paths");
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Memory Command - Simplified
|
|
3
|
+
*
|
|
4
|
+
* 命令:roy memory
|
|
5
|
+
*
|
|
6
|
+
* Simplified 设计:只保留 record 和 recall 命令
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { CommandModule } from "yargs";
|
|
10
|
+
import { RecordCommand } from "./record";
|
|
11
|
+
import { RecallCommand } from "./recall";
|
|
12
|
+
|
|
13
|
+
export const MemoryCommand: CommandModule = {
|
|
14
|
+
command: "memory",
|
|
15
|
+
describe: "管理记忆文件 (record, recall)",
|
|
16
|
+
builder: (yargs) =>
|
|
17
|
+
yargs
|
|
18
|
+
.command(RecordCommand)
|
|
19
|
+
.command(RecallCommand)
|
|
20
|
+
.demandCommand(1, "请指定子命令。可用子命令: record, recall"),
|
|
21
|
+
|
|
22
|
+
handler: () => {
|
|
23
|
+
// 默认显示帮助
|
|
24
|
+
},
|
|
25
|
+
};
|