@vegamo/loom 0.1.1

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.
Files changed (196) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +465 -0
  3. package/dist/agents/core/agent.d.ts +65 -0
  4. package/dist/agents/core/agent.d.ts.map +1 -0
  5. package/dist/agents/core/agent.js +277 -0
  6. package/dist/agents/core/agent.js.map +1 -0
  7. package/dist/agents/core/prompt.d.ts +11 -0
  8. package/dist/agents/core/prompt.d.ts.map +1 -0
  9. package/dist/agents/core/prompt.js +117 -0
  10. package/dist/agents/core/prompt.js.map +1 -0
  11. package/dist/agents/core/types.d.ts +49 -0
  12. package/dist/agents/core/types.d.ts.map +1 -0
  13. package/dist/agents/core/types.js +5 -0
  14. package/dist/agents/core/types.js.map +1 -0
  15. package/dist/agents/memory/memory.d.ts +62 -0
  16. package/dist/agents/memory/memory.d.ts.map +1 -0
  17. package/dist/agents/memory/memory.js +113 -0
  18. package/dist/agents/memory/memory.js.map +1 -0
  19. package/dist/agents/memory/types.d.ts +15 -0
  20. package/dist/agents/memory/types.d.ts.map +1 -0
  21. package/dist/agents/memory/types.js +5 -0
  22. package/dist/agents/memory/types.js.map +1 -0
  23. package/dist/index.d.ts +13 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +104 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/llm/client.d.ts +49 -0
  28. package/dist/llm/client.d.ts.map +1 -0
  29. package/dist/llm/client.js +256 -0
  30. package/dist/llm/client.js.map +1 -0
  31. package/dist/llm/config.d.ts +13 -0
  32. package/dist/llm/config.d.ts.map +1 -0
  33. package/dist/llm/config.js +50 -0
  34. package/dist/llm/config.js.map +1 -0
  35. package/dist/llm/types.d.ts +74 -0
  36. package/dist/llm/types.d.ts.map +1 -0
  37. package/dist/llm/types.js +17 -0
  38. package/dist/llm/types.js.map +1 -0
  39. package/dist/mocks/generator.d.ts +10 -0
  40. package/dist/mocks/generator.d.ts.map +1 -0
  41. package/dist/mocks/generator.js +19 -0
  42. package/dist/mocks/generator.js.map +1 -0
  43. package/dist/mocks/router.d.ts +13 -0
  44. package/dist/mocks/router.d.ts.map +1 -0
  45. package/dist/mocks/router.js +44 -0
  46. package/dist/mocks/router.js.map +1 -0
  47. package/dist/mocks/server.d.ts +21 -0
  48. package/dist/mocks/server.d.ts.map +1 -0
  49. package/dist/mocks/server.js +36 -0
  50. package/dist/mocks/server.js.map +1 -0
  51. package/dist/serve.d.ts +17 -0
  52. package/dist/serve.d.ts.map +1 -0
  53. package/dist/serve.js +56 -0
  54. package/dist/serve.js.map +1 -0
  55. package/dist/shared/config-wizard.d.ts +7 -0
  56. package/dist/shared/config-wizard.d.ts.map +1 -0
  57. package/dist/shared/config-wizard.js +84 -0
  58. package/dist/shared/config-wizard.js.map +1 -0
  59. package/dist/shared/config.d.ts +32 -0
  60. package/dist/shared/config.d.ts.map +1 -0
  61. package/dist/shared/config.js +77 -0
  62. package/dist/shared/config.js.map +1 -0
  63. package/dist/shared/entity-utils.d.ts +30 -0
  64. package/dist/shared/entity-utils.d.ts.map +1 -0
  65. package/dist/shared/entity-utils.js +207 -0
  66. package/dist/shared/entity-utils.js.map +1 -0
  67. package/dist/shared/logger.d.ts +13 -0
  68. package/dist/shared/logger.d.ts.map +1 -0
  69. package/dist/shared/logger.js +45 -0
  70. package/dist/shared/logger.js.map +1 -0
  71. package/dist/shared/manifest-utils.d.ts +9 -0
  72. package/dist/shared/manifest-utils.d.ts.map +1 -0
  73. package/dist/shared/manifest-utils.js +110 -0
  74. package/dist/shared/manifest-utils.js.map +1 -0
  75. package/dist/shared/schema-entity-resolver.d.ts +15 -0
  76. package/dist/shared/schema-entity-resolver.d.ts.map +1 -0
  77. package/dist/shared/schema-entity-resolver.js +134 -0
  78. package/dist/shared/schema-entity-resolver.js.map +1 -0
  79. package/dist/shared/schema-utils.d.ts +21 -0
  80. package/dist/shared/schema-utils.d.ts.map +1 -0
  81. package/dist/shared/schema-utils.js +56 -0
  82. package/dist/shared/schema-utils.js.map +1 -0
  83. package/dist/shared/types.d.ts +130 -0
  84. package/dist/shared/types.d.ts.map +1 -0
  85. package/dist/shared/types.js +5 -0
  86. package/dist/shared/types.js.map +1 -0
  87. package/dist/tools/entity-file-ops.d.ts +10 -0
  88. package/dist/tools/entity-file-ops.d.ts.map +1 -0
  89. package/dist/tools/entity-file-ops.js +183 -0
  90. package/dist/tools/entity-file-ops.js.map +1 -0
  91. package/dist/tools/entity-workflow.d.ts +10 -0
  92. package/dist/tools/entity-workflow.d.ts.map +1 -0
  93. package/dist/tools/entity-workflow.js +447 -0
  94. package/dist/tools/entity-workflow.js.map +1 -0
  95. package/dist/tools/file-ops.d.ts +9 -0
  96. package/dist/tools/file-ops.d.ts.map +1 -0
  97. package/dist/tools/file-ops.js +83 -0
  98. package/dist/tools/file-ops.js.map +1 -0
  99. package/dist/tools/registry.d.ts +31 -0
  100. package/dist/tools/registry.d.ts.map +1 -0
  101. package/dist/tools/registry.js +58 -0
  102. package/dist/tools/registry.js.map +1 -0
  103. package/dist/tools/schema-gen.d.ts +8 -0
  104. package/dist/tools/schema-gen.d.ts.map +1 -0
  105. package/dist/tools/schema-gen.js +82 -0
  106. package/dist/tools/schema-gen.js.map +1 -0
  107. package/dist/tools/schema-validate.d.ts +8 -0
  108. package/dist/tools/schema-validate.d.ts.map +1 -0
  109. package/dist/tools/schema-validate.js +79 -0
  110. package/dist/tools/schema-validate.js.map +1 -0
  111. package/dist/tools/types.d.ts +29 -0
  112. package/dist/tools/types.d.ts.map +1 -0
  113. package/dist/tools/types.js +5 -0
  114. package/dist/tools/types.js.map +1 -0
  115. package/dist/tui/app.d.ts +13 -0
  116. package/dist/tui/app.d.ts.map +1 -0
  117. package/dist/tui/app.js +357 -0
  118. package/dist/tui/app.js.map +1 -0
  119. package/dist/tui/components/Chat.d.ts +14 -0
  120. package/dist/tui/components/Chat.d.ts.map +1 -0
  121. package/dist/tui/components/Chat.js +24 -0
  122. package/dist/tui/components/Chat.js.map +1 -0
  123. package/dist/tui/components/Header.d.ts +14 -0
  124. package/dist/tui/components/Header.d.ts.map +1 -0
  125. package/dist/tui/components/Header.js +6 -0
  126. package/dist/tui/components/Header.js.map +1 -0
  127. package/dist/tui/components/Input.d.ts +15 -0
  128. package/dist/tui/components/Input.d.ts.map +1 -0
  129. package/dist/tui/components/Input.js +74 -0
  130. package/dist/tui/components/Input.js.map +1 -0
  131. package/dist/tui/components/SchemaPreview.d.ts +13 -0
  132. package/dist/tui/components/SchemaPreview.d.ts.map +1 -0
  133. package/dist/tui/components/SchemaPreview.js +9 -0
  134. package/dist/tui/components/SchemaPreview.js.map +1 -0
  135. package/dist/tui/components/StatusBar.d.ts +15 -0
  136. package/dist/tui/components/StatusBar.d.ts.map +1 -0
  137. package/dist/tui/components/StatusBar.js +7 -0
  138. package/dist/tui/components/StatusBar.js.map +1 -0
  139. package/dist/tui/hooks/useAgent.d.ts +41 -0
  140. package/dist/tui/hooks/useAgent.d.ts.map +1 -0
  141. package/dist/tui/hooks/useAgent.js +180 -0
  142. package/dist/tui/hooks/useAgent.js.map +1 -0
  143. package/dist/view/frontend/components/App.d.ts +4 -0
  144. package/dist/view/frontend/components/App.d.ts.map +1 -0
  145. package/dist/view/frontend/components/App.js +35 -0
  146. package/dist/view/frontend/components/App.js.map +1 -0
  147. package/dist/view/frontend/components/EndpointDetailPage.d.ts +4 -0
  148. package/dist/view/frontend/components/EndpointDetailPage.d.ts.map +1 -0
  149. package/dist/view/frontend/components/EndpointDetailPage.js +103 -0
  150. package/dist/view/frontend/components/EndpointDetailPage.js.map +1 -0
  151. package/dist/view/frontend/components/HomePage.d.ts +4 -0
  152. package/dist/view/frontend/components/HomePage.d.ts.map +1 -0
  153. package/dist/view/frontend/components/HomePage.js +6 -0
  154. package/dist/view/frontend/components/HomePage.js.map +1 -0
  155. package/dist/view/frontend/components/ModuleDetailPage.d.ts +4 -0
  156. package/dist/view/frontend/components/ModuleDetailPage.d.ts.map +1 -0
  157. package/dist/view/frontend/components/ModuleDetailPage.js +64 -0
  158. package/dist/view/frontend/components/ModuleDetailPage.js.map +1 -0
  159. package/dist/view/frontend/components/ModulesPage.d.ts +4 -0
  160. package/dist/view/frontend/components/ModulesPage.d.ts.map +1 -0
  161. package/dist/view/frontend/components/ModulesPage.js +40 -0
  162. package/dist/view/frontend/components/ModulesPage.js.map +1 -0
  163. package/dist/view/frontend/index.d.ts +2 -0
  164. package/dist/view/frontend/index.d.ts.map +1 -0
  165. package/dist/view/frontend/index.js +15 -0
  166. package/dist/view/frontend/index.js.map +1 -0
  167. package/dist/view/frontend/types.d.ts +35 -0
  168. package/dist/view/frontend/types.d.ts.map +1 -0
  169. package/dist/view/frontend/types.js +2 -0
  170. package/dist/view/frontend/types.js.map +1 -0
  171. package/dist/view/frontend/utils/api.d.ts +5 -0
  172. package/dist/view/frontend/utils/api.d.ts.map +1 -0
  173. package/dist/view/frontend/utils/api.js +28 -0
  174. package/dist/view/frontend/utils/api.js.map +1 -0
  175. package/dist/view/public/bundle.js +104633 -0
  176. package/dist/view/public/bundle.js.map +7 -0
  177. package/dist/view/public/index.html +50 -0
  178. package/dist/view/routes/docs.d.ts +13 -0
  179. package/dist/view/routes/docs.d.ts.map +1 -0
  180. package/dist/view/routes/docs.js +53 -0
  181. package/dist/view/routes/docs.js.map +1 -0
  182. package/dist/view/routes/entities.d.ts +11 -0
  183. package/dist/view/routes/entities.d.ts.map +1 -0
  184. package/dist/view/routes/entities.js +39 -0
  185. package/dist/view/routes/entities.js.map +1 -0
  186. package/dist/view/routes/schema.d.ts +11 -0
  187. package/dist/view/routes/schema.d.ts.map +1 -0
  188. package/dist/view/routes/schema.js +43 -0
  189. package/dist/view/routes/schema.js.map +1 -0
  190. package/dist/view/server.d.ts +20 -0
  191. package/dist/view/server.d.ts.map +1 -0
  192. package/dist/view/server.js +54 -0
  193. package/dist/view/server.js.map +1 -0
  194. package/docgen.config.json +19 -0
  195. package/docgen.config.json.example +19 -0
  196. package/package.json +79 -0
@@ -0,0 +1,277 @@
1
+ /**
2
+ * Agent 主类
3
+ *
4
+ * 核心职责: 编排 LLM 调用与 Tool 执行的循环
5
+ *
6
+ * 流程:
7
+ * 1. 接收用户输入
8
+ * 2. 构建 messages (system prompt + memory + user message)
9
+ * 3. 调用 LLM (streaming)
10
+ * 4. 如果 LLM 返回 tool_calls → 执行工具 → 将结果拼入 messages → 回到步骤 3
11
+ * 5. 如果 LLM 返回纯文本 → 返回给用户
12
+ *
13
+ * 特性:
14
+ * - 支持 streaming (逐字输出到 TUI)
15
+ * - 自动降级到非 streaming (如果 streaming 不可用)
16
+ * - 完善的错误分类和向上传播
17
+ * - 通过事件系统通知上层进度
18
+ */
19
+ import { LLMClient } from '../../llm/client.js';
20
+ import { LLMError } from '../../llm/types.js';
21
+ import { ToolRegistry } from '../../tools/registry.js';
22
+ import { Memory } from '../memory/memory.js';
23
+ import { buildSystemPrompt } from './prompt.js';
24
+ import { listSchemaFiles } from '../../shared/schema-utils.js';
25
+ import { listEntityFiles } from '../../shared/entity-utils.js';
26
+ import { getOutDir } from '../../shared/config.js';
27
+ import { logger } from '../../shared/logger.js';
28
+ import { schemaGenTool } from '../../tools/schema-gen.js';
29
+ import { schemaValidateTool } from '../../tools/schema-validate.js';
30
+ import { listSchemasTool, readSchemaTool } from '../../tools/file-ops.js';
31
+ import { listEntitiesTool, readEntityTool, writeEntityTool } from '../../tools/entity-file-ops.js';
32
+ import { entityImpactTool, entitySyncTool, entityValidateTool } from '../../tools/entity-workflow.js';
33
+ const DEFAULT_MAX_ITERATIONS = 10;
34
+ export class Agent {
35
+ llm;
36
+ tools;
37
+ memory;
38
+ config;
39
+ toolContext;
40
+ state = 'idle';
41
+ abortController = null;
42
+ /** 事件回调 */
43
+ onEvent;
44
+ /** 向后兼容的状态变更回调 */
45
+ onStateChange;
46
+ constructor(config) {
47
+ this.config = config;
48
+ // 初始化 LLM 客户端
49
+ this.llm = new LLMClient(config.loomConfig.llm);
50
+ // 初始化工具注册中心
51
+ this.tools = new ToolRegistry();
52
+ this.tools.registerAll([
53
+ schemaGenTool,
54
+ schemaValidateTool,
55
+ listSchemasTool,
56
+ readSchemaTool,
57
+ listEntitiesTool,
58
+ readEntityTool,
59
+ writeEntityTool,
60
+ entityImpactTool,
61
+ entitySyncTool,
62
+ entityValidateTool,
63
+ ]);
64
+ // 初始化记忆
65
+ this.memory = new Memory();
66
+ // 工具执行上下文
67
+ const outDir = getOutDir(config.loomConfig, config.projectDir);
68
+ this.toolContext = {
69
+ projectDir: config.projectDir,
70
+ outDir,
71
+ };
72
+ // 设置 system prompt
73
+ this.initSystemPrompt();
74
+ }
75
+ /**
76
+ * 处理用户输入,返回 Agent 回复
77
+ *
78
+ * 根据 config.streaming 自动选择 streaming 或非 streaming 模式
79
+ */
80
+ async chat(userMessage) {
81
+ // 创建新的 abort controller
82
+ this.abortController = new AbortController();
83
+ // 添加用户消息到记忆
84
+ this.memory.add({ role: 'user', content: userMessage });
85
+ const schemasGenerated = [];
86
+ let totalToolCalls = 0;
87
+ let iterations = 0;
88
+ const maxIter = this.config.maxIterations ?? DEFAULT_MAX_ITERATIONS;
89
+ const useStreaming = this.config.streaming !== false;
90
+ try {
91
+ while (iterations < maxIter) {
92
+ iterations++;
93
+ // 调用 LLM
94
+ this.setState('thinking');
95
+ let response;
96
+ if (useStreaming) {
97
+ response = await this.callLLMStreaming();
98
+ }
99
+ else {
100
+ response = await this.callLLM();
101
+ }
102
+ // 如果没有 tool calls,返回纯文本回复
103
+ if (response.toolCalls.length === 0) {
104
+ const content = response.content || '';
105
+ this.memory.add({ role: 'assistant', content });
106
+ this.setState('idle');
107
+ this.emit({ type: 'reply_done' });
108
+ return { content, schemasGenerated, toolCallCount: totalToolCalls };
109
+ }
110
+ // 有 tool calls — 构建 assistant 消息并加入记忆
111
+ const assistantMessage = {
112
+ role: 'assistant',
113
+ content: response.content,
114
+ tool_calls: response.toolCalls.map((tc) => ({
115
+ id: tc.id,
116
+ type: 'function',
117
+ function: tc.function,
118
+ })),
119
+ };
120
+ this.memory.add(assistantMessage);
121
+ // 执行每个 tool call
122
+ this.setState('calling_tool');
123
+ for (const toolCall of response.toolCalls) {
124
+ const toolName = toolCall.function.name;
125
+ totalToolCalls++;
126
+ this.emit({
127
+ type: 'tool_start',
128
+ tool: { name: toolName },
129
+ });
130
+ // 向后兼容
131
+ this.onStateChange?.({
132
+ state: 'calling_tool',
133
+ message: `Calling ${toolName}...`,
134
+ toolName,
135
+ });
136
+ // 解析参数
137
+ let args;
138
+ try {
139
+ args = JSON.parse(toolCall.function.arguments);
140
+ }
141
+ catch (parseErr) {
142
+ logger.error(`Failed to parse arguments for tool "${toolName}": ${toolCall.function.arguments}`);
143
+ // 参数解析失败 → 将错误返回给 LLM,让它修正
144
+ const errorResult = {
145
+ success: false,
146
+ error: `Invalid JSON in tool arguments: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`,
147
+ };
148
+ this.memory.add({
149
+ role: 'tool',
150
+ tool_call_id: toolCall.id,
151
+ content: JSON.stringify(errorResult),
152
+ });
153
+ this.emit({
154
+ type: 'tool_end',
155
+ tool: { name: toolName, success: false, message: 'Invalid arguments' },
156
+ });
157
+ continue;
158
+ }
159
+ // 执行工具
160
+ const result = await this.tools.execute(toolName, args, this.toolContext);
161
+ // 记录生成的 schema 文件
162
+ if (toolName === 'write_schema' && result.success) {
163
+ const data = result.data;
164
+ if (data.filepath) {
165
+ schemasGenerated.push(data.filepath);
166
+ }
167
+ }
168
+ // 将 tool 结果加入记忆
169
+ this.memory.add({
170
+ role: 'tool',
171
+ tool_call_id: toolCall.id,
172
+ content: JSON.stringify(result),
173
+ });
174
+ this.emit({
175
+ type: 'tool_end',
176
+ tool: {
177
+ name: toolName,
178
+ success: result.success,
179
+ message: result.success
180
+ ? result.data?.message || 'Done'
181
+ : result.error || 'Failed',
182
+ },
183
+ });
184
+ }
185
+ }
186
+ // 超出最大轮次
187
+ logger.warn(`Agent reached max iterations (${maxIter})`);
188
+ this.setState('idle');
189
+ return {
190
+ content: 'I have reached the maximum number of tool call iterations. ' +
191
+ 'Please try a simpler request or break it into smaller steps.',
192
+ schemasGenerated,
193
+ toolCallCount: totalToolCalls,
194
+ };
195
+ }
196
+ catch (err) {
197
+ this.setState('error');
198
+ // 分类错误,给上层有意义的信息
199
+ if (err instanceof LLMError) {
200
+ this.emit({ type: 'error', error: `LLM error (${err.code}): ${err.message}` });
201
+ throw err;
202
+ }
203
+ const message = err instanceof Error ? err.message : String(err);
204
+ this.emit({ type: 'error', error: message });
205
+ throw new Error(`Agent error: ${message}`);
206
+ }
207
+ finally {
208
+ this.abortController = null;
209
+ }
210
+ }
211
+ /**
212
+ * 中断当前请求
213
+ */
214
+ abort() {
215
+ this.abortController?.abort();
216
+ this.setState('idle');
217
+ }
218
+ /**
219
+ * 重置对话
220
+ */
221
+ reset() {
222
+ this.abort();
223
+ this.memory.clear();
224
+ this.initSystemPrompt();
225
+ this.setState('idle');
226
+ }
227
+ // ============================================================
228
+ // LLM 调用 (内部)
229
+ // ============================================================
230
+ /**
231
+ * 非 streaming LLM 调用
232
+ */
233
+ async callLLM() {
234
+ return this.llm.chat({
235
+ messages: this.memory.getMessages(),
236
+ tools: this.tools.getDefinitions(),
237
+ signal: this.abortController?.signal,
238
+ });
239
+ }
240
+ /**
241
+ * Streaming LLM 调用
242
+ *
243
+ * 逐字发送 content_delta 事件到 TUI,同时累积完整响应
244
+ */
245
+ async callLLMStreaming() {
246
+ this.setState('streaming');
247
+ return this.llm.chatStream({
248
+ messages: this.memory.getMessages(),
249
+ tools: this.tools.getDefinitions(),
250
+ signal: this.abortController?.signal,
251
+ }, (event) => {
252
+ // 将 LLM stream 事件转发为 Agent 事件
253
+ if (event.type === 'content_delta' && event.delta) {
254
+ this.emit({ type: 'content_delta', delta: event.delta });
255
+ }
256
+ });
257
+ }
258
+ // ============================================================
259
+ // 内部工具方法
260
+ // ============================================================
261
+ initSystemPrompt() {
262
+ const existing = listSchemaFiles(this.toolContext.outDir);
263
+ const existingEntities = listEntityFiles(this.toolContext.outDir);
264
+ const prompt = buildSystemPrompt(existing.map((f) => f.filename), existingEntities.map((f) => f.filename));
265
+ this.memory.add({ role: 'system', content: prompt });
266
+ }
267
+ setState(state) {
268
+ this.state = state;
269
+ this.emit({ type: 'state_change', state });
270
+ // 向后兼容
271
+ this.onStateChange?.({ state });
272
+ }
273
+ emit(event) {
274
+ this.onEvent?.(event);
275
+ }
276
+ }
277
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../src/agents/core/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * System Prompt 模板管理
3
+ */
4
+ /**
5
+ * 构建 Agent 的 system prompt
6
+ *
7
+ * @param existingSchemas 当前已有的 schema 文件列表 (提供上下文)
8
+ * @param existingEntities 当前已有的实体文件列表
9
+ */
10
+ export declare function buildSystemPrompt(existingSchemas?: string[], existingEntities?: string[]): string;
11
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../src/agents/core/prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,eAAe,GAAE,MAAM,EAAO,EAC9B,gBAAgB,GAAE,MAAM,EAAO,GAC9B,MAAM,CA6GR"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * System Prompt 模板管理
3
+ */
4
+ /**
5
+ * 构建 Agent 的 system prompt
6
+ *
7
+ * @param existingSchemas 当前已有的 schema 文件列表 (提供上下文)
8
+ * @param existingEntities 当前已有的实体文件列表
9
+ */
10
+ export function buildSystemPrompt(existingSchemas = [], existingEntities = []) {
11
+ const schemaList = existingSchemas.length > 0
12
+ ? `\nExisting schema files in docs directory:\n${existingSchemas.map((s) => `- ${s}`).join('\n')}`
13
+ : '\nNo existing schema files yet.';
14
+ const entityList = existingEntities.length > 0
15
+ ? `\nExisting entity files in docs/entities:\n${existingEntities.map((s) => `- ${s}`).join('\n')}`
16
+ : '\nNo existing entity files yet.';
17
+ return `You are Loom, an AI assistant specialized in generating JSON Schema API documentation.
18
+
19
+ ## Your Role
20
+
21
+ Help users design RESTful API endpoints based on their business requirements, and generate well-structured JSON Schema documents that define API contracts.
22
+
23
+ ## Schema Document Format
24
+
25
+ Each schema file groups related API endpoints (e.g., all user-related APIs in one file). The file structure MUST follow this exact format:
26
+
27
+ \`\`\`json
28
+ {
29
+ "$schema": "http://json-schema.org/draft-07/schema#",
30
+ "title": "User Management API",
31
+ "description": "User registration, authentication, and profile management",
32
+ "version": "1.0.0",
33
+ "endpoints": [
34
+ {
35
+ "path": "/api/users/register",
36
+ "method": "POST",
37
+ "summary": "Register a new user",
38
+ "description": "Create a new user account with email and password",
39
+ "tags": ["auth"],
40
+ "request": {
41
+ "body": {
42
+ "type": "object",
43
+ "properties": {
44
+ "email": { "type": "string", "format": "email", "description": "User email address" },
45
+ "password": { "type": "string", "minLength": 8, "description": "User password, min 8 characters" },
46
+ "name": { "type": "string", "minLength": 1, "description": "Display name" }
47
+ },
48
+ "required": ["email", "password", "name"]
49
+ }
50
+ },
51
+ "response": {
52
+ "201": {
53
+ "type": "object",
54
+ "properties": {
55
+ "id": { "type": "integer", "description": "User ID" },
56
+ "email": { "type": "string" },
57
+ "name": { "type": "string" },
58
+ "createdAt": { "type": "string", "format": "date-time" }
59
+ },
60
+ "required": ["id", "email", "name", "createdAt"]
61
+ },
62
+ "400": {
63
+ "type": "object",
64
+ "properties": {
65
+ "error": { "type": "string" },
66
+ "message": { "type": "string" }
67
+ },
68
+ "required": ["error", "message"]
69
+ }
70
+ }
71
+ }
72
+ ]
73
+ }
74
+ \`\`\`
75
+
76
+ ## Rules
77
+
78
+ 1. **File naming**: Use lowercase with hyphens, always end with \`.schema.json\`. Examples: \`users.schema.json\`, \`order-management.schema.json\`.
79
+ 2. **Paths**: Use RESTful conventions. Use \`:paramName\` for path parameters (e.g., \`/api/users/:id\`).
80
+ 3. **Methods**: Use appropriate HTTP methods — GET (read), POST (create), PUT (full update), PATCH (partial update), DELETE (remove).
81
+ 4. **Request schemas**: Define \`body\` for POST/PUT/PATCH. Define \`query\` for GET filters/pagination. Define \`params\` for path parameters.
82
+ 5. **Response schemas**: Always include success status (200/201) and common error statuses (400, 404, 500). Each status code maps to a JSON Schema object.
83
+ 6. **JSON Schema**: Use draft-07. Include \`type\`, \`properties\`, \`required\`, \`description\`, and constraints (\`minLength\`, \`format\`, \`minimum\`, \`enum\`, etc.) where appropriate.
84
+ 7. **Grouping**: Group related endpoints in one file. For example, all user-related APIs (\`/api/users/*\`) in \`users.schema.json\`.
85
+ 8. **Modifying existing schemas**: When the user asks to modify/update/change existing APIs, ALWAYS:
86
+ - use \`list_schemas\` to find candidate files,
87
+ - use \`read_schema\` to load the target file,
88
+ - use \`write_schema\` with the SAME filename and \`mustExist: true\`.
89
+ Never create a new file unless the user explicitly asks for a new file.
90
+ 9. **Entity workflow**: When requests involve entities or entity-linked updates, follow this flow with tools:
91
+ - analyze impact using \`entity_impact\`,
92
+ - sync changes using \`entity_sync\` (dry-run first, then apply if user confirms or intent is explicit),
93
+ - validate consistency using \`entity_validate\`.
94
+ 10. **Entity references in endpoint schemas**: Use \`x-entity-ref\` on schema nodes:
95
+ - string form: \`"x-entity-ref": "User"\`
96
+ - object form: \`"x-entity-ref": { "entity": "User", "pick": ["id", "name"] }\`
97
+ 11. **Always use tools**: Never just show JSON in chat. Always use tools to read/write/validate.
98
+ 12. **Language**: Respond in the same language the user uses.
99
+
100
+ ## Available Tools
101
+
102
+ - \`write_schema\` — Write a complete schema document to a file (creates or overwrites, supports \`mustExist\` for update-only mode)
103
+ - \`validate_schema\` — Validate an existing schema file for correctness
104
+ - \`list_schemas\` — List all existing schema files in the docs directory
105
+ - \`read_schema\` — Read the full content of an existing schema file
106
+ - \`list_entities\` — List all entity definition files in docs/entities
107
+ - \`read_entity\` — Read one entity definition
108
+ - \`write_entity\` — Write one entity definition (supports \`mustExist\` for update-only mode)
109
+ - \`entity_impact\` — Analyze impacted endpoints/files for an entity change
110
+ - \`entity_sync\` — Sync endpoint schema fragments from entity refs
111
+ - \`entity_validate\` — Validate entity refs and schema consistency
112
+
113
+ ## Current State
114
+ ${schemaList}
115
+ ${entityList}`;
116
+ }
117
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../src/agents/core/prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,kBAA4B,EAAE,EAC9B,mBAA6B,EAAE;IAE/B,MAAM,UAAU,GACd,eAAe,CAAC,MAAM,GAAG,CAAC;QACxB,CAAC,CAAC,+CAA+C,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAClG,CAAC,CAAC,iCAAiC,CAAC;IACxC,MAAM,UAAU,GACd,gBAAgB,CAAC,MAAM,GAAG,CAAC;QACzB,CAAC,CAAC,8CAA8C,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAClG,CAAC,CAAC,iCAAiC,CAAC;IAExC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiGP,UAAU;EACV,UAAU,EAAE,CAAC;AACf,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Agent 核心类型定义
3
+ */
4
+ import type { LoomConfig } from '../../shared/types.js';
5
+ /** Agent 运行状态 */
6
+ export type AgentState = 'idle' | 'thinking' | 'streaming' | 'calling_tool' | 'error';
7
+ /** Agent 配置 */
8
+ export interface AgentConfig {
9
+ /** 全局配置 */
10
+ loomConfig: LoomConfig;
11
+ /** 目标项目目录 */
12
+ projectDir: string;
13
+ /** 最大工具调用轮次 (防止无限循环) */
14
+ maxIterations?: number;
15
+ /** 是否启用 streaming (默认 true) */
16
+ streaming?: boolean;
17
+ }
18
+ /** 事件类型 */
19
+ export type AgentEventType = 'state_change' | 'content_delta' | 'tool_start' | 'tool_end' | 'reply_done' | 'error';
20
+ /** Agent 事件 */
21
+ export interface AgentEvent {
22
+ type: AgentEventType;
23
+ /** state_change 时的新状态 */
24
+ state?: AgentState;
25
+ /** content_delta 时的文本片段 */
26
+ delta?: string;
27
+ /** tool_start / tool_end 时的工具信息 */
28
+ tool?: {
29
+ name: string;
30
+ /** tool_end 时表示是否成功 */
31
+ success?: boolean;
32
+ /** tool_end 时的结果摘要 */
33
+ message?: string;
34
+ };
35
+ /** error 时的错误信息 */
36
+ error?: string;
37
+ }
38
+ /** Agent 事件回调 */
39
+ export type AgentEventCallback = (event: AgentEvent) => void;
40
+ /** Agent 对用户的回复 */
41
+ export interface AgentReply {
42
+ /** 文本回复 */
43
+ content: string;
44
+ /** 本轮是否生成了新的 schema 文件 */
45
+ schemasGenerated: string[];
46
+ /** 本轮使用的 tool calls 数量 */
47
+ toolCallCount: number;
48
+ }
49
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/agents/core/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,iBAAiB;AACjB,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,cAAc,GAAG,OAAO,CAAC;AAEtF,eAAe;AACf,MAAM,WAAW,WAAW;IAC1B,WAAW;IACX,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,wBAAwB;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+BAA+B;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAMD,WAAW;AACX,MAAM,MAAM,cAAc,GACtB,cAAc,GACd,eAAe,GACf,YAAY,GACZ,UAAU,GACV,YAAY,GACZ,OAAO,CAAC;AAEZ,eAAe;AACf,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,yBAAyB;IACzB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,uBAAuB;QACvB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,sBAAsB;QACtB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,iBAAiB;AACjB,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;AAM7D,mBAAmB;AACnB,MAAM,WAAW,UAAU;IACzB,WAAW;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,0BAA0B;IAC1B,aAAa,EAAE,MAAM,CAAC;CACvB"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Agent 核心类型定义
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/agents/core/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * 对话历史管理
3
+ *
4
+ * 维护 Agent 与用户的对话上下文,支持上下文窗口控制
5
+ *
6
+ * 关键约束:
7
+ * - system 消息始终保留
8
+ * - tool_calls (assistant) 与 tool (result) 必须配对保留,不能截断一半
9
+ * - 裁剪时按"轮次"为单位,一轮 = user + assistant(可能带 tool_calls) + tool results
10
+ */
11
+ import type { ChatCompletionMessageParam } from 'openai/resources/chat/completions.js';
12
+ import type { MemoryConfig, ConversationSnapshot } from './types.js';
13
+ export declare class Memory {
14
+ private messages;
15
+ private maxMessages;
16
+ constructor(config?: MemoryConfig);
17
+ /**
18
+ * 添加一条消息
19
+ */
20
+ add(message: ChatCompletionMessageParam): void;
21
+ /**
22
+ * 批量添加消息
23
+ */
24
+ addAll(messages: ChatCompletionMessageParam[]): void;
25
+ /**
26
+ * 获取所有消息 (用于发送给 LLM)
27
+ */
28
+ getMessages(): ChatCompletionMessageParam[];
29
+ /**
30
+ * 获取消息数量
31
+ */
32
+ get length(): number;
33
+ /**
34
+ * 获取快照
35
+ */
36
+ snapshot(): ConversationSnapshot;
37
+ /**
38
+ * 清空历史
39
+ */
40
+ clear(): void;
41
+ /**
42
+ * 智能裁剪超出上限的旧消息
43
+ *
44
+ * 策略:
45
+ * 1. 分离 system 消息 (始终保留)
46
+ * 2. 将非 system 消息按"轮次"分组
47
+ * - 一个轮次 = [user, assistant(+tool_calls), tool_result_1, tool_result_2, ..., assistant(纯文本)]
48
+ * - 保证 tool_calls 和对应 tool results 不会被拆散
49
+ * 3. 从最老的轮次开始丢弃,直到总数 <= maxMessages
50
+ */
51
+ private trim;
52
+ /**
53
+ * 将消息序列按轮次分组
54
+ *
55
+ * 分组规则:
56
+ * - 遇到 user 消息 → 开始新轮次
57
+ * - assistant / tool 消息归入当前轮次
58
+ * - 保证每个轮次是一个完整的交互单元
59
+ */
60
+ private groupIntoRounds;
61
+ }
62
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/agents/memory/memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AACvF,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAIrE,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAoC;IACpD,OAAO,CAAC,WAAW,CAAS;gBAEhB,MAAM,CAAC,EAAE,YAAY;IAIjC;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,0BAA0B,GAAG,IAAI;IAK9C;;OAEG;IACH,MAAM,CAAC,QAAQ,EAAE,0BAA0B,EAAE,GAAG,IAAI;IAKpD;;OAEG;IACH,WAAW,IAAI,0BAA0B,EAAE;IAI3C;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,QAAQ,IAAI,oBAAoB;IAOhC;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;;;;;;;;OASG;IACH,OAAO,CAAC,IAAI;IAwBZ;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;CAoBxB"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * 对话历史管理
3
+ *
4
+ * 维护 Agent 与用户的对话上下文,支持上下文窗口控制
5
+ *
6
+ * 关键约束:
7
+ * - system 消息始终保留
8
+ * - tool_calls (assistant) 与 tool (result) 必须配对保留,不能截断一半
9
+ * - 裁剪时按"轮次"为单位,一轮 = user + assistant(可能带 tool_calls) + tool results
10
+ */
11
+ const DEFAULT_MAX_MESSAGES = 50;
12
+ export class Memory {
13
+ messages = [];
14
+ maxMessages;
15
+ constructor(config) {
16
+ this.maxMessages = config?.maxMessages ?? DEFAULT_MAX_MESSAGES;
17
+ }
18
+ /**
19
+ * 添加一条消息
20
+ */
21
+ add(message) {
22
+ this.messages.push(message);
23
+ this.trim();
24
+ }
25
+ /**
26
+ * 批量添加消息
27
+ */
28
+ addAll(messages) {
29
+ this.messages.push(...messages);
30
+ this.trim();
31
+ }
32
+ /**
33
+ * 获取所有消息 (用于发送给 LLM)
34
+ */
35
+ getMessages() {
36
+ return [...this.messages];
37
+ }
38
+ /**
39
+ * 获取消息数量
40
+ */
41
+ get length() {
42
+ return this.messages.length;
43
+ }
44
+ /**
45
+ * 获取快照
46
+ */
47
+ snapshot() {
48
+ return {
49
+ messages: this.getMessages(),
50
+ messageCount: this.messages.length,
51
+ };
52
+ }
53
+ /**
54
+ * 清空历史
55
+ */
56
+ clear() {
57
+ this.messages = [];
58
+ }
59
+ /**
60
+ * 智能裁剪超出上限的旧消息
61
+ *
62
+ * 策略:
63
+ * 1. 分离 system 消息 (始终保留)
64
+ * 2. 将非 system 消息按"轮次"分组
65
+ * - 一个轮次 = [user, assistant(+tool_calls), tool_result_1, tool_result_2, ..., assistant(纯文本)]
66
+ * - 保证 tool_calls 和对应 tool results 不会被拆散
67
+ * 3. 从最老的轮次开始丢弃,直到总数 <= maxMessages
68
+ */
69
+ trim() {
70
+ if (this.messages.length <= this.maxMessages)
71
+ return;
72
+ const systemMessages = this.messages.filter((m) => m.role === 'system');
73
+ const nonSystemMessages = this.messages.filter((m) => m.role !== 'system');
74
+ // 将消息按轮次分组
75
+ const rounds = this.groupIntoRounds(nonSystemMessages);
76
+ // 从最新轮次开始保留,直到超出预算
77
+ const budget = this.maxMessages - systemMessages.length;
78
+ const kept = [];
79
+ let totalKept = 0;
80
+ for (let i = rounds.length - 1; i >= 0; i--) {
81
+ const round = rounds[i];
82
+ if (totalKept + round.length > budget)
83
+ break;
84
+ kept.unshift(...round);
85
+ totalKept += round.length;
86
+ }
87
+ this.messages = [...systemMessages, ...kept];
88
+ }
89
+ /**
90
+ * 将消息序列按轮次分组
91
+ *
92
+ * 分组规则:
93
+ * - 遇到 user 消息 → 开始新轮次
94
+ * - assistant / tool 消息归入当前轮次
95
+ * - 保证每个轮次是一个完整的交互单元
96
+ */
97
+ groupIntoRounds(messages) {
98
+ const rounds = [];
99
+ let current = [];
100
+ for (const msg of messages) {
101
+ if (msg.role === 'user' && current.length > 0) {
102
+ rounds.push(current);
103
+ current = [];
104
+ }
105
+ current.push(msg);
106
+ }
107
+ if (current.length > 0) {
108
+ rounds.push(current);
109
+ }
110
+ return rounds;
111
+ }
112
+ }
113
+ //# sourceMappingURL=memory.js.map