@loom-framework/core 0.1.0-alpha.39 → 0.1.0-alpha.40

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 (138) hide show
  1. package/dist/backend/ai/button-resolver.d.ts +17 -0
  2. package/dist/backend/ai/button-resolver.d.ts.map +1 -0
  3. package/dist/backend/ai/button-resolver.js +40 -0
  4. package/dist/backend/ai/button-resolver.js.map +1 -0
  5. package/dist/backend/ai/engine.d.ts +51 -0
  6. package/dist/backend/ai/engine.d.ts.map +1 -0
  7. package/dist/backend/ai/engine.js +188 -0
  8. package/dist/backend/ai/engine.js.map +1 -0
  9. package/dist/backend/ai/index.d.ts +11 -0
  10. package/dist/backend/ai/index.d.ts.map +1 -0
  11. package/dist/backend/ai/index.js +8 -0
  12. package/dist/backend/ai/index.js.map +1 -0
  13. package/dist/backend/ai/output-parser.d.ts +29 -0
  14. package/dist/backend/ai/output-parser.d.ts.map +1 -0
  15. package/dist/backend/ai/output-parser.js +247 -0
  16. package/dist/backend/ai/output-parser.js.map +1 -0
  17. package/dist/backend/ai/session-manager.d.ts +102 -0
  18. package/dist/backend/ai/session-manager.d.ts.map +1 -0
  19. package/dist/backend/ai/session-manager.js +291 -0
  20. package/dist/backend/ai/session-manager.js.map +1 -0
  21. package/dist/backend/index.d.ts +61 -0
  22. package/dist/backend/index.d.ts.map +1 -0
  23. package/dist/backend/index.js +160 -0
  24. package/dist/backend/index.js.map +1 -0
  25. package/dist/backend/observe/index.d.ts +6 -0
  26. package/dist/backend/observe/index.d.ts.map +1 -0
  27. package/dist/backend/observe/index.js +5 -0
  28. package/dist/backend/observe/index.js.map +1 -0
  29. package/dist/backend/observe/logger.d.ts +28 -0
  30. package/dist/backend/observe/logger.d.ts.map +1 -0
  31. package/dist/backend/observe/logger.js +80 -0
  32. package/dist/backend/observe/logger.js.map +1 -0
  33. package/dist/backend/observe/types.d.ts +26 -0
  34. package/dist/backend/observe/types.d.ts.map +1 -0
  35. package/dist/backend/observe/types.js +7 -0
  36. package/dist/backend/observe/types.js.map +1 -0
  37. package/dist/backend/routes/chat.d.ts +31 -0
  38. package/dist/backend/routes/chat.d.ts.map +1 -0
  39. package/dist/backend/routes/chat.js +426 -0
  40. package/dist/backend/routes/chat.js.map +1 -0
  41. package/dist/backend/routes/data.d.ts +13 -0
  42. package/dist/backend/routes/data.d.ts.map +1 -0
  43. package/dist/backend/routes/data.js +129 -0
  44. package/dist/backend/routes/data.js.map +1 -0
  45. package/dist/backend/routes/health.d.ts +7 -0
  46. package/dist/backend/routes/health.d.ts.map +1 -0
  47. package/dist/backend/routes/health.js +15 -0
  48. package/dist/backend/routes/health.js.map +1 -0
  49. package/dist/backend/routes/index.d.ts +9 -0
  50. package/dist/backend/routes/index.d.ts.map +1 -0
  51. package/dist/backend/routes/index.js +8 -0
  52. package/dist/backend/routes/index.js.map +1 -0
  53. package/dist/backend/routes/upload.d.ts +24 -0
  54. package/dist/backend/routes/upload.d.ts.map +1 -0
  55. package/dist/backend/routes/upload.js +67 -0
  56. package/dist/backend/routes/upload.js.map +1 -0
  57. package/dist/bin.d.ts +8 -0
  58. package/dist/bin.d.ts.map +1 -0
  59. package/dist/bin.js +12 -0
  60. package/dist/bin.js.map +1 -0
  61. package/dist/cli/commands/build.d.ts +11 -0
  62. package/dist/cli/commands/build.d.ts.map +1 -0
  63. package/dist/cli/commands/build.js +170 -0
  64. package/dist/cli/commands/build.js.map +1 -0
  65. package/dist/cli/commands/data.d.ts +11 -0
  66. package/dist/cli/commands/data.d.ts.map +1 -0
  67. package/dist/cli/commands/data.js +137 -0
  68. package/dist/cli/commands/data.js.map +1 -0
  69. package/dist/cli/commands/dev.d.ts +9 -0
  70. package/dist/cli/commands/dev.d.ts.map +1 -0
  71. package/dist/cli/commands/dev.js +114 -0
  72. package/dist/cli/commands/dev.js.map +1 -0
  73. package/dist/cli/commands/generate-capabilities.d.ts +8 -0
  74. package/dist/cli/commands/generate-capabilities.d.ts.map +1 -0
  75. package/dist/cli/commands/generate-capabilities.js +40 -0
  76. package/dist/cli/commands/generate-capabilities.js.map +1 -0
  77. package/dist/cli/commands/generate-cli-command.d.ts +8 -0
  78. package/dist/cli/commands/generate-cli-command.d.ts.map +1 -0
  79. package/dist/cli/commands/generate-cli-command.js +64 -0
  80. package/dist/cli/commands/generate-cli-command.js.map +1 -0
  81. package/dist/cli/commands/generate-page.d.ts +9 -0
  82. package/dist/cli/commands/generate-page.d.ts.map +1 -0
  83. package/dist/cli/commands/generate-page.js +325 -0
  84. package/dist/cli/commands/generate-page.js.map +1 -0
  85. package/dist/cli/commands/generate-skill.d.ts +8 -0
  86. package/dist/cli/commands/generate-skill.d.ts.map +1 -0
  87. package/dist/cli/commands/generate-skill.js +75 -0
  88. package/dist/cli/commands/generate-skill.js.map +1 -0
  89. package/dist/cli/commands/generate.d.ts +6 -0
  90. package/dist/cli/commands/generate.d.ts.map +1 -0
  91. package/dist/cli/commands/generate.js +17 -0
  92. package/dist/cli/commands/generate.js.map +1 -0
  93. package/dist/cli/commands/init.d.ts +8 -0
  94. package/dist/cli/commands/init.d.ts.map +1 -0
  95. package/dist/cli/commands/init.js +400 -0
  96. package/dist/cli/commands/init.js.map +1 -0
  97. package/dist/cli/commands/observe.d.ts +9 -0
  98. package/dist/cli/commands/observe.d.ts.map +1 -0
  99. package/dist/cli/commands/observe.js +142 -0
  100. package/dist/cli/commands/observe.js.map +1 -0
  101. package/dist/cli/commands/skill.d.ts +9 -0
  102. package/dist/cli/commands/skill.d.ts.map +1 -0
  103. package/dist/cli/commands/skill.js +186 -0
  104. package/dist/cli/commands/skill.js.map +1 -0
  105. package/dist/cli/helpers/duration.d.ts +5 -0
  106. package/dist/cli/helpers/duration.d.ts.map +1 -0
  107. package/dist/cli/helpers/duration.js +19 -0
  108. package/dist/cli/helpers/duration.js.map +1 -0
  109. package/dist/cli/helpers/field-template.d.ts +9 -0
  110. package/dist/cli/helpers/field-template.d.ts.map +1 -0
  111. package/dist/cli/helpers/field-template.js +59 -0
  112. package/dist/cli/helpers/field-template.js.map +1 -0
  113. package/dist/cli/helpers/naming.d.ts +6 -0
  114. package/dist/cli/helpers/naming.d.ts.map +1 -0
  115. package/dist/cli/helpers/naming.js +14 -0
  116. package/dist/cli/helpers/naming.js.map +1 -0
  117. package/dist/cli/index.d.ts +9 -0
  118. package/dist/cli/index.d.ts.map +1 -0
  119. package/dist/cli/index.js +33 -0
  120. package/dist/cli/index.js.map +1 -0
  121. package/dist/cli/utils.d.ts +10 -0
  122. package/dist/cli/utils.d.ts.map +1 -0
  123. package/dist/cli/utils.js +31 -0
  124. package/dist/cli/utils.js.map +1 -0
  125. package/dist/index.d.ts +3 -0
  126. package/dist/index.d.ts.map +1 -1
  127. package/dist/index.js +4 -0
  128. package/dist/index.js.map +1 -1
  129. package/dist/server-bin.d.ts +12 -0
  130. package/dist/server-bin.d.ts.map +1 -0
  131. package/dist/server-bin.js +75 -0
  132. package/dist/server-bin.js.map +1 -0
  133. package/package.json +17 -5
  134. package/templates/skill/SKILL.md +91 -0
  135. package/templates/skill/references/README.md +67 -0
  136. package/templates/skill/references/data-model.md +87 -0
  137. package/templates/skill/references/skill-development.md +46 -0
  138. package/templates/skill/references/troubleshooting.md +35 -0
@@ -0,0 +1,400 @@
1
+ /**
2
+ * loom init <name>
3
+ *
4
+ * Create a new Loom project. All options via CLI flags, no interactive prompts.
5
+ */
6
+ import chalk from 'chalk';
7
+ import { promises as fs } from 'fs';
8
+ import path from 'path';
9
+ import { fileURLToPath } from 'url';
10
+ export function registerInitCommand(program) {
11
+ program
12
+ .command('init <name>')
13
+ .description('Create a new Loom project')
14
+ .option('-d, --description <desc>', 'Project description', '')
15
+ .option('-a, --adapter <adapter>', 'Data adapter (filesystem|sqlite)', 'filesystem')
16
+ .action(async (name, cmdOptions) => {
17
+ const options = {
18
+ name,
19
+ description: cmdOptions.description || '',
20
+ adapter: cmdOptions.adapter === 'sqlite' ? 'sqlite' : 'filesystem',
21
+ };
22
+ await createProject(options);
23
+ });
24
+ }
25
+ async function createProject(options) {
26
+ const targetDir = path.resolve(process.cwd(), options.name);
27
+ // Check if directory already exists
28
+ try {
29
+ await fs.access(targetDir);
30
+ console.error(chalk.red(`Directory "${options.name}" already exists.`));
31
+ process.exit(1);
32
+ }
33
+ catch {
34
+ // Directory does not exist, proceed
35
+ }
36
+ console.log();
37
+ console.log(chalk.bold.cyan(' Welcome to Loom!'));
38
+ console.log(chalk.dim(' Weave AI capabilities into your application'));
39
+ console.log();
40
+ console.log(chalk.dim(` Creating project in ${targetDir}...`));
41
+ console.log();
42
+ // Create directory structure
43
+ await createDirectoryStructure(targetDir);
44
+ // Copy SKILL.md + references from templates
45
+ await copySkillTemplates(targetDir);
46
+ // Create loom.config.ts
47
+ await createLoomConfig(targetDir, options);
48
+ // Create package.json
49
+ await createPackageJson(targetDir, options);
50
+ // Create README
51
+ await createReadme(targetDir, options);
52
+ // Create tsconfig
53
+ await createTsconfig(targetDir);
54
+ // Create vite config
55
+ await createViteConfig(targetDir);
56
+ // Create frontend entry files
57
+ await createFrontendEntry(targetDir, options);
58
+ // Create backend entry file
59
+ await createBackendEntry(targetDir);
60
+ // Create .gitignore
61
+ await createGitignore(targetDir);
62
+ // Install dependencies
63
+ await installDependencies(targetDir);
64
+ console.log();
65
+ console.log(chalk.green.bold(' Project created successfully!'));
66
+ console.log();
67
+ console.log(chalk.dim(' Next steps:'));
68
+ console.log(chalk.cyan(` cd ${options.name}`));
69
+ console.log(chalk.cyan(` loom generate page <Name> --model <model-name>`));
70
+ console.log(chalk.cyan(' loom dev'));
71
+ console.log();
72
+ }
73
+ async function createDirectoryStructure(targetDir) {
74
+ const dirs = [
75
+ '',
76
+ 'data',
77
+ '.claude',
78
+ '.claude/skills',
79
+ '.claude/skills/loom',
80
+ '.claude/skills/loom/references',
81
+ '.loom',
82
+ 'cli',
83
+ 'cli/src',
84
+ 'cli/src/commands',
85
+ 'frontend',
86
+ 'frontend/src',
87
+ 'frontend/src/components',
88
+ 'frontend/src/components/pages',
89
+ 'backend',
90
+ 'backend/src',
91
+ ];
92
+ for (const dir of dirs) {
93
+ await fs.mkdir(path.join(targetDir, dir), { recursive: true });
94
+ }
95
+ // Create .gitkeep files for empty directories
96
+ const gitkeepDirs = ['data', '.loom', 'cli/src/commands', 'frontend/src/components/pages', '.claude/skills/loom/references'];
97
+ for (const dir of gitkeepDirs) {
98
+ await fs.writeFile(path.join(targetDir, dir, '.gitkeep'), '', 'utf-8');
99
+ }
100
+ console.log(chalk.green(' ✓'), 'Directory structure');
101
+ }
102
+ async function copySkillTemplates(targetDir) {
103
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
104
+ // From dist/cli/commands/ → go up to package root → templates/skill/
105
+ const templatesDir = path.resolve(__dirname, '../../../templates/skill');
106
+ // Copy SKILL.md
107
+ const skillMd = await fs.readFile(path.join(templatesDir, 'SKILL.md'), 'utf-8');
108
+ await fs.writeFile(path.join(targetDir, '.claude/skills/loom/SKILL.md'), skillMd, 'utf-8');
109
+ console.log(chalk.green(' ✓'), '.claude/skills/loom/SKILL.md');
110
+ // Copy references
111
+ const refsDir = path.join(templatesDir, 'references');
112
+ const refFiles = await fs.readdir(refsDir);
113
+ for (const file of refFiles) {
114
+ if (file.endsWith('.md')) {
115
+ const content = await fs.readFile(path.join(refsDir, file), 'utf-8');
116
+ await fs.writeFile(path.join(targetDir, '.claude/skills/loom/references', file), content, 'utf-8');
117
+ }
118
+ }
119
+ console.log(chalk.green(' ✓'), `.claude/skills/loom/references/ (${refFiles.filter(f => f.endsWith('.md')).length} files)`);
120
+ }
121
+ async function createLoomConfig(targetDir, options) {
122
+ const config = `import { defineConfig } from '@loom-framework/core';
123
+
124
+ export default defineConfig({
125
+ project: {
126
+ name: '${options.name}',
127
+ description: '${options.description}',
128
+ },
129
+ data: {
130
+ defaultAdapter: '${options.adapter}',
131
+ models: [
132
+ {
133
+ name: 'items',
134
+ fields: [
135
+ { name: 'id', type: 'string', required: true },
136
+ { name: 'name', type: 'string', required: true },
137
+ { name: 'description', type: 'string' },
138
+ { name: 'createdAt', type: 'date' },
139
+ ],
140
+ // 示例模型 - 运行 loom generate page Items --model items 后可自定义
141
+ description: 'Example items model - customize or remove',
142
+ },
143
+ ],
144
+ },
145
+ });
146
+ `;
147
+ await fs.writeFile(path.join(targetDir, 'loom.config.ts'), config, 'utf-8');
148
+ console.log(chalk.green(' ✓'), 'loom.config.ts');
149
+ }
150
+ async function createPackageJson(targetDir, options) {
151
+ const pkg = {
152
+ name: options.name,
153
+ version: '0.1.0',
154
+ type: 'module',
155
+ scripts: {
156
+ dev: 'loom dev',
157
+ build: 'loom build',
158
+ generate: 'loom generate capabilities',
159
+ },
160
+ dependencies: {
161
+ '@loom-framework/core': '^0.1.0-alpha.40',
162
+ '@loom-framework/frontend-antd': '^0.1.0-alpha.40',
163
+ 'fastify': '^5.2.0',
164
+ '@ant-design/x': '^2.5.0',
165
+ '@ant-design/x-sdk': '^2.5.0',
166
+ '@ant-design/x-markdown': '^2.5.0',
167
+ '@ant-design/icons': '^6.1.1',
168
+ '@fastify/cors': '^10.0.0',
169
+ '@fastify/static': '^8.0.0',
170
+ 'react': '^19.0.0',
171
+ 'react-dom': '^19.0.0',
172
+ 'antd': '^6.3.5',
173
+ },
174
+ devDependencies: {
175
+ 'typescript': '^5.6.0',
176
+ 'tsx': '^4.7.0',
177
+ 'vite': '^6.0.0',
178
+ '@types/react': '^19.0.0',
179
+ '@types/react-dom': '^19.0.0',
180
+ '@vitejs/plugin-react': '^4.3.0',
181
+ },
182
+ };
183
+ await fs.writeFile(path.join(targetDir, 'package.json'), JSON.stringify(pkg, null, 2), 'utf-8');
184
+ console.log(chalk.green(' ✓'), 'package.json');
185
+ }
186
+ async function createReadme(targetDir, options) {
187
+ const readme = `# ${options.name}
188
+
189
+ ${options.description || 'A Loom application.'}
190
+
191
+ ## Getting Started
192
+
193
+ \`\`\`bash
194
+ # Generate a CRUD page from your data model
195
+ loom generate page <Name> --model <model-name>
196
+
197
+ # Start development servers (frontend + backend, hot-reload)
198
+ loom dev
199
+
200
+ # Build for production
201
+ loom build
202
+ \`\`\`
203
+
204
+ ## Project Structure
205
+
206
+ \`\`\`
207
+ ${options.name}/
208
+ ├── loom.config.ts # Project configuration
209
+ ├── data/ # Data storage (filesystem adapter)
210
+ ├── .claude/skills/ # AI skill definitions
211
+ ├── cli/ # CLI commands
212
+ ├── frontend/ # Frontend application
213
+ ├── backend/ # Backend server
214
+ └── .loom/ # Generated files (MCP server, etc.)
215
+ \`\`\`
216
+
217
+ ## Commands
218
+
219
+ - \`loom init <name>\` - Create a new project
220
+ - \`loom generate page <Name> --model <model>\` - Generate CRUD page (includes capabilities + wiring)
221
+ - \`loom generate skill <name>\` - Create a new skill
222
+ - \`loom dev\` - Start development servers
223
+ - \`loom build\` - Build all components
224
+ - \`loom data <command>\` - Data operations
225
+ - \`loom skill list\` - List skills
226
+ - \`loom skill validate\` - Validate skill definitions
227
+ `;
228
+ await fs.writeFile(path.join(targetDir, 'README.md'), readme, 'utf-8');
229
+ console.log(chalk.green(' ✓'), 'README.md');
230
+ }
231
+ async function createTsconfig(targetDir) {
232
+ const tsconfig = {
233
+ compilerOptions: {
234
+ target: 'ES2022',
235
+ module: 'Node16',
236
+ moduleResolution: 'Node16',
237
+ strict: true,
238
+ esModuleInterop: true,
239
+ skipLibCheck: true,
240
+ forceConsistentCasingInFileNames: true,
241
+ resolveJsonModule: true,
242
+ declaration: true,
243
+ sourceMap: true,
244
+ },
245
+ exclude: ['node_modules', 'dist', 'frontend'],
246
+ };
247
+ await fs.writeFile(path.join(targetDir, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2), 'utf-8');
248
+ console.log(chalk.green(' ✓'), 'tsconfig.json');
249
+ }
250
+ async function createViteConfig(targetDir) {
251
+ const viteConfig = `import { defineConfig } from 'vite';
252
+ import react from '@vitejs/plugin-react';
253
+
254
+ export default defineConfig({
255
+ plugins: [react()],
256
+ root: 'frontend',
257
+ build: {
258
+ outDir: '../dist/frontend',
259
+ emptyOutDir: true,
260
+ },
261
+ server: {
262
+ port: 5173,
263
+ proxy: {
264
+ '/api': 'http://localhost:3000',
265
+ },
266
+ },
267
+ });
268
+ `;
269
+ await fs.writeFile(path.join(targetDir, 'vite.config.ts'), viteConfig, 'utf-8');
270
+ console.log(chalk.green(' ✓'), 'vite.config.ts');
271
+ }
272
+ async function createFrontendEntry(targetDir, options) {
273
+ const mainTsx = `import React from 'react';
274
+ import ReactDOM from 'react-dom/client';
275
+ import App from './App';
276
+
277
+ ReactDOM.createRoot(document.getElementById('root')!).render(
278
+ <React.StrictMode>
279
+ <App />
280
+ </React.StrictMode>,
281
+ );
282
+ `;
283
+ const appTsx = `import React, { useState } from 'react';
284
+ import { AppShell } from '@loom-framework/frontend-antd';
285
+
286
+ const navItems = [
287
+ { key: 'home', label: '首页' },
288
+ // Add more nav items as you generate pages:
289
+ // { key: 'model-name', label: '模型名' },
290
+ ];
291
+
292
+ export default function App() {
293
+ const [selectedKey, setSelectedKey] = useState('home');
294
+
295
+ const renderPage = () => {
296
+ switch (selectedKey) {
297
+ case 'home':
298
+ default:
299
+ return (
300
+ <div style={{ padding: 24 }}>
301
+ <h2>${options.name}</h2>
302
+ <p>${options.description || 'A Loom application.'}</p>
303
+ <p>运行 <code>loom generate page &lt;Name&gt; --model &lt;model&gt;</code> 生成页面后,在此处引入。</p>
304
+ </div>
305
+ );
306
+ }
307
+ };
308
+
309
+ return (
310
+ <AppShell
311
+ title="${options.name}"
312
+ navItems={navItems}
313
+ selectedNavKey={selectedKey}
314
+ onNavClick={setSelectedKey}
315
+ baseUrl=""
316
+ >
317
+ {renderPage()}
318
+ </AppShell>
319
+ );
320
+ }
321
+ `;
322
+ const indexHtml = `<!DOCTYPE html>
323
+ <html lang="en">
324
+ <head>
325
+ <meta charset="UTF-8" />
326
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
327
+ <title>${options.name}</title>
328
+ </head>
329
+ <body>
330
+ <div id="root"></div>
331
+ <script type="module" src="/src/main.tsx"></script>
332
+ </body>
333
+ </html>
334
+ `;
335
+ await fs.writeFile(path.join(targetDir, 'frontend/src/main.tsx'), mainTsx, 'utf-8');
336
+ await fs.writeFile(path.join(targetDir, 'frontend/src/App.tsx'), appTsx, 'utf-8');
337
+ await fs.writeFile(path.join(targetDir, 'frontend/index.html'), indexHtml, 'utf-8');
338
+ const frontendTsconfig = `{
339
+ "compilerOptions": {
340
+ "target": "ES2022",
341
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
342
+ "module": "ESNext",
343
+ "moduleResolution": "bundler",
344
+ "jsx": "react-jsx",
345
+ "strict": true,
346
+ "esModuleInterop": true,
347
+ "skipLibCheck": true,
348
+ "forceConsistentCasingInFileNames": true,
349
+ "resolveJsonModule": true,
350
+ "isolatedModules": true,
351
+ "noEmit": true
352
+ },
353
+ "include": ["src"]
354
+ }
355
+ `;
356
+ await fs.writeFile(path.join(targetDir, 'frontend/tsconfig.json'), frontendTsconfig, 'utf-8');
357
+ console.log(chalk.green(' ✓'), 'frontend entry files');
358
+ }
359
+ async function createBackendEntry(targetDir) {
360
+ const serverTs = `import { fileURLToPath } from 'url';
361
+ import path from 'path';
362
+ import { LoomServer } from '@loom-framework/core';
363
+
364
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
365
+ const projectRoot = path.resolve(__dirname, '../..');
366
+
367
+ const server = new LoomServer({ projectRoot });
368
+ await server.initialize();
369
+ await server.start();
370
+ `;
371
+ await fs.writeFile(path.join(targetDir, 'backend/src/index.ts'), serverTs, 'utf-8');
372
+ console.log(chalk.green(' ✓'), 'backend/src/index.ts');
373
+ }
374
+ async function createGitignore(targetDir) {
375
+ const gitignore = `node_modules/
376
+ dist/
377
+ .loom/
378
+ *.local
379
+ .env
380
+ data/*.db
381
+ `;
382
+ await fs.writeFile(path.join(targetDir, '.gitignore'), gitignore, 'utf-8');
383
+ console.log(chalk.green(' ✓'), '.gitignore');
384
+ }
385
+ async function installDependencies(targetDir) {
386
+ const { execSync } = await import('child_process');
387
+ console.log(chalk.dim(' Installing dependencies...'));
388
+ try {
389
+ execSync('npm install', {
390
+ cwd: targetDir,
391
+ stdio: 'pipe',
392
+ timeout: 120000,
393
+ });
394
+ console.log(chalk.green(' ✓'), 'Dependencies installed');
395
+ }
396
+ catch {
397
+ console.log(chalk.yellow(' ⚠'), 'Dependency installation failed. Run `npm install` manually.');
398
+ }
399
+ }
400
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * loom observe - Observability commands
3
+ *
4
+ * loom observe logs [--session <id>] [--last <duration>]
5
+ * loom observe metrics
6
+ */
7
+ import type { Command } from 'commander';
8
+ export declare function registerObserveCommand(program: Command): void;
9
+ //# sourceMappingURL=observe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/observe.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiH7D"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * loom observe - Observability commands
3
+ *
4
+ * loom observe logs [--session <id>] [--last <duration>]
5
+ * loom observe metrics
6
+ */
7
+ import chalk from 'chalk';
8
+ import { promises as fs } from 'fs';
9
+ import path from 'path';
10
+ import { resolveProjectRoot } from '../utils.js';
11
+ import { parseDuration } from '../helpers/duration.js';
12
+ export function registerObserveCommand(program) {
13
+ const observe = program
14
+ .command('observe')
15
+ .description('Observability: logs and metrics');
16
+ // loom observe logs
17
+ observe
18
+ .command('logs')
19
+ .description('View AI interaction logs')
20
+ .option('--session <id>', 'Filter by session ID')
21
+ .option('--last <duration>', 'Filter by time range (e.g. 1h, 30m, 7d)')
22
+ .option('--limit <number>', 'Max number of logs to show', parseInt, 20)
23
+ .action(async (options) => {
24
+ try {
25
+ const projectRoot = await resolveProjectRoot();
26
+ const logsDir = path.join(projectRoot, '.loom', 'logs');
27
+ const logs = await readLogs(logsDir, {
28
+ session: options.session,
29
+ last: options.last,
30
+ });
31
+ if (logs.length === 0) {
32
+ console.log(chalk.dim('No interaction logs found.'));
33
+ return;
34
+ }
35
+ const display = logs.slice(0, options.limit);
36
+ for (const entry of display) {
37
+ const duration = chalk.dim(`${entry.duration}ms`);
38
+ const ts = chalk.gray(new Date(entry.timestamp).toLocaleString());
39
+ const session = chalk.cyan(entry.sessionId.slice(0, 16));
40
+ const tokens = entry.usage
41
+ ? chalk.dim(`in:${entry.usage.inputTokens} out:${entry.usage.outputTokens}`)
42
+ : '';
43
+ console.log(chalk.bold(`[${entry.messageId}]`) + ` ${ts} ${session} ${duration} ${tokens}`);
44
+ console.log(` ${chalk.dim('Prompt:')} ${entry.prompt.slice(0, 100)}${entry.prompt.length > 100 ? '...' : ''}`);
45
+ console.log(` ${chalk.dim('Response:')} ${entry.response.slice(0, 100)}${entry.response.length > 100 ? '...' : ''}`);
46
+ if (entry.error) {
47
+ console.log(` ${chalk.red('Error:')} ${entry.error}`);
48
+ }
49
+ if (entry.mcpCalls.length > 0) {
50
+ console.log(` ${chalk.dim('MCP:')} ${entry.mcpCalls.join(', ')}`);
51
+ }
52
+ if (entry.cliCalls.length > 0) {
53
+ console.log(` ${chalk.dim('CLI:')} ${entry.cliCalls.join(', ')}`);
54
+ }
55
+ console.log();
56
+ }
57
+ console.log(chalk.dim(`Showing ${display.length} of ${logs.length} logs`));
58
+ }
59
+ catch (err) {
60
+ const message = err instanceof Error ? err.message : String(err);
61
+ console.error(chalk.red('Failed to read logs:'), message);
62
+ process.exit(1);
63
+ }
64
+ });
65
+ // loom observe metrics
66
+ observe
67
+ .command('metrics')
68
+ .description('View aggregated metrics from AI interaction logs')
69
+ .action(async () => {
70
+ try {
71
+ const projectRoot = await resolveProjectRoot();
72
+ const logsDir = path.join(projectRoot, '.loom', 'logs');
73
+ const logs = await readLogs(logsDir);
74
+ if (logs.length === 0) {
75
+ console.log(chalk.dim('No interaction logs found. Run some AI interactions first.'));
76
+ return;
77
+ }
78
+ const totalInteractions = logs.length;
79
+ const avgResponseTime = Math.round(logs.reduce((sum, l) => sum + l.duration, 0) / totalInteractions);
80
+ const errorLogs = logs.filter((l) => l.error);
81
+ const errorRate = ((errorLogs.length / totalInteractions) * 100).toFixed(1);
82
+ const totalInputTokens = logs.reduce((sum, l) => sum + (l.usage?.inputTokens || 0), 0);
83
+ const totalOutputTokens = logs.reduce((sum, l) => sum + (l.usage?.outputTokens || 0), 0);
84
+ // Skill trigger counts from mcpCalls / cliCalls
85
+ const skillCounts = {};
86
+ for (const log of logs) {
87
+ for (const call of [...log.mcpCalls, ...log.cliCalls]) {
88
+ skillCounts[call] = (skillCounts[call] || 0) + 1;
89
+ }
90
+ }
91
+ console.log(chalk.bold('Loom Metrics'));
92
+ console.log();
93
+ console.log(` ${chalk.cyan('Total Interactions:')} ${totalInteractions}`);
94
+ console.log(` ${chalk.cyan('Avg Response Time:')} ${avgResponseTime}ms`);
95
+ console.log(` ${chalk.cyan('Tokens Used:')} in:${totalInputTokens} out:${totalOutputTokens}`);
96
+ console.log(` ${chalk.cyan('Error Rate:')} ${errorRate}%`);
97
+ if (Object.keys(skillCounts).length > 0) {
98
+ console.log();
99
+ console.log(chalk.cyan(' Tool/Skill Calls:'));
100
+ for (const [name, count] of Object.entries(skillCounts).sort((a, b) => b[1] - a[1])) {
101
+ console.log(` ${name}: ${count}`);
102
+ }
103
+ }
104
+ }
105
+ catch (err) {
106
+ const message = err instanceof Error ? err.message : String(err);
107
+ console.error(chalk.red('Failed to compute metrics:'), message);
108
+ process.exit(1);
109
+ }
110
+ });
111
+ }
112
+ async function readLogs(logsDir, filter) {
113
+ try {
114
+ const files = await fs.readdir(logsDir);
115
+ const logs = [];
116
+ for (const file of files) {
117
+ if (!file.endsWith('.json'))
118
+ continue;
119
+ try {
120
+ const content = await fs.readFile(path.join(logsDir, file), 'utf-8');
121
+ const entry = JSON.parse(content);
122
+ if (filter?.session && entry.sessionId !== filter.session)
123
+ continue;
124
+ if (filter?.last) {
125
+ const cutoff = Date.now() - parseDuration(filter.last);
126
+ if (new Date(entry.timestamp).getTime() < cutoff)
127
+ continue;
128
+ }
129
+ logs.push(entry);
130
+ }
131
+ catch {
132
+ // Skip malformed
133
+ }
134
+ }
135
+ logs.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
136
+ return logs;
137
+ }
138
+ catch {
139
+ return [];
140
+ }
141
+ }
142
+ //# sourceMappingURL=observe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observe.js","sourceRoot":"","sources":["../../../src/cli/commands/observe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * loom skill - Skill management commands
3
+ *
4
+ * loom skill list - Scan .claude/skills/ directory, list all skills
5
+ * loom skill validate [name] - Validate SKILL.md frontmatter and references
6
+ */
7
+ import type { Command } from 'commander';
8
+ export declare function registerSkillCommand(program: Command): void;
9
+ //# sourceMappingURL=skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/skill.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+H3D"}