@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.
- package/dist/adapter-base.d.ts +29 -0
- package/dist/adapter-base.d.ts.map +1 -0
- package/dist/adapter-base.js +62 -0
- package/dist/adapter-base.js.map +1 -0
- package/dist/adapter-factory.d.ts +8 -0
- package/dist/adapter-factory.d.ts.map +1 -0
- package/dist/adapter-factory.js +25 -0
- package/dist/adapter-factory.js.map +1 -0
- package/dist/adapter-filesystem.d.ts +6 -11
- package/dist/adapter-filesystem.d.ts.map +1 -1
- package/dist/adapter-filesystem.js +17 -38
- package/dist/adapter-filesystem.js.map +1 -1
- package/dist/adapter-sqlite.d.ts +6 -23
- package/dist/adapter-sqlite.d.ts.map +1 -1
- package/dist/adapter-sqlite.js +45 -50
- package/dist/adapter-sqlite.js.map +1 -1
- package/dist/backend/ai/button-resolver.d.ts +18 -0
- package/dist/backend/ai/button-resolver.d.ts.map +1 -0
- package/dist/backend/ai/button-resolver.js +58 -0
- package/dist/backend/ai/button-resolver.js.map +1 -0
- package/dist/backend/ai/engine.d.ts +52 -0
- package/dist/backend/ai/engine.d.ts.map +1 -0
- package/dist/backend/ai/engine.js +189 -0
- package/dist/backend/ai/engine.js.map +1 -0
- package/dist/backend/ai/index.d.ts +11 -0
- package/dist/backend/ai/index.d.ts.map +1 -0
- package/dist/backend/ai/index.js +8 -0
- package/dist/backend/ai/index.js.map +1 -0
- package/dist/backend/ai/output-parser.d.ts +29 -0
- package/dist/backend/ai/output-parser.d.ts.map +1 -0
- package/dist/backend/ai/output-parser.js +247 -0
- package/dist/backend/ai/output-parser.js.map +1 -0
- package/dist/backend/ai/session-manager.d.ts +103 -0
- package/dist/backend/ai/session-manager.d.ts.map +1 -0
- package/dist/backend/ai/session-manager.js +298 -0
- package/dist/backend/ai/session-manager.js.map +1 -0
- package/dist/backend/index.d.ts +61 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +160 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/observe/index.d.ts +6 -0
- package/dist/backend/observe/index.d.ts.map +1 -0
- package/dist/backend/observe/index.js +5 -0
- package/dist/backend/observe/index.js.map +1 -0
- package/dist/backend/observe/logger.d.ts +28 -0
- package/dist/backend/observe/logger.d.ts.map +1 -0
- package/dist/backend/observe/logger.js +80 -0
- package/dist/backend/observe/logger.js.map +1 -0
- package/dist/backend/observe/types.d.ts +26 -0
- package/dist/backend/observe/types.d.ts.map +1 -0
- package/dist/backend/observe/types.js +7 -0
- package/dist/backend/observe/types.js.map +1 -0
- package/dist/backend/routes/chat.d.ts +31 -0
- package/dist/backend/routes/chat.d.ts.map +1 -0
- package/dist/backend/routes/chat.js +426 -0
- package/dist/backend/routes/chat.js.map +1 -0
- package/dist/backend/routes/data.d.ts +13 -0
- package/dist/backend/routes/data.d.ts.map +1 -0
- package/dist/backend/routes/data.js +129 -0
- package/dist/backend/routes/data.js.map +1 -0
- package/dist/backend/routes/health.d.ts +7 -0
- package/dist/backend/routes/health.d.ts.map +1 -0
- package/dist/backend/routes/health.js +15 -0
- package/dist/backend/routes/health.js.map +1 -0
- package/dist/backend/routes/index.d.ts +9 -0
- package/dist/backend/routes/index.d.ts.map +1 -0
- package/dist/backend/routes/index.js +8 -0
- package/dist/backend/routes/index.js.map +1 -0
- package/dist/backend/routes/upload.d.ts +24 -0
- package/dist/backend/routes/upload.d.ts.map +1 -0
- package/dist/backend/routes/upload.js +67 -0
- package/dist/backend/routes/upload.js.map +1 -0
- package/dist/bin.d.ts +8 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +12 -0
- package/dist/bin.js.map +1 -0
- package/dist/capability-generator.d.ts +16 -6
- package/dist/capability-generator.d.ts.map +1 -1
- package/dist/capability-generator.js +160 -248
- package/dist/capability-generator.js.map +1 -1
- package/dist/cli/commands/build.d.ts +11 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +170 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/data.d.ts +12 -0
- package/dist/cli/commands/data.d.ts.map +1 -0
- package/dist/cli/commands/data.js +158 -0
- package/dist/cli/commands/data.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +9 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +114 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/generate-capabilities.d.ts +8 -0
- package/dist/cli/commands/generate-capabilities.d.ts.map +1 -0
- package/dist/cli/commands/generate-capabilities.js +40 -0
- package/dist/cli/commands/generate-capabilities.js.map +1 -0
- package/dist/cli/commands/generate-cli-command.d.ts +8 -0
- package/dist/cli/commands/generate-cli-command.d.ts.map +1 -0
- package/dist/cli/commands/generate-cli-command.js +64 -0
- package/dist/cli/commands/generate-cli-command.js.map +1 -0
- package/dist/cli/commands/generate-page.d.ts +9 -0
- package/dist/cli/commands/generate-page.d.ts.map +1 -0
- package/dist/cli/commands/generate-page.js +418 -0
- package/dist/cli/commands/generate-page.js.map +1 -0
- package/dist/cli/commands/generate-skill.d.ts +8 -0
- package/dist/cli/commands/generate-skill.d.ts.map +1 -0
- package/dist/cli/commands/generate-skill.js +75 -0
- package/dist/cli/commands/generate-skill.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +6 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +17 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +8 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +539 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/observe.d.ts +9 -0
- package/dist/cli/commands/observe.d.ts.map +1 -0
- package/dist/cli/commands/observe.js +142 -0
- package/dist/cli/commands/observe.js.map +1 -0
- package/dist/cli/commands/skill.d.ts +9 -0
- package/dist/cli/commands/skill.d.ts.map +1 -0
- package/dist/cli/commands/skill.js +186 -0
- package/dist/cli/commands/skill.js.map +1 -0
- package/dist/cli/helpers/duration.d.ts +5 -0
- package/dist/cli/helpers/duration.d.ts.map +1 -0
- package/dist/cli/helpers/duration.js +19 -0
- package/dist/cli/helpers/duration.js.map +1 -0
- package/dist/cli/helpers/field-template.d.ts +9 -0
- package/dist/cli/helpers/field-template.d.ts.map +1 -0
- package/dist/cli/helpers/field-template.js +92 -0
- package/dist/cli/helpers/field-template.js.map +1 -0
- package/dist/cli/helpers/naming.d.ts +12 -0
- package/dist/cli/helpers/naming.d.ts.map +1 -0
- package/dist/cli/helpers/naming.js +25 -0
- package/dist/cli/helpers/naming.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +33 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/utils.d.ts +10 -0
- package/dist/cli/utils.d.ts.map +1 -0
- package/dist/cli/utils.js +31 -0
- package/dist/cli/utils.js.map +1 -0
- package/dist/config.d.ts +8 -33
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -7
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/server-bin.d.ts +12 -0
- package/dist/server-bin.d.ts.map +1 -0
- package/dist/server-bin.js +75 -0
- package/dist/server-bin.js.map +1 -0
- package/dist/types.d.ts +28 -18
- package/dist/types.d.ts.map +1 -1
- package/package.json +17 -4
- package/templates/skill/SKILL.md +140 -0
- package/templates/skill/references/README.md +128 -0
- 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 →
|
|
4
|
+
* Core innovation: One schema definition → Skill + CLI data access
|
|
5
5
|
*
|
|
6
6
|
* From loom.config.ts model definitions, generates:
|
|
7
|
-
* 1.
|
|
8
|
-
* 2.
|
|
9
|
-
*
|
|
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
|
-
// ──
|
|
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
|
-
*
|
|
26
|
+
* Build CLI examples for a specific model
|
|
16
27
|
*/
|
|
17
|
-
function
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
26
|
-
|
|
37
|
+
Read all records:
|
|
38
|
+
\`\`\`bash
|
|
39
|
+
loom data read ${name}
|
|
40
|
+
\`\`\`
|
|
27
41
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
42
|
+
Read by ID:
|
|
43
|
+
\`\`\`bash
|
|
44
|
+
loom data read ${name} --id ${firstRecordId}
|
|
45
|
+
\`\`\`
|
|
31
46
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
|
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
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
88
|
+
## Usage Scenarios
|
|
158
89
|
|
|
159
|
-
|
|
160
|
-
|
|
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
|
-
|
|
97
|
+
For model schemas, CLI commands, AI buttons, and guidelines, see **references/models.md**.
|
|
164
98
|
`;
|
|
165
99
|
}
|
|
166
100
|
/**
|
|
167
|
-
* Generate
|
|
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
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
return
|
|
190
|
-
|
|
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
|
-
|
|
134
|
+
All data operations use \`loom data\` CLI commands. Run from the project root directory.
|
|
193
135
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
|
219
|
-
const
|
|
220
|
-
const
|
|
221
|
-
const
|
|
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
|
-
//
|
|
224
|
-
await fs.mkdir(
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
//
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
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
|
-
//
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
filesWritten
|
|
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":"AAAA
|
|
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"}
|