@hyorman/copilot-proxy-core 1.0.0
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/out/assistants/index.d.ts +15 -0
- package/out/assistants/index.js +16 -0
- package/out/assistants/index.js.map +1 -0
- package/out/assistants/routes.d.ts +16 -0
- package/out/assistants/routes.js +597 -0
- package/out/assistants/routes.js.map +1 -0
- package/out/assistants/runner.d.ts +48 -0
- package/out/assistants/runner.js +851 -0
- package/out/assistants/runner.js.map +1 -0
- package/out/assistants/state.d.ts +81 -0
- package/out/assistants/state.js +351 -0
- package/out/assistants/state.js.map +1 -0
- package/out/assistants/tools.d.ts +4 -0
- package/out/assistants/tools.js +8 -0
- package/out/assistants/tools.js.map +1 -0
- package/out/assistants/types.d.ts +254 -0
- package/out/assistants/types.js +5 -0
- package/out/assistants/types.js.map +1 -0
- package/out/backend.d.ts +24 -0
- package/out/backend.js +12 -0
- package/out/backend.js.map +1 -0
- package/out/index.d.ts +13 -0
- package/out/index.js +21 -0
- package/out/index.js.map +1 -0
- package/out/server.d.ts +12 -0
- package/out/server.js +504 -0
- package/out/server.js.map +1 -0
- package/out/skills/index.d.ts +3 -0
- package/out/skills/index.js +4 -0
- package/out/skills/index.js.map +1 -0
- package/out/skills/manifest.d.ts +25 -0
- package/out/skills/manifest.js +96 -0
- package/out/skills/manifest.js.map +1 -0
- package/out/skills/resolver.d.ts +22 -0
- package/out/skills/resolver.js +66 -0
- package/out/skills/resolver.js.map +1 -0
- package/out/skills/routes.d.ts +3 -0
- package/out/skills/routes.js +191 -0
- package/out/skills/routes.js.map +1 -0
- package/out/skills/state.d.ts +35 -0
- package/out/skills/state.js +155 -0
- package/out/skills/state.js.map +1 -0
- package/out/skills/storage.d.ts +30 -0
- package/out/skills/storage.js +171 -0
- package/out/skills/storage.js.map +1 -0
- package/out/skills/types.d.ts +141 -0
- package/out/skills/types.js +8 -0
- package/out/skills/types.js.map +1 -0
- package/out/toolConvert.d.ts +24 -0
- package/out/toolConvert.js +56 -0
- package/out/toolConvert.js.map +1 -0
- package/out/types.d.ts +291 -0
- package/out/types.js +2 -0
- package/out/types.js.map +1 -0
- package/out/utils.d.ts +28 -0
- package/out/utils.js +81 -0
- package/out/utils.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a SKILL.md manifest file to extract metadata
|
|
3
|
+
* @param content - Raw string content of a SKILL.md file
|
|
4
|
+
* @returns Parsed SkillManifest object
|
|
5
|
+
* @throws Error if frontmatter is invalid or required fields are missing
|
|
6
|
+
*/
|
|
7
|
+
export function parseManifest(content) {
|
|
8
|
+
const lines = content.split('\n');
|
|
9
|
+
// Find opening --- (must be the first non-blank line)
|
|
10
|
+
let openingIndex = -1;
|
|
11
|
+
for (let i = 0; i < lines.length; i++) {
|
|
12
|
+
if (lines[i].trim() === '')
|
|
13
|
+
continue;
|
|
14
|
+
if (lines[i].trim() === '---') {
|
|
15
|
+
openingIndex = i;
|
|
16
|
+
}
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
if (openingIndex === -1) {
|
|
20
|
+
throw new Error('No YAML frontmatter found. SKILL.md must start with --- delimiter.');
|
|
21
|
+
}
|
|
22
|
+
// Find closing ---
|
|
23
|
+
let closingIndex = -1;
|
|
24
|
+
for (let i = openingIndex + 1; i < lines.length; i++) {
|
|
25
|
+
if (lines[i].trim() === '---') {
|
|
26
|
+
closingIndex = i;
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (closingIndex === -1) {
|
|
31
|
+
throw new Error('Invalid YAML frontmatter. Missing closing --- delimiter.');
|
|
32
|
+
}
|
|
33
|
+
// Extract frontmatter content
|
|
34
|
+
const frontmatterLines = lines.slice(openingIndex + 1, closingIndex);
|
|
35
|
+
// Parse key-value pairs
|
|
36
|
+
const metadata = {};
|
|
37
|
+
for (const line of frontmatterLines) {
|
|
38
|
+
const trimmedLine = line.trim();
|
|
39
|
+
if (trimmedLine === '')
|
|
40
|
+
continue;
|
|
41
|
+
const colonIndex = trimmedLine.indexOf(':');
|
|
42
|
+
if (colonIndex === -1)
|
|
43
|
+
continue;
|
|
44
|
+
const key = trimmedLine.substring(0, colonIndex).trim();
|
|
45
|
+
const value = trimmedLine.substring(colonIndex + 1).trim();
|
|
46
|
+
metadata[key] = value;
|
|
47
|
+
}
|
|
48
|
+
// Validate required fields
|
|
49
|
+
if (!metadata.name || metadata.name === '') {
|
|
50
|
+
throw new Error('SKILL.md frontmatter must contain a "name" field.');
|
|
51
|
+
}
|
|
52
|
+
if (!metadata.description || metadata.description === '') {
|
|
53
|
+
throw new Error('SKILL.md frontmatter must contain a "description" field.');
|
|
54
|
+
}
|
|
55
|
+
// Extract body (everything after closing ---)
|
|
56
|
+
const body = lines.slice(closingIndex + 1).join('\n').trim();
|
|
57
|
+
return {
|
|
58
|
+
name: metadata.name,
|
|
59
|
+
description: metadata.description,
|
|
60
|
+
body,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Find the SKILL.md manifest file in an array of uploaded files
|
|
65
|
+
* @param files - Array of uploaded files
|
|
66
|
+
* @returns The matching SkillFile
|
|
67
|
+
* @throws Error if no manifest file or multiple manifest files are found
|
|
68
|
+
*/
|
|
69
|
+
export function findManifestFile(files) {
|
|
70
|
+
const manifestFiles = files.filter((file) => {
|
|
71
|
+
const basename = file.path.split('/').pop()?.toLowerCase();
|
|
72
|
+
return basename === 'skill.md';
|
|
73
|
+
});
|
|
74
|
+
if (manifestFiles.length === 0) {
|
|
75
|
+
throw new Error('No SKILL.md manifest file found in the uploaded bundle.');
|
|
76
|
+
}
|
|
77
|
+
if (manifestFiles.length > 1) {
|
|
78
|
+
throw new Error('Multiple SKILL.md manifest files found. Only one is allowed.');
|
|
79
|
+
}
|
|
80
|
+
return manifestFiles[0];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Validate and parse a skill bundle
|
|
84
|
+
* @param files - Array of files from the uploaded bundle
|
|
85
|
+
* @returns Object containing parsed manifest and the manifest file reference
|
|
86
|
+
* @throws Error if validation fails
|
|
87
|
+
*/
|
|
88
|
+
export function validateBundle(files) {
|
|
89
|
+
const manifestFile = findManifestFile(files);
|
|
90
|
+
const manifest = parseManifest(manifestFile.content.toString('utf-8'));
|
|
91
|
+
return {
|
|
92
|
+
manifest,
|
|
93
|
+
manifestFile,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/skills/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SkillAttachment } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolved skill content ready for injection into the model context.
|
|
4
|
+
*/
|
|
5
|
+
export interface ResolvedSkill {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
body: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolve an array of skill attachments into instruction text blocks.
|
|
12
|
+
* - SkillReference: looks up the skill in state and reads the manifest body
|
|
13
|
+
* - InlineSkill: decodes base64 source as a SKILL.md and extracts the body
|
|
14
|
+
*
|
|
15
|
+
* Returns an array of resolved skills. Throws on unresolvable references.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveSkills(attachments: SkillAttachment[]): ResolvedSkill[];
|
|
18
|
+
/**
|
|
19
|
+
* Build a combined instruction block from resolved skills.
|
|
20
|
+
* Returns a string to prepend/append to the system prompt, or empty string if no skills.
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildSkillInstructions(skills: ResolvedSkill[]): string;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { skillsState } from './state.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve an array of skill attachments into instruction text blocks.
|
|
4
|
+
* - SkillReference: looks up the skill in state and reads the manifest body
|
|
5
|
+
* - InlineSkill: decodes base64 source as a SKILL.md and extracts the body
|
|
6
|
+
*
|
|
7
|
+
* Returns an array of resolved skills. Throws on unresolvable references.
|
|
8
|
+
*/
|
|
9
|
+
export function resolveSkills(attachments) {
|
|
10
|
+
const resolved = [];
|
|
11
|
+
for (const attachment of attachments) {
|
|
12
|
+
if (attachment.type === 'skill_reference') {
|
|
13
|
+
resolved.push(resolveReference(attachment));
|
|
14
|
+
}
|
|
15
|
+
else if (attachment.type === 'inline') {
|
|
16
|
+
resolved.push(resolveInline(attachment));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return resolved;
|
|
20
|
+
}
|
|
21
|
+
function resolveReference(ref) {
|
|
22
|
+
const skill = skillsState.getSkill(ref.skill_id);
|
|
23
|
+
if (!skill) {
|
|
24
|
+
throw new Error(`Skill not found: ${ref.skill_id}`);
|
|
25
|
+
}
|
|
26
|
+
let version;
|
|
27
|
+
if (ref.version === 'latest') {
|
|
28
|
+
version = skill.versions.find((v) => v.version === skill.latest_version);
|
|
29
|
+
}
|
|
30
|
+
else if (typeof ref.version === 'number') {
|
|
31
|
+
version = skill.versions.find((v) => v.version === ref.version);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
// Default: use default_version
|
|
35
|
+
version = skill.versions.find((v) => v.version === skill.default_version);
|
|
36
|
+
}
|
|
37
|
+
if (!version) {
|
|
38
|
+
throw new Error(`Version ${ref.version ?? skill.default_version} not found for skill ${ref.skill_id}`);
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
name: version.manifest.name,
|
|
42
|
+
description: version.manifest.description,
|
|
43
|
+
body: version.manifest.body,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function resolveInline(inline) {
|
|
47
|
+
// Inline skills provide their content as base64-encoded data.
|
|
48
|
+
// For simplicity, treat the decoded content as the skill body directly.
|
|
49
|
+
const decoded = Buffer.from(inline.source.data, 'base64').toString('utf-8');
|
|
50
|
+
return {
|
|
51
|
+
name: inline.name,
|
|
52
|
+
description: inline.description,
|
|
53
|
+
body: decoded,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Build a combined instruction block from resolved skills.
|
|
58
|
+
* Returns a string to prepend/append to the system prompt, or empty string if no skills.
|
|
59
|
+
*/
|
|
60
|
+
export function buildSkillInstructions(skills) {
|
|
61
|
+
if (skills.length === 0)
|
|
62
|
+
return '';
|
|
63
|
+
const blocks = skills.map((s) => `<skill name="${s.name}">\n${s.body}\n</skill>`);
|
|
64
|
+
return `\n\n<!-- Attached Skills -->\n${blocks.join('\n\n')}`;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/skills/resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import multer from 'multer';
|
|
3
|
+
import { errorResponse, notFoundError } from '../utils.js';
|
|
4
|
+
import { skillsState } from './state.js';
|
|
5
|
+
import { validateBundle } from './manifest.js';
|
|
6
|
+
import { processMultipartFiles, processZipUpload, saveSkillVersion, deleteSkillStorage, guessContentType, } from './storage.js';
|
|
7
|
+
const router = Router();
|
|
8
|
+
const upload = multer({
|
|
9
|
+
storage: multer.memoryStorage(),
|
|
10
|
+
limits: { fileSize: 50 * 1024 * 1024 },
|
|
11
|
+
});
|
|
12
|
+
let storageDir = '';
|
|
13
|
+
export function setSkillStorageDir(dir) {
|
|
14
|
+
storageDir = dir;
|
|
15
|
+
}
|
|
16
|
+
function parsePaginationParams(query) {
|
|
17
|
+
return {
|
|
18
|
+
limit: query.limit ? Math.min(parseInt(query.limit, 10), 100) : 20,
|
|
19
|
+
order: query.order ?? 'desc',
|
|
20
|
+
after: query.after,
|
|
21
|
+
before: query.before,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Process uploaded multer files into SkillFile[], detecting zip vs multipart.
|
|
26
|
+
*/
|
|
27
|
+
async function extractSkillFiles(files) {
|
|
28
|
+
const firstFile = files[0];
|
|
29
|
+
const isZip = firstFile.mimetype === 'application/zip' || firstFile.originalname.endsWith('.zip');
|
|
30
|
+
if (isZip) {
|
|
31
|
+
return processZipUpload(firstFile.buffer);
|
|
32
|
+
}
|
|
33
|
+
return processMultipartFiles(files);
|
|
34
|
+
}
|
|
35
|
+
function buildVersionFiles(files) {
|
|
36
|
+
return files.map((f) => ({
|
|
37
|
+
path: f.path,
|
|
38
|
+
content_type: guessContentType(f.path),
|
|
39
|
+
size: f.size,
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
// POST /v1/skills — create a new skill from file upload
|
|
43
|
+
router.post('/', upload.any(), async (req, res) => {
|
|
44
|
+
try {
|
|
45
|
+
const multerFiles = req.files;
|
|
46
|
+
if (!multerFiles || multerFiles.length === 0) {
|
|
47
|
+
return res.status(400).json(errorResponse('No files provided'));
|
|
48
|
+
}
|
|
49
|
+
let skillFiles;
|
|
50
|
+
try {
|
|
51
|
+
skillFiles = await extractSkillFiles(multerFiles);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
return res.status(400).json(errorResponse(error instanceof Error ? error.message : 'Failed to process files'));
|
|
55
|
+
}
|
|
56
|
+
let manifest;
|
|
57
|
+
try {
|
|
58
|
+
const result = validateBundle(skillFiles);
|
|
59
|
+
manifest = result.manifest;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
return res.status(400).json(errorResponse(error instanceof Error ? error.message : 'Invalid skill bundle'));
|
|
63
|
+
}
|
|
64
|
+
const now = Math.floor(Date.now() / 1000);
|
|
65
|
+
const skillId = skillsState.generateSkillId();
|
|
66
|
+
const version = {
|
|
67
|
+
version: 1,
|
|
68
|
+
created_at: now,
|
|
69
|
+
files: buildVersionFiles(skillFiles),
|
|
70
|
+
manifest,
|
|
71
|
+
};
|
|
72
|
+
const skill = {
|
|
73
|
+
id: skillId,
|
|
74
|
+
object: 'skill',
|
|
75
|
+
created_at: now,
|
|
76
|
+
name: manifest.name,
|
|
77
|
+
description: manifest.description,
|
|
78
|
+
default_version: 1,
|
|
79
|
+
latest_version: 1,
|
|
80
|
+
versions: [version],
|
|
81
|
+
metadata: {},
|
|
82
|
+
};
|
|
83
|
+
skillsState.createSkill(skill);
|
|
84
|
+
saveSkillVersion(storageDir, skillId, 1, skillFiles);
|
|
85
|
+
return res.status(201).json(skillsState.toSkillResponse(skill));
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
console.error('Error creating skill:', error);
|
|
89
|
+
return res.status(500).json(errorResponse(error instanceof Error ? error.message : 'Internal server error'));
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
// GET /v1/skills — list skills (paginated)
|
|
93
|
+
router.get('/', (req, res) => {
|
|
94
|
+
const pagination = parsePaginationParams(req.query);
|
|
95
|
+
return res.json(skillsState.listSkills(pagination));
|
|
96
|
+
});
|
|
97
|
+
// GET /v1/skills/:skill_id — retrieve a skill
|
|
98
|
+
router.get('/:skill_id', (req, res) => {
|
|
99
|
+
const response = skillsState.getSkillResponse(req.params.skill_id);
|
|
100
|
+
if (!response) {
|
|
101
|
+
return res.status(404).json(notFoundError('skill'));
|
|
102
|
+
}
|
|
103
|
+
return res.json(response);
|
|
104
|
+
});
|
|
105
|
+
// POST /v1/skills/:skill_id — update a skill (default_version, metadata)
|
|
106
|
+
router.post('/:skill_id', (req, res) => {
|
|
107
|
+
const { skill_id } = req.params;
|
|
108
|
+
const body = req.body;
|
|
109
|
+
const skill = skillsState.getSkill(skill_id);
|
|
110
|
+
if (!skill) {
|
|
111
|
+
return res.status(404).json(notFoundError('skill'));
|
|
112
|
+
}
|
|
113
|
+
if (body.default_version !== undefined) {
|
|
114
|
+
const versionExists = skill.versions.some((v) => v.version === body.default_version);
|
|
115
|
+
if (!versionExists) {
|
|
116
|
+
return res.status(400).json(errorResponse(`Version ${body.default_version} does not exist for this skill`));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const updated = skillsState.updateSkill(skill_id, body);
|
|
120
|
+
if (!updated) {
|
|
121
|
+
return res.status(404).json(notFoundError('skill'));
|
|
122
|
+
}
|
|
123
|
+
return res.json(skillsState.toSkillResponse(updated));
|
|
124
|
+
});
|
|
125
|
+
// DELETE /v1/skills/:skill_id — delete a skill
|
|
126
|
+
router.delete('/:skill_id', (req, res) => {
|
|
127
|
+
const { skill_id } = req.params;
|
|
128
|
+
const deleted = skillsState.deleteSkill(skill_id);
|
|
129
|
+
if (deleted) {
|
|
130
|
+
deleteSkillStorage(storageDir, skill_id);
|
|
131
|
+
}
|
|
132
|
+
return res.json({
|
|
133
|
+
id: skill_id,
|
|
134
|
+
object: 'skill.deleted',
|
|
135
|
+
deleted,
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
// POST /v1/skills/:skill_id/versions — upload a new version
|
|
139
|
+
router.post('/:skill_id/versions', upload.any(), async (req, res) => {
|
|
140
|
+
try {
|
|
141
|
+
const { skill_id } = req.params;
|
|
142
|
+
const multerFiles = req.files;
|
|
143
|
+
if (!multerFiles || multerFiles.length === 0) {
|
|
144
|
+
return res.status(400).json(errorResponse('No files provided'));
|
|
145
|
+
}
|
|
146
|
+
const skill = skillsState.getSkill(skill_id);
|
|
147
|
+
if (!skill) {
|
|
148
|
+
return res.status(404).json(notFoundError('skill'));
|
|
149
|
+
}
|
|
150
|
+
let skillFiles;
|
|
151
|
+
try {
|
|
152
|
+
skillFiles = await extractSkillFiles(multerFiles);
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
return res.status(400).json(errorResponse(error instanceof Error ? error.message : 'Failed to process files'));
|
|
156
|
+
}
|
|
157
|
+
let manifest;
|
|
158
|
+
try {
|
|
159
|
+
const result = validateBundle(skillFiles);
|
|
160
|
+
manifest = result.manifest;
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
return res.status(400).json(errorResponse(error instanceof Error ? error.message : 'Invalid skill bundle'));
|
|
164
|
+
}
|
|
165
|
+
const newVersionNum = skill.latest_version + 1;
|
|
166
|
+
const now = Math.floor(Date.now() / 1000);
|
|
167
|
+
const version = {
|
|
168
|
+
version: newVersionNum,
|
|
169
|
+
created_at: now,
|
|
170
|
+
files: buildVersionFiles(skillFiles),
|
|
171
|
+
manifest,
|
|
172
|
+
};
|
|
173
|
+
skillsState.addVersion(skill_id, version);
|
|
174
|
+
saveSkillVersion(storageDir, skill_id, newVersionNum, skillFiles);
|
|
175
|
+
// Update skill name/description from new manifest
|
|
176
|
+
const updated = skillsState.updateSkill(skill_id, {
|
|
177
|
+
name: manifest.name,
|
|
178
|
+
description: manifest.description,
|
|
179
|
+
});
|
|
180
|
+
if (!updated) {
|
|
181
|
+
return res.status(404).json(notFoundError('skill'));
|
|
182
|
+
}
|
|
183
|
+
return res.status(201).json(skillsState.toSkillResponse(updated));
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
console.error('Error creating skill version:', error);
|
|
187
|
+
return res.status(500).json(errorResponse(error instanceof Error ? error.message : 'Internal server error'));
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
export default router;
|
|
191
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/skills/routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { OpenAIListResponse, PaginationParams } from '../assistants/types.js';
|
|
2
|
+
import { Skill, SkillVersion, SkillResponse } from './types.js';
|
|
3
|
+
type PersistCallback = (data: SerializedSkillsState) => void;
|
|
4
|
+
export interface SerializedSkillsState {
|
|
5
|
+
skills: [string, Skill][];
|
|
6
|
+
}
|
|
7
|
+
declare class SkillsState {
|
|
8
|
+
private skills;
|
|
9
|
+
private persistCallback;
|
|
10
|
+
private persistDebounceTimer;
|
|
11
|
+
private persistDebounceMs;
|
|
12
|
+
setPersistCallback(callback: PersistCallback, debounceMs?: number): void;
|
|
13
|
+
private triggerPersist;
|
|
14
|
+
generateSkillId(): string;
|
|
15
|
+
createSkill(skill: Skill): void;
|
|
16
|
+
getSkill(id: string): Skill | undefined;
|
|
17
|
+
getSkillResponse(id: string): SkillResponse | undefined;
|
|
18
|
+
listSkills(params?: PaginationParams): OpenAIListResponse<SkillResponse>;
|
|
19
|
+
updateSkill(id: string, updates: {
|
|
20
|
+
default_version?: number;
|
|
21
|
+
metadata?: Record<string, string>;
|
|
22
|
+
name?: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
}): Skill | undefined;
|
|
25
|
+
deleteSkill(id: string): boolean;
|
|
26
|
+
addVersion(skillId: string, version: SkillVersion): Skill | undefined;
|
|
27
|
+
getVersion(skillId: string, version: number): SkillVersion | undefined;
|
|
28
|
+
deleteVersion(skillId: string, version: number): Skill | undefined;
|
|
29
|
+
toSkillResponse(skill: Skill): SkillResponse;
|
|
30
|
+
serialize(): SerializedSkillsState;
|
|
31
|
+
restore(data: Partial<SerializedSkillsState>): void;
|
|
32
|
+
clear(): void;
|
|
33
|
+
}
|
|
34
|
+
export declare const skillsState: SkillsState;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { generateId } from '../utils.js';
|
|
2
|
+
class SkillsState {
|
|
3
|
+
skills = new Map();
|
|
4
|
+
persistCallback = null;
|
|
5
|
+
persistDebounceTimer = null;
|
|
6
|
+
persistDebounceMs = 1000;
|
|
7
|
+
setPersistCallback(callback, debounceMs) {
|
|
8
|
+
this.persistCallback = callback;
|
|
9
|
+
if (debounceMs !== undefined) {
|
|
10
|
+
this.persistDebounceMs = debounceMs;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
triggerPersist() {
|
|
14
|
+
if (!this.persistCallback)
|
|
15
|
+
return;
|
|
16
|
+
if (this.persistDebounceTimer) {
|
|
17
|
+
clearTimeout(this.persistDebounceTimer);
|
|
18
|
+
}
|
|
19
|
+
this.persistDebounceTimer = setTimeout(() => {
|
|
20
|
+
this.persistCallback?.(this.serialize());
|
|
21
|
+
this.persistDebounceTimer = null;
|
|
22
|
+
}, this.persistDebounceMs);
|
|
23
|
+
}
|
|
24
|
+
generateSkillId() {
|
|
25
|
+
return generateId('skill');
|
|
26
|
+
}
|
|
27
|
+
createSkill(skill) {
|
|
28
|
+
this.skills.set(skill.id, skill);
|
|
29
|
+
this.triggerPersist();
|
|
30
|
+
}
|
|
31
|
+
getSkill(id) {
|
|
32
|
+
return this.skills.get(id);
|
|
33
|
+
}
|
|
34
|
+
getSkillResponse(id) {
|
|
35
|
+
const skill = this.skills.get(id);
|
|
36
|
+
if (!skill)
|
|
37
|
+
return undefined;
|
|
38
|
+
return this.toSkillResponse(skill);
|
|
39
|
+
}
|
|
40
|
+
listSkills(params) {
|
|
41
|
+
const order = params?.order ?? 'desc';
|
|
42
|
+
const sortedSkills = Array.from(this.skills.values()).sort((a, b) => order === 'desc' ? b.created_at - a.created_at : a.created_at - b.created_at);
|
|
43
|
+
const limit = Math.min(params?.limit ?? 20, 100);
|
|
44
|
+
const after = params?.after;
|
|
45
|
+
const before = params?.before;
|
|
46
|
+
let items = sortedSkills;
|
|
47
|
+
if (after) {
|
|
48
|
+
const afterIndex = items.findIndex((s) => s.id === after);
|
|
49
|
+
if (afterIndex >= 0) {
|
|
50
|
+
items = items.slice(afterIndex + 1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (before) {
|
|
54
|
+
const beforeIndex = items.findIndex((s) => s.id === before);
|
|
55
|
+
if (beforeIndex >= 0) {
|
|
56
|
+
items = items.slice(0, beforeIndex);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const paginatedSkills = items.slice(0, limit);
|
|
60
|
+
const hasMore = paginatedSkills.length < items.length;
|
|
61
|
+
return {
|
|
62
|
+
object: 'list',
|
|
63
|
+
data: paginatedSkills.map((s) => this.toSkillResponse(s)),
|
|
64
|
+
first_id: paginatedSkills.length > 0 ? paginatedSkills[0].id : null,
|
|
65
|
+
last_id: paginatedSkills.length > 0 ? paginatedSkills[paginatedSkills.length - 1].id : null,
|
|
66
|
+
has_more: hasMore,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
updateSkill(id, updates) {
|
|
70
|
+
const skill = this.skills.get(id);
|
|
71
|
+
if (!skill)
|
|
72
|
+
return undefined;
|
|
73
|
+
if (updates.default_version !== undefined) {
|
|
74
|
+
skill.default_version = updates.default_version;
|
|
75
|
+
}
|
|
76
|
+
if (updates.metadata !== undefined) {
|
|
77
|
+
skill.metadata = updates.metadata;
|
|
78
|
+
}
|
|
79
|
+
if (updates.name !== undefined) {
|
|
80
|
+
skill.name = updates.name;
|
|
81
|
+
}
|
|
82
|
+
if (updates.description !== undefined) {
|
|
83
|
+
skill.description = updates.description;
|
|
84
|
+
}
|
|
85
|
+
this.triggerPersist();
|
|
86
|
+
return skill;
|
|
87
|
+
}
|
|
88
|
+
deleteSkill(id) {
|
|
89
|
+
const deleted = this.skills.delete(id);
|
|
90
|
+
if (deleted) {
|
|
91
|
+
this.triggerPersist();
|
|
92
|
+
}
|
|
93
|
+
return deleted;
|
|
94
|
+
}
|
|
95
|
+
addVersion(skillId, version) {
|
|
96
|
+
const skill = this.skills.get(skillId);
|
|
97
|
+
if (!skill)
|
|
98
|
+
return undefined;
|
|
99
|
+
skill.versions.push(version);
|
|
100
|
+
skill.latest_version = version.version;
|
|
101
|
+
this.triggerPersist();
|
|
102
|
+
return skill;
|
|
103
|
+
}
|
|
104
|
+
getVersion(skillId, version) {
|
|
105
|
+
const skill = this.skills.get(skillId);
|
|
106
|
+
if (!skill)
|
|
107
|
+
return undefined;
|
|
108
|
+
return skill.versions.find((v) => v.version === version);
|
|
109
|
+
}
|
|
110
|
+
deleteVersion(skillId, version) {
|
|
111
|
+
const skill = this.skills.get(skillId);
|
|
112
|
+
if (!skill)
|
|
113
|
+
return undefined;
|
|
114
|
+
skill.versions = skill.versions.filter((v) => v.version !== version);
|
|
115
|
+
// Recompute latest_version from remaining versions
|
|
116
|
+
if (skill.versions.length > 0) {
|
|
117
|
+
skill.latest_version = Math.max(...skill.versions.map((v) => v.version));
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
skill.latest_version = 0;
|
|
121
|
+
}
|
|
122
|
+
// Reset default_version if it pointed to the deleted version
|
|
123
|
+
if (skill.default_version === version) {
|
|
124
|
+
skill.default_version = skill.latest_version;
|
|
125
|
+
}
|
|
126
|
+
this.triggerPersist();
|
|
127
|
+
return skill;
|
|
128
|
+
}
|
|
129
|
+
toSkillResponse(skill) {
|
|
130
|
+
const { versions, ...response } = skill;
|
|
131
|
+
return response;
|
|
132
|
+
}
|
|
133
|
+
serialize() {
|
|
134
|
+
return {
|
|
135
|
+
skills: Array.from(this.skills.entries()),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
restore(data) {
|
|
139
|
+
if (!data.skills)
|
|
140
|
+
return;
|
|
141
|
+
this.skills.clear();
|
|
142
|
+
for (const [id, skill] of data.skills) {
|
|
143
|
+
this.skills.set(id, skill);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
clear() {
|
|
147
|
+
this.skills.clear();
|
|
148
|
+
if (this.persistDebounceTimer) {
|
|
149
|
+
clearTimeout(this.persistDebounceTimer);
|
|
150
|
+
this.persistDebounceTimer = null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
export const skillsState = new SkillsState();
|
|
155
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/skills/state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SkillFile } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Process multipart files from multer into SkillFile array
|
|
4
|
+
*/
|
|
5
|
+
export declare function processMultipartFiles(files: Express.Multer.File[]): SkillFile[];
|
|
6
|
+
/**
|
|
7
|
+
* Parse zip buffer and extract files
|
|
8
|
+
* Implements minimal zip format reader using Node.js built-ins
|
|
9
|
+
*/
|
|
10
|
+
export declare function processZipUpload(zipBuffer: Buffer): Promise<SkillFile[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Get the skill storage directory
|
|
13
|
+
*/
|
|
14
|
+
export declare function getSkillStorageDir(extensionPath: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Save a skill version to disk
|
|
17
|
+
*/
|
|
18
|
+
export declare function saveSkillVersion(storageDir: string, skillId: string, version: number, files: SkillFile[]): void;
|
|
19
|
+
/**
|
|
20
|
+
* Delete a specific skill version
|
|
21
|
+
*/
|
|
22
|
+
export declare function deleteSkillVersion(storageDir: string, skillId: string, version: number): void;
|
|
23
|
+
/**
|
|
24
|
+
* Delete all versions of a skill
|
|
25
|
+
*/
|
|
26
|
+
export declare function deleteSkillStorage(storageDir: string, skillId: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Guess MIME type based on file extension
|
|
29
|
+
*/
|
|
30
|
+
export declare function guessContentType(filePath: string): string;
|