skill-tree 0.1.0 → 0.1.2

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.
@@ -13751,6 +13751,509 @@ function conditionalHook(filter, handler) {
13751
13751
  };
13752
13752
  }
13753
13753
 
13754
+ // src/learning/providers/cognitive-core.ts
13755
+ var CognitiveCoreProvider = class {
13756
+ constructor(options) {
13757
+ this.name = "cognitive-core";
13758
+ this.description = "Advanced learning using cognitive-core with batch extraction and feedback";
13759
+ this.capabilities = {
13760
+ accumulating: true,
13761
+ feedbackEnabled: true,
13762
+ persistent: true,
13763
+ minTrajectories: 5,
13764
+ supportedKinds: ["skill", "strategy", "pattern", "error-fix"]
13765
+ };
13766
+ this.initialized = false;
13767
+ // ID mapping: playbook.id <-> candidate.id
13768
+ // For cognitive-core, we use playbook.id as the candidate.id directly
13769
+ this.playbookIdCache = /* @__PURE__ */ new Map();
13770
+ this.factory = options.factory;
13771
+ this.config = {
13772
+ storagePath: options.storagePath ?? "./.cognitive-core",
13773
+ minTrajectories: options.minTrajectories ?? 5,
13774
+ deduplicationThreshold: options.deduplicationThreshold ?? 0.85,
13775
+ creditStrategy: options.creditStrategy ?? "simple",
13776
+ convertToReAct: options.convertToReAct ?? true
13777
+ };
13778
+ this.memory = this.factory.createMemorySystem(this.config.storagePath);
13779
+ this.pipeline = this.factory.createLearningPipeline(this.memory, {
13780
+ creditStrategy: this.config.creditStrategy,
13781
+ minTrajectories: this.config.minTrajectories,
13782
+ deduplicationThreshold: this.config.deduplicationThreshold
13783
+ });
13784
+ }
13785
+ /**
13786
+ * Initialize the provider (load persisted state)
13787
+ */
13788
+ async initialize() {
13789
+ if (this.initialized) return;
13790
+ await this.memory.init();
13791
+ this.initialized = true;
13792
+ }
13793
+ /**
13794
+ * Shutdown cleanly (persist state, release resources)
13795
+ */
13796
+ async shutdown() {
13797
+ await this.memory.close();
13798
+ this.initialized = false;
13799
+ }
13800
+ /**
13801
+ * Analyze a trajectory and accumulate for batch learning.
13802
+ * Returns empty candidates until flush() or batch threshold.
13803
+ */
13804
+ async analyze(trajectory, options) {
13805
+ await this.initialize();
13806
+ const startTime = Date.now();
13807
+ const ccTrajectory = this.convertTrajectory(trajectory, options);
13808
+ await this.pipeline.processTrajectory(ccTrajectory);
13809
+ let candidates = [];
13810
+ let updates = [];
13811
+ let demotions = [];
13812
+ let antiPatterns = [];
13813
+ if (options?.forceImmediate || this.pipeline.shouldRunBatch()) {
13814
+ const batchResult = await this.runBatchExtraction(options);
13815
+ candidates = batchResult.candidates;
13816
+ updates = batchResult.updates ?? [];
13817
+ demotions = batchResult.demotions ?? [];
13818
+ antiPatterns = batchResult.antiPatterns ?? [];
13819
+ }
13820
+ return {
13821
+ candidates,
13822
+ updates: updates.length > 0 ? updates : void 0,
13823
+ demotions: demotions.length > 0 ? demotions : void 0,
13824
+ antiPatterns: antiPatterns.length > 0 ? antiPatterns : void 0,
13825
+ providerState: {
13826
+ pendingCount: this.pipeline.getAccumulatedCount(),
13827
+ readyForFlush: this.pipeline.shouldRunBatch()
13828
+ },
13829
+ metadata: {
13830
+ trajectoriesAnalyzed: 1,
13831
+ durationMs: Date.now() - startTime
13832
+ }
13833
+ };
13834
+ }
13835
+ /**
13836
+ * Analyze multiple trajectories together.
13837
+ * Enables better cross-trajectory pattern detection.
13838
+ */
13839
+ async analyzeBatch(trajectories, options) {
13840
+ await this.initialize();
13841
+ const startTime = Date.now();
13842
+ for (const trajectory of trajectories) {
13843
+ const ccTrajectory = this.convertTrajectory(trajectory, options);
13844
+ await this.pipeline.processTrajectory(ccTrajectory);
13845
+ }
13846
+ const batchResult = await this.runBatchExtraction(options);
13847
+ return {
13848
+ candidates: batchResult.candidates,
13849
+ updates: batchResult.updates,
13850
+ demotions: batchResult.demotions,
13851
+ antiPatterns: batchResult.antiPatterns,
13852
+ providerState: {
13853
+ pendingCount: this.pipeline.getAccumulatedCount(),
13854
+ readyForFlush: this.pipeline.shouldRunBatch()
13855
+ },
13856
+ metadata: {
13857
+ trajectoriesAnalyzed: trajectories.length,
13858
+ durationMs: Date.now() - startTime
13859
+ }
13860
+ };
13861
+ }
13862
+ /**
13863
+ * Force extraction from accumulated trajectories.
13864
+ */
13865
+ async flush(options) {
13866
+ await this.initialize();
13867
+ const startTime = Date.now();
13868
+ const pendingCount = this.pipeline.getAccumulatedCount();
13869
+ const batchResult = await this.runBatchExtraction(options);
13870
+ return {
13871
+ ...batchResult,
13872
+ metadata: {
13873
+ trajectoriesAnalyzed: pendingCount,
13874
+ durationMs: Date.now() - startTime
13875
+ }
13876
+ };
13877
+ }
13878
+ /**
13879
+ * Record outcome when a candidate/playbook is applied.
13880
+ * Updates playbook confidence and may generate refinements.
13881
+ */
13882
+ async recordOutcome(feedback) {
13883
+ await this.initialize();
13884
+ const playbookId = feedback.candidateId;
13885
+ const playbook = await this.memory.playbooks.get(playbookId);
13886
+ if (!playbook) {
13887
+ return { recorded: false };
13888
+ }
13889
+ await this.memory.recordPlaybookUsage(
13890
+ playbookId,
13891
+ feedback.trajectoryId,
13892
+ feedback.success,
13893
+ feedback.context,
13894
+ feedback.failureMode
13895
+ );
13896
+ const updates = [];
13897
+ const antiPatterns = [];
13898
+ if (feedback.success) {
13899
+ updates.push({
13900
+ candidateId: playbookId,
13901
+ incrementSuccess: true,
13902
+ confidenceAdjustment: 0.05
13903
+ // Slight boost on success
13904
+ });
13905
+ } else {
13906
+ updates.push({
13907
+ candidateId: playbookId,
13908
+ incrementFailure: true,
13909
+ confidenceAdjustment: -0.1
13910
+ // Decrease confidence on failure
13911
+ });
13912
+ if (feedback.context || feedback.failureMode) {
13913
+ antiPatterns.push({
13914
+ id: `anti-${playbookId}-${Date.now()}`,
13915
+ candidateId: playbookId,
13916
+ pattern: feedback.context ?? "Unknown context",
13917
+ reason: feedback.failureMode ?? "Unknown failure mode",
13918
+ discoveredFrom: feedback.trajectoryId,
13919
+ createdAt: /* @__PURE__ */ new Date()
13920
+ });
13921
+ }
13922
+ }
13923
+ return {
13924
+ recorded: true,
13925
+ updates: updates.length > 0 ? updates : void 0,
13926
+ antiPatterns: antiPatterns.length > 0 ? antiPatterns : void 0
13927
+ };
13928
+ }
13929
+ /**
13930
+ * Check if a candidate is a duplicate based on playbook similarity
13931
+ */
13932
+ isDuplicate(candidate, existing) {
13933
+ if (existing.some((e) => e.id === candidate.id)) {
13934
+ return true;
13935
+ }
13936
+ for (const e of existing) {
13937
+ const similarity = this.computeSimilarity(candidate, e);
13938
+ if (similarity > this.config.deduplicationThreshold) {
13939
+ return true;
13940
+ }
13941
+ }
13942
+ return false;
13943
+ }
13944
+ /**
13945
+ * Compute similarity between two candidates
13946
+ */
13947
+ computeSimilarity(a, b) {
13948
+ if (a.kind !== b.kind) return 0.1;
13949
+ const nameA = this.tokenize(a.name);
13950
+ const nameB = this.tokenize(b.name);
13951
+ const nameSimilarity = this.jaccardSimilarity(nameA, nameB);
13952
+ let contentSimilarity = 0;
13953
+ if (a.content.kind === "skill" && b.content.kind === "skill") {
13954
+ const aWords = this.tokenize(a.content.problem + " " + a.content.solution);
13955
+ const bWords = this.tokenize(b.content.problem + " " + b.content.solution);
13956
+ contentSimilarity = this.jaccardSimilarity(aWords, bWords);
13957
+ }
13958
+ return nameSimilarity * 0.3 + contentSimilarity * 0.7;
13959
+ }
13960
+ // ==========================================================================
13961
+ // Private Methods
13962
+ // ==========================================================================
13963
+ /**
13964
+ * Run batch extraction and convert results to LearningCandidates
13965
+ */
13966
+ async runBatchExtraction(options) {
13967
+ await this.pipeline.runBatchLearning();
13968
+ const allPlaybooks = await this.memory.playbooks.getAll();
13969
+ const candidates = [];
13970
+ const updates = [];
13971
+ const demotions = [];
13972
+ const antiPatterns = [];
13973
+ const minConfidence = options?.minConfidence ?? 0;
13974
+ const requestedKinds = options?.kinds;
13975
+ for (const playbook of allPlaybooks) {
13976
+ if (!this.playbookIdCache.has(playbook.id)) {
13977
+ const candidate = this.playbookToCandidate(playbook);
13978
+ if (candidate.confidence < minConfidence) {
13979
+ continue;
13980
+ }
13981
+ if (requestedKinds && !requestedKinds.includes(candidate.kind)) {
13982
+ continue;
13983
+ }
13984
+ candidates.push(candidate);
13985
+ this.playbookIdCache.set(playbook.id, true);
13986
+ }
13987
+ const successRate = playbook.evolution.successCount + playbook.evolution.failureCount > 0 ? playbook.evolution.successCount / (playbook.evolution.successCount + playbook.evolution.failureCount) : 1;
13988
+ if (successRate < 0.3 && playbook.evolution.successCount + playbook.evolution.failureCount >= 3) {
13989
+ demotions.push({
13990
+ candidateId: playbook.id,
13991
+ reason: `Low success rate: ${Math.round(successRate * 100)}%`,
13992
+ newConfidence: successRate,
13993
+ deprecate: successRate < 0.1
13994
+ });
13995
+ }
13996
+ for (const antiPattern of playbook.applicability.antiPatterns) {
13997
+ antiPatterns.push({
13998
+ id: `anti-${playbook.id}-${antiPattern.slice(0, 10)}`,
13999
+ candidateId: playbook.id,
14000
+ pattern: antiPattern,
14001
+ reason: "Learned from playbook applicability",
14002
+ discoveredFrom: playbook.evolution.createdFrom[0] ?? "unknown",
14003
+ createdAt: playbook.createdAt
14004
+ });
14005
+ }
14006
+ }
14007
+ return {
14008
+ candidates,
14009
+ updates: updates.length > 0 ? updates : void 0,
14010
+ demotions: demotions.length > 0 ? demotions : void 0,
14011
+ antiPatterns: antiPatterns.length > 0 ? antiPatterns : void 0,
14012
+ providerState: {
14013
+ pendingCount: this.pipeline.getAccumulatedCount(),
14014
+ readyForFlush: this.pipeline.shouldRunBatch()
14015
+ }
14016
+ };
14017
+ }
14018
+ /**
14019
+ * Convert a skill-tree Trajectory to cognitive-core Trajectory format
14020
+ */
14021
+ convertTrajectory(trajectory, options) {
14022
+ const firstUserTurn = trajectory.turns.find((t) => t.role === "user");
14023
+ let taskDescription = firstUserTurn?.content ?? "Unknown task";
14024
+ if (options?.context) {
14025
+ taskDescription = `${taskDescription}
14026
+
14027
+ Context: ${options.context}`;
14028
+ }
14029
+ const task = this.factory.createTask({
14030
+ id: trajectory.sessionId,
14031
+ domain: trajectory.metadata.projectName ?? "general",
14032
+ description: taskDescription,
14033
+ context: trajectory.metadata.custom ?? {}
14034
+ });
14035
+ const [startTurn, endTurn] = options?.turnRange ?? [0, trajectory.turns.length - 1];
14036
+ const turnsToProcess = trajectory.turns.slice(startTurn, endTurn + 1);
14037
+ const steps = [];
14038
+ if (this.config.convertToReAct) {
14039
+ for (let i = 0; i < turnsToProcess.length; i++) {
14040
+ const turn = turnsToProcess[i];
14041
+ if (turn.role === "assistant") {
14042
+ const step = this.turnToStep(turn, turnsToProcess, i);
14043
+ if (step) {
14044
+ steps.push(step);
14045
+ }
14046
+ }
14047
+ }
14048
+ }
14049
+ const outcome = {
14050
+ success: trajectory.outcome?.success ?? false,
14051
+ partialScore: trajectory.outcome?.success ? 1 : 0,
14052
+ solution: trajectory.outcome?.summary ?? "",
14053
+ errorInfo: trajectory.outcome?.errors?.join("; ")
14054
+ };
14055
+ return this.factory.createTrajectory({
14056
+ id: trajectory.sessionId,
14057
+ task,
14058
+ steps,
14059
+ outcome,
14060
+ agentId: trajectory.metadata.agentType ?? "skill-tree",
14061
+ metadata: trajectory.metadata.custom ?? {}
14062
+ });
14063
+ }
14064
+ /**
14065
+ * Convert an assistant turn to a cognitive-core Step
14066
+ */
14067
+ turnToStep(turn, allTurns, turnIndex) {
14068
+ let observation = "";
14069
+ const nextTurn = allTurns[turnIndex + 1];
14070
+ if (nextTurn?.role === "tool" && nextTurn.toolResults?.length) {
14071
+ observation = nextTurn.toolResults.map((r) => r.output).join("\n");
14072
+ } else if (nextTurn?.role === "user") {
14073
+ observation = nextTurn.content.slice(0, 500);
14074
+ }
14075
+ let action = "";
14076
+ if (turn.toolCalls?.length) {
14077
+ action = turn.toolCalls.map((tc) => `${tc.name}(${JSON.stringify(tc.input).slice(0, 200)})`).join("; ");
14078
+ } else {
14079
+ action = turn.content.slice(0, 300);
14080
+ }
14081
+ const thought = turn.toolCalls?.length ? turn.content.slice(0, 500) : void 0;
14082
+ return this.factory.createStep({
14083
+ thought,
14084
+ action,
14085
+ observation
14086
+ });
14087
+ }
14088
+ /**
14089
+ * Convert a cognitive-core Playbook to a LearningCandidate
14090
+ */
14091
+ playbookToCandidate(playbook) {
14092
+ const kind = this.inferKind(playbook);
14093
+ const content = this.createContentForKind(kind, playbook);
14094
+ const attribution = playbook.evolution.createdFrom.map(
14095
+ (trajectoryId, i) => ({
14096
+ turnIndex: i,
14097
+ score: 1 / Math.max(1, playbook.evolution.createdFrom.length),
14098
+ reasoning: `Derived from trajectory ${trajectoryId}`
14099
+ })
14100
+ );
14101
+ return {
14102
+ kind,
14103
+ id: playbook.id,
14104
+ name: playbook.name,
14105
+ content,
14106
+ confidence: playbook.confidence,
14107
+ attribution,
14108
+ source: {
14109
+ provider: this.name,
14110
+ trajectoryId: playbook.evolution.createdFrom[0] ?? "unknown",
14111
+ turnRange: [0, 0],
14112
+ // Playbooks don't track specific turn ranges
14113
+ extractedAt: playbook.createdAt,
14114
+ metadata: {
14115
+ version: playbook.evolution.version,
14116
+ successCount: playbook.evolution.successCount,
14117
+ failureCount: playbook.evolution.failureCount,
14118
+ complexity: playbook.complexity
14119
+ }
14120
+ },
14121
+ embedding: playbook.embedding,
14122
+ // Pass through embedding if present
14123
+ tags: playbook.applicability.domains,
14124
+ reasoning: playbook.guidance.strategy
14125
+ };
14126
+ }
14127
+ /**
14128
+ * Create appropriate content type for the inferred kind
14129
+ */
14130
+ createContentForKind(kind, playbook) {
14131
+ switch (kind) {
14132
+ case "strategy":
14133
+ return {
14134
+ kind: "strategy",
14135
+ situation: playbook.applicability.situations.join(". "),
14136
+ suggestion: playbook.guidance.strategy,
14137
+ parameters: playbook.guidance.codeExample ? { example: playbook.guidance.codeExample } : void 0
14138
+ };
14139
+ case "pattern":
14140
+ return {
14141
+ kind: "pattern",
14142
+ pattern: playbook.applicability.triggers[0] ?? playbook.name,
14143
+ description: playbook.guidance.strategy,
14144
+ examples: playbook.applicability.situations
14145
+ };
14146
+ case "error-fix":
14147
+ return {
14148
+ kind: "error-fix",
14149
+ errorPattern: playbook.applicability.triggers.join(" | "),
14150
+ fix: playbook.guidance.strategy + (playbook.guidance.steps?.length ? "\n\nSteps:\n" + playbook.guidance.steps.map((s, i) => `${i + 1}. ${s}`).join("\n") : ""),
14151
+ frequency: playbook.evolution.successCount + playbook.evolution.failureCount,
14152
+ errorExamples: playbook.applicability.triggers
14153
+ };
14154
+ case "skill":
14155
+ default:
14156
+ return {
14157
+ kind: "skill",
14158
+ problem: playbook.applicability.situations.join(". "),
14159
+ solution: playbook.guidance.strategy + (playbook.guidance.steps?.length ? "\n\nSteps:\n" + playbook.guidance.steps.map((s, i) => `${i + 1}. ${s}`).join("\n") : ""),
14160
+ verification: playbook.verification.successIndicators.join(". "),
14161
+ triggers: this.extractTriggers(playbook),
14162
+ examples: []
14163
+ // Playbooks don't have direct examples
14164
+ };
14165
+ }
14166
+ }
14167
+ /**
14168
+ * Infer the kind of learning from a playbook
14169
+ */
14170
+ inferKind(playbook) {
14171
+ const hasErrorTriggers = playbook.applicability.triggers.some(
14172
+ (t) => t.toLowerCase().includes("error") || /^[A-Z]{2,}\d+/.test(t)
14173
+ );
14174
+ if (hasErrorTriggers) {
14175
+ return "error-fix";
14176
+ }
14177
+ const strategy = playbook.guidance.strategy.toLowerCase();
14178
+ if (strategy.includes("approach") || strategy.includes("strategy") || strategy.includes("when you see")) {
14179
+ return "strategy";
14180
+ }
14181
+ if (playbook.applicability.situations.some((s) => s.includes("pattern"))) {
14182
+ return "pattern";
14183
+ }
14184
+ return "skill";
14185
+ }
14186
+ /**
14187
+ * Extract triggers from playbook applicability
14188
+ */
14189
+ extractTriggers(playbook) {
14190
+ const triggers = [];
14191
+ for (const situation of playbook.applicability.situations) {
14192
+ triggers.push({
14193
+ type: "context",
14194
+ value: situation,
14195
+ description: "Situation trigger"
14196
+ });
14197
+ }
14198
+ for (const trigger of playbook.applicability.triggers) {
14199
+ let type = "keyword";
14200
+ if (trigger.toLowerCase().includes("error") || /^[A-Z]{2,}\d+/.test(trigger)) {
14201
+ type = "error";
14202
+ } else if (trigger.startsWith("/") || trigger.includes("*")) {
14203
+ type = "pattern";
14204
+ }
14205
+ triggers.push({
14206
+ type,
14207
+ value: trigger,
14208
+ description: "Explicit trigger"
14209
+ });
14210
+ }
14211
+ return triggers;
14212
+ }
14213
+ /**
14214
+ * Tokenize text into words
14215
+ */
14216
+ tokenize(text) {
14217
+ return text.toLowerCase().split(/\W+/).filter((w) => w.length > 2);
14218
+ }
14219
+ /**
14220
+ * Compute Jaccard similarity between two arrays
14221
+ */
14222
+ jaccardSimilarity(a, b) {
14223
+ const setA = new Set(a);
14224
+ const setB = new Set(b);
14225
+ const intersection = new Set([...setA].filter((x) => setB.has(x)));
14226
+ const union = /* @__PURE__ */ new Set([...setA, ...setB]);
14227
+ return union.size === 0 ? 0 : intersection.size / union.size;
14228
+ }
14229
+ };
14230
+ function createCognitiveCoreProvider(options) {
14231
+ return new CognitiveCoreProvider(options);
14232
+ }
14233
+ async function createDefaultCognitiveCoreFactory() {
14234
+ const cc = await import("cognitive-core");
14235
+ return {
14236
+ createMemorySystem(storagePath) {
14237
+ return cc.createMemorySystem(storagePath);
14238
+ },
14239
+ createLearningPipeline(memory, config) {
14240
+ return cc.createLearningPipeline(
14241
+ memory,
14242
+ config
14243
+ );
14244
+ },
14245
+ createTrajectory(params) {
14246
+ return cc.createTrajectory(params);
14247
+ },
14248
+ createTask(params) {
14249
+ return cc.createTask(params);
14250
+ },
14251
+ createStep(params) {
14252
+ return cc.createStep(params);
14253
+ }
14254
+ };
14255
+ }
14256
+
13754
14257
  // src/sync/git-sync-adapter.ts
13755
14258
  import * as fs8 from "fs";
13756
14259
  import * as path8 from "path";
@@ -15364,6 +15867,9 @@ export {
15364
15867
  createMetricsHook,
15365
15868
  combineHandlers,
15366
15869
  conditionalHook,
15870
+ CognitiveCoreProvider,
15871
+ createCognitiveCoreProvider,
15872
+ createDefaultCognitiveCoreFactory,
15367
15873
  ConflictStore,
15368
15874
  createConflictStore,
15369
15875
  GitSyncAdapter,