@loom-framework/core 0.1.0-alpha.141 → 0.1.0-alpha.143
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/adapters/base.d.ts +31 -0
- package/dist/adapters/base.d.ts.map +1 -0
- package/dist/adapters/base.js +69 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/factory.d.ts +8 -0
- package/dist/adapters/factory.d.ts.map +1 -0
- package/dist/adapters/factory.js +25 -0
- package/dist/adapters/factory.js.map +1 -0
- package/dist/adapters/filesystem.d.ts +46 -0
- package/dist/adapters/filesystem.d.ts.map +1 -0
- package/dist/adapters/filesystem.js +321 -0
- package/dist/adapters/filesystem.js.map +1 -0
- package/dist/adapters/index.d.ts +10 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +8 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/sqlite.d.ts +37 -0
- package/dist/adapters/sqlite.d.ts.map +1 -0
- package/dist/adapters/sqlite.js +264 -0
- package/dist/adapters/sqlite.js.map +1 -0
- package/dist/backend/ai/button-resolver.d.ts +1 -1
- package/dist/backend/ai/button-resolver.d.ts.map +1 -1
- package/dist/backend/ai/engine.d.ts +1 -1
- package/dist/backend/ai/engine.d.ts.map +1 -1
- package/dist/backend/ai/output-parser.d.ts +1 -1
- package/dist/backend/ai/output-parser.d.ts.map +1 -1
- package/dist/backend/ai/session-manager.d.ts +1 -1
- package/dist/backend/ai/session-manager.d.ts.map +1 -1
- package/dist/backend/index.d.ts +3 -5
- package/dist/backend/index.d.ts.map +1 -1
- package/dist/backend/index.js +3 -15
- package/dist/backend/index.js.map +1 -1
- package/dist/backend/observe/logger.d.ts +1 -4
- package/dist/backend/observe/logger.d.ts.map +1 -1
- package/dist/backend/observe/logger.js +3 -18
- package/dist/backend/observe/logger.js.map +1 -1
- package/dist/backend/routes/chat-sse.d.ts +17 -0
- package/dist/backend/routes/chat-sse.d.ts.map +1 -0
- package/dist/backend/routes/chat-sse.js +60 -0
- package/dist/backend/routes/chat-sse.js.map +1 -0
- package/dist/backend/routes/chat.d.ts +2 -6
- package/dist/backend/routes/chat.d.ts.map +1 -1
- package/dist/backend/routes/chat.js +4 -137
- package/dist/backend/routes/chat.js.map +1 -1
- package/dist/backend/routes/data.d.ts +2 -1
- package/dist/backend/routes/data.d.ts.map +1 -1
- package/dist/backend/routes/data.js +1 -1
- package/dist/backend/routes/data.js.map +1 -1
- package/dist/backend/routes/health.d.ts +1 -1
- package/dist/backend/routes/health.d.ts.map +1 -1
- package/dist/backend/routes/index.d.ts +2 -0
- package/dist/backend/routes/index.d.ts.map +1 -1
- package/dist/backend/routes/index.js +1 -0
- package/dist/backend/routes/index.js.map +1 -1
- package/dist/backend/routes/session-routes.d.ts +20 -0
- package/dist/backend/routes/session-routes.d.ts.map +1 -0
- package/dist/backend/routes/session-routes.js +94 -0
- package/dist/backend/routes/session-routes.js.map +1 -0
- package/dist/backend/routes/skill-archive.d.ts +13 -0
- package/dist/backend/routes/skill-archive.d.ts.map +1 -0
- package/dist/backend/routes/skill-archive.js +84 -0
- package/dist/backend/routes/skill-archive.js.map +1 -0
- package/dist/backend/routes/skill-parser.d.ts +41 -0
- package/dist/backend/routes/skill-parser.d.ts.map +1 -0
- package/dist/backend/routes/skill-parser.js +184 -0
- package/dist/backend/routes/skill-parser.js.map +1 -0
- package/dist/backend/routes/skill-service.d.ts +113 -0
- package/dist/backend/routes/skill-service.d.ts.map +1 -0
- package/dist/backend/routes/skill-service.js +265 -0
- package/dist/backend/routes/skill-service.js.map +1 -0
- package/dist/backend/routes/skills.d.ts +3 -0
- package/dist/backend/routes/skills.d.ts.map +1 -1
- package/dist/backend/routes/skills.js +33 -456
- package/dist/backend/routes/skills.js.map +1 -1
- package/dist/backend/services/skill-archive.d.ts +13 -0
- package/dist/backend/services/skill-archive.d.ts.map +1 -0
- package/dist/backend/services/skill-archive.js +84 -0
- package/dist/backend/services/skill-archive.js.map +1 -0
- package/dist/backend/services/skill-parser.d.ts +41 -0
- package/dist/backend/services/skill-parser.d.ts.map +1 -0
- package/dist/backend/services/skill-parser.js +184 -0
- package/dist/backend/services/skill-parser.js.map +1 -0
- package/dist/backend/services/skill-service.d.ts +113 -0
- package/dist/backend/services/skill-service.d.ts.map +1 -0
- package/dist/backend/services/skill-service.js +265 -0
- package/dist/backend/services/skill-service.js.map +1 -0
- package/dist/cli/commands/data.d.ts.map +1 -1
- package/dist/cli/commands/data.js +3 -1
- package/dist/cli/commands/data.js.map +1 -1
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +2 -1
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/generate-capabilities.d.ts.map +1 -1
- package/dist/cli/commands/generate-capabilities.js +2 -1
- package/dist/cli/commands/generate-capabilities.js.map +1 -1
- package/dist/cli/commands/generate-dashboard.d.ts.map +1 -1
- package/dist/cli/commands/generate-dashboard.js +3 -452
- package/dist/cli/commands/generate-dashboard.js.map +1 -1
- package/dist/cli/commands/generate-page.d.ts.map +1 -1
- package/dist/cli/commands/generate-page.js +6 -436
- package/dist/cli/commands/generate-page.js.map +1 -1
- package/dist/cli/commands/serve.d.ts +12 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +43 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/framework.d.ts +28 -0
- package/dist/cli/framework.d.ts.map +1 -0
- package/dist/cli/framework.js +29 -0
- package/dist/cli/framework.js.map +1 -0
- package/dist/cli/helpers/app-tsx-wiring.d.ts.map +1 -1
- package/dist/cli/helpers/app-tsx-wiring.js +39 -24
- package/dist/cli/helpers/app-tsx-wiring.js.map +1 -1
- package/dist/cli/helpers/column-template.d.ts +3 -1
- package/dist/cli/helpers/column-template.d.ts.map +1 -1
- package/dist/cli/helpers/column-template.js +1 -1
- package/dist/cli/helpers/column-template.js.map +1 -1
- package/dist/cli/helpers/duration.d.ts +2 -2
- package/dist/cli/helpers/duration.d.ts.map +1 -1
- package/dist/cli/helpers/duration.js +2 -16
- package/dist/cli/helpers/duration.js.map +1 -1
- package/dist/cli/helpers/field-template.d.ts +1 -1
- package/dist/cli/helpers/field-template.d.ts.map +1 -1
- package/dist/cli/helpers/field-template.js +1 -1
- package/dist/cli/helpers/field-template.js.map +1 -1
- package/dist/cli/helpers/i18n-template.d.ts +13 -0
- package/dist/cli/helpers/i18n-template.d.ts.map +1 -0
- package/dist/cli/helpers/i18n-template.js +48 -0
- package/dist/cli/helpers/i18n-template.js.map +1 -0
- package/dist/cli/templates/crud-page.d.ts +14 -0
- package/dist/cli/templates/crud-page.d.ts.map +1 -0
- package/dist/cli/templates/crud-page.js +405 -0
- package/dist/cli/templates/crud-page.js.map +1 -0
- package/dist/cli/templates/dashboard-page.d.ts +11 -0
- package/dist/cli/templates/dashboard-page.d.ts.map +1 -0
- package/dist/cli/templates/dashboard-page.js +456 -0
- package/dist/cli/templates/dashboard-page.js.map +1 -0
- package/dist/cli/templates/index.d.ts +2 -0
- package/dist/cli/templates/index.d.ts.map +1 -1
- package/dist/cli/templates/index.js +2 -0
- package/dist/cli/templates/index.js.map +1 -1
- package/dist/config.d.ts +22 -22
- package/dist/dashboard-config.d.ts +10 -10
- package/dist/index.d.ts +8 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/types/chat.d.ts +33 -32
- package/dist/types/chat.d.ts.map +1 -1
- package/dist/types/chat.js +4 -1
- package/dist/types/chat.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/duration.d.ts +8 -0
- package/dist/utils/duration.d.ts.map +1 -0
- package/dist/utils/duration.js +22 -0
- package/dist/utils/duration.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/** Skill ZIP archive parsing and creation utilities */
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import AdmZip from 'adm-zip';
|
|
4
|
+
import { parseFrontmatter, isValidSkillName, isTextFile } from './skill-parser.js';
|
|
5
|
+
/**
|
|
6
|
+
* Parse a zip archive buffer and extract skill structure.
|
|
7
|
+
*/
|
|
8
|
+
export function parseZipArchive(buffer) {
|
|
9
|
+
const zip = new AdmZip(buffer);
|
|
10
|
+
const entries = zip.getEntries();
|
|
11
|
+
// Collect valid file entries
|
|
12
|
+
const validEntries = entries.filter((entry) => {
|
|
13
|
+
if (entry.isDirectory)
|
|
14
|
+
return false;
|
|
15
|
+
const entryPath = entry.entryName;
|
|
16
|
+
// Skip macOS metadata
|
|
17
|
+
if (entryPath.startsWith('__MACOSX/'))
|
|
18
|
+
return false;
|
|
19
|
+
// Skip .DS_Store and hidden files in root
|
|
20
|
+
const parts = entryPath.split('/');
|
|
21
|
+
if (parts.some((p) => p.startsWith('.') && p !== '.gitkeep' && p !== '.gitignore'))
|
|
22
|
+
return false;
|
|
23
|
+
return true;
|
|
24
|
+
});
|
|
25
|
+
if (validEntries.length === 0) {
|
|
26
|
+
throw new Error('压缩包中没有任何有效文件');
|
|
27
|
+
}
|
|
28
|
+
// Detect common top-level directory prefix
|
|
29
|
+
let prefix = '';
|
|
30
|
+
const firstEntry = validEntries[0].entryName;
|
|
31
|
+
const slashIdx = firstEntry.indexOf('/');
|
|
32
|
+
if (slashIdx > 0) {
|
|
33
|
+
const candidate = firstEntry.substring(0, slashIdx + 1);
|
|
34
|
+
if (validEntries.every((e) => e.entryName.startsWith(candidate))) {
|
|
35
|
+
prefix = candidate;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Strip prefix and collect files
|
|
39
|
+
const allFiles = [];
|
|
40
|
+
for (const entry of validEntries) {
|
|
41
|
+
let relPath = entry.entryName;
|
|
42
|
+
if (prefix && relPath.startsWith(prefix)) {
|
|
43
|
+
relPath = relPath.substring(prefix.length);
|
|
44
|
+
}
|
|
45
|
+
// Skip if empty after stripping prefix
|
|
46
|
+
if (!relPath)
|
|
47
|
+
continue;
|
|
48
|
+
// Only keep text files
|
|
49
|
+
if (!isTextFile(relPath))
|
|
50
|
+
continue;
|
|
51
|
+
const content = entry.getData().toString('utf-8');
|
|
52
|
+
allFiles.push({ path: relPath, content });
|
|
53
|
+
}
|
|
54
|
+
// Find SKILL.md
|
|
55
|
+
const skillMdEntry = allFiles.find((f) => f.path === 'SKILL.md');
|
|
56
|
+
if (!skillMdEntry) {
|
|
57
|
+
throw new Error('压缩包中未找到 SKILL.md 文件');
|
|
58
|
+
}
|
|
59
|
+
// Check for duplicate SKILL.md in subdirectories
|
|
60
|
+
const skillMdCount = allFiles.filter((f) => path.basename(f.path) === 'SKILL.md').length;
|
|
61
|
+
if (skillMdCount > 1) {
|
|
62
|
+
throw new Error('压缩包中包含多个 SKILL.md 文件,请确保只有一个');
|
|
63
|
+
}
|
|
64
|
+
// Extract skill name from frontmatter or directory name
|
|
65
|
+
const { metadata } = parseFrontmatter(skillMdEntry.content);
|
|
66
|
+
let skillName = metadata.name;
|
|
67
|
+
if (!skillName || typeof skillName !== 'string') {
|
|
68
|
+
// Fallback to directory name from prefix
|
|
69
|
+
if (prefix) {
|
|
70
|
+
skillName = prefix.replace(/\/$/, '');
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
throw new Error('无法确定 Skill 名称,请在 SKILL.md 的 frontmatter 中指定 name 字段');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Validate skill name
|
|
77
|
+
if (!isValidSkillName(skillName)) {
|
|
78
|
+
throw new Error(`Skill 名称 "${skillName}" 不合法,只能包含字母、数字、中划线和下划线,且以字母开头`);
|
|
79
|
+
}
|
|
80
|
+
// Separate SKILL.md from other files
|
|
81
|
+
const files = allFiles.filter((f) => f.path !== 'SKILL.md');
|
|
82
|
+
return { skillName, skillMd: skillMdEntry.content, files };
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=skill-archive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-archive.js","sourceRoot":"","sources":["../../../src/backend/services/skill-archive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Skill file parsing utilities */
|
|
2
|
+
export interface SkillMetadata {
|
|
3
|
+
name?: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
version?: string;
|
|
6
|
+
'allowed-tools'?: string[];
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Parse YAML frontmatter from markdown content using simple regex.
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseFrontmatter(content: string): {
|
|
13
|
+
metadata: SkillMetadata;
|
|
14
|
+
body: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Recursively scan a directory for files, returning relative paths.
|
|
18
|
+
* Excludes SKILL.md (handled separately).
|
|
19
|
+
*/
|
|
20
|
+
export declare function scanDirFiles(dir: string, base: string): Promise<string[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Safely resolve a file path within a directory. Rejects '..' traversal.
|
|
23
|
+
*/
|
|
24
|
+
export declare function safeResolve(baseDir: string, filePath: string): string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Validate skill name.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isValidSkillName(name: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Text file extensions that should be kept when parsing zip archives.
|
|
31
|
+
*/
|
|
32
|
+
export declare const TEXT_EXTENSIONS: Set<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Check if a file path looks like a text file based on extension.
|
|
35
|
+
*/
|
|
36
|
+
export declare function isTextFile(filePath: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Get MIME type for a file extension.
|
|
39
|
+
*/
|
|
40
|
+
export declare function getContentType(filePath: string): string;
|
|
41
|
+
//# sourceMappingURL=skill-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-parser.d.ts","sourceRoot":"","sources":["../../../src/backend/services/skill-parser.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAQnC,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAID;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAqG3F;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAkB/E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK5E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,aAK1B,CAAC;AAEH;;GAEG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQpD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAevD"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/** Skill file parsing utilities */
|
|
2
|
+
import { promises as fs } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
// ── Functions ──
|
|
5
|
+
/**
|
|
6
|
+
* Parse YAML frontmatter from markdown content using simple regex.
|
|
7
|
+
*/
|
|
8
|
+
export function parseFrontmatter(content) {
|
|
9
|
+
// The \n before closing --- is optional to handle empty frontmatter (---\n---\nBody)
|
|
10
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n?---\r?\n?([\s\S]*)$/);
|
|
11
|
+
if (!match)
|
|
12
|
+
return { metadata: {}, body: content };
|
|
13
|
+
const metadataRaw = match[1];
|
|
14
|
+
const body = match[2];
|
|
15
|
+
try {
|
|
16
|
+
const metadata = {};
|
|
17
|
+
const lines = metadataRaw.split('\n');
|
|
18
|
+
let currentKey = '';
|
|
19
|
+
let currentValues = [];
|
|
20
|
+
let inArray = false;
|
|
21
|
+
let inBlock = false;
|
|
22
|
+
let blockLines = [];
|
|
23
|
+
const flushArray = () => {
|
|
24
|
+
if (inArray && currentKey) {
|
|
25
|
+
// If array items were collected, store as array; otherwise store empty string
|
|
26
|
+
metadata[currentKey] = currentValues.length > 0 ? currentValues : '';
|
|
27
|
+
inArray = false;
|
|
28
|
+
currentValues = [];
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const flushBlock = () => {
|
|
32
|
+
if (inBlock && currentKey) {
|
|
33
|
+
metadata[currentKey] = blockLines.join('\n').trim();
|
|
34
|
+
}
|
|
35
|
+
inBlock = false;
|
|
36
|
+
blockLines = [];
|
|
37
|
+
};
|
|
38
|
+
for (const line of lines) {
|
|
39
|
+
if (inBlock) {
|
|
40
|
+
if (/^[ \t]+/.test(line) || (line === '' && blockLines.length > 0)) {
|
|
41
|
+
blockLines.push(line.replace(/^[ \t]+/, ''));
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
flushBlock();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const trimmed = line.trim();
|
|
49
|
+
if (!trimmed)
|
|
50
|
+
continue;
|
|
51
|
+
const arrayMatch = trimmed.match(/^-\s+(.+)$/);
|
|
52
|
+
if (inArray && arrayMatch) {
|
|
53
|
+
currentValues.push(arrayMatch[1].replace(/^['"]|['"]$/g, '').trim());
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (inArray) {
|
|
57
|
+
flushArray();
|
|
58
|
+
}
|
|
59
|
+
const kvMatch = trimmed.match(/^([a-zA-Z_-][a-zA-Z0-9_-]*):\s*(.*)$/);
|
|
60
|
+
if (kvMatch) {
|
|
61
|
+
currentKey = kvMatch[1];
|
|
62
|
+
let val = kvMatch[2].trim();
|
|
63
|
+
if ((val.startsWith("'") && val.endsWith("'")) || (val.startsWith('"') && val.endsWith('"'))) {
|
|
64
|
+
val = val.slice(1, -1);
|
|
65
|
+
}
|
|
66
|
+
if (val === '|' || val === '>') {
|
|
67
|
+
inBlock = true;
|
|
68
|
+
blockLines = [];
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (val === '[') {
|
|
72
|
+
inArray = true;
|
|
73
|
+
currentValues = [];
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (val.startsWith('[') && val.endsWith(']')) {
|
|
77
|
+
metadata[currentKey] = val.slice(1, -1).split(',').map((s) => s.trim().replace(/^['"]|['"]$/g, ''));
|
|
78
|
+
currentKey = '';
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
// Empty value means multi-line array follows (YAML list syntax: "key:\n - item")
|
|
82
|
+
if (val === '') {
|
|
83
|
+
inArray = true;
|
|
84
|
+
currentValues = [];
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
metadata[currentKey] = val;
|
|
88
|
+
currentKey = '';
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
flushArray();
|
|
92
|
+
flushBlock();
|
|
93
|
+
return { metadata, body };
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return { metadata: {}, body: content };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Recursively scan a directory for files, returning relative paths.
|
|
101
|
+
* Excludes SKILL.md (handled separately).
|
|
102
|
+
*/
|
|
103
|
+
export async function scanDirFiles(dir, base) {
|
|
104
|
+
const results = [];
|
|
105
|
+
let entries;
|
|
106
|
+
try {
|
|
107
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return results;
|
|
111
|
+
}
|
|
112
|
+
for (const entry of entries) {
|
|
113
|
+
if (entry.isDirectory()) {
|
|
114
|
+
const subFiles = await scanDirFiles(path.join(dir, entry.name), base);
|
|
115
|
+
results.push(...subFiles);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const relPath = path.relative(base, path.join(dir, entry.name));
|
|
119
|
+
results.push(relPath);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return results;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Safely resolve a file path within a directory. Rejects '..' traversal.
|
|
126
|
+
*/
|
|
127
|
+
export function safeResolve(baseDir, filePath) {
|
|
128
|
+
if (filePath.includes('..'))
|
|
129
|
+
return null;
|
|
130
|
+
const resolved = path.resolve(baseDir, filePath);
|
|
131
|
+
if (!resolved.startsWith(baseDir))
|
|
132
|
+
return null;
|
|
133
|
+
return resolved;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Validate skill name.
|
|
137
|
+
*/
|
|
138
|
+
export function isValidSkillName(name) {
|
|
139
|
+
return /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Text file extensions that should be kept when parsing zip archives.
|
|
143
|
+
*/
|
|
144
|
+
export const TEXT_EXTENSIONS = new Set([
|
|
145
|
+
'.md', '.json', '.yaml', '.yml', '.txt', '.ts', '.js', '.tsx', '.jsx',
|
|
146
|
+
'.xml', '.html', '.css', '.sh', '.py', '.rb', '.go', '.rs', '.java',
|
|
147
|
+
'.kt', '.swift', '.c', '.cpp', '.h', '.hpp', '.toml', '.ini', '.cfg',
|
|
148
|
+
'.env', '.gitignore', '.prettierrc', '.eslintrc', '.conf', '.properties',
|
|
149
|
+
]);
|
|
150
|
+
/**
|
|
151
|
+
* Check if a file path looks like a text file based on extension.
|
|
152
|
+
*/
|
|
153
|
+
export function isTextFile(filePath) {
|
|
154
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
155
|
+
if (TEXT_EXTENSIONS.has(ext))
|
|
156
|
+
return true;
|
|
157
|
+
// Files with no extension but common names
|
|
158
|
+
const basename = path.basename(filePath).toLowerCase();
|
|
159
|
+
if (['readme', 'license', 'makefile', 'dockerfile', '.gitkeep', '.gitignore'].includes(basename))
|
|
160
|
+
return true;
|
|
161
|
+
if (basename.startsWith('.git'))
|
|
162
|
+
return true;
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Get MIME type for a file extension.
|
|
167
|
+
*/
|
|
168
|
+
export function getContentType(filePath) {
|
|
169
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
170
|
+
const types = {
|
|
171
|
+
'.md': 'text/markdown',
|
|
172
|
+
'.txt': 'text/plain',
|
|
173
|
+
'.json': 'application/json',
|
|
174
|
+
'.xml': 'application/xml',
|
|
175
|
+
'.yaml': 'text/yaml',
|
|
176
|
+
'.yml': 'text/yaml',
|
|
177
|
+
'.ts': 'text/typescript',
|
|
178
|
+
'.js': 'text/javascript',
|
|
179
|
+
'.html': 'text/html',
|
|
180
|
+
'.css': 'text/css',
|
|
181
|
+
};
|
|
182
|
+
return types[ext] || 'text/plain';
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=skill-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-parser.js","sourceRoot":"","sources":["../../../src/backend/services/skill-parser.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAGnC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAY7B,kBAAkB;AAElB;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,qFAAqF;IACrF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAC5E,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACnD,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAkB,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,UAAU,GAAG,EAAE,CAAC;QACpB,IAAI,aAAa,GAAa,EAAE,CAAC;QACjC,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,UAAU,GAAa,EAAE,CAAC;QAE9B,MAAM,UAAU,GAAG,GAAG,EAAE;YACtB,IAAI,OAAO,IAAI,UAAU,EAAE,CAAC;gBAC1B,8EAA8E;gBAC9E,QAAQ,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrE,OAAO,GAAG,KAAK,CAAC;gBAChB,aAAa,GAAG,EAAE,CAAC;YACrB,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,UAAU,GAAG,GAAG,EAAE;YACtB,IAAI,OAAO,IAAI,UAAU,EAAE,CAAC;gBAC1B,QAAQ,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YACtD,CAAC;YACD,OAAO,GAAG,KAAK,CAAC;YAChB,UAAU,GAAG,EAAE,CAAC;QAClB,CAAC,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,EAAE,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;oBACnE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;oBAC7C,SAAS;gBACX,CAAC;qBAAM,CAAC;oBACN,UAAU,EAAE,CAAC;gBACf,CAAC;YACH,CAAC;YAED,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO;gBAAE,SAAS;YAEvB,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAC/C,IAAI,OAAO,IAAI,UAAU,EAAE,CAAC;gBAC1B,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBACrE,SAAS;YACX,CAAC;YAED,IAAI,OAAO,EAAE,CAAC;gBACZ,UAAU,EAAE,CAAC;YACf,CAAC;YAED,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;YACtE,IAAI,OAAO,EAAE,CAAC;gBACZ,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBACxB,IAAI,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAE5B,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;oBAC7F,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACzB,CAAC;gBAED,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;oBAC/B,OAAO,GAAG,IAAI,CAAC;oBACf,UAAU,GAAG,EAAE,CAAC;oBAChB,SAAS;gBACX,CAAC;gBAED,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;oBAChB,OAAO,GAAG,IAAI,CAAC;oBACf,aAAa,GAAG,EAAE,CAAC;oBACnB,SAAS;gBACX,CAAC;gBAED,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC7C,QAAQ,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC;oBAC5G,UAAU,GAAG,EAAE,CAAC;oBAChB,SAAS;gBACX,CAAC;gBAED,kFAAkF;gBAClF,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;oBACf,OAAO,GAAG,IAAI,CAAC;oBACf,aAAa,GAAG,EAAE,CAAC;oBACnB,SAAS;gBACX,CAAC;gBAED,QAAQ,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC;gBAC3B,UAAU,GAAG,EAAE,CAAC;YAClB,CAAC;QACH,CAAC;QAED,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,CAAC;QAEb,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACzC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAW,EAAE,IAAY;IAC1D,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAa,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;YACtE,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAChE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,QAAgB;IAC3D,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACjD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IACrC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM;IACrE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO;IACnE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM;IACpE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa;CACzE,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACjD,IAAI,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,2CAA2C;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACvD,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9G,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACjD,MAAM,KAAK,GAA2B;QACpC,KAAK,EAAE,eAAe;QACtB,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,kBAAkB;QAC3B,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,WAAW;QACpB,MAAM,EAAE,WAAW;QACnB,KAAK,EAAE,iBAAiB;QACxB,KAAK,EAAE,iBAAiB;QACxB,OAAO,EAAE,WAAW;QACpB,MAAM,EAAE,UAAU;KACnB,CAAC;IACF,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/** Skill business logic — filesystem operations independent of Fastify */
|
|
2
|
+
import type { SkillMetadata } from './skill-parser.js';
|
|
3
|
+
import { parseZipArchive } from './skill-archive.js';
|
|
4
|
+
export interface SkillInfo {
|
|
5
|
+
name: string;
|
|
6
|
+
metadata: SkillMetadata;
|
|
7
|
+
subDirs: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface SkillDetail {
|
|
10
|
+
name: string;
|
|
11
|
+
metadata: SkillMetadata;
|
|
12
|
+
skillMd: string;
|
|
13
|
+
files: {
|
|
14
|
+
name: string;
|
|
15
|
+
path: string;
|
|
16
|
+
}[];
|
|
17
|
+
}
|
|
18
|
+
export interface CreateSkillBody {
|
|
19
|
+
name: string;
|
|
20
|
+
skillMd?: string;
|
|
21
|
+
references?: Array<{
|
|
22
|
+
name: string;
|
|
23
|
+
content: string;
|
|
24
|
+
}>;
|
|
25
|
+
scripts?: Array<{
|
|
26
|
+
name: string;
|
|
27
|
+
content: string;
|
|
28
|
+
}>;
|
|
29
|
+
files?: Array<{
|
|
30
|
+
path: string;
|
|
31
|
+
content: string;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
export interface UploadFileBody {
|
|
35
|
+
filename: string;
|
|
36
|
+
content: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* List all skills with metadata.
|
|
40
|
+
*/
|
|
41
|
+
export declare function listSkills(skillsDir: string): Promise<SkillInfo[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Get detailed information about a single skill.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getSkillDetail(skillsDir: string, skillName: string): Promise<SkillDetail | null>;
|
|
46
|
+
/**
|
|
47
|
+
* Create a new skill directory with SKILL.md and optional files.
|
|
48
|
+
* Returns the created skill info, or throws on conflict / invalid name.
|
|
49
|
+
*/
|
|
50
|
+
export declare function createSkill(skillsDir: string, body: CreateSkillBody): Promise<{
|
|
51
|
+
created: true;
|
|
52
|
+
info: SkillInfo;
|
|
53
|
+
} | {
|
|
54
|
+
created: false;
|
|
55
|
+
status: number;
|
|
56
|
+
error: string;
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* Delete a skill directory.
|
|
60
|
+
*/
|
|
61
|
+
export declare function deleteSkill(skillsDir: string, skillName: string): Promise<{
|
|
62
|
+
ok: true;
|
|
63
|
+
} | {
|
|
64
|
+
ok: false;
|
|
65
|
+
status: number;
|
|
66
|
+
error: string;
|
|
67
|
+
}>;
|
|
68
|
+
/**
|
|
69
|
+
* Read a file within a skill directory.
|
|
70
|
+
*/
|
|
71
|
+
export declare function getSkillFile(skillsDir: string, skillName: string, filePath: string): Promise<{
|
|
72
|
+
ok: true;
|
|
73
|
+
content: string;
|
|
74
|
+
path: string;
|
|
75
|
+
} | {
|
|
76
|
+
ok: false;
|
|
77
|
+
status: number;
|
|
78
|
+
error: string;
|
|
79
|
+
}>;
|
|
80
|
+
/**
|
|
81
|
+
* Upload/replace a file in a skill directory.
|
|
82
|
+
*/
|
|
83
|
+
export declare function uploadSkillFile(skillsDir: string, skillName: string, filename: string, content: string): Promise<{
|
|
84
|
+
ok: true;
|
|
85
|
+
path: string;
|
|
86
|
+
} | {
|
|
87
|
+
ok: false;
|
|
88
|
+
status: number;
|
|
89
|
+
error: string;
|
|
90
|
+
}>;
|
|
91
|
+
/**
|
|
92
|
+
* Create a ZIP archive of a skill directory.
|
|
93
|
+
*/
|
|
94
|
+
export declare function createSkillArchive(skillsDir: string, skillName: string): Promise<{
|
|
95
|
+
ok: true;
|
|
96
|
+
buffer: Buffer;
|
|
97
|
+
} | {
|
|
98
|
+
ok: false;
|
|
99
|
+
status: number;
|
|
100
|
+
error: string;
|
|
101
|
+
}>;
|
|
102
|
+
/**
|
|
103
|
+
* Parse a base64-encoded ZIP archive and extract skill structure.
|
|
104
|
+
*/
|
|
105
|
+
export declare function parseSkillArchive(base64Data: string): {
|
|
106
|
+
ok: true;
|
|
107
|
+
data: ReturnType<typeof parseZipArchive>;
|
|
108
|
+
} | {
|
|
109
|
+
ok: false;
|
|
110
|
+
status: number;
|
|
111
|
+
error: string;
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=skill-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-service.d.ts","sourceRoot":"","sources":["../../../src/backend/services/skill-service.ts"],"names":[],"mappings":"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"}
|