@memtensor/memos-local-openclaw-plugin 0.1.4 → 0.1.6

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 (104) hide show
  1. package/README.md +196 -84
  2. package/dist/ingest/dedup.d.ts +8 -0
  3. package/dist/ingest/dedup.d.ts.map +1 -1
  4. package/dist/ingest/dedup.js +21 -0
  5. package/dist/ingest/dedup.js.map +1 -1
  6. package/dist/ingest/providers/anthropic.d.ts +14 -0
  7. package/dist/ingest/providers/anthropic.d.ts.map +1 -1
  8. package/dist/ingest/providers/anthropic.js +104 -0
  9. package/dist/ingest/providers/anthropic.js.map +1 -1
  10. package/dist/ingest/providers/bedrock.d.ts +14 -0
  11. package/dist/ingest/providers/bedrock.d.ts.map +1 -1
  12. package/dist/ingest/providers/bedrock.js +100 -0
  13. package/dist/ingest/providers/bedrock.js.map +1 -1
  14. package/dist/ingest/providers/gemini.d.ts +14 -0
  15. package/dist/ingest/providers/gemini.d.ts.map +1 -1
  16. package/dist/ingest/providers/gemini.js +96 -0
  17. package/dist/ingest/providers/gemini.js.map +1 -1
  18. package/dist/ingest/providers/index.d.ts +22 -0
  19. package/dist/ingest/providers/index.d.ts.map +1 -1
  20. package/dist/ingest/providers/index.js +68 -0
  21. package/dist/ingest/providers/index.js.map +1 -1
  22. package/dist/ingest/providers/openai.d.ts +22 -0
  23. package/dist/ingest/providers/openai.d.ts.map +1 -1
  24. package/dist/ingest/providers/openai.js +143 -0
  25. package/dist/ingest/providers/openai.js.map +1 -1
  26. package/dist/ingest/task-processor.d.ts +2 -0
  27. package/dist/ingest/task-processor.d.ts.map +1 -1
  28. package/dist/ingest/task-processor.js +15 -0
  29. package/dist/ingest/task-processor.js.map +1 -1
  30. package/dist/ingest/worker.d.ts +2 -0
  31. package/dist/ingest/worker.d.ts.map +1 -1
  32. package/dist/ingest/worker.js +115 -12
  33. package/dist/ingest/worker.js.map +1 -1
  34. package/dist/recall/engine.d.ts.map +1 -1
  35. package/dist/recall/engine.js +1 -0
  36. package/dist/recall/engine.js.map +1 -1
  37. package/dist/skill/bundled-memory-guide.d.ts +6 -0
  38. package/dist/skill/bundled-memory-guide.d.ts.map +1 -0
  39. package/dist/skill/bundled-memory-guide.js +95 -0
  40. package/dist/skill/bundled-memory-guide.js.map +1 -0
  41. package/dist/skill/evaluator.d.ts +31 -0
  42. package/dist/skill/evaluator.d.ts.map +1 -0
  43. package/dist/skill/evaluator.js +194 -0
  44. package/dist/skill/evaluator.js.map +1 -0
  45. package/dist/skill/evolver.d.ts +22 -0
  46. package/dist/skill/evolver.d.ts.map +1 -0
  47. package/dist/skill/evolver.js +193 -0
  48. package/dist/skill/evolver.js.map +1 -0
  49. package/dist/skill/generator.d.ts +25 -0
  50. package/dist/skill/generator.d.ts.map +1 -0
  51. package/dist/skill/generator.js +477 -0
  52. package/dist/skill/generator.js.map +1 -0
  53. package/dist/skill/installer.d.ts +16 -0
  54. package/dist/skill/installer.d.ts.map +1 -0
  55. package/dist/skill/installer.js +89 -0
  56. package/dist/skill/installer.js.map +1 -0
  57. package/dist/skill/upgrader.d.ts +19 -0
  58. package/dist/skill/upgrader.d.ts.map +1 -0
  59. package/dist/skill/upgrader.js +263 -0
  60. package/dist/skill/upgrader.js.map +1 -0
  61. package/dist/skill/validator.d.ts +29 -0
  62. package/dist/skill/validator.d.ts.map +1 -0
  63. package/dist/skill/validator.js +227 -0
  64. package/dist/skill/validator.js.map +1 -0
  65. package/dist/storage/sqlite.d.ts +75 -1
  66. package/dist/storage/sqlite.d.ts.map +1 -1
  67. package/dist/storage/sqlite.js +417 -6
  68. package/dist/storage/sqlite.js.map +1 -1
  69. package/dist/types.d.ts +78 -0
  70. package/dist/types.d.ts.map +1 -1
  71. package/dist/types.js +6 -0
  72. package/dist/types.js.map +1 -1
  73. package/dist/viewer/html.d.ts +1 -1
  74. package/dist/viewer/html.d.ts.map +1 -1
  75. package/dist/viewer/html.js +1549 -113
  76. package/dist/viewer/html.js.map +1 -1
  77. package/dist/viewer/server.d.ts +13 -0
  78. package/dist/viewer/server.d.ts.map +1 -1
  79. package/dist/viewer/server.js +289 -4
  80. package/dist/viewer/server.js.map +1 -1
  81. package/index.ts +489 -181
  82. package/package.json +1 -1
  83. package/skill/memos-memory-guide/SKILL.md +86 -0
  84. package/src/ingest/dedup.ts +29 -0
  85. package/src/ingest/providers/anthropic.ts +130 -0
  86. package/src/ingest/providers/bedrock.ts +126 -0
  87. package/src/ingest/providers/gemini.ts +124 -0
  88. package/src/ingest/providers/index.ts +86 -4
  89. package/src/ingest/providers/openai.ts +174 -0
  90. package/src/ingest/task-processor.ts +16 -0
  91. package/src/ingest/worker.ts +126 -21
  92. package/src/recall/engine.ts +1 -0
  93. package/src/skill/bundled-memory-guide.ts +91 -0
  94. package/src/skill/evaluator.ts +220 -0
  95. package/src/skill/evolver.ts +169 -0
  96. package/src/skill/generator.ts +506 -0
  97. package/src/skill/installer.ts +59 -0
  98. package/src/skill/upgrader.ts +257 -0
  99. package/src/skill/validator.ts +227 -0
  100. package/src/storage/sqlite.ts +508 -6
  101. package/src/types.ts +77 -0
  102. package/src/viewer/html.ts +1549 -113
  103. package/src/viewer/server.ts +285 -4
  104. package/skill/SKILL.md +0 -59
@@ -0,0 +1,263 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SkillUpgrader = void 0;
37
+ const uuid_1 = require("uuid");
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const validator_1 = require("./validator");
41
+ const UPGRADE_PROMPT = `You are a Skill upgrade expert. You're merging new real-world execution experience into an existing Skill to make it better.
42
+
43
+ Remember: this is based on ACTUAL execution — the new task was really run, errors were really encountered and fixed. This makes the upgrade valuable.
44
+
45
+ ## Core principles (follow strictly but do NOT include in output)
46
+
47
+ ### Progressive disclosure
48
+ - Keep the frontmatter description as the primary trigger mechanism (~60-120 words, proactive — see below)
49
+ - SKILL.md body should stay under 400 lines total
50
+ - If content grows too large, consider moving deep details to references/ and just pointing to them
51
+
52
+ ### Description as trigger
53
+ The description decides whether the agent activates this skill. Write it "proactively":
54
+ - Cover what it does + situations/keywords/phrasings that should trigger it
55
+ - Be explicit about edge cases — "even if the user doesn't say X explicitly but describes Y"
56
+ - If the new task reveals new trigger scenarios, ADD them to the description
57
+
58
+ ### Writing style
59
+ - Imperative form
60
+ - Explain WHY for each step — reasoning beats rigid rules
61
+ - Avoid ALWAYS/NEVER in caps — rephrase with reasoning instead
62
+ - Generalize from specific tasks
63
+ - Keep verified commands/code/config from both old and new tasks
64
+ - CRITICAL: Match the language of the skill and task record. If the existing skill or the new task record is in Chinese, write ALL upgraded content in Chinese. If English, write in English. Only the "name" field stays in English kebab-case. DO NOT default to English.
65
+
66
+ ## Existing skill (v{VERSION}):
67
+ {SKILL_CONTENT}
68
+
69
+ ## Upgrade context
70
+ - Type: {UPGRADE_TYPE}
71
+ - Dimensions improved: {DIMENSIONS}
72
+ - Reason: {REASON}
73
+ - Merge strategy: {MERGE_STRATEGY}
74
+
75
+ ## New task record
76
+ Title: {TITLE}
77
+ Summary:
78
+ {SUMMARY}
79
+
80
+ ## Merge rules
81
+ 1. Preserve all valid core content from the existing skill — upgrades should ADD value, not lose it
82
+ 2. Merge new experience strategically:
83
+ - Better approach found → replace old, keep old as "Alternative approach" if it's still valid
84
+ - New scenario discovered → add a new section (don't replace unrelated content)
85
+ - Bug/error corrected → replace directly, add to "Pitfalls and solutions" section
86
+ - Performance improvement → update steps, note the improvement in why-reasoning
87
+ 3. Update description if new scenarios/keywords/triggers need coverage
88
+ 4. Update "When to use this skill" section if the new task reveals new use cases
89
+ 5. If a "Pitfalls and solutions" section exists, append new pitfalls; if it doesn't exist, create it
90
+ 6. Total length ≤ 400 lines — if approaching limit, move detailed configs/references to references/
91
+ 7. Add version comment at end:
92
+ <!-- v{NEW_VERSION}: {one-line change note} (from task: {TASK_ID}) -->
93
+
94
+ ## Output format
95
+
96
+ Output the complete upgraded SKILL.md (with full frontmatter), then on a new line write:
97
+ ---CHANGELOG---
98
+ {one-line changelog title}
99
+ ---CHANGE_SUMMARY---
100
+ {A 3-5 sentence summary in the same language as the skill. Cover: (1) What specifically was changed and what triggered the change, (2) What concrete new capability or improvement this version brings, (3) What real problem from the new task this solves. Write for a human reader who wants to quickly understand the value of this upgrade.}`;
101
+ class SkillUpgrader {
102
+ store;
103
+ ctx;
104
+ validator;
105
+ constructor(store, ctx) {
106
+ this.store = store;
107
+ this.ctx = ctx;
108
+ this.validator = new validator_1.SkillValidator(ctx);
109
+ }
110
+ async upgrade(task, skill, evalResult) {
111
+ const currentContent = this.readCurrentContent(skill);
112
+ if (!currentContent) {
113
+ this.ctx.log.warn(`SkillUpgrader: could not read content for "${skill.name}"`);
114
+ return { upgraded: false, qualityScore: null };
115
+ }
116
+ const { newContent, changelog, changeSummary } = await this.callUpgradeLLM(task, skill, currentContent, evalResult);
117
+ if (!newContent || newContent.length < 100) {
118
+ this.ctx.log.warn(`SkillUpgrader: generated content too short for "${skill.name}", skipping`);
119
+ return { upgraded: false, qualityScore: null };
120
+ }
121
+ fs.writeFileSync(path.join(skill.dirPath, "SKILL.md"), newContent, "utf-8");
122
+ const validation = await this.validator.validate(skill.dirPath, {
123
+ previousContent: currentContent,
124
+ });
125
+ if (!validation.valid) {
126
+ this.ctx.log.warn(`SkillUpgrader: validation failed for "${skill.name}", reverting: ${validation.errors.join("; ")}`);
127
+ fs.writeFileSync(path.join(skill.dirPath, "SKILL.md"), currentContent, "utf-8");
128
+ return { upgraded: false, qualityScore: null };
129
+ }
130
+ const newVersion = skill.version + 1;
131
+ const newDescription = this.parseDescription(newContent) || skill.description;
132
+ const newStatus = validation.qualityScore !== null && validation.qualityScore < 6 ? "draft" : skill.status;
133
+ this.store.updateSkill(skill.id, {
134
+ description: newDescription,
135
+ version: newVersion,
136
+ status: newStatus,
137
+ qualityScore: validation.qualityScore,
138
+ updatedAt: Date.now(),
139
+ });
140
+ this.store.insertSkillVersion({
141
+ id: (0, uuid_1.v4)(),
142
+ skillId: skill.id,
143
+ version: newVersion,
144
+ content: newContent,
145
+ changelog: changelog || `Upgraded from task "${task.title}"`,
146
+ changeSummary: changeSummary || `基于任务"${task.title}"的执行记录进行了版本升级。`,
147
+ upgradeType: evalResult.upgradeType,
148
+ sourceTaskId: task.id,
149
+ metrics: JSON.stringify({
150
+ dimensions: evalResult.dimensions,
151
+ confidence: evalResult.confidence,
152
+ validation: {
153
+ errors: validation.errors,
154
+ warnings: validation.warnings,
155
+ suggestions: validation.suggestions,
156
+ },
157
+ }),
158
+ qualityScore: validation.qualityScore,
159
+ createdAt: Date.now(),
160
+ });
161
+ if (validation.warnings.length > 0) {
162
+ this.ctx.log.info(`Skill "${skill.name}" upgrade warnings: ${validation.warnings.join("; ")}`);
163
+ }
164
+ this.ctx.log.info(`Skill upgraded: "${skill.name}" v${skill.version} → v${newVersion} [${newStatus}] score=${validation.qualityScore ?? "N/A"}`);
165
+ return { upgraded: true, qualityScore: validation.qualityScore };
166
+ }
167
+ readCurrentContent(skill) {
168
+ const filePath = path.join(skill.dirPath, "SKILL.md");
169
+ try {
170
+ return fs.readFileSync(filePath, "utf-8");
171
+ }
172
+ catch {
173
+ const sv = this.store.getLatestSkillVersion(skill.id);
174
+ return sv?.content ?? null;
175
+ }
176
+ }
177
+ async callUpgradeLLM(task, skill, currentContent, evalResult) {
178
+ const cfg = this.getProviderConfig();
179
+ if (!cfg)
180
+ throw new Error("No LLM configured for skill upgrade");
181
+ const newVersion = skill.version + 1;
182
+ const detectLang = (text) => {
183
+ const cjk = text.match(/[\u4e00-\u9fff\u3400-\u4dbf]/g)?.length ?? 0;
184
+ const total = text.replace(/\s+/g, "").length || 1;
185
+ return (cjk / total > 0.15) ? "Chinese (中文)" : "English";
186
+ };
187
+ const lang = detectLang(task.summary + currentContent);
188
+ const langInstruction = `\n\n⚠️ LANGUAGE REQUIREMENT: The content is in ${lang}. You MUST write ALL prose (description, headings, explanations, pitfalls, changelog, change summary) in ${lang}. Only the "name" field stays in English kebab-case.\n`;
189
+ const prompt = UPGRADE_PROMPT
190
+ .replace("{VERSION}", String(skill.version))
191
+ .replace("{SKILL_CONTENT}", currentContent.slice(0, 6000))
192
+ .replace("{UPGRADE_TYPE}", evalResult.upgradeType)
193
+ .replace("{DIMENSIONS}", evalResult.dimensions.join(", "))
194
+ .replace("{REASON}", evalResult.reason)
195
+ .replace("{MERGE_STRATEGY}", evalResult.mergeStrategy)
196
+ .replace("{TITLE}", task.title)
197
+ .replace("{SUMMARY}", task.summary.slice(0, 4000))
198
+ .replace("{NEW_VERSION}", String(newVersion))
199
+ .replace("{TASK_ID}", task.id)
200
+ + langInstruction;
201
+ const endpoint = this.normalizeEndpoint(cfg.endpoint ?? "https://api.openai.com/v1/chat/completions");
202
+ const model = cfg.model ?? "gpt-4o-mini";
203
+ const headers = {
204
+ "Content-Type": "application/json",
205
+ Authorization: `Bearer ${cfg.apiKey}`,
206
+ ...cfg.headers,
207
+ };
208
+ const resp = await fetch(endpoint, {
209
+ method: "POST",
210
+ headers,
211
+ body: JSON.stringify({
212
+ model,
213
+ temperature: cfg.temperature ?? 0.2,
214
+ max_tokens: 6000,
215
+ messages: [
216
+ { role: "user", content: prompt },
217
+ ],
218
+ }),
219
+ signal: AbortSignal.timeout(cfg.timeoutMs ?? 90_000),
220
+ });
221
+ if (!resp.ok) {
222
+ const body = await resp.text();
223
+ throw new Error(`Skill upgrade LLM failed (${resp.status}): ${body}`);
224
+ }
225
+ const json = (await resp.json());
226
+ const raw = json.choices[0]?.message?.content?.trim() ?? "";
227
+ const changelogSep = raw.indexOf("---CHANGELOG---");
228
+ if (changelogSep !== -1) {
229
+ const newContent = raw.slice(0, changelogSep).trim();
230
+ const afterChangelog = raw.slice(changelogSep + "---CHANGELOG---".length).trim();
231
+ const summarySep = afterChangelog.indexOf("---CHANGE_SUMMARY---");
232
+ if (summarySep !== -1) {
233
+ const changelog = afterChangelog.slice(0, summarySep).trim();
234
+ const changeSummary = afterChangelog.slice(summarySep + "---CHANGE_SUMMARY---".length).trim();
235
+ return { newContent, changelog, changeSummary };
236
+ }
237
+ return { newContent, changelog: afterChangelog, changeSummary: "" };
238
+ }
239
+ return { newContent: raw, changelog: "", changeSummary: "" };
240
+ }
241
+ parseDescription(content) {
242
+ const match = content.match(/description:\s*"([^"]+)"/);
243
+ if (match)
244
+ return match[1];
245
+ const match2 = content.match(/description:\s*'([^']+)'/);
246
+ if (match2)
247
+ return match2[1];
248
+ return "";
249
+ }
250
+ getProviderConfig() {
251
+ return this.ctx.config.skillEvolution?.summarizer ?? this.ctx.config.summarizer;
252
+ }
253
+ normalizeEndpoint(url) {
254
+ const stripped = url.replace(/\/+$/, "");
255
+ if (stripped.endsWith("/chat/completions"))
256
+ return stripped;
257
+ if (stripped.endsWith("/completions"))
258
+ return stripped;
259
+ return `${stripped}/chat/completions`;
260
+ }
261
+ }
262
+ exports.SkillUpgrader = SkillUpgrader;
263
+ //# sourceMappingURL=upgrader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrader.js","sourceRoot":"","sources":["../../src/skill/upgrader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { PluginContext } from "../types";
2
+ export interface ValidationResult {
3
+ valid: boolean;
4
+ qualityScore: number | null;
5
+ errors: string[];
6
+ warnings: string[];
7
+ suggestions: string[];
8
+ }
9
+ export declare class SkillValidator {
10
+ private ctx;
11
+ constructor(ctx: PluginContext);
12
+ /**
13
+ * Format validation (no LLM needed) + optional LLM quality assessment.
14
+ * Returns combined result with score 0-10.
15
+ */
16
+ validate(dirPath: string, opts?: {
17
+ skipLLM?: boolean;
18
+ previousContent?: string;
19
+ }): Promise<ValidationResult>;
20
+ private validateFormat;
21
+ /**
22
+ * Check that an upgrade doesn't lose significant content from the previous version.
23
+ */
24
+ private regressionCheck;
25
+ private assessQuality;
26
+ private getProviderConfig;
27
+ private normalizeEndpoint;
28
+ }
29
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/skill/validator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAoB,MAAM,UAAU,CAAC;AAGhE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,qBAAa,cAAc;IACb,OAAO,CAAC,GAAG;gBAAH,GAAG,EAAE,aAAa;IAEtC;;;OAGG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA4BlH,OAAO,CAAC,cAAc;IA8DtB;;OAEG;IACH,OAAO,CAAC,eAAe;YAqBT,aAAa;IA8D3B,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,iBAAiB;CAM1B"}
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SkillValidator = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const types_1 = require("../types");
40
+ class SkillValidator {
41
+ ctx;
42
+ constructor(ctx) {
43
+ this.ctx = ctx;
44
+ }
45
+ /**
46
+ * Format validation (no LLM needed) + optional LLM quality assessment.
47
+ * Returns combined result with score 0-10.
48
+ */
49
+ async validate(dirPath, opts) {
50
+ const result = {
51
+ valid: true,
52
+ qualityScore: null,
53
+ errors: [],
54
+ warnings: [],
55
+ suggestions: [],
56
+ };
57
+ this.validateFormat(dirPath, result);
58
+ if (!result.valid)
59
+ return result;
60
+ if (opts?.previousContent) {
61
+ this.regressionCheck(dirPath, opts.previousContent, result);
62
+ }
63
+ if (!opts?.skipLLM) {
64
+ try {
65
+ await this.assessQuality(dirPath, result);
66
+ }
67
+ catch (err) {
68
+ this.ctx.log.warn(`SkillValidator: LLM quality assessment failed: ${err}`);
69
+ result.warnings.push(`Quality assessment skipped: ${err}`);
70
+ }
71
+ }
72
+ return result;
73
+ }
74
+ validateFormat(dirPath, result) {
75
+ const skillMdPath = path.join(dirPath, "SKILL.md");
76
+ if (!fs.existsSync(skillMdPath)) {
77
+ result.valid = false;
78
+ result.errors.push("SKILL.md not found");
79
+ return;
80
+ }
81
+ const content = fs.readFileSync(skillMdPath, "utf-8");
82
+ if (!content.trim()) {
83
+ result.valid = false;
84
+ result.errors.push("SKILL.md is empty");
85
+ return;
86
+ }
87
+ const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
88
+ if (!fmMatch) {
89
+ result.valid = false;
90
+ result.errors.push("YAML frontmatter missing (expected --- ... ---)");
91
+ return;
92
+ }
93
+ const frontmatter = fmMatch[1];
94
+ const nameMatch = frontmatter.match(/^name:\s*["']?(.+?)["']?\s*$/m);
95
+ if (!nameMatch || !nameMatch[1].trim()) {
96
+ result.valid = false;
97
+ result.errors.push("Frontmatter missing 'name' field");
98
+ return;
99
+ }
100
+ const name = nameMatch[1].trim();
101
+ if (name.length > 64) {
102
+ result.errors.push(`Name too long (${name.length} chars, max 64)`);
103
+ result.valid = false;
104
+ }
105
+ if (!/^[a-z0-9][a-z0-9-]*[a-z0-9]$/.test(name) && name.length > 1) {
106
+ result.warnings.push(`Name "${name}" is not strict kebab-case`);
107
+ }
108
+ const descMatch = frontmatter.match(/^description:\s*["']?([\s\S]*?)["']?\s*$/m);
109
+ if (!descMatch || !descMatch[1].trim()) {
110
+ result.valid = false;
111
+ result.errors.push("Frontmatter missing 'description' field");
112
+ return;
113
+ }
114
+ const desc = descMatch[1].trim();
115
+ if (desc.length > 1024) {
116
+ result.warnings.push(`Description too long (${desc.length} chars, max 1024)`);
117
+ }
118
+ const maxLines = this.ctx.config.skillEvolution?.maxSkillLines ?? types_1.DEFAULTS.skillMaxLines;
119
+ const lineCount = content.split("\n").length;
120
+ if (lineCount > maxLines) {
121
+ result.warnings.push(`Content exceeds ${maxLines} lines (has ${lineCount})`);
122
+ }
123
+ if (content.length < 200) {
124
+ result.warnings.push("Content seems very short (< 200 chars)");
125
+ }
126
+ }
127
+ /**
128
+ * Check that an upgrade doesn't lose significant content from the previous version.
129
+ */
130
+ regressionCheck(dirPath, previousContent, result) {
131
+ const skillMdPath = path.join(dirPath, "SKILL.md");
132
+ const newContent = fs.readFileSync(skillMdPath, "utf-8");
133
+ const prevLines = previousContent.split("\n").length;
134
+ const newLines = newContent.split("\n").length;
135
+ if (newLines < prevLines * 0.7 && prevLines > 20) {
136
+ result.warnings.push(`Content shrank significantly: ${prevLines} → ${newLines} lines (${Math.round((1 - newLines / prevLines) * 100)}% reduction)`);
137
+ }
138
+ const prevSections = (previousContent.match(/^##\s+.+$/gm) || []).map(s => s.replace(/^##\s+/, "").trim().toLowerCase());
139
+ const newSections = (newContent.match(/^##\s+.+$/gm) || []).map(s => s.replace(/^##\s+/, "").trim().toLowerCase());
140
+ const missingSections = prevSections.filter(s => !newSections.some(ns => ns.includes(s) || s.includes(ns)));
141
+ if (missingSections.length > 0) {
142
+ result.warnings.push(`Sections may have been lost: ${missingSections.join(", ")}`);
143
+ }
144
+ }
145
+ async assessQuality(dirPath, result) {
146
+ const cfg = this.getProviderConfig();
147
+ if (!cfg)
148
+ return;
149
+ const skillMdPath = path.join(dirPath, "SKILL.md");
150
+ const content = fs.readFileSync(skillMdPath, "utf-8");
151
+ const prompt = QUALITY_PROMPT.replace("{SKILL_CONTENT}", content.slice(0, 6000));
152
+ const endpoint = this.normalizeEndpoint(cfg.endpoint ?? "https://api.openai.com/v1/chat/completions");
153
+ const headers = {
154
+ "Content-Type": "application/json",
155
+ Authorization: `Bearer ${cfg.apiKey}`,
156
+ ...cfg.headers,
157
+ };
158
+ const resp = await fetch(endpoint, {
159
+ method: "POST",
160
+ headers,
161
+ body: JSON.stringify({
162
+ model: cfg.model ?? "gpt-4o-mini",
163
+ temperature: cfg.temperature ?? 0.1,
164
+ max_tokens: 1024,
165
+ messages: [{ role: "user", content: prompt }],
166
+ }),
167
+ signal: AbortSignal.timeout(cfg.timeoutMs ?? 30_000),
168
+ });
169
+ if (!resp.ok) {
170
+ const body = await resp.text();
171
+ throw new Error(`Quality LLM failed (${resp.status}): ${body}`);
172
+ }
173
+ const json = (await resp.json());
174
+ const raw = json.choices[0]?.message?.content?.trim() ?? "";
175
+ const jsonMatch = raw.match(/\{[\s\S]*\}/);
176
+ if (!jsonMatch)
177
+ return;
178
+ try {
179
+ const assessment = JSON.parse(jsonMatch[0]);
180
+ result.qualityScore = Math.max(0, Math.min(10, assessment.score));
181
+ if (assessment.suggestions) {
182
+ result.suggestions.push(...assessment.suggestions);
183
+ }
184
+ if (assessment.weaknesses) {
185
+ result.warnings.push(...assessment.weaknesses);
186
+ }
187
+ if (result.qualityScore < 6) {
188
+ result.warnings.push(`Quality score ${result.qualityScore}/10 is below threshold, marked as draft`);
189
+ }
190
+ }
191
+ catch {
192
+ this.ctx.log.warn("SkillValidator: failed to parse quality assessment JSON");
193
+ }
194
+ }
195
+ getProviderConfig() {
196
+ return this.ctx.config.skillEvolution?.summarizer ?? this.ctx.config.summarizer;
197
+ }
198
+ normalizeEndpoint(url) {
199
+ const stripped = url.replace(/\/+$/, "");
200
+ if (stripped.endsWith("/chat/completions"))
201
+ return stripped;
202
+ if (stripped.endsWith("/completions"))
203
+ return stripped;
204
+ return `${stripped}/chat/completions`;
205
+ }
206
+ }
207
+ exports.SkillValidator = SkillValidator;
208
+ const QUALITY_PROMPT = `You are a skill quality reviewer. Evaluate the following SKILL.md and give a score from 0 to 10.
209
+
210
+ Criteria:
211
+ 1. Clarity: Are the steps clear and actionable? (0-2 pts)
212
+ 2. Completeness: Does it cover scenarios, pitfalls, and key code? (0-2 pts)
213
+ 3. Reusability: Can this skill be applied to similar future tasks? (0-2 pts)
214
+ 4. Accuracy: Are commands, code, and configurations correct? (0-2 pts)
215
+ 5. Structure: Is the format well-organized with proper sections? (0-2 pts)
216
+
217
+ SKILL.md:
218
+ {SKILL_CONTENT}
219
+
220
+ Reply in JSON only:
221
+ {
222
+ "score": 0-10,
223
+ "strengths": ["what's good"],
224
+ "weaknesses": ["what's lacking"],
225
+ "suggestions": ["how to improve"]
226
+ }`;
227
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/skill/validator.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { Chunk, ChunkRef, Task, TaskStatus, Logger } from "../types";
1
+ import type { Chunk, ChunkRef, Task, TaskStatus, Skill, SkillStatus, SkillVersion, TaskSkillRelation, Logger } from "../types";
2
2
  export declare class SqliteStore {
3
3
  private log;
4
4
  private db;
@@ -6,6 +6,49 @@ export declare class SqliteStore {
6
6
  private migrate;
7
7
  private migrateTaskId;
8
8
  private migrateContentHash;
9
+ private migrateSkillTables;
10
+ private migrateSkillId;
11
+ private migrateSkillQualityScore;
12
+ private migrateTaskSkillMeta;
13
+ setTaskSkillMeta(taskId: string, meta: {
14
+ skillStatus: string;
15
+ skillReason: string;
16
+ }): void;
17
+ private migrateMergeFields;
18
+ private migrateApiLogs;
19
+ private migrateDedupStatus;
20
+ recordApiLog(toolName: string, input: unknown, output: string, durationMs: number, success: boolean): void;
21
+ getApiLogs(limit?: number, offset?: number, toolFilter?: string): {
22
+ logs: Array<{
23
+ id: number;
24
+ toolName: string;
25
+ input: string;
26
+ output: string;
27
+ durationMs: number;
28
+ success: boolean;
29
+ calledAt: number;
30
+ }>;
31
+ total: number;
32
+ };
33
+ getApiLogToolNames(): string[];
34
+ recordMergeHit(chunkId: string, action: "DUPLICATE" | "UPDATE", reason: string, oldSummary?: string, newSummary?: string): void;
35
+ updateChunkSummaryAndContent(chunkId: string, newSummary: string, appendContent: string): void;
36
+ private migrateToolCalls;
37
+ recordToolCall(toolName: string, durationMs: number, success: boolean): void;
38
+ getToolMetrics(minutes: number): {
39
+ tools: string[];
40
+ series: Array<{
41
+ minute: string;
42
+ [tool: string]: number | string;
43
+ }>;
44
+ aggregated: Array<{
45
+ tool: string;
46
+ totalCalls: number;
47
+ avgMs: number;
48
+ p95Ms: number;
49
+ errorCount: number;
50
+ }>;
51
+ };
9
52
  /** Record a viewer API call for analytics (list, search, etc.). */
10
53
  recordViewerEvent(eventType: string): void;
11
54
  /**
@@ -33,6 +76,7 @@ export declare class SqliteStore {
33
76
  };
34
77
  };
35
78
  insertChunk(chunk: Chunk): void;
79
+ markDedupStatus(chunkId: string, status: "duplicate" | "merged", targetChunkId: string | null, reason: string): void;
36
80
  updateSummary(chunkId: string, summary: string): void;
37
81
  upsertEmbedding(chunkId: string, vector: number[]): void;
38
82
  getChunk(chunkId: string): Chunk | null;
@@ -95,6 +139,36 @@ export declare class SqliteStore {
95
139
  chunkExistsByContent(sessionKey: string, role: string, content: string): boolean;
96
140
  getRecentChunkIds(limit: number): string[];
97
141
  countChunks(): number;
142
+ insertSkill(skill: Skill): void;
143
+ getSkill(skillId: string): Skill | null;
144
+ getSkillByName(name: string): Skill | null;
145
+ updateSkill(skillId: string, fields: {
146
+ description?: string;
147
+ version?: number;
148
+ status?: SkillStatus;
149
+ installed?: number;
150
+ qualityScore?: number | null;
151
+ updatedAt?: number;
152
+ }): void;
153
+ listSkills(opts?: {
154
+ status?: string;
155
+ }): Skill[];
156
+ insertSkillVersion(sv: SkillVersion): void;
157
+ getLatestSkillVersion(skillId: string): SkillVersion | null;
158
+ getSkillVersions(skillId: string): SkillVersion[];
159
+ getSkillVersion(skillId: string, version: number): SkillVersion | null;
160
+ linkTaskSkill(taskId: string, skillId: string, relation: TaskSkillRelation, versionAt: number): void;
161
+ getSkillsByTask(taskId: string): Array<{
162
+ skill: Skill;
163
+ relation: TaskSkillRelation;
164
+ versionAt: number;
165
+ }>;
166
+ getTasksBySkill(skillId: string): Array<{
167
+ task: Task;
168
+ relation: TaskSkillRelation;
169
+ }>;
170
+ countSkills(status?: string): number;
171
+ setChunkSkillId(chunkId: string, skillId: string): void;
98
172
  close(): void;
99
173
  }
100
174
  //# sourceMappingURL=sqlite.d.ts.map