@loom-framework/core 0.1.0-alpha.6 → 0.1.0-alpha.61

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 (162) hide show
  1. package/dist/adapter-base.d.ts +29 -0
  2. package/dist/adapter-base.d.ts.map +1 -0
  3. package/dist/adapter-base.js +62 -0
  4. package/dist/adapter-base.js.map +1 -0
  5. package/dist/adapter-factory.d.ts +8 -0
  6. package/dist/adapter-factory.d.ts.map +1 -0
  7. package/dist/adapter-factory.js +25 -0
  8. package/dist/adapter-factory.js.map +1 -0
  9. package/dist/adapter-filesystem.d.ts +6 -11
  10. package/dist/adapter-filesystem.d.ts.map +1 -1
  11. package/dist/adapter-filesystem.js +17 -38
  12. package/dist/adapter-filesystem.js.map +1 -1
  13. package/dist/adapter-sqlite.d.ts +6 -23
  14. package/dist/adapter-sqlite.d.ts.map +1 -1
  15. package/dist/adapter-sqlite.js +45 -50
  16. package/dist/adapter-sqlite.js.map +1 -1
  17. package/dist/backend/ai/button-resolver.d.ts +18 -0
  18. package/dist/backend/ai/button-resolver.d.ts.map +1 -0
  19. package/dist/backend/ai/button-resolver.js +58 -0
  20. package/dist/backend/ai/button-resolver.js.map +1 -0
  21. package/dist/backend/ai/engine.d.ts +52 -0
  22. package/dist/backend/ai/engine.d.ts.map +1 -0
  23. package/dist/backend/ai/engine.js +189 -0
  24. package/dist/backend/ai/engine.js.map +1 -0
  25. package/dist/backend/ai/index.d.ts +11 -0
  26. package/dist/backend/ai/index.d.ts.map +1 -0
  27. package/dist/backend/ai/index.js +8 -0
  28. package/dist/backend/ai/index.js.map +1 -0
  29. package/dist/backend/ai/output-parser.d.ts +29 -0
  30. package/dist/backend/ai/output-parser.d.ts.map +1 -0
  31. package/dist/backend/ai/output-parser.js +247 -0
  32. package/dist/backend/ai/output-parser.js.map +1 -0
  33. package/dist/backend/ai/session-manager.d.ts +103 -0
  34. package/dist/backend/ai/session-manager.d.ts.map +1 -0
  35. package/dist/backend/ai/session-manager.js +298 -0
  36. package/dist/backend/ai/session-manager.js.map +1 -0
  37. package/dist/backend/index.d.ts +61 -0
  38. package/dist/backend/index.d.ts.map +1 -0
  39. package/dist/backend/index.js +160 -0
  40. package/dist/backend/index.js.map +1 -0
  41. package/dist/backend/observe/index.d.ts +6 -0
  42. package/dist/backend/observe/index.d.ts.map +1 -0
  43. package/dist/backend/observe/index.js +5 -0
  44. package/dist/backend/observe/index.js.map +1 -0
  45. package/dist/backend/observe/logger.d.ts +28 -0
  46. package/dist/backend/observe/logger.d.ts.map +1 -0
  47. package/dist/backend/observe/logger.js +80 -0
  48. package/dist/backend/observe/logger.js.map +1 -0
  49. package/dist/backend/observe/types.d.ts +26 -0
  50. package/dist/backend/observe/types.d.ts.map +1 -0
  51. package/dist/backend/observe/types.js +7 -0
  52. package/dist/backend/observe/types.js.map +1 -0
  53. package/dist/backend/routes/chat.d.ts +31 -0
  54. package/dist/backend/routes/chat.d.ts.map +1 -0
  55. package/dist/backend/routes/chat.js +426 -0
  56. package/dist/backend/routes/chat.js.map +1 -0
  57. package/dist/backend/routes/data.d.ts +13 -0
  58. package/dist/backend/routes/data.d.ts.map +1 -0
  59. package/dist/backend/routes/data.js +129 -0
  60. package/dist/backend/routes/data.js.map +1 -0
  61. package/dist/backend/routes/health.d.ts +7 -0
  62. package/dist/backend/routes/health.d.ts.map +1 -0
  63. package/dist/backend/routes/health.js +15 -0
  64. package/dist/backend/routes/health.js.map +1 -0
  65. package/dist/backend/routes/index.d.ts +9 -0
  66. package/dist/backend/routes/index.d.ts.map +1 -0
  67. package/dist/backend/routes/index.js +8 -0
  68. package/dist/backend/routes/index.js.map +1 -0
  69. package/dist/backend/routes/upload.d.ts +24 -0
  70. package/dist/backend/routes/upload.d.ts.map +1 -0
  71. package/dist/backend/routes/upload.js +67 -0
  72. package/dist/backend/routes/upload.js.map +1 -0
  73. package/dist/bin.d.ts +8 -0
  74. package/dist/bin.d.ts.map +1 -0
  75. package/dist/bin.js +12 -0
  76. package/dist/bin.js.map +1 -0
  77. package/dist/capability-generator.d.ts +16 -6
  78. package/dist/capability-generator.d.ts.map +1 -1
  79. package/dist/capability-generator.js +160 -248
  80. package/dist/capability-generator.js.map +1 -1
  81. package/dist/cli/commands/build.d.ts +11 -0
  82. package/dist/cli/commands/build.d.ts.map +1 -0
  83. package/dist/cli/commands/build.js +170 -0
  84. package/dist/cli/commands/build.js.map +1 -0
  85. package/dist/cli/commands/data.d.ts +12 -0
  86. package/dist/cli/commands/data.d.ts.map +1 -0
  87. package/dist/cli/commands/data.js +158 -0
  88. package/dist/cli/commands/data.js.map +1 -0
  89. package/dist/cli/commands/dev.d.ts +9 -0
  90. package/dist/cli/commands/dev.d.ts.map +1 -0
  91. package/dist/cli/commands/dev.js +114 -0
  92. package/dist/cli/commands/dev.js.map +1 -0
  93. package/dist/cli/commands/generate-capabilities.d.ts +8 -0
  94. package/dist/cli/commands/generate-capabilities.d.ts.map +1 -0
  95. package/dist/cli/commands/generate-capabilities.js +40 -0
  96. package/dist/cli/commands/generate-capabilities.js.map +1 -0
  97. package/dist/cli/commands/generate-cli-command.d.ts +8 -0
  98. package/dist/cli/commands/generate-cli-command.d.ts.map +1 -0
  99. package/dist/cli/commands/generate-cli-command.js +64 -0
  100. package/dist/cli/commands/generate-cli-command.js.map +1 -0
  101. package/dist/cli/commands/generate-page.d.ts +9 -0
  102. package/dist/cli/commands/generate-page.d.ts.map +1 -0
  103. package/dist/cli/commands/generate-page.js +418 -0
  104. package/dist/cli/commands/generate-page.js.map +1 -0
  105. package/dist/cli/commands/generate-skill.d.ts +8 -0
  106. package/dist/cli/commands/generate-skill.d.ts.map +1 -0
  107. package/dist/cli/commands/generate-skill.js +75 -0
  108. package/dist/cli/commands/generate-skill.js.map +1 -0
  109. package/dist/cli/commands/generate.d.ts +6 -0
  110. package/dist/cli/commands/generate.d.ts.map +1 -0
  111. package/dist/cli/commands/generate.js +17 -0
  112. package/dist/cli/commands/generate.js.map +1 -0
  113. package/dist/cli/commands/init.d.ts +8 -0
  114. package/dist/cli/commands/init.d.ts.map +1 -0
  115. package/dist/cli/commands/init.js +539 -0
  116. package/dist/cli/commands/init.js.map +1 -0
  117. package/dist/cli/commands/observe.d.ts +9 -0
  118. package/dist/cli/commands/observe.d.ts.map +1 -0
  119. package/dist/cli/commands/observe.js +142 -0
  120. package/dist/cli/commands/observe.js.map +1 -0
  121. package/dist/cli/commands/skill.d.ts +9 -0
  122. package/dist/cli/commands/skill.d.ts.map +1 -0
  123. package/dist/cli/commands/skill.js +186 -0
  124. package/dist/cli/commands/skill.js.map +1 -0
  125. package/dist/cli/helpers/duration.d.ts +5 -0
  126. package/dist/cli/helpers/duration.d.ts.map +1 -0
  127. package/dist/cli/helpers/duration.js +19 -0
  128. package/dist/cli/helpers/duration.js.map +1 -0
  129. package/dist/cli/helpers/field-template.d.ts +9 -0
  130. package/dist/cli/helpers/field-template.d.ts.map +1 -0
  131. package/dist/cli/helpers/field-template.js +92 -0
  132. package/dist/cli/helpers/field-template.js.map +1 -0
  133. package/dist/cli/helpers/naming.d.ts +12 -0
  134. package/dist/cli/helpers/naming.d.ts.map +1 -0
  135. package/dist/cli/helpers/naming.js +25 -0
  136. package/dist/cli/helpers/naming.js.map +1 -0
  137. package/dist/cli/index.d.ts +9 -0
  138. package/dist/cli/index.d.ts.map +1 -0
  139. package/dist/cli/index.js +33 -0
  140. package/dist/cli/index.js.map +1 -0
  141. package/dist/cli/utils.d.ts +10 -0
  142. package/dist/cli/utils.d.ts.map +1 -0
  143. package/dist/cli/utils.js +31 -0
  144. package/dist/cli/utils.js.map +1 -0
  145. package/dist/config.d.ts +8 -33
  146. package/dist/config.d.ts.map +1 -1
  147. package/dist/config.js +6 -7
  148. package/dist/config.js.map +1 -1
  149. package/dist/index.d.ts +6 -1
  150. package/dist/index.d.ts.map +1 -1
  151. package/dist/index.js +6 -0
  152. package/dist/index.js.map +1 -1
  153. package/dist/server-bin.d.ts +12 -0
  154. package/dist/server-bin.d.ts.map +1 -0
  155. package/dist/server-bin.js +75 -0
  156. package/dist/server-bin.js.map +1 -0
  157. package/dist/types.d.ts +28 -18
  158. package/dist/types.d.ts.map +1 -1
  159. package/package.json +17 -4
  160. package/templates/skill/SKILL.md +140 -0
  161. package/templates/skill/references/README.md +128 -0
  162. package/templates/skill/references/data-model.md +78 -0
@@ -1,288 +1,200 @@
1
1
  /**
2
2
  * Capability Generator
3
3
  *
4
- * Core innovation: One schema definition → MCP Server + CLI commands
4
+ * Core innovation: One schema definition → Skill + CLI data access
5
5
  *
6
6
  * From loom.config.ts model definitions, generates:
7
- * 1. MCP Server (.loom/mcp-server/) - structured data CRUD tools
8
- * 2. CLI data commands (cli/commands/data/) - dev/debug data access
9
- * 3. MCP config (.loom/mcp.json) - Claude Code MCP registration
7
+ * 1. SKILL.md user-written natural language (only generated on first run, never overwritten)
8
+ * 2. references/models.md auto-generated technical content (always overwritten on generate)
9
+ *
10
+ * This split ensures that user-filled descriptions/overview/scenarios survive re-generation.
10
11
  */
11
12
  import { promises as fs } from 'fs';
12
13
  import path from 'path';
13
- // ── MCP Tool Generation ──
14
+ // ── Skill Generation ──
15
+ /**
16
+ * Build a markdown table row for a model field
17
+ */
18
+ function fieldTableRow(f) {
19
+ const req = f.required ? 'yes' : 'no';
20
+ const enums = f.enum ? ` (${f.enum.join('/')})` : '';
21
+ const def = f.default !== undefined ? ` [default: ${JSON.stringify(f.default)}]` : '';
22
+ const desc = (f.description || '') + enums + def;
23
+ return `| ${f.name} | ${f.type} | ${req} | ${desc} |`;
24
+ }
14
25
  /**
15
- * Generate MCP server code from model schemas
26
+ * Build CLI examples for a specific model
16
27
  */
17
- function generateMcpToolForModel(model) {
18
- const modelName = model.name;
19
- const capitalName = modelName.split(/[-_]/).map(s => s.charAt(0).toUpperCase() + s.slice(1)).join('');
20
- const readParams = generateMcpParams(model, 'read');
21
- const writeParams = generateMcpParams(model, 'write');
22
- return `// Auto-generated by loom generate capabilities
23
- // Model: ${modelName}
28
+ function modelCliExamples(model) {
29
+ const name = model.name;
30
+ const requiredFields = model.fields.filter(f => f.required && f.name !== 'id');
31
+ const sampleData = requiredFields.length > 0
32
+ ? `{${requiredFields.map(f => `"${f.name}": "${f.type === 'number' ? '1' : f.enum ? f.enum[0] : 'value'}"`).join(', ')}}`
33
+ : '{}';
34
+ const firstRecordId = 'rec_xxx';
35
+ return `#### ${name}
24
36
 
25
- import { z } from 'zod';
26
- import type { DataAdapter } from '@loom-framework/core';
37
+ Read all records:
38
+ \`\`\`bash
39
+ loom data read ${name}
40
+ \`\`\`
27
41
 
28
- const ${modelName}Schema = z.object({
29
- ${model.fields.map(f => ` ${f.name}: ${fieldToZod(f)},`).join('\n')}
30
- });
42
+ Read by ID:
43
+ \`\`\`bash
44
+ loom data read ${name} --id ${firstRecordId}
45
+ \`\`\`
31
46
 
32
- export function register${capitalName}Tools(
33
- server: { tool: (name: string, description: string, schema: z.ZodObject<any>, handler: (params: any) => Promise<{ content: Array<{ type: string; text: string }> }>) => void },
34
- adapter: DataAdapter
35
- ) {
36
- // read_${modelName}
37
- server.tool(
38
- 'read_${modelName}',
39
- 'Read ${modelName} records${model.description ? ': ' + model.description : ''}',
40
- z.object({
41
- id: z.string().optional().describe('Record ID for single lookup'),
42
- filter: z.record(z.unknown()).optional().describe('Filter conditions'),
43
- limit: z.number().optional().describe('Max records to return'),
44
- }),
45
- async (params) => {
46
- const result = await adapter.read('${modelName}', params);
47
- return {
48
- content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
49
- };
50
- }
51
- );
47
+ Filter records:
48
+ \`\`\`bash
49
+ loom data read ${name} --filter '{"field": "value"}' --limit 10
50
+ \`\`\`
52
51
 
53
- // write_${modelName}
54
- server.tool(
55
- 'write_${modelName}',
56
- 'Create a new ${modelName} record',
57
- ${modelName}Schema,
58
- async (params) => {
59
- const result = await adapter.write('${modelName}', params);
60
- return {
61
- content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
62
- };
63
- }
64
- );
52
+ Create a record:
53
+ \`\`\`bash
54
+ loom data write ${name} --data '${sampleData}'
55
+ \`\`\`
65
56
 
66
- // update_${modelName}
67
- server.tool(
68
- 'update_${modelName}',
69
- 'Update an existing ${modelName} record',
70
- z.object({
71
- id: z.string().describe('Record ID to update'),
72
- data: ${modelName}Schema.partial().describe('Fields to update'),
73
- }),
74
- async (params) => {
75
- const result = await adapter.update('${modelName}', params.id, params.data);
76
- return {
77
- content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
78
- };
79
- }
80
- );
57
+ Update a record:
58
+ \`\`\`bash
59
+ loom data update ${name} --id ${firstRecordId} --data '{"field": "new_value"}'
60
+ \`\`\`
81
61
 
82
- // delete_${modelName}
83
- server.tool(
84
- 'delete_${modelName}',
85
- 'Delete a ${modelName} record',
86
- z.object({
87
- id: z.string().describe('Record ID to delete'),
88
- }),
89
- async (params) => {
90
- await adapter.delete('${modelName}', params.id);
91
- return {
92
- content: [{ type: 'text', text: \`Deleted ${modelName} record: \${params.id}\` }],
93
- };
94
- }
95
- );
96
- }`;
97
- }
98
- function fieldToZod(field) {
99
- const base = (() => {
100
- switch (field.type) {
101
- case 'string': return 'z.string()';
102
- case 'number': return 'z.number()';
103
- case 'boolean': return 'z.boolean()';
104
- case 'date': return 'z.string().describe("ISO date string")';
105
- case 'string[]': return 'z.array(z.string())';
106
- case 'number[]': return 'z.array(z.number())';
107
- case 'json': return 'z.unknown()';
108
- }
109
- })();
110
- const withDesc = field.description ? `${base}.describe("${field.description}")` : base;
111
- const withEnum = field.enum ? `z.enum([${field.enum.map(e => `"${e}"`).join(', ')}])` : withDesc;
112
- const withRequired = field.required ? withEnum : `${withEnum}.optional()`;
113
- return withRequired;
114
- }
115
- function generateMcpParams(model, operation) {
116
- if (operation === 'read') {
117
- return `{ id?: string, filter?: Record<string, unknown>, limit?: number }`;
118
- }
119
- return `{\n${model.fields.map(f => ` ${f.name}: ${f.type}${f.required ? '' : '?'},`).join('\n')}\n}`;
62
+ Delete a record:
63
+ \`\`\`bash
64
+ loom data delete ${name} --id ${firstRecordId}
65
+ \`\`\``;
120
66
  }
121
67
  /**
122
- * Generate MCP Server index.ts
68
+ * Generate the SKILL.md skeleton — only created on first run.
69
+ * Contains natural language sections with TODO placeholders for the user to fill in.
70
+ * References references/models.md for auto-generated technical content.
123
71
  */
124
- function generateMcpServerIndex(models) {
125
- const imports = models.map(m => {
126
- const capitalName = m.name.split(/[-_]/).map(s => s.charAt(0).toUpperCase() + s.slice(1)).join('');
127
- return `import { register${capitalName}Tools } from './tools/${m.name}.js';`;
128
- }).join('\n');
129
- const registrations = models.map(m => {
130
- const capitalName = m.name.split(/[-_]/).map(s => s.charAt(0).toUpperCase() + s.slice(1)).join('');
131
- return ` register${capitalName}Tools(server, adapter);`;
132
- }).join('\n');
133
- return `// Auto-generated by loom generate capabilities
134
- // Loom MCP Server - Data Access Layer
72
+ function generateSkillSkeleton(config) {
73
+ const projectName = config.project.name;
74
+ return `---
75
+ name: ${projectName}-data
76
+ description: |
77
+ TODO: Add trigger phrases for this project's app skill.
78
+ Example: "This skill should be used when the user asks to 'create a record', 'query data', 'update a record', or 'delete a record' in the ${projectName} project."
79
+ version: 1.0.0
80
+ ---
135
81
 
136
- import path from 'path';
137
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
138
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
139
- import { FileSystemAdapter } from '@loom-framework/core';
140
- import { loadConfig } from '@loom-framework/core';
141
- ${imports}
82
+ # ${projectName} App Skill
142
83
 
143
- async function main() {
144
- const projectRoot = process.env.LOOM_PROJECT_ROOT || process.cwd();
145
- const config = await loadConfig(projectRoot);
146
- const adapter = new FileSystemAdapter({
147
- dataDir: process.env.LOOM_DATA_DIR || path.join(projectRoot, 'data'),
148
- config,
149
- });
150
- await adapter.initialize();
84
+ ## Overview
151
85
 
152
- const server = new McpServer({
153
- name: 'loom-data',
154
- version: '1.0.0',
155
- });
86
+ TODO: Describe what this project does and how users interact with the data. For example: "This is an error tracking platform for elementary students. Users can manage subjects, wrong questions, and review plans through AI conversations."
156
87
 
157
- ${registrations}
88
+ ## Usage Scenarios
158
89
 
159
- const transport = new StdioServerTransport();
160
- await server.connect(transport);
161
- }
90
+ TODO: Add typical user requests and how to handle them with CLI commands. For example:
91
+ - "创建一个语文科目" → \`loom data write subjects --data '{"name": "语文"}'\`
92
+ - "查看所有未掌握的错题" → \`loom data read wrong_questions --filter '{"status": "未掌握"}'\`
93
+ - "把这道题标记为已掌握" → \`loom data update wrong_questions --id <id> --data '{"status": "已掌握"}'\`
94
+
95
+ ## Technical Reference
162
96
 
163
- main().catch(console.error);
97
+ For model schemas, CLI commands, AI buttons, and guidelines, see **references/models.md**.
164
98
  `;
165
99
  }
166
100
  /**
167
- * Generate .loom/mcp.json
101
+ * Generate references/models.md — always overwritten with latest technical content.
102
+ * Contains model schema tables, CLI command reference, AI button configs, and data access guidelines.
168
103
  */
169
- function generateMcpJson(projectRoot) {
170
- return JSON.stringify({
171
- mcpServers: {
172
- 'loom-data': {
173
- command: 'npx',
174
- args: ['tsx', '.loom/mcp-server/index.ts'],
175
- env: {
176
- LOOM_PROJECT_ROOT: projectRoot,
177
- LOOM_DATA_DIR: './data',
178
- },
179
- },
180
- },
181
- }, null, 2);
182
- }
183
- // ── CLI Command Generation ──
184
- /**
185
- * Generate CLI data command for a model
186
- */
187
- function generateCliDataCommand(model) {
188
- const modelName = model.name;
189
- return `// Auto-generated by loom generate capabilities
190
- // Model: ${modelName}
104
+ function generateModelsReference(config) {
105
+ const models = config.data.models;
106
+ const aiButtons = config.aiButtons || [];
107
+ // Build model schema sections
108
+ const modelSections = models.map(model => {
109
+ const header = `### ${model.name}${model.description ? ` — ${model.description}` : ''}`;
110
+ const tableHeader = '| Field | Type | Required | Description |';
111
+ const tableSep = '|-------|------|----------|-------------|';
112
+ const tableRows = model.fields.map(fieldTableRow).join('\n');
113
+ return `${header}\n\n${tableHeader}\n${tableSep}\n${tableRows}`;
114
+ }).join('\n\n');
115
+ // Build CLI examples section
116
+ const cliExamples = models.map(modelCliExamples).join('\n\n');
117
+ // Build AI buttons section
118
+ const buttonSection = aiButtons.length > 0
119
+ ? `## AI Buttons\n\n${aiButtons.map(btn => {
120
+ const placement = btn.placement ? ` (available on: ${btn.placement})` : ' (available on all pages)';
121
+ return `- **${btn.id}** ("${btn.label}"): \`${btn.prompt}\`${placement}`;
122
+ }).join('\n')}`
123
+ : '';
124
+ return `# Data Models & CLI Reference
125
+
126
+ > This file is auto-generated by \`loom generate capabilities\`. Do not edit manually — changes will be overwritten.
127
+
128
+ ## Data Models
129
+
130
+ ${modelSections}
131
+
132
+ ## CLI Commands
191
133
 
192
- import { defineCommand } from '@loom-framework/core';
134
+ All data operations use \`loom data\` CLI commands. Run from the project root directory.
193
135
 
194
- export default defineCommand({
195
- name: 'data:read:${modelName}',
196
- description: 'Read ${modelName} records${model.description ? ' - ' + model.description : ''}',
197
- options: {
198
- id: { type: 'string', description: 'Record ID for single lookup' },
199
- filter: { type: 'json', description: 'Filter conditions as JSON' },
200
- limit: { type: 'number', description: 'Max records to return' },
201
- },
202
- async execute(args, context) {
203
- const adapter = context.getDataAdapter();
204
- const result = await adapter.read('${modelName}', {
205
- id: args.id as string | undefined,
206
- filter: args.filter as Record<string, unknown> | undefined,
207
- limit: args.limit as number | undefined,
208
- });
209
- return JSON.stringify(result, null, 2);
210
- },
211
- });
136
+ ### Command Reference
137
+
138
+ | Command | Description |
139
+ |---------|-------------|
140
+ | \`loom data read <model> [--id <id>] [--filter <json>] [--limit <n>]\` | Read records |
141
+ | \`loom data write <model> --data '<json>'\` | Create a record |
142
+ | \`loom data update <model> --id <id> --data '<json>'\` | Update a record |
143
+ | \`loom data delete <model> --id <id>\` | Delete a record |
144
+ | \`loom data schema [model]\` | View model schema |
145
+
146
+ ### Examples by Model
147
+
148
+ ${cliExamples}
149
+ ${buttonSection ? '\n' + buttonSection + '\n' : ''}
150
+ ## Guidelines
151
+
152
+ 1. Use \`loom data\` CLI commands for all data operations. Do not access files or database directly.
153
+ 2. Run commands from the project root directory.
154
+ 3. Wrap JSON in single quotes to avoid shell escaping issues: \`--data '{"key": "value"}'\`
155
+ 4. Use \`--filter\` with JSON for queries: \`--filter '{"status": "未掌握"}'\`
156
+ 5. Confirm destructive operations (delete) with the user before executing.
157
+ 6. Prefer \`--limit\` for large datasets to avoid overwhelming output.
158
+ 7. CLI outputs JSON — parse the output to understand data structure.
159
+ 8. For write/update, ensure required fields are included. Use \`loom data schema <model>\` if unsure.
160
+ 9. The \`update\` command only needs the fields to change; unspecified fields are preserved.
161
+ 10. After data modifications, inform the user that the page will auto-refresh.
212
162
  `;
213
163
  }
214
164
  /**
215
- * Generate all capabilities from config
165
+ * Generate all capabilities from config.
166
+ *
167
+ * Two-file strategy:
168
+ * - SKILL.md: natural language content (only created if not exists, never overwritten)
169
+ * - references/models.md: technical content (always regenerated)
216
170
  */
217
171
  export async function generateCapabilities(projectRoot, config) {
218
- const loomDir = path.join(projectRoot, '.loom');
219
- const mcpServerDir = path.join(loomDir, 'mcp-server');
220
- const mcpToolsDir = path.join(mcpServerDir, 'tools');
221
- const cliDataDir = path.join(projectRoot, 'cli', 'src', 'commands', 'data');
172
+ const projectName = config.project.name;
173
+ const skillDir = path.join(projectRoot, '.claude', 'skills', projectName);
174
+ const skillPromptFile = path.join(skillDir, 'SKILL.md');
175
+ const referencesDir = path.join(skillDir, 'references');
176
+ const modelsFile = path.join(referencesDir, 'models.md');
222
177
  const filesWritten = [];
223
- // Clean and create directories
224
- await fs.mkdir(mcpToolsDir, { recursive: true });
225
- await fs.mkdir(cliDataDir, { recursive: true });
226
- // Generate MCP tools for each model
227
- for (const model of config.data.models) {
228
- // MCP tool file
229
- const mcpToolPath = path.join(mcpToolsDir, `${model.name}.ts`);
230
- await fs.writeFile(mcpToolPath, generateMcpToolForModel(model), 'utf-8');
231
- filesWritten.push(mcpToolPath);
232
- // CLI data command
233
- const cliCmdPath = path.join(cliDataDir, `${model.name}.ts`);
234
- await fs.writeFile(cliCmdPath, generateCliDataCommand(model), 'utf-8');
235
- filesWritten.push(cliCmdPath);
178
+ // Create skill directory structure
179
+ await fs.mkdir(referencesDir, { recursive: true });
180
+ // SKILL.md: only write if it doesn't exist (preserve user-written content)
181
+ const skillExists = await fs.access(skillPromptFile).then(() => true, () => false);
182
+ if (skillExists) {
183
+ // Update the reference pointer in existing SKILL.md if it doesn't have one
184
+ const existingContent = await fs.readFile(skillPromptFile, 'utf-8');
185
+ if (!existingContent.includes('references/models.md')) {
186
+ const updated = existingContent + '\n\n## Technical Reference\n\nFor model schemas, CLI commands, AI buttons, and guidelines, see **references/models.md**.\n';
187
+ await fs.writeFile(skillPromptFile, updated, 'utf-8');
188
+ }
189
+ }
190
+ else {
191
+ // First time: generate skeleton with TODO placeholders
192
+ await fs.writeFile(skillPromptFile, generateSkillSkeleton(config), 'utf-8');
193
+ filesWritten.push(skillPromptFile);
236
194
  }
237
- // Generate MCP Server index
238
- const indexPath = path.join(mcpServerDir, 'index.ts');
239
- await fs.writeFile(indexPath, generateMcpServerIndex(config.data.models), 'utf-8');
240
- filesWritten.push(indexPath);
241
- // Generate MCP Server package.json
242
- // Note: @loom-framework/core is resolved from parent project's node_modules at runtime (via tsx)
243
- const mcpPkgPath = path.join(mcpServerDir, 'package.json');
244
- await fs.writeFile(mcpPkgPath, JSON.stringify({
245
- name: 'loom-mcp-server',
246
- version: '1.0.0',
247
- type: 'module',
248
- main: 'index.js',
249
- dependencies: {
250
- '@modelcontextprotocol/sdk': '^1.12.0',
251
- '@loom-framework/core': '^0.1.0',
252
- 'zod': '^3.23.0',
253
- },
254
- devDependencies: {
255
- '@types/node': '^22.0.0',
256
- 'tsx': '^4.7.0',
257
- 'typescript': '^5.6.0',
258
- },
259
- }, null, 2), 'utf-8');
260
- filesWritten.push(mcpPkgPath);
261
- // Generate MCP Server tsconfig (self-contained, no external extends)
262
- const mcpTsconfigPath = path.join(mcpServerDir, 'tsconfig.json');
263
- await fs.writeFile(mcpTsconfigPath, JSON.stringify({
264
- compilerOptions: {
265
- target: 'ES2022',
266
- module: 'Node16',
267
- moduleResolution: 'Node16',
268
- lib: ['ES2022'],
269
- strict: true,
270
- esModuleInterop: true,
271
- skipLibCheck: true,
272
- forceConsistentCasingInFileNames: true,
273
- resolveJsonModule: true,
274
- declaration: true,
275
- sourceMap: true,
276
- outDir: '.',
277
- rootDir: '.',
278
- },
279
- include: ['*.ts', 'tools/*.ts'],
280
- }, null, 2), 'utf-8');
281
- filesWritten.push(mcpTsconfigPath);
282
- // Generate mcp.json
283
- const mcpJsonPath = path.join(loomDir, 'mcp.json');
284
- await fs.writeFile(mcpJsonPath, generateMcpJson(projectRoot), 'utf-8');
285
- filesWritten.push(mcpJsonPath);
286
- return { mcpServerDir, filesWritten };
195
+ // references/models.md: always regenerated with latest technical content
196
+ await fs.writeFile(modelsFile, generateModelsReference(config), 'utf-8');
197
+ filesWritten.push(modelsFile);
198
+ return { skillDir, skillPromptFile, modelsFile, filesWritten };
287
199
  }
288
200
  //# sourceMappingURL=capability-generator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"capability-generator.js","sourceRoot":"","sources":["../src/capability-generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"capability-generator.js","sourceRoot":"","sources":["../src/capability-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * loom build
3
+ *
4
+ * Build a Loom project for production:
5
+ * 1. Frontend (vite build) → dist/frontend/
6
+ * 2. Backend (tsc) → dist/backend/
7
+ * 3. MCP Server (copy source, runs via tsx) → dist/mcp-server/
8
+ */
9
+ import type { Command } from 'commander';
10
+ export declare function registerBuildCommand(program: Command): void;
11
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyBzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8D3D"}