skill-tree 0.1.2 → 0.1.3
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/cli/index.js +68 -1171
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/index.mjs +10664 -74
- package/dist/cli/index.mjs.map +1 -0
- package/dist/index.d.mts +23 -1090
- package/dist/index.d.ts +23 -1090
- package/dist/index.js +171 -1855
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +14091 -127
- package/dist/index.mjs.map +1 -0
- package/package.json +2 -3
- package/dist/chunk-3SRB47JW.mjs +0 -8344
- package/dist/chunk-43YOKLZP.mjs +0 -6081
- package/dist/chunk-4AGZU52D.mjs +0 -7918
- package/dist/chunk-4OC5QFIF.mjs +0 -11267
- package/dist/chunk-55SMGVTP.mjs +0 -7126
- package/dist/chunk-6FX4IK4Z.mjs +0 -5368
- package/dist/chunk-7EGDKOHV.mjs +0 -9439
- package/dist/chunk-7LMOQW5H.mjs +0 -4893
- package/dist/chunk-7VB4ZRZO.mjs +0 -7127
- package/dist/chunk-BPVRW25O.mjs +0 -6089
- package/dist/chunk-CI4476KM.mjs +0 -6607
- package/dist/chunk-DDXYQ74I.mjs +0 -13969
- package/dist/chunk-DQOFJXBX.mjs +0 -6595
- package/dist/chunk-E2CVK23F.mjs +0 -8751
- package/dist/chunk-II7DECZQ.mjs +0 -9111
- package/dist/chunk-INKVOZXK.mjs +0 -15898
- package/dist/chunk-K6NRCSAZ.mjs +0 -4355
- package/dist/chunk-ZQVS7MQK.mjs +0 -6081
package/dist/cli/index.js
CHANGED
|
@@ -712,11 +712,76 @@ var LoadoutCompiler = class {
|
|
|
712
712
|
// src/serving/project-detector.ts
|
|
713
713
|
var import_fs = require("fs");
|
|
714
714
|
var import_path = require("path");
|
|
715
|
-
var
|
|
715
|
+
var ProjectDetector = class _ProjectDetector {
|
|
716
716
|
constructor() {
|
|
717
717
|
/** Cache for project context */
|
|
718
718
|
this.cache = /* @__PURE__ */ new Map();
|
|
719
719
|
}
|
|
720
|
+
static {
|
|
721
|
+
/** Project type patterns */
|
|
722
|
+
this.PROJECT_TYPES = [
|
|
723
|
+
{ manifestFile: "package.json", type: "nodejs", tags: ["nodejs", "javascript"], packageManager: "npm" },
|
|
724
|
+
{ manifestFile: "pyproject.toml", type: "python", tags: ["python"], packageManager: "pip" },
|
|
725
|
+
{ manifestFile: "requirements.txt", type: "python", tags: ["python"], packageManager: "pip" },
|
|
726
|
+
{ manifestFile: "Cargo.toml", type: "rust", tags: ["rust"], packageManager: "cargo" },
|
|
727
|
+
{ manifestFile: "go.mod", type: "go", tags: ["go", "golang"] },
|
|
728
|
+
{ manifestFile: "pom.xml", type: "java", tags: ["java", "maven"], packageManager: "maven" },
|
|
729
|
+
{ manifestFile: "build.gradle", type: "java", tags: ["java", "gradle"], packageManager: "gradle" },
|
|
730
|
+
{ manifestFile: "build.gradle.kts", type: "kotlin", tags: ["kotlin", "gradle"], packageManager: "gradle" }
|
|
731
|
+
];
|
|
732
|
+
}
|
|
733
|
+
static {
|
|
734
|
+
/** TypeScript detection */
|
|
735
|
+
this.TYPESCRIPT_FILES = ["tsconfig.json", "tsconfig.base.json"];
|
|
736
|
+
}
|
|
737
|
+
static {
|
|
738
|
+
/** Node.js framework patterns */
|
|
739
|
+
this.NODE_FRAMEWORKS = [
|
|
740
|
+
{ name: "react", packageName: "react", tags: ["react", "frontend"] },
|
|
741
|
+
{ name: "next", packageName: "next", tags: ["nextjs", "react", "fullstack"] },
|
|
742
|
+
{ name: "vue", packageName: "vue", tags: ["vue", "frontend"] },
|
|
743
|
+
{ name: "nuxt", packageName: "nuxt", tags: ["nuxt", "vue", "fullstack"] },
|
|
744
|
+
{ name: "angular", packageName: "@angular/core", tags: ["angular", "frontend"] },
|
|
745
|
+
{ name: "svelte", packageName: "svelte", tags: ["svelte", "frontend"] },
|
|
746
|
+
{ name: "express", packageName: "express", tags: ["express", "backend", "api"] },
|
|
747
|
+
{ name: "fastify", packageName: "fastify", tags: ["fastify", "backend", "api"] },
|
|
748
|
+
{ name: "nestjs", packageName: "@nestjs/core", tags: ["nestjs", "backend", "api"] },
|
|
749
|
+
{ name: "hono", packageName: "hono", tags: ["hono", "backend", "api"] },
|
|
750
|
+
{ name: "prisma", packageName: "@prisma/client", tags: ["prisma", "database", "orm"] },
|
|
751
|
+
{ name: "drizzle", packageName: "drizzle-orm", tags: ["drizzle", "database", "orm"] },
|
|
752
|
+
{ name: "typeorm", packageName: "typeorm", tags: ["typeorm", "database", "orm"] },
|
|
753
|
+
{ name: "jest", packageName: "jest", tags: ["testing", "jest"] },
|
|
754
|
+
{ name: "vitest", packageName: "vitest", tags: ["testing", "vitest"] },
|
|
755
|
+
{ name: "playwright", packageName: "@playwright/test", tags: ["testing", "e2e", "playwright"] },
|
|
756
|
+
{ name: "cypress", packageName: "cypress", tags: ["testing", "e2e", "cypress"] }
|
|
757
|
+
];
|
|
758
|
+
}
|
|
759
|
+
static {
|
|
760
|
+
/** Python framework patterns (from pyproject.toml or requirements.txt) */
|
|
761
|
+
this.PYTHON_FRAMEWORKS = [
|
|
762
|
+
{ name: "fastapi", packageName: "fastapi", tags: ["fastapi", "backend", "api"] },
|
|
763
|
+
{ name: "django", packageName: "django", tags: ["django", "backend", "fullstack"] },
|
|
764
|
+
{ name: "flask", packageName: "flask", tags: ["flask", "backend", "api"] },
|
|
765
|
+
{ name: "sqlalchemy", packageName: "sqlalchemy", tags: ["sqlalchemy", "database", "orm"] },
|
|
766
|
+
{ name: "pytest", packageName: "pytest", tags: ["testing", "pytest"] },
|
|
767
|
+
{ name: "pydantic", packageName: "pydantic", tags: ["pydantic", "validation"] }
|
|
768
|
+
];
|
|
769
|
+
}
|
|
770
|
+
static {
|
|
771
|
+
/** Directory patterns */
|
|
772
|
+
this.DIRECTORY_PATTERNS = [
|
|
773
|
+
{ pattern: ".github/workflows", feature: "github-actions", tags: ["ci", "github-actions"] },
|
|
774
|
+
{ pattern: ".gitlab-ci.yml", feature: "gitlab-ci", tags: ["ci", "gitlab"] },
|
|
775
|
+
{ pattern: "Dockerfile", feature: "docker", tags: ["docker", "containers"] },
|
|
776
|
+
{ pattern: "docker-compose.yml", feature: "docker-compose", tags: ["docker", "containers"] },
|
|
777
|
+
{ pattern: "docker-compose.yaml", feature: "docker-compose", tags: ["docker", "containers"] },
|
|
778
|
+
{ pattern: "terraform", feature: "terraform", tags: ["terraform", "infrastructure"] },
|
|
779
|
+
{ pattern: "kubernetes", feature: "kubernetes", tags: ["kubernetes", "infrastructure"] },
|
|
780
|
+
{ pattern: "k8s", feature: "kubernetes", tags: ["kubernetes", "infrastructure"] },
|
|
781
|
+
{ pattern: ".env.example", feature: "env-config", tags: ["configuration"] },
|
|
782
|
+
{ pattern: "prisma/schema.prisma", feature: "prisma", tags: ["prisma", "database"] }
|
|
783
|
+
];
|
|
784
|
+
}
|
|
720
785
|
/**
|
|
721
786
|
* Detect project context from a directory
|
|
722
787
|
*/
|
|
@@ -878,62 +943,6 @@ var _ProjectDetector = class _ProjectDetector {
|
|
|
878
943
|
}
|
|
879
944
|
}
|
|
880
945
|
};
|
|
881
|
-
/** Project type patterns */
|
|
882
|
-
_ProjectDetector.PROJECT_TYPES = [
|
|
883
|
-
{ manifestFile: "package.json", type: "nodejs", tags: ["nodejs", "javascript"], packageManager: "npm" },
|
|
884
|
-
{ manifestFile: "pyproject.toml", type: "python", tags: ["python"], packageManager: "pip" },
|
|
885
|
-
{ manifestFile: "requirements.txt", type: "python", tags: ["python"], packageManager: "pip" },
|
|
886
|
-
{ manifestFile: "Cargo.toml", type: "rust", tags: ["rust"], packageManager: "cargo" },
|
|
887
|
-
{ manifestFile: "go.mod", type: "go", tags: ["go", "golang"] },
|
|
888
|
-
{ manifestFile: "pom.xml", type: "java", tags: ["java", "maven"], packageManager: "maven" },
|
|
889
|
-
{ manifestFile: "build.gradle", type: "java", tags: ["java", "gradle"], packageManager: "gradle" },
|
|
890
|
-
{ manifestFile: "build.gradle.kts", type: "kotlin", tags: ["kotlin", "gradle"], packageManager: "gradle" }
|
|
891
|
-
];
|
|
892
|
-
/** TypeScript detection */
|
|
893
|
-
_ProjectDetector.TYPESCRIPT_FILES = ["tsconfig.json", "tsconfig.base.json"];
|
|
894
|
-
/** Node.js framework patterns */
|
|
895
|
-
_ProjectDetector.NODE_FRAMEWORKS = [
|
|
896
|
-
{ name: "react", packageName: "react", tags: ["react", "frontend"] },
|
|
897
|
-
{ name: "next", packageName: "next", tags: ["nextjs", "react", "fullstack"] },
|
|
898
|
-
{ name: "vue", packageName: "vue", tags: ["vue", "frontend"] },
|
|
899
|
-
{ name: "nuxt", packageName: "nuxt", tags: ["nuxt", "vue", "fullstack"] },
|
|
900
|
-
{ name: "angular", packageName: "@angular/core", tags: ["angular", "frontend"] },
|
|
901
|
-
{ name: "svelte", packageName: "svelte", tags: ["svelte", "frontend"] },
|
|
902
|
-
{ name: "express", packageName: "express", tags: ["express", "backend", "api"] },
|
|
903
|
-
{ name: "fastify", packageName: "fastify", tags: ["fastify", "backend", "api"] },
|
|
904
|
-
{ name: "nestjs", packageName: "@nestjs/core", tags: ["nestjs", "backend", "api"] },
|
|
905
|
-
{ name: "hono", packageName: "hono", tags: ["hono", "backend", "api"] },
|
|
906
|
-
{ name: "prisma", packageName: "@prisma/client", tags: ["prisma", "database", "orm"] },
|
|
907
|
-
{ name: "drizzle", packageName: "drizzle-orm", tags: ["drizzle", "database", "orm"] },
|
|
908
|
-
{ name: "typeorm", packageName: "typeorm", tags: ["typeorm", "database", "orm"] },
|
|
909
|
-
{ name: "jest", packageName: "jest", tags: ["testing", "jest"] },
|
|
910
|
-
{ name: "vitest", packageName: "vitest", tags: ["testing", "vitest"] },
|
|
911
|
-
{ name: "playwright", packageName: "@playwright/test", tags: ["testing", "e2e", "playwright"] },
|
|
912
|
-
{ name: "cypress", packageName: "cypress", tags: ["testing", "e2e", "cypress"] }
|
|
913
|
-
];
|
|
914
|
-
/** Python framework patterns (from pyproject.toml or requirements.txt) */
|
|
915
|
-
_ProjectDetector.PYTHON_FRAMEWORKS = [
|
|
916
|
-
{ name: "fastapi", packageName: "fastapi", tags: ["fastapi", "backend", "api"] },
|
|
917
|
-
{ name: "django", packageName: "django", tags: ["django", "backend", "fullstack"] },
|
|
918
|
-
{ name: "flask", packageName: "flask", tags: ["flask", "backend", "api"] },
|
|
919
|
-
{ name: "sqlalchemy", packageName: "sqlalchemy", tags: ["sqlalchemy", "database", "orm"] },
|
|
920
|
-
{ name: "pytest", packageName: "pytest", tags: ["testing", "pytest"] },
|
|
921
|
-
{ name: "pydantic", packageName: "pydantic", tags: ["pydantic", "validation"] }
|
|
922
|
-
];
|
|
923
|
-
/** Directory patterns */
|
|
924
|
-
_ProjectDetector.DIRECTORY_PATTERNS = [
|
|
925
|
-
{ pattern: ".github/workflows", feature: "github-actions", tags: ["ci", "github-actions"] },
|
|
926
|
-
{ pattern: ".gitlab-ci.yml", feature: "gitlab-ci", tags: ["ci", "gitlab"] },
|
|
927
|
-
{ pattern: "Dockerfile", feature: "docker", tags: ["docker", "containers"] },
|
|
928
|
-
{ pattern: "docker-compose.yml", feature: "docker-compose", tags: ["docker", "containers"] },
|
|
929
|
-
{ pattern: "docker-compose.yaml", feature: "docker-compose", tags: ["docker", "containers"] },
|
|
930
|
-
{ pattern: "terraform", feature: "terraform", tags: ["terraform", "infrastructure"] },
|
|
931
|
-
{ pattern: "kubernetes", feature: "kubernetes", tags: ["kubernetes", "infrastructure"] },
|
|
932
|
-
{ pattern: "k8s", feature: "kubernetes", tags: ["kubernetes", "infrastructure"] },
|
|
933
|
-
{ pattern: ".env.example", feature: "env-config", tags: ["configuration"] },
|
|
934
|
-
{ pattern: "prisma/schema.prisma", feature: "prisma", tags: ["prisma", "database"] }
|
|
935
|
-
];
|
|
936
|
-
var ProjectDetector = _ProjectDetector;
|
|
937
946
|
|
|
938
947
|
// src/serving/view-renderer.ts
|
|
939
948
|
var DEFAULT_CONFIG2 = {
|
|
@@ -6227,10 +6236,7 @@ var MemoryStorageAdapter = class extends BaseStorageAdapter {
|
|
|
6227
6236
|
this.skills = /* @__PURE__ */ new Map();
|
|
6228
6237
|
// skillId -> version -> skill
|
|
6229
6238
|
this.lineages = /* @__PURE__ */ new Map();
|
|
6230
|
-
this.candidates = /* @__PURE__ */ new Map();
|
|
6231
|
-
this.antiPatterns = /* @__PURE__ */ new Map();
|
|
6232
6239
|
}
|
|
6233
|
-
// skillId -> patterns
|
|
6234
6240
|
async initialize() {
|
|
6235
6241
|
this.initialized = true;
|
|
6236
6242
|
}
|
|
@@ -6361,78 +6367,6 @@ var MemoryStorageAdapter = class extends BaseStorageAdapter {
|
|
|
6361
6367
|
clear() {
|
|
6362
6368
|
this.skills.clear();
|
|
6363
6369
|
this.lineages.clear();
|
|
6364
|
-
this.candidates.clear();
|
|
6365
|
-
this.antiPatterns.clear();
|
|
6366
|
-
}
|
|
6367
|
-
// ==========================================================================
|
|
6368
|
-
// Learning Candidate Operations
|
|
6369
|
-
// ==========================================================================
|
|
6370
|
-
async saveCandidate(candidate) {
|
|
6371
|
-
this.ensureInitialized();
|
|
6372
|
-
this.candidates.set(candidate.id, { ...candidate });
|
|
6373
|
-
}
|
|
6374
|
-
async getCandidate(id) {
|
|
6375
|
-
this.ensureInitialized();
|
|
6376
|
-
return this.candidates.get(id) || null;
|
|
6377
|
-
}
|
|
6378
|
-
async listCandidates(filter) {
|
|
6379
|
-
this.ensureInitialized();
|
|
6380
|
-
let results = Array.from(this.candidates.values());
|
|
6381
|
-
if (filter) {
|
|
6382
|
-
if (filter.kind && filter.kind.length > 0) {
|
|
6383
|
-
results = results.filter((c) => filter.kind.includes(c.kind));
|
|
6384
|
-
}
|
|
6385
|
-
if (filter.status && filter.status.length > 0) {
|
|
6386
|
-
results = results.filter((c) => filter.status.includes(c.status));
|
|
6387
|
-
}
|
|
6388
|
-
if (filter.minConfidence !== void 0) {
|
|
6389
|
-
results = results.filter((c) => c.confidence >= filter.minConfidence);
|
|
6390
|
-
}
|
|
6391
|
-
if (filter.createdAfter) {
|
|
6392
|
-
results = results.filter((c) => c.createdAt >= filter.createdAfter);
|
|
6393
|
-
}
|
|
6394
|
-
if (filter.createdBefore) {
|
|
6395
|
-
results = results.filter((c) => c.createdAt <= filter.createdBefore);
|
|
6396
|
-
}
|
|
6397
|
-
}
|
|
6398
|
-
return results;
|
|
6399
|
-
}
|
|
6400
|
-
async updateCandidateStatus(id, status, details) {
|
|
6401
|
-
this.ensureInitialized();
|
|
6402
|
-
const candidate = this.candidates.get(id);
|
|
6403
|
-
if (!candidate) return false;
|
|
6404
|
-
candidate.status = status;
|
|
6405
|
-
candidate.updatedAt = /* @__PURE__ */ new Date();
|
|
6406
|
-
if (details?.promotedToSkillId) {
|
|
6407
|
-
candidate.promotedToSkillId = details.promotedToSkillId;
|
|
6408
|
-
}
|
|
6409
|
-
if (details?.rejectionReason) {
|
|
6410
|
-
candidate.rejectionReason = details.rejectionReason;
|
|
6411
|
-
}
|
|
6412
|
-
return true;
|
|
6413
|
-
}
|
|
6414
|
-
async deleteCandidate(id) {
|
|
6415
|
-
this.ensureInitialized();
|
|
6416
|
-
return this.candidates.delete(id);
|
|
6417
|
-
}
|
|
6418
|
-
// ==========================================================================
|
|
6419
|
-
// Anti-Pattern Operations
|
|
6420
|
-
// ==========================================================================
|
|
6421
|
-
async saveAntiPatterns(skillId, patterns) {
|
|
6422
|
-
this.ensureInitialized();
|
|
6423
|
-
this.antiPatterns.set(skillId, [...patterns]);
|
|
6424
|
-
}
|
|
6425
|
-
async getAntiPatterns(skillId) {
|
|
6426
|
-
this.ensureInitialized();
|
|
6427
|
-
return this.antiPatterns.get(skillId) || [];
|
|
6428
|
-
}
|
|
6429
|
-
async listAntiPatterns() {
|
|
6430
|
-
this.ensureInitialized();
|
|
6431
|
-
const results = [];
|
|
6432
|
-
for (const [skillId, patterns] of this.antiPatterns) {
|
|
6433
|
-
results.push({ skillId, patterns });
|
|
6434
|
-
}
|
|
6435
|
-
return results;
|
|
6436
6370
|
}
|
|
6437
6371
|
// ==========================================================================
|
|
6438
6372
|
// Fork Tracking
|
|
@@ -6983,152 +6917,6 @@ ${body}`;
|
|
|
6983
6917
|
return Math.abs(hash).toString(16);
|
|
6984
6918
|
}
|
|
6985
6919
|
// ==========================================================================
|
|
6986
|
-
// Learning Candidate Operations
|
|
6987
|
-
// ==========================================================================
|
|
6988
|
-
get candidatesDir() {
|
|
6989
|
-
return path4.join(this.skilltreeDir, "candidates");
|
|
6990
|
-
}
|
|
6991
|
-
get antiPatternsDir() {
|
|
6992
|
-
return path4.join(this.skilltreeDir, "anti-patterns");
|
|
6993
|
-
}
|
|
6994
|
-
async saveCandidate(candidate) {
|
|
6995
|
-
this.ensureInitialized();
|
|
6996
|
-
await fs4.mkdir(this.candidatesDir, { recursive: true });
|
|
6997
|
-
const candidatePath = path4.join(this.candidatesDir, `${candidate.id}.json`);
|
|
6998
|
-
await fs4.writeFile(candidatePath, JSON.stringify(candidate, null, 2), "utf-8");
|
|
6999
|
-
}
|
|
7000
|
-
async getCandidate(id) {
|
|
7001
|
-
this.ensureInitialized();
|
|
7002
|
-
const candidatePath = path4.join(this.candidatesDir, `${id}.json`);
|
|
7003
|
-
try {
|
|
7004
|
-
const content = await fs4.readFile(candidatePath, "utf-8");
|
|
7005
|
-
const candidate = JSON.parse(content);
|
|
7006
|
-
candidate.createdAt = new Date(candidate.createdAt);
|
|
7007
|
-
candidate.updatedAt = new Date(candidate.updatedAt);
|
|
7008
|
-
candidate.source.extractedAt = new Date(candidate.source.extractedAt);
|
|
7009
|
-
return candidate;
|
|
7010
|
-
} catch (error) {
|
|
7011
|
-
if (error.code === "ENOENT") {
|
|
7012
|
-
return null;
|
|
7013
|
-
}
|
|
7014
|
-
throw error;
|
|
7015
|
-
}
|
|
7016
|
-
}
|
|
7017
|
-
async listCandidates(filter) {
|
|
7018
|
-
this.ensureInitialized();
|
|
7019
|
-
try {
|
|
7020
|
-
const files = await fs4.readdir(this.candidatesDir);
|
|
7021
|
-
const candidates = [];
|
|
7022
|
-
for (const file of files) {
|
|
7023
|
-
if (!file.endsWith(".json")) continue;
|
|
7024
|
-
const id = file.replace(".json", "");
|
|
7025
|
-
const candidate = await this.getCandidate(id);
|
|
7026
|
-
if (candidate) {
|
|
7027
|
-
candidates.push(candidate);
|
|
7028
|
-
}
|
|
7029
|
-
}
|
|
7030
|
-
let results = candidates;
|
|
7031
|
-
if (filter) {
|
|
7032
|
-
if (filter.kind && filter.kind.length > 0) {
|
|
7033
|
-
results = results.filter((c) => filter.kind.includes(c.kind));
|
|
7034
|
-
}
|
|
7035
|
-
if (filter.status && filter.status.length > 0) {
|
|
7036
|
-
results = results.filter((c) => filter.status.includes(c.status));
|
|
7037
|
-
}
|
|
7038
|
-
if (filter.minConfidence !== void 0) {
|
|
7039
|
-
results = results.filter((c) => c.confidence >= filter.minConfidence);
|
|
7040
|
-
}
|
|
7041
|
-
if (filter.createdAfter) {
|
|
7042
|
-
results = results.filter((c) => c.createdAt >= filter.createdAfter);
|
|
7043
|
-
}
|
|
7044
|
-
if (filter.createdBefore) {
|
|
7045
|
-
results = results.filter((c) => c.createdAt <= filter.createdBefore);
|
|
7046
|
-
}
|
|
7047
|
-
}
|
|
7048
|
-
return results;
|
|
7049
|
-
} catch (error) {
|
|
7050
|
-
if (error.code === "ENOENT") {
|
|
7051
|
-
return [];
|
|
7052
|
-
}
|
|
7053
|
-
throw error;
|
|
7054
|
-
}
|
|
7055
|
-
}
|
|
7056
|
-
async updateCandidateStatus(id, status, details) {
|
|
7057
|
-
this.ensureInitialized();
|
|
7058
|
-
const candidate = await this.getCandidate(id);
|
|
7059
|
-
if (!candidate) return false;
|
|
7060
|
-
candidate.status = status;
|
|
7061
|
-
candidate.updatedAt = /* @__PURE__ */ new Date();
|
|
7062
|
-
if (details?.promotedToSkillId) {
|
|
7063
|
-
candidate.promotedToSkillId = details.promotedToSkillId;
|
|
7064
|
-
}
|
|
7065
|
-
if (details?.rejectionReason) {
|
|
7066
|
-
candidate.rejectionReason = details.rejectionReason;
|
|
7067
|
-
}
|
|
7068
|
-
await this.saveCandidate(candidate);
|
|
7069
|
-
return true;
|
|
7070
|
-
}
|
|
7071
|
-
async deleteCandidate(id) {
|
|
7072
|
-
this.ensureInitialized();
|
|
7073
|
-
const candidatePath = path4.join(this.candidatesDir, `${id}.json`);
|
|
7074
|
-
try {
|
|
7075
|
-
await fs4.unlink(candidatePath);
|
|
7076
|
-
return true;
|
|
7077
|
-
} catch (error) {
|
|
7078
|
-
if (error.code === "ENOENT") {
|
|
7079
|
-
return false;
|
|
7080
|
-
}
|
|
7081
|
-
throw error;
|
|
7082
|
-
}
|
|
7083
|
-
}
|
|
7084
|
-
// ==========================================================================
|
|
7085
|
-
// Anti-Pattern Operations
|
|
7086
|
-
// ==========================================================================
|
|
7087
|
-
async saveAntiPatterns(skillId, patterns) {
|
|
7088
|
-
this.ensureInitialized();
|
|
7089
|
-
await fs4.mkdir(this.antiPatternsDir, { recursive: true });
|
|
7090
|
-
const patternPath = path4.join(this.antiPatternsDir, `${skillId}.json`);
|
|
7091
|
-
await fs4.writeFile(patternPath, JSON.stringify(patterns, null, 2), "utf-8");
|
|
7092
|
-
}
|
|
7093
|
-
async getAntiPatterns(skillId) {
|
|
7094
|
-
this.ensureInitialized();
|
|
7095
|
-
const patternPath = path4.join(this.antiPatternsDir, `${skillId}.json`);
|
|
7096
|
-
try {
|
|
7097
|
-
const content = await fs4.readFile(patternPath, "utf-8");
|
|
7098
|
-
const patterns = JSON.parse(content);
|
|
7099
|
-
for (const pattern of patterns) {
|
|
7100
|
-
pattern.learnedAt = new Date(pattern.learnedAt);
|
|
7101
|
-
}
|
|
7102
|
-
return patterns;
|
|
7103
|
-
} catch (error) {
|
|
7104
|
-
if (error.code === "ENOENT") {
|
|
7105
|
-
return [];
|
|
7106
|
-
}
|
|
7107
|
-
throw error;
|
|
7108
|
-
}
|
|
7109
|
-
}
|
|
7110
|
-
async listAntiPatterns() {
|
|
7111
|
-
this.ensureInitialized();
|
|
7112
|
-
try {
|
|
7113
|
-
const files = await fs4.readdir(this.antiPatternsDir);
|
|
7114
|
-
const results = [];
|
|
7115
|
-
for (const file of files) {
|
|
7116
|
-
if (!file.endsWith(".json")) continue;
|
|
7117
|
-
const skillId = file.replace(".json", "");
|
|
7118
|
-
const patterns = await this.getAntiPatterns(skillId);
|
|
7119
|
-
if (patterns.length > 0) {
|
|
7120
|
-
results.push({ skillId, patterns });
|
|
7121
|
-
}
|
|
7122
|
-
}
|
|
7123
|
-
return results;
|
|
7124
|
-
} catch (error) {
|
|
7125
|
-
if (error.code === "ENOENT") {
|
|
7126
|
-
return [];
|
|
7127
|
-
}
|
|
7128
|
-
throw error;
|
|
7129
|
-
}
|
|
7130
|
-
}
|
|
7131
|
-
// ==========================================================================
|
|
7132
6920
|
// Fork Tracking
|
|
7133
6921
|
// ==========================================================================
|
|
7134
6922
|
async recordFork(sourceSkillId, fork) {
|
|
@@ -7455,310 +7243,6 @@ ${source}`;
|
|
|
7455
7243
|
}
|
|
7456
7244
|
};
|
|
7457
7245
|
|
|
7458
|
-
// src/learning/providers/naive.ts
|
|
7459
|
-
var NaiveLearningProvider = class {
|
|
7460
|
-
constructor(config2) {
|
|
7461
|
-
this.name = "naive";
|
|
7462
|
-
this.description = "Built-in extraction using heuristics and optional LLM analysis";
|
|
7463
|
-
this.capabilities = {
|
|
7464
|
-
accumulating: false,
|
|
7465
|
-
feedbackEnabled: false,
|
|
7466
|
-
persistent: false,
|
|
7467
|
-
supportedKinds: ["skill", "strategy", "pattern", "error-fix"]
|
|
7468
|
-
};
|
|
7469
|
-
this.config = {
|
|
7470
|
-
llmProvider: config2?.llmProvider ?? null,
|
|
7471
|
-
minConfidence: config2?.minConfidence ?? 0.6,
|
|
7472
|
-
runQualityGates: config2?.runQualityGates ?? true,
|
|
7473
|
-
creditStrategy: config2?.creditStrategy ?? "simple"
|
|
7474
|
-
};
|
|
7475
|
-
this.manualExtractor = new ManualExtractor();
|
|
7476
|
-
this.automaticExtractor = new AutomaticExtractor({
|
|
7477
|
-
llmProvider: this.config.llmProvider || void 0,
|
|
7478
|
-
minConfidence: this.config.minConfidence
|
|
7479
|
-
});
|
|
7480
|
-
}
|
|
7481
|
-
/**
|
|
7482
|
-
* Set or update the LLM provider
|
|
7483
|
-
*/
|
|
7484
|
-
setLLMProvider(provider) {
|
|
7485
|
-
this.config.llmProvider = provider;
|
|
7486
|
-
this.automaticExtractor.setLLMProvider(provider);
|
|
7487
|
-
}
|
|
7488
|
-
/**
|
|
7489
|
-
* Analyze a trajectory and extract learning candidates
|
|
7490
|
-
*/
|
|
7491
|
-
async analyze(trajectory, options) {
|
|
7492
|
-
const startTime = Date.now();
|
|
7493
|
-
const candidates = [];
|
|
7494
|
-
const kinds = options?.kinds ?? ["skill"];
|
|
7495
|
-
const useAutomatic = this.config.llmProvider != null;
|
|
7496
|
-
let results;
|
|
7497
|
-
if (useAutomatic) {
|
|
7498
|
-
results = await this.automaticExtractor.extract(trajectory, {
|
|
7499
|
-
turnRange: options?.turnRange,
|
|
7500
|
-
minConfidence: options?.minConfidence ?? this.config.minConfidence,
|
|
7501
|
-
skipValidation: options?.skipValidation ?? !this.config.runQualityGates,
|
|
7502
|
-
context: options?.context
|
|
7503
|
-
});
|
|
7504
|
-
} else {
|
|
7505
|
-
results = await this.manualExtractor.extract(trajectory, {
|
|
7506
|
-
turnRange: options?.turnRange,
|
|
7507
|
-
skipValidation: options?.skipValidation ?? !this.config.runQualityGates,
|
|
7508
|
-
context: options?.context
|
|
7509
|
-
});
|
|
7510
|
-
}
|
|
7511
|
-
for (const result of results) {
|
|
7512
|
-
if (!result.success || !result.skill) continue;
|
|
7513
|
-
const kind = this.inferKind(result.skill);
|
|
7514
|
-
if (!kinds.includes(kind)) continue;
|
|
7515
|
-
const candidate = this.extractionResultToCandidate(result, trajectory);
|
|
7516
|
-
candidates.push(candidate);
|
|
7517
|
-
}
|
|
7518
|
-
return {
|
|
7519
|
-
candidates,
|
|
7520
|
-
// Naive provider doesn't produce updates, demotions, or anti-patterns
|
|
7521
|
-
metadata: {
|
|
7522
|
-
trajectoriesAnalyzed: 1,
|
|
7523
|
-
durationMs: Date.now() - startTime
|
|
7524
|
-
}
|
|
7525
|
-
};
|
|
7526
|
-
}
|
|
7527
|
-
/**
|
|
7528
|
-
* Batch analysis - runs individual analysis on each trajectory.
|
|
7529
|
-
* A more sophisticated provider could do cross-trajectory pattern detection.
|
|
7530
|
-
*/
|
|
7531
|
-
async analyzeBatch(trajectories, options) {
|
|
7532
|
-
const startTime = Date.now();
|
|
7533
|
-
const allCandidates = [];
|
|
7534
|
-
for (const trajectory of trajectories) {
|
|
7535
|
-
const result = await this.analyze(trajectory, options);
|
|
7536
|
-
allCandidates.push(...result.candidates);
|
|
7537
|
-
}
|
|
7538
|
-
const deduplicated = this.deduplicateCandidates(allCandidates);
|
|
7539
|
-
return {
|
|
7540
|
-
candidates: deduplicated,
|
|
7541
|
-
metadata: {
|
|
7542
|
-
trajectoriesAnalyzed: trajectories.length,
|
|
7543
|
-
durationMs: Date.now() - startTime
|
|
7544
|
-
}
|
|
7545
|
-
};
|
|
7546
|
-
}
|
|
7547
|
-
/**
|
|
7548
|
-
* Check if a candidate is a duplicate based on name/content similarity
|
|
7549
|
-
*/
|
|
7550
|
-
isDuplicate(candidate, existing) {
|
|
7551
|
-
if (existing.some((e) => e.id === candidate.id)) {
|
|
7552
|
-
return true;
|
|
7553
|
-
}
|
|
7554
|
-
const normalizedName = this.normalizeName(candidate.name);
|
|
7555
|
-
for (const e of existing) {
|
|
7556
|
-
if (this.normalizeName(e.name) === normalizedName) {
|
|
7557
|
-
return true;
|
|
7558
|
-
}
|
|
7559
|
-
}
|
|
7560
|
-
return false;
|
|
7561
|
-
}
|
|
7562
|
-
/**
|
|
7563
|
-
* Compute similarity between two candidates (basic implementation)
|
|
7564
|
-
*/
|
|
7565
|
-
computeSimilarity(a, b) {
|
|
7566
|
-
if (a.kind !== b.kind) return 0.1;
|
|
7567
|
-
const nameA = this.normalizeName(a.name);
|
|
7568
|
-
const nameB = this.normalizeName(b.name);
|
|
7569
|
-
const nameSimilarity = this.jaccardSimilarity(
|
|
7570
|
-
nameA.split("-"),
|
|
7571
|
-
nameB.split("-")
|
|
7572
|
-
);
|
|
7573
|
-
let contentSimilarity = 0;
|
|
7574
|
-
if (a.content.kind === "skill" && b.content.kind === "skill") {
|
|
7575
|
-
const aWords = this.tokenize(a.content.problem + " " + a.content.solution);
|
|
7576
|
-
const bWords = this.tokenize(b.content.problem + " " + b.content.solution);
|
|
7577
|
-
contentSimilarity = this.jaccardSimilarity(aWords, bWords);
|
|
7578
|
-
}
|
|
7579
|
-
return nameSimilarity * 0.3 + contentSimilarity * 0.7;
|
|
7580
|
-
}
|
|
7581
|
-
// ==========================================================================
|
|
7582
|
-
// Private Methods
|
|
7583
|
-
// ==========================================================================
|
|
7584
|
-
/**
|
|
7585
|
-
* Convert an ExtractionResult to a LearningCandidate
|
|
7586
|
-
*/
|
|
7587
|
-
extractionResultToCandidate(result, trajectory) {
|
|
7588
|
-
const skill = result.skill;
|
|
7589
|
-
const turnRange = result.sourceTrajectory.turnRange;
|
|
7590
|
-
return {
|
|
7591
|
-
kind: this.inferKind(skill),
|
|
7592
|
-
id: skill.id,
|
|
7593
|
-
name: skill.name,
|
|
7594
|
-
content: this.skillToContent(skill),
|
|
7595
|
-
confidence: result.confidence,
|
|
7596
|
-
attribution: this.computeAttribution(trajectory, turnRange),
|
|
7597
|
-
source: {
|
|
7598
|
-
provider: this.name,
|
|
7599
|
-
trajectoryId: trajectory.sessionId,
|
|
7600
|
-
turnRange,
|
|
7601
|
-
extractedAt: /* @__PURE__ */ new Date(),
|
|
7602
|
-
metadata: {
|
|
7603
|
-
gateResults: result.gateResults,
|
|
7604
|
-
extractionMode: this.config.llmProvider ? "automatic" : "manual"
|
|
7605
|
-
}
|
|
7606
|
-
},
|
|
7607
|
-
tags: skill.tags,
|
|
7608
|
-
reasoning: result.failureReason
|
|
7609
|
-
};
|
|
7610
|
-
}
|
|
7611
|
-
/**
|
|
7612
|
-
* Convert a Skill to LearningContent
|
|
7613
|
-
*/
|
|
7614
|
-
skillToContent(skill) {
|
|
7615
|
-
return {
|
|
7616
|
-
kind: "skill",
|
|
7617
|
-
problem: skill.problem,
|
|
7618
|
-
solution: skill.solution,
|
|
7619
|
-
verification: skill.verification,
|
|
7620
|
-
triggers: skill.triggerConditions.map(
|
|
7621
|
-
(t) => ({
|
|
7622
|
-
type: t.type,
|
|
7623
|
-
value: t.value,
|
|
7624
|
-
description: t.description
|
|
7625
|
-
})
|
|
7626
|
-
),
|
|
7627
|
-
examples: skill.examples.map(
|
|
7628
|
-
(e) => ({
|
|
7629
|
-
scenario: e.scenario,
|
|
7630
|
-
before: e.before,
|
|
7631
|
-
after: e.after
|
|
7632
|
-
})
|
|
7633
|
-
)
|
|
7634
|
-
};
|
|
7635
|
-
}
|
|
7636
|
-
/**
|
|
7637
|
-
* Infer the kind of learning from a skill
|
|
7638
|
-
*/
|
|
7639
|
-
inferKind(skill) {
|
|
7640
|
-
const hasErrorTriggers = skill.triggerConditions.some(
|
|
7641
|
-
(t) => t.type === "error"
|
|
7642
|
-
);
|
|
7643
|
-
if (hasErrorTriggers && skill.problem.toLowerCase().includes("error")) {
|
|
7644
|
-
return "error-fix";
|
|
7645
|
-
}
|
|
7646
|
-
if (skill.solution.toLowerCase().includes("approach") || skill.solution.toLowerCase().includes("strategy") || skill.solution.toLowerCase().includes("when you see")) {
|
|
7647
|
-
return "strategy";
|
|
7648
|
-
}
|
|
7649
|
-
return "skill";
|
|
7650
|
-
}
|
|
7651
|
-
/**
|
|
7652
|
-
* Compute step attribution using the configured strategy
|
|
7653
|
-
*/
|
|
7654
|
-
computeAttribution(trajectory, turnRange) {
|
|
7655
|
-
const [start, end] = turnRange;
|
|
7656
|
-
const turns = trajectory.turns.slice(start, end + 1);
|
|
7657
|
-
switch (this.config.creditStrategy) {
|
|
7658
|
-
case "simple":
|
|
7659
|
-
return this.simpleCredit(turns, start);
|
|
7660
|
-
case "uniform":
|
|
7661
|
-
return this.uniformCredit(turns, start);
|
|
7662
|
-
case "llm":
|
|
7663
|
-
return this.simpleCredit(turns, start);
|
|
7664
|
-
default:
|
|
7665
|
-
return this.simpleCredit(turns, start);
|
|
7666
|
-
}
|
|
7667
|
-
}
|
|
7668
|
-
/**
|
|
7669
|
-
* Simple credit assignment: exponential decay from end.
|
|
7670
|
-
* Last step gets most credit, earlier steps get less.
|
|
7671
|
-
*/
|
|
7672
|
-
simpleCredit(turns, startOffset) {
|
|
7673
|
-
const attributions = [];
|
|
7674
|
-
const n = turns.length;
|
|
7675
|
-
for (let i = 0; i < n; i++) {
|
|
7676
|
-
const turn = turns[i];
|
|
7677
|
-
if (turn.role === "system") continue;
|
|
7678
|
-
const distanceFromEnd = n - 1 - i;
|
|
7679
|
-
const score = Math.pow(0.7, distanceFromEnd);
|
|
7680
|
-
const hasToolCalls = turn.toolCalls && turn.toolCalls.length > 0;
|
|
7681
|
-
const boostedScore = hasToolCalls ? Math.min(1, score * 1.3) : score;
|
|
7682
|
-
attributions.push({
|
|
7683
|
-
turnIndex: startOffset + i,
|
|
7684
|
-
score: Math.round(boostedScore * 100) / 100,
|
|
7685
|
-
reasoning: this.getAttributionReasoning(turn, boostedScore)
|
|
7686
|
-
});
|
|
7687
|
-
}
|
|
7688
|
-
return attributions;
|
|
7689
|
-
}
|
|
7690
|
-
/**
|
|
7691
|
-
* Uniform credit assignment: all steps get equal credit.
|
|
7692
|
-
*/
|
|
7693
|
-
uniformCredit(turns, startOffset) {
|
|
7694
|
-
const nonSystemTurns = turns.filter((t) => t.role !== "system");
|
|
7695
|
-
const score = 1 / nonSystemTurns.length;
|
|
7696
|
-
return turns.map((turn, i) => {
|
|
7697
|
-
if (turn.role === "system") return null;
|
|
7698
|
-
return {
|
|
7699
|
-
turnIndex: startOffset + i,
|
|
7700
|
-
score: Math.round(score * 100) / 100
|
|
7701
|
-
};
|
|
7702
|
-
}).filter((a) => a !== null);
|
|
7703
|
-
}
|
|
7704
|
-
/**
|
|
7705
|
-
* Generate reasoning for attribution
|
|
7706
|
-
*/
|
|
7707
|
-
getAttributionReasoning(turn, score) {
|
|
7708
|
-
const reasons = [];
|
|
7709
|
-
if (score >= 0.8) {
|
|
7710
|
-
reasons.push("High impact (near end of solution)");
|
|
7711
|
-
} else if (score >= 0.5) {
|
|
7712
|
-
reasons.push("Medium impact");
|
|
7713
|
-
} else {
|
|
7714
|
-
reasons.push("Lower impact (early in trajectory)");
|
|
7715
|
-
}
|
|
7716
|
-
if (turn.toolCalls && turn.toolCalls.length > 0) {
|
|
7717
|
-
const toolNames = turn.toolCalls.map((t) => t.name).join(", ");
|
|
7718
|
-
reasons.push(`Used tools: ${toolNames}`);
|
|
7719
|
-
}
|
|
7720
|
-
if (turn.toolResults?.some((r) => !r.success)) {
|
|
7721
|
-
reasons.push("Encountered and handled errors");
|
|
7722
|
-
}
|
|
7723
|
-
return reasons.join(". ");
|
|
7724
|
-
}
|
|
7725
|
-
/**
|
|
7726
|
-
* Deduplicate candidates by ID
|
|
7727
|
-
*/
|
|
7728
|
-
deduplicateCandidates(candidates) {
|
|
7729
|
-
const seen = /* @__PURE__ */ new Map();
|
|
7730
|
-
for (const candidate of candidates) {
|
|
7731
|
-
const existing = seen.get(candidate.id);
|
|
7732
|
-
if (!existing || candidate.confidence > existing.confidence) {
|
|
7733
|
-
seen.set(candidate.id, candidate);
|
|
7734
|
-
}
|
|
7735
|
-
}
|
|
7736
|
-
return Array.from(seen.values());
|
|
7737
|
-
}
|
|
7738
|
-
/**
|
|
7739
|
-
* Normalize a name for comparison
|
|
7740
|
-
*/
|
|
7741
|
-
normalizeName(name) {
|
|
7742
|
-
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
7743
|
-
}
|
|
7744
|
-
/**
|
|
7745
|
-
* Tokenize text into words
|
|
7746
|
-
*/
|
|
7747
|
-
tokenize(text) {
|
|
7748
|
-
return text.toLowerCase().split(/\W+/).filter((w) => w.length > 2);
|
|
7749
|
-
}
|
|
7750
|
-
/**
|
|
7751
|
-
* Compute Jaccard similarity between two arrays
|
|
7752
|
-
*/
|
|
7753
|
-
jaccardSimilarity(a, b) {
|
|
7754
|
-
const setA = new Set(a);
|
|
7755
|
-
const setB = new Set(b);
|
|
7756
|
-
const intersection = new Set([...setA].filter((x) => setB.has(x)));
|
|
7757
|
-
const union = /* @__PURE__ */ new Set([...setA, ...setB]);
|
|
7758
|
-
return union.size === 0 ? 0 : intersection.size / union.size;
|
|
7759
|
-
}
|
|
7760
|
-
};
|
|
7761
|
-
|
|
7762
7246
|
// src/hooks/registry.ts
|
|
7763
7247
|
var import_crypto = require("crypto");
|
|
7764
7248
|
var PRIORITY_ORDER = {
|
|
@@ -8228,10 +7712,6 @@ var SkillBank = class {
|
|
|
8228
7712
|
this.eventHandlers = [];
|
|
8229
7713
|
this.initialized = false;
|
|
8230
7714
|
this.autoIndexOnInit = false;
|
|
8231
|
-
/** Learning providers for meta-learning integration */
|
|
8232
|
-
this.learningProviders = /* @__PURE__ */ new Map();
|
|
8233
|
-
/** Anti-patterns stored separately as metadata */
|
|
8234
|
-
this.antiPatterns = /* @__PURE__ */ new Map();
|
|
8235
7715
|
/** Validation mode: advisory (non-blocking) or blocking */
|
|
8236
7716
|
this.validationMode = "advisory";
|
|
8237
7717
|
/** Whether validation is enabled */
|
|
@@ -8269,11 +7749,6 @@ var SkillBank = class {
|
|
|
8269
7749
|
similarityThreshold: config2.matching?.similarityThreshold
|
|
8270
7750
|
});
|
|
8271
7751
|
this.autoIndexOnInit = config2.matching?.autoIndex ?? false;
|
|
8272
|
-
const naiveProvider = new NaiveLearningProvider({
|
|
8273
|
-
llmProvider: config2.llmProvider,
|
|
8274
|
-
minConfidence: config2.minExtractionConfidence
|
|
8275
|
-
});
|
|
8276
|
-
this.learningProviders.set(naiveProvider.name, naiveProvider);
|
|
8277
7752
|
if (config2.namespace) {
|
|
8278
7753
|
this.namespaceConfig = {
|
|
8279
7754
|
agentId: config2.namespace.agentId,
|
|
@@ -8301,11 +7776,6 @@ var SkillBank = class {
|
|
|
8301
7776
|
*/
|
|
8302
7777
|
async initialize() {
|
|
8303
7778
|
await this.storage.initialize();
|
|
8304
|
-
for (const provider of this.learningProviders.values()) {
|
|
8305
|
-
if (provider.initialize) {
|
|
8306
|
-
await provider.initialize();
|
|
8307
|
-
}
|
|
8308
|
-
}
|
|
8309
7779
|
if (this.validator) {
|
|
8310
7780
|
this.validator.setStorage(this.storage);
|
|
8311
7781
|
}
|
|
@@ -8318,11 +7788,6 @@ var SkillBank = class {
|
|
|
8318
7788
|
* Shutdown the skill bank cleanly
|
|
8319
7789
|
*/
|
|
8320
7790
|
async shutdown() {
|
|
8321
|
-
for (const provider of this.learningProviders.values()) {
|
|
8322
|
-
if (provider.shutdown) {
|
|
8323
|
-
await provider.shutdown();
|
|
8324
|
-
}
|
|
8325
|
-
}
|
|
8326
7791
|
}
|
|
8327
7792
|
/**
|
|
8328
7793
|
* Ensure initialized before operations
|
|
@@ -8480,569 +7945,6 @@ var SkillBank = class {
|
|
|
8480
7945
|
*/
|
|
8481
7946
|
setLLMProvider(provider) {
|
|
8482
7947
|
this.automaticExtractor.setLLMProvider(provider);
|
|
8483
|
-
const naiveProvider = this.learningProviders.get("naive");
|
|
8484
|
-
if (naiveProvider && "setLLMProvider" in naiveProvider) {
|
|
8485
|
-
naiveProvider.setLLMProvider(provider);
|
|
8486
|
-
}
|
|
8487
|
-
}
|
|
8488
|
-
// ==========================================================================
|
|
8489
|
-
// Learning Providers (Meta-learning Integration)
|
|
8490
|
-
// ==========================================================================
|
|
8491
|
-
/**
|
|
8492
|
-
* Register a learning provider.
|
|
8493
|
-
* Learning providers analyze trajectories and produce learning candidates.
|
|
8494
|
-
* Use this to integrate external learning engines like cognitive-core.
|
|
8495
|
-
*/
|
|
8496
|
-
async registerLearningProvider(provider) {
|
|
8497
|
-
if (provider.initialize) {
|
|
8498
|
-
await provider.initialize();
|
|
8499
|
-
}
|
|
8500
|
-
this.learningProviders.set(provider.name, provider);
|
|
8501
|
-
}
|
|
8502
|
-
/**
|
|
8503
|
-
* Get a registered learning provider by name
|
|
8504
|
-
*/
|
|
8505
|
-
getLearningProvider(name) {
|
|
8506
|
-
return this.learningProviders.get(name);
|
|
8507
|
-
}
|
|
8508
|
-
/**
|
|
8509
|
-
* List all registered learning providers
|
|
8510
|
-
*/
|
|
8511
|
-
listLearningProviders() {
|
|
8512
|
-
return Array.from(this.learningProviders.values());
|
|
8513
|
-
}
|
|
8514
|
-
/**
|
|
8515
|
-
* Learn from a trajectory using a learning provider.
|
|
8516
|
-
* This is the primary integration point for meta-learning engines.
|
|
8517
|
-
*
|
|
8518
|
-
* For accumulating providers, this may not return immediate results.
|
|
8519
|
-
* Use flushProviders() to force extraction from accumulated trajectories.
|
|
8520
|
-
*/
|
|
8521
|
-
async learnFrom(trajectory, options) {
|
|
8522
|
-
this.ensureInitialized();
|
|
8523
|
-
const providerName = options?.provider ?? "naive";
|
|
8524
|
-
const provider = this.learningProviders.get(providerName);
|
|
8525
|
-
if (!provider) {
|
|
8526
|
-
throw new Error(
|
|
8527
|
-
`Learning provider not found: ${providerName}. Available: ${Array.from(this.learningProviders.keys()).join(", ")}`
|
|
8528
|
-
);
|
|
8529
|
-
}
|
|
8530
|
-
const result = await provider.analyze(trajectory, options);
|
|
8531
|
-
return this.processAnalyzeResult(result);
|
|
8532
|
-
}
|
|
8533
|
-
/**
|
|
8534
|
-
* Learn from multiple trajectories.
|
|
8535
|
-
* Providers that support batch analysis can find cross-trajectory patterns.
|
|
8536
|
-
*/
|
|
8537
|
-
async learnFromBatch(trajectories, options) {
|
|
8538
|
-
this.ensureInitialized();
|
|
8539
|
-
const providerName = options?.provider ?? "naive";
|
|
8540
|
-
const provider = this.learningProviders.get(providerName);
|
|
8541
|
-
if (!provider) {
|
|
8542
|
-
throw new Error(`Learning provider not found: ${providerName}`);
|
|
8543
|
-
}
|
|
8544
|
-
let result;
|
|
8545
|
-
if (provider.analyzeBatch) {
|
|
8546
|
-
result = await provider.analyzeBatch(trajectories, options);
|
|
8547
|
-
} else {
|
|
8548
|
-
const candidates = [];
|
|
8549
|
-
const updates = [];
|
|
8550
|
-
const demotions = [];
|
|
8551
|
-
const antiPatterns = [];
|
|
8552
|
-
let totalDuration = 0;
|
|
8553
|
-
for (const trajectory of trajectories) {
|
|
8554
|
-
const r = await provider.analyze(trajectory, options);
|
|
8555
|
-
candidates.push(...r.candidates);
|
|
8556
|
-
if (r.updates) updates.push(...r.updates);
|
|
8557
|
-
if (r.demotions) demotions.push(...r.demotions);
|
|
8558
|
-
if (r.antiPatterns) antiPatterns.push(...r.antiPatterns);
|
|
8559
|
-
totalDuration += r.metadata.durationMs;
|
|
8560
|
-
}
|
|
8561
|
-
result = {
|
|
8562
|
-
candidates,
|
|
8563
|
-
updates: updates.length > 0 ? updates : void 0,
|
|
8564
|
-
demotions: demotions.length > 0 ? demotions : void 0,
|
|
8565
|
-
antiPatterns: antiPatterns.length > 0 ? antiPatterns : void 0,
|
|
8566
|
-
metadata: {
|
|
8567
|
-
trajectoriesAnalyzed: trajectories.length,
|
|
8568
|
-
durationMs: totalDuration
|
|
8569
|
-
}
|
|
8570
|
-
};
|
|
8571
|
-
}
|
|
8572
|
-
return this.processAnalyzeResult(result);
|
|
8573
|
-
}
|
|
8574
|
-
/**
|
|
8575
|
-
* Force extraction from all accumulating providers.
|
|
8576
|
-
*/
|
|
8577
|
-
async flushProviders() {
|
|
8578
|
-
this.ensureInitialized();
|
|
8579
|
-
const mergedResult = {
|
|
8580
|
-
skillsCreated: 0,
|
|
8581
|
-
skillsUpdated: 0,
|
|
8582
|
-
skillsDemoted: 0,
|
|
8583
|
-
antiPatternsAdded: 0,
|
|
8584
|
-
createdSkillIds: [],
|
|
8585
|
-
updatedSkillIds: []
|
|
8586
|
-
};
|
|
8587
|
-
for (const provider of this.learningProviders.values()) {
|
|
8588
|
-
if (provider.capabilities.accumulating && provider.flush) {
|
|
8589
|
-
const result = await provider.flush();
|
|
8590
|
-
const processed = await this.processAnalyzeResult(result);
|
|
8591
|
-
mergedResult.skillsCreated += processed.skillsCreated;
|
|
8592
|
-
mergedResult.skillsUpdated += processed.skillsUpdated;
|
|
8593
|
-
mergedResult.skillsDemoted += processed.skillsDemoted;
|
|
8594
|
-
mergedResult.antiPatternsAdded += processed.antiPatternsAdded;
|
|
8595
|
-
mergedResult.createdSkillIds.push(...processed.createdSkillIds);
|
|
8596
|
-
mergedResult.updatedSkillIds.push(...processed.updatedSkillIds);
|
|
8597
|
-
}
|
|
8598
|
-
}
|
|
8599
|
-
return mergedResult;
|
|
8600
|
-
}
|
|
8601
|
-
/**
|
|
8602
|
-
* Record outcome when a skill is applied.
|
|
8603
|
-
* Provider updates internal state and returns updates for SkillBank.
|
|
8604
|
-
*/
|
|
8605
|
-
async recordOutcome(feedback, providerName) {
|
|
8606
|
-
this.ensureInitialized();
|
|
8607
|
-
const skill = await this.storage.getSkill(feedback.candidateId);
|
|
8608
|
-
if (skill) {
|
|
8609
|
-
skill.metrics.usageCount++;
|
|
8610
|
-
if (feedback.success) {
|
|
8611
|
-
const totalUses = skill.metrics.usageCount;
|
|
8612
|
-
const currentSuccesses = skill.metrics.successRate * (totalUses - 1);
|
|
8613
|
-
skill.metrics.successRate = (currentSuccesses + 1) / totalUses;
|
|
8614
|
-
} else {
|
|
8615
|
-
const totalUses = skill.metrics.usageCount;
|
|
8616
|
-
const currentSuccesses = skill.metrics.successRate * (totalUses - 1);
|
|
8617
|
-
skill.metrics.successRate = currentSuccesses / totalUses;
|
|
8618
|
-
}
|
|
8619
|
-
skill.metrics.lastUsed = /* @__PURE__ */ new Date();
|
|
8620
|
-
await this.storage.saveSkill(skill);
|
|
8621
|
-
}
|
|
8622
|
-
const providersToNotify = providerName ? [this.learningProviders.get(providerName)].filter(Boolean) : Array.from(this.learningProviders.values());
|
|
8623
|
-
for (const provider of providersToNotify) {
|
|
8624
|
-
if (provider.capabilities.feedbackEnabled && provider.recordOutcome) {
|
|
8625
|
-
const result = await provider.recordOutcome(feedback);
|
|
8626
|
-
if (result.updates) {
|
|
8627
|
-
for (const update of result.updates) {
|
|
8628
|
-
await this.applyUpdate(update);
|
|
8629
|
-
}
|
|
8630
|
-
}
|
|
8631
|
-
if (result.antiPatterns) {
|
|
8632
|
-
for (const ap of result.antiPatterns) {
|
|
8633
|
-
await this.addAntiPattern(ap);
|
|
8634
|
-
}
|
|
8635
|
-
}
|
|
8636
|
-
}
|
|
8637
|
-
}
|
|
8638
|
-
}
|
|
8639
|
-
/**
|
|
8640
|
-
* Process an AnalyzeResult: store candidates, apply updates, etc.
|
|
8641
|
-
*/
|
|
8642
|
-
async processAnalyzeResult(result) {
|
|
8643
|
-
const learnResult = {
|
|
8644
|
-
skillsCreated: 0,
|
|
8645
|
-
skillsUpdated: 0,
|
|
8646
|
-
skillsDemoted: 0,
|
|
8647
|
-
antiPatternsAdded: 0,
|
|
8648
|
-
providerState: result.providerState,
|
|
8649
|
-
createdSkillIds: [],
|
|
8650
|
-
updatedSkillIds: []
|
|
8651
|
-
};
|
|
8652
|
-
for (const candidate of result.candidates) {
|
|
8653
|
-
if (candidate.content.kind === "skill") {
|
|
8654
|
-
const skill = await this.promoteToSkill(candidate);
|
|
8655
|
-
learnResult.skillsCreated++;
|
|
8656
|
-
learnResult.createdSkillIds.push(skill.id);
|
|
8657
|
-
} else {
|
|
8658
|
-
await this.storeCandidateForReview(candidate);
|
|
8659
|
-
}
|
|
8660
|
-
}
|
|
8661
|
-
if (result.updates) {
|
|
8662
|
-
for (const update of result.updates) {
|
|
8663
|
-
const updated = await this.applyUpdate(update);
|
|
8664
|
-
if (updated) {
|
|
8665
|
-
learnResult.skillsUpdated++;
|
|
8666
|
-
learnResult.updatedSkillIds.push(update.candidateId);
|
|
8667
|
-
}
|
|
8668
|
-
}
|
|
8669
|
-
}
|
|
8670
|
-
if (result.demotions) {
|
|
8671
|
-
for (const demotion of result.demotions) {
|
|
8672
|
-
await this.applyDemotion(demotion);
|
|
8673
|
-
learnResult.skillsDemoted++;
|
|
8674
|
-
}
|
|
8675
|
-
}
|
|
8676
|
-
if (result.antiPatterns) {
|
|
8677
|
-
for (const ap of result.antiPatterns) {
|
|
8678
|
-
await this.addAntiPattern(ap);
|
|
8679
|
-
learnResult.antiPatternsAdded++;
|
|
8680
|
-
}
|
|
8681
|
-
}
|
|
8682
|
-
return learnResult;
|
|
8683
|
-
}
|
|
8684
|
-
/**
|
|
8685
|
-
* Store a non-skill candidate for later review
|
|
8686
|
-
*/
|
|
8687
|
-
async storeCandidateForReview(candidate) {
|
|
8688
|
-
if (!this.storage.saveCandidate) {
|
|
8689
|
-
return;
|
|
8690
|
-
}
|
|
8691
|
-
const record = {
|
|
8692
|
-
id: candidate.id,
|
|
8693
|
-
kind: candidate.kind,
|
|
8694
|
-
name: candidate.name,
|
|
8695
|
-
content: candidate.content,
|
|
8696
|
-
confidence: candidate.confidence,
|
|
8697
|
-
source: {
|
|
8698
|
-
trajectoryId: candidate.source.trajectoryId,
|
|
8699
|
-
provider: candidate.source.provider,
|
|
8700
|
-
extractedAt: candidate.source.extractedAt,
|
|
8701
|
-
turnRange: candidate.source.turnRange
|
|
8702
|
-
},
|
|
8703
|
-
tags: candidate.tags,
|
|
8704
|
-
reasoning: candidate.reasoning,
|
|
8705
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
8706
|
-
updatedAt: /* @__PURE__ */ new Date(),
|
|
8707
|
-
status: "pending"
|
|
8708
|
-
};
|
|
8709
|
-
await this.storage.saveCandidate(record);
|
|
8710
|
-
}
|
|
8711
|
-
/**
|
|
8712
|
-
* Apply an update to an existing skill
|
|
8713
|
-
*/
|
|
8714
|
-
async applyUpdate(update) {
|
|
8715
|
-
const skill = await this.storage.getSkill(update.candidateId);
|
|
8716
|
-
if (!skill) return false;
|
|
8717
|
-
let modified = false;
|
|
8718
|
-
if (update.addTrigger) {
|
|
8719
|
-
const exists = skill.triggerConditions.some(
|
|
8720
|
-
(t) => t.type === update.addTrigger.type && t.value === update.addTrigger.value
|
|
8721
|
-
);
|
|
8722
|
-
if (!exists) {
|
|
8723
|
-
skill.triggerConditions.push({
|
|
8724
|
-
type: update.addTrigger.type,
|
|
8725
|
-
value: update.addTrigger.value,
|
|
8726
|
-
description: update.addTrigger.description
|
|
8727
|
-
});
|
|
8728
|
-
modified = true;
|
|
8729
|
-
}
|
|
8730
|
-
}
|
|
8731
|
-
if (update.refinement) {
|
|
8732
|
-
const refinementNote = `[${update.refinement.source}] ${update.refinement.context}: ${update.refinement.addition}`;
|
|
8733
|
-
skill.notes = skill.notes ? `${skill.notes}
|
|
8734
|
-
${refinementNote}` : refinementNote;
|
|
8735
|
-
modified = true;
|
|
8736
|
-
}
|
|
8737
|
-
if (update.confidenceAdjustment) {
|
|
8738
|
-
skill.metrics.successRate = Math.max(
|
|
8739
|
-
0,
|
|
8740
|
-
Math.min(1, skill.metrics.successRate + update.confidenceAdjustment)
|
|
8741
|
-
);
|
|
8742
|
-
modified = true;
|
|
8743
|
-
}
|
|
8744
|
-
if (update.incrementSuccess || update.incrementFailure) {
|
|
8745
|
-
skill.metrics.usageCount++;
|
|
8746
|
-
if (update.incrementSuccess) {
|
|
8747
|
-
const total = skill.metrics.usageCount;
|
|
8748
|
-
const currentSuccesses = skill.metrics.successRate * (total - 1);
|
|
8749
|
-
skill.metrics.successRate = (currentSuccesses + 1) / total;
|
|
8750
|
-
}
|
|
8751
|
-
modified = true;
|
|
8752
|
-
}
|
|
8753
|
-
if (modified) {
|
|
8754
|
-
skill.updatedAt = /* @__PURE__ */ new Date();
|
|
8755
|
-
await this.storage.saveSkill(skill);
|
|
8756
|
-
this.emit({ type: "skill:updated", skill, previousVersion: skill.version });
|
|
8757
|
-
}
|
|
8758
|
-
return modified;
|
|
8759
|
-
}
|
|
8760
|
-
/**
|
|
8761
|
-
* Apply a demotion to an existing skill
|
|
8762
|
-
*/
|
|
8763
|
-
async applyDemotion(demotion) {
|
|
8764
|
-
const skill = await this.storage.getSkill(demotion.candidateId);
|
|
8765
|
-
if (!skill) return;
|
|
8766
|
-
skill.metrics.successRate = demotion.newConfidence;
|
|
8767
|
-
if (demotion.deprecate) {
|
|
8768
|
-
skill.status = "deprecated";
|
|
8769
|
-
this.emit({ type: "skill:deprecated", skillId: skill.id });
|
|
8770
|
-
}
|
|
8771
|
-
skill.notes = skill.notes ? `${skill.notes}
|
|
8772
|
-
[demotion] ${demotion.reason}` : `[demotion] ${demotion.reason}`;
|
|
8773
|
-
skill.updatedAt = /* @__PURE__ */ new Date();
|
|
8774
|
-
await this.storage.saveSkill(skill);
|
|
8775
|
-
}
|
|
8776
|
-
// ==========================================================================
|
|
8777
|
-
// Anti-Pattern Management
|
|
8778
|
-
// ==========================================================================
|
|
8779
|
-
/**
|
|
8780
|
-
* Get anti-patterns for a skill
|
|
8781
|
-
*/
|
|
8782
|
-
async getAntiPatterns(skillId) {
|
|
8783
|
-
return this.antiPatterns.get(skillId) ?? [];
|
|
8784
|
-
}
|
|
8785
|
-
/**
|
|
8786
|
-
* Add an anti-pattern
|
|
8787
|
-
*/
|
|
8788
|
-
async addAntiPattern(antiPattern) {
|
|
8789
|
-
const existing = this.antiPatterns.get(antiPattern.candidateId) ?? [];
|
|
8790
|
-
existing.push(antiPattern);
|
|
8791
|
-
this.antiPatterns.set(antiPattern.candidateId, existing);
|
|
8792
|
-
if (this.storage.saveAntiPatterns) {
|
|
8793
|
-
const records = existing.map((ap) => ({
|
|
8794
|
-
id: ap.id,
|
|
8795
|
-
pattern: ap.pattern,
|
|
8796
|
-
description: ap.reason,
|
|
8797
|
-
context: ap.discoveredFrom,
|
|
8798
|
-
severity: "warning",
|
|
8799
|
-
learnedAt: ap.createdAt,
|
|
8800
|
-
occurrences: 1
|
|
8801
|
-
}));
|
|
8802
|
-
await this.storage.saveAntiPatterns(antiPattern.candidateId, records);
|
|
8803
|
-
}
|
|
8804
|
-
}
|
|
8805
|
-
/**
|
|
8806
|
-
* Remove an anti-pattern by ID
|
|
8807
|
-
*/
|
|
8808
|
-
async removeAntiPattern(antiPatternId) {
|
|
8809
|
-
for (const [skillId, patterns] of this.antiPatterns.entries()) {
|
|
8810
|
-
const index = patterns.findIndex((p) => p.id === antiPatternId);
|
|
8811
|
-
if (index >= 0) {
|
|
8812
|
-
patterns.splice(index, 1);
|
|
8813
|
-
if (patterns.length === 0) {
|
|
8814
|
-
this.antiPatterns.delete(skillId);
|
|
8815
|
-
}
|
|
8816
|
-
return true;
|
|
8817
|
-
}
|
|
8818
|
-
}
|
|
8819
|
-
return false;
|
|
8820
|
-
}
|
|
8821
|
-
// ==========================================================================
|
|
8822
|
-
// Candidate Lifecycle Management
|
|
8823
|
-
// ==========================================================================
|
|
8824
|
-
/**
|
|
8825
|
-
* List pending learning candidates for review
|
|
8826
|
-
*/
|
|
8827
|
-
async listCandidates(filter) {
|
|
8828
|
-
this.ensureInitialized();
|
|
8829
|
-
if (!this.storage.listCandidates) {
|
|
8830
|
-
return [];
|
|
8831
|
-
}
|
|
8832
|
-
return this.storage.listCandidates(filter);
|
|
8833
|
-
}
|
|
8834
|
-
/**
|
|
8835
|
-
* Get a specific candidate by ID
|
|
8836
|
-
*/
|
|
8837
|
-
async getCandidate(id) {
|
|
8838
|
-
this.ensureInitialized();
|
|
8839
|
-
if (!this.storage.getCandidate) {
|
|
8840
|
-
return null;
|
|
8841
|
-
}
|
|
8842
|
-
return this.storage.getCandidate(id);
|
|
8843
|
-
}
|
|
8844
|
-
/**
|
|
8845
|
-
* Promote a candidate to a skill
|
|
8846
|
-
* Works for strategy, pattern, and error-fix candidates that were stored for review
|
|
8847
|
-
*/
|
|
8848
|
-
async promoteCandidate(candidateId) {
|
|
8849
|
-
this.ensureInitialized();
|
|
8850
|
-
if (!this.storage.getCandidate || !this.storage.updateCandidateStatus) {
|
|
8851
|
-
throw new Error("Storage does not support candidate operations");
|
|
8852
|
-
}
|
|
8853
|
-
const record = await this.storage.getCandidate(candidateId);
|
|
8854
|
-
if (!record) return null;
|
|
8855
|
-
if (record.status !== "pending") {
|
|
8856
|
-
throw new Error(`Cannot promote candidate with status: ${record.status}`);
|
|
8857
|
-
}
|
|
8858
|
-
const candidate = {
|
|
8859
|
-
id: record.id,
|
|
8860
|
-
kind: record.kind,
|
|
8861
|
-
name: record.name,
|
|
8862
|
-
content: record.content,
|
|
8863
|
-
confidence: record.confidence,
|
|
8864
|
-
source: {
|
|
8865
|
-
provider: record.source.provider,
|
|
8866
|
-
trajectoryId: record.source.trajectoryId,
|
|
8867
|
-
extractedAt: record.source.extractedAt,
|
|
8868
|
-
turnRange: record.source.turnRange ?? [0, 0]
|
|
8869
|
-
},
|
|
8870
|
-
tags: record.tags,
|
|
8871
|
-
reasoning: record.reasoning
|
|
8872
|
-
};
|
|
8873
|
-
const skill = await this.promoteToSkill(candidate);
|
|
8874
|
-
await this.storage.updateCandidateStatus(candidateId, "promoted", {
|
|
8875
|
-
promotedToSkillId: skill.id
|
|
8876
|
-
});
|
|
8877
|
-
return skill;
|
|
8878
|
-
}
|
|
8879
|
-
/**
|
|
8880
|
-
* Reject a candidate with a reason
|
|
8881
|
-
*/
|
|
8882
|
-
async rejectCandidate(candidateId, reason) {
|
|
8883
|
-
this.ensureInitialized();
|
|
8884
|
-
if (!this.storage.updateCandidateStatus) {
|
|
8885
|
-
throw new Error("Storage does not support candidate operations");
|
|
8886
|
-
}
|
|
8887
|
-
return this.storage.updateCandidateStatus(candidateId, "rejected", {
|
|
8888
|
-
rejectionReason: reason
|
|
8889
|
-
});
|
|
8890
|
-
}
|
|
8891
|
-
/**
|
|
8892
|
-
* Delete a candidate
|
|
8893
|
-
*/
|
|
8894
|
-
async deleteCandidate(candidateId) {
|
|
8895
|
-
this.ensureInitialized();
|
|
8896
|
-
if (!this.storage.deleteCandidate) {
|
|
8897
|
-
return false;
|
|
8898
|
-
}
|
|
8899
|
-
return this.storage.deleteCandidate(candidateId);
|
|
8900
|
-
}
|
|
8901
|
-
/**
|
|
8902
|
-
* Find skills with anti-pattern awareness
|
|
8903
|
-
*/
|
|
8904
|
-
async findSkillsWithAntiPatterns(query, options) {
|
|
8905
|
-
this.ensureInitialized();
|
|
8906
|
-
const skills = await this.storage.listSkills({ status: ["active"] });
|
|
8907
|
-
const matches = await this.semanticMatcher.findMatches(query, skills, {
|
|
8908
|
-
threshold: options?.minSimilarity,
|
|
8909
|
-
maxResults: options?.maxResults
|
|
8910
|
-
});
|
|
8911
|
-
const results = [];
|
|
8912
|
-
for (const match of matches) {
|
|
8913
|
-
const skillAntiPatterns = await this.getAntiPatterns(match.skill.id);
|
|
8914
|
-
const warnings = [];
|
|
8915
|
-
let relevantAntiPatterns;
|
|
8916
|
-
if (options?.context && skillAntiPatterns.length > 0) {
|
|
8917
|
-
relevantAntiPatterns = skillAntiPatterns.filter(
|
|
8918
|
-
(ap) => options.context.toLowerCase().includes(ap.pattern.toLowerCase())
|
|
8919
|
-
);
|
|
8920
|
-
if (relevantAntiPatterns.length > 0) {
|
|
8921
|
-
warnings.push(
|
|
8922
|
-
`This skill has failed in similar contexts: ${relevantAntiPatterns.map((ap) => ap.reason).join("; ")}`
|
|
8923
|
-
);
|
|
8924
|
-
}
|
|
8925
|
-
}
|
|
8926
|
-
if (options?.excludeAntiPatternMatches && relevantAntiPatterns && relevantAntiPatterns.length > 0) {
|
|
8927
|
-
continue;
|
|
8928
|
-
}
|
|
8929
|
-
if (match.skill.metrics.successRate < 0.5 && match.skill.metrics.usageCount > 2) {
|
|
8930
|
-
warnings.push(`Low success rate: ${Math.round(match.skill.metrics.successRate * 100)}%`);
|
|
8931
|
-
}
|
|
8932
|
-
results.push({
|
|
8933
|
-
...match,
|
|
8934
|
-
relevantAntiPatterns: relevantAntiPatterns && relevantAntiPatterns.length > 0 ? relevantAntiPatterns : void 0,
|
|
8935
|
-
warnings: warnings.length > 0 ? warnings : void 0
|
|
8936
|
-
});
|
|
8937
|
-
}
|
|
8938
|
-
return results;
|
|
8939
|
-
}
|
|
8940
|
-
// ==========================================================================
|
|
8941
|
-
// Legacy Learning Methods (backwards compatibility)
|
|
8942
|
-
// ==========================================================================
|
|
8943
|
-
/**
|
|
8944
|
-
* Extract learning candidates from a trajectory using a learning provider.
|
|
8945
|
-
* @deprecated Use learnFrom() instead
|
|
8946
|
-
*/
|
|
8947
|
-
async extractLearnings(trajectory, options) {
|
|
8948
|
-
this.ensureInitialized();
|
|
8949
|
-
const providerName = options?.provider ?? "naive";
|
|
8950
|
-
const provider = this.learningProviders.get(providerName);
|
|
8951
|
-
if (!provider) {
|
|
8952
|
-
throw new Error(
|
|
8953
|
-
`Learning provider not found: ${providerName}. Available: ${Array.from(this.learningProviders.keys()).join(", ")}`
|
|
8954
|
-
);
|
|
8955
|
-
}
|
|
8956
|
-
const result = await provider.analyze(trajectory, options);
|
|
8957
|
-
return result.candidates;
|
|
8958
|
-
}
|
|
8959
|
-
/**
|
|
8960
|
-
* Extract learning candidates from multiple trajectories.
|
|
8961
|
-
* @deprecated Use learnFromBatch() instead
|
|
8962
|
-
*/
|
|
8963
|
-
async extractLearningsBatch(trajectories, options) {
|
|
8964
|
-
this.ensureInitialized();
|
|
8965
|
-
const providerName = options?.provider ?? "naive";
|
|
8966
|
-
const provider = this.learningProviders.get(providerName);
|
|
8967
|
-
if (!provider) {
|
|
8968
|
-
throw new Error(`Learning provider not found: ${providerName}`);
|
|
8969
|
-
}
|
|
8970
|
-
if (provider.analyzeBatch) {
|
|
8971
|
-
const result = await provider.analyzeBatch(trajectories, options);
|
|
8972
|
-
return result.candidates;
|
|
8973
|
-
}
|
|
8974
|
-
const allCandidates = [];
|
|
8975
|
-
for (const trajectory of trajectories) {
|
|
8976
|
-
const result = await provider.analyze(trajectory, options);
|
|
8977
|
-
allCandidates.push(...result.candidates);
|
|
8978
|
-
}
|
|
8979
|
-
return allCandidates;
|
|
8980
|
-
}
|
|
8981
|
-
/**
|
|
8982
|
-
* Promote a learning candidate to a versioned skill.
|
|
8983
|
-
* This converts the raw learning into a curated, versioned skill.
|
|
8984
|
-
*/
|
|
8985
|
-
async promoteToSkill(candidate, options) {
|
|
8986
|
-
this.ensureInitialized();
|
|
8987
|
-
if (candidate.content.kind !== "skill") {
|
|
8988
|
-
throw new Error(
|
|
8989
|
-
`Cannot promote ${candidate.content.kind} to skill directly. Only 'skill' kind is supported.`
|
|
8990
|
-
);
|
|
8991
|
-
}
|
|
8992
|
-
const agentId = this.activationManager.getCurrentAgentId();
|
|
8993
|
-
const agentMetadata = this.activationManager.getAgentMetadata();
|
|
8994
|
-
const agentName = agentMetadata?.agentName;
|
|
8995
|
-
const content = candidate.content;
|
|
8996
|
-
const skill = {
|
|
8997
|
-
id: candidate.id,
|
|
8998
|
-
name: candidate.name,
|
|
8999
|
-
version: "1.0.0",
|
|
9000
|
-
description: content.problem.substring(0, 150),
|
|
9001
|
-
problem: content.problem,
|
|
9002
|
-
triggerConditions: (content.triggers ?? []).map((t) => ({
|
|
9003
|
-
type: t.type,
|
|
9004
|
-
value: t.value,
|
|
9005
|
-
description: t.description
|
|
9006
|
-
})),
|
|
9007
|
-
solution: content.solution,
|
|
9008
|
-
verification: content.verification,
|
|
9009
|
-
examples: (content.examples ?? []).map((e) => ({
|
|
9010
|
-
scenario: e.scenario,
|
|
9011
|
-
before: e.before,
|
|
9012
|
-
after: e.after
|
|
9013
|
-
})),
|
|
9014
|
-
author: options?.author ?? agentName ?? candidate.source.provider,
|
|
9015
|
-
tags: options?.tags ?? candidate.tags ?? [],
|
|
9016
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
9017
|
-
updatedAt: /* @__PURE__ */ new Date(),
|
|
9018
|
-
status: options?.status ?? "draft",
|
|
9019
|
-
metrics: {
|
|
9020
|
-
usageCount: 0,
|
|
9021
|
-
successRate: candidate.confidence,
|
|
9022
|
-
feedbackScores: []
|
|
9023
|
-
},
|
|
9024
|
-
source: {
|
|
9025
|
-
type: "extracted",
|
|
9026
|
-
sessionId: candidate.source.trajectoryId,
|
|
9027
|
-
importedAt: candidate.source.extractedAt,
|
|
9028
|
-
agentId,
|
|
9029
|
-
agentName
|
|
9030
|
-
}
|
|
9031
|
-
};
|
|
9032
|
-
skill.serving = computeServingMetadata(skill);
|
|
9033
|
-
await this.storage.saveSkill(skill);
|
|
9034
|
-
this.emit({ type: "skill:created", skill });
|
|
9035
|
-
if (this.validationEnabled && this.validator) {
|
|
9036
|
-
this.runValidationAsync(skill).catch((err) => {
|
|
9037
|
-
console.error("Validation error:", err);
|
|
9038
|
-
});
|
|
9039
|
-
}
|
|
9040
|
-
if (this.compositionEnabled && this.composer) {
|
|
9041
|
-
this.runCompositionSuggestionsAsync(skill).catch((err) => {
|
|
9042
|
-
console.error("Composition suggestion error:", err);
|
|
9043
|
-
});
|
|
9044
|
-
}
|
|
9045
|
-
return skill;
|
|
9046
7948
|
}
|
|
9047
7949
|
/**
|
|
9048
7950
|
* Validate a skill and store the result
|
|
@@ -9501,7 +8403,6 @@ ${refinementNote}` : refinementNote;
|
|
|
9501
8403
|
const deleted = await this.storage.deleteSkill(id, version);
|
|
9502
8404
|
if (deleted) {
|
|
9503
8405
|
this.emit({ type: "skill:deleted", skillId: id });
|
|
9504
|
-
this.antiPatterns.delete(id);
|
|
9505
8406
|
}
|
|
9506
8407
|
return deleted;
|
|
9507
8408
|
}
|
|
@@ -9975,8 +8876,7 @@ ${refinementNote}` : refinementNote;
|
|
|
9975
8876
|
},
|
|
9976
8877
|
byTag: {},
|
|
9977
8878
|
avgSuccessRate: 0,
|
|
9978
|
-
totalUsage: 0
|
|
9979
|
-
totalAntiPatterns: 0
|
|
8879
|
+
totalUsage: 0
|
|
9980
8880
|
};
|
|
9981
8881
|
if (this.namespaceConfig) {
|
|
9982
8882
|
stats.byScope = { personal: 0, team: 0, global: 0 };
|
|
@@ -9994,10 +8894,6 @@ ${refinementNote}` : refinementNote;
|
|
|
9994
8894
|
successRateSum += skill.metrics.successRate;
|
|
9995
8895
|
successRateCount++;
|
|
9996
8896
|
}
|
|
9997
|
-
const ap = this.antiPatterns.get(skill.id);
|
|
9998
|
-
if (ap) {
|
|
9999
|
-
stats.totalAntiPatterns += ap.length;
|
|
10000
|
-
}
|
|
10001
8897
|
if (stats.byScope && stats.byVisibility) {
|
|
10002
8898
|
const scope = skill.namespace?.scope || "personal";
|
|
10003
8899
|
const visibility = skill.namespace?.visibility || "private";
|
|
@@ -15283,3 +14179,4 @@ program.addCommand(configCommand);
|
|
|
15283
14179
|
program.addCommand(syncCommand2);
|
|
15284
14180
|
program.addCommand(mcpCommand);
|
|
15285
14181
|
program.parse();
|
|
14182
|
+
//# sourceMappingURL=index.js.map
|