cognitive-core 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/README.md +302 -116
  2. package/SKILL.md +193 -0
  3. package/dist/agents/index.d.ts +3 -0
  4. package/dist/agents/index.d.ts.map +1 -0
  5. package/dist/agents/index.js +5 -0
  6. package/dist/agents/index.js.map +1 -0
  7. package/dist/agents/mock-provider.d.ts +23 -0
  8. package/dist/agents/mock-provider.d.ts.map +1 -0
  9. package/dist/agents/mock-provider.js +71 -0
  10. package/dist/agents/mock-provider.js.map +1 -0
  11. package/dist/agents/types.d.ts +98 -0
  12. package/dist/agents/types.d.ts.map +1 -0
  13. package/dist/agents/types.js +44 -0
  14. package/dist/agents/types.js.map +1 -0
  15. package/dist/atlas.d.ts +196 -0
  16. package/dist/atlas.d.ts.map +1 -0
  17. package/dist/atlas.js +373 -0
  18. package/dist/atlas.js.map +1 -0
  19. package/dist/bin/cognitive-core.d.ts +18 -0
  20. package/dist/bin/cognitive-core.d.ts.map +1 -0
  21. package/dist/bin/cognitive-core.js +419 -0
  22. package/dist/bin/cognitive-core.js.map +1 -0
  23. package/dist/embeddings/bm25.d.ts +104 -0
  24. package/dist/embeddings/bm25.d.ts.map +1 -0
  25. package/dist/embeddings/bm25.js +264 -0
  26. package/dist/embeddings/bm25.js.map +1 -0
  27. package/dist/embeddings/index.d.ts +12 -0
  28. package/dist/embeddings/index.d.ts.map +1 -0
  29. package/dist/embeddings/index.js +16 -0
  30. package/dist/embeddings/index.js.map +1 -0
  31. package/dist/embeddings/manager.d.ts +112 -0
  32. package/dist/embeddings/manager.d.ts.map +1 -0
  33. package/dist/embeddings/manager.js +215 -0
  34. package/dist/embeddings/manager.js.map +1 -0
  35. package/dist/embeddings/provider.d.ts +101 -0
  36. package/dist/embeddings/provider.d.ts.map +1 -0
  37. package/dist/embeddings/provider.js +232 -0
  38. package/dist/embeddings/provider.js.map +1 -0
  39. package/dist/embeddings/vector-store.d.ts +101 -0
  40. package/dist/embeddings/vector-store.d.ts.map +1 -0
  41. package/dist/embeddings/vector-store.js +256 -0
  42. package/dist/embeddings/vector-store.js.map +1 -0
  43. package/dist/factory.d.ts +193 -0
  44. package/dist/factory.d.ts.map +1 -0
  45. package/dist/factory.js +109 -0
  46. package/dist/factory.js.map +1 -0
  47. package/dist/index.d.ts +30 -453
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +84 -509
  50. package/dist/index.js.map +1 -0
  51. package/dist/learning/analyzer.d.ts +110 -0
  52. package/dist/learning/analyzer.d.ts.map +1 -0
  53. package/dist/learning/analyzer.js +213 -0
  54. package/dist/learning/analyzer.js.map +1 -0
  55. package/dist/learning/effectiveness.d.ts +158 -0
  56. package/dist/learning/effectiveness.d.ts.map +1 -0
  57. package/dist/learning/effectiveness.js +251 -0
  58. package/dist/learning/effectiveness.js.map +1 -0
  59. package/dist/learning/index.d.ts +8 -0
  60. package/dist/learning/index.d.ts.map +1 -0
  61. package/dist/learning/index.js +11 -0
  62. package/dist/learning/index.js.map +1 -0
  63. package/dist/learning/llm-extractor.d.ts +88 -0
  64. package/dist/learning/llm-extractor.d.ts.map +1 -0
  65. package/dist/learning/llm-extractor.js +372 -0
  66. package/dist/learning/llm-extractor.js.map +1 -0
  67. package/dist/learning/meta-learner.d.ts +80 -0
  68. package/dist/learning/meta-learner.d.ts.map +1 -0
  69. package/dist/learning/meta-learner.js +355 -0
  70. package/dist/learning/meta-learner.js.map +1 -0
  71. package/dist/learning/pipeline.d.ts +65 -0
  72. package/dist/learning/pipeline.d.ts.map +1 -0
  73. package/dist/learning/pipeline.js +170 -0
  74. package/dist/learning/pipeline.js.map +1 -0
  75. package/dist/learning/playbook-extractor.d.ts +113 -0
  76. package/dist/learning/playbook-extractor.d.ts.map +1 -0
  77. package/dist/learning/playbook-extractor.js +523 -0
  78. package/dist/learning/playbook-extractor.js.map +1 -0
  79. package/dist/learning/usage-inference.d.ts +82 -0
  80. package/dist/learning/usage-inference.d.ts.map +1 -0
  81. package/dist/learning/usage-inference.js +261 -0
  82. package/dist/learning/usage-inference.js.map +1 -0
  83. package/dist/mcp/index.d.ts +6 -0
  84. package/dist/mcp/index.d.ts.map +1 -0
  85. package/dist/mcp/index.js +6 -0
  86. package/dist/mcp/index.js.map +1 -0
  87. package/dist/mcp/playbook-server.d.ts +120 -0
  88. package/dist/mcp/playbook-server.d.ts.map +1 -0
  89. package/dist/mcp/playbook-server.js +427 -0
  90. package/dist/mcp/playbook-server.js.map +1 -0
  91. package/dist/memory/curated-loader.d.ts +62 -0
  92. package/dist/memory/curated-loader.d.ts.map +1 -0
  93. package/dist/memory/curated-loader.js +106 -0
  94. package/dist/memory/curated-loader.js.map +1 -0
  95. package/dist/memory/experience.d.ts +122 -0
  96. package/dist/memory/experience.d.ts.map +1 -0
  97. package/dist/memory/experience.js +392 -0
  98. package/dist/memory/experience.js.map +1 -0
  99. package/dist/memory/index.d.ts +6 -0
  100. package/dist/memory/index.d.ts.map +1 -0
  101. package/dist/memory/index.js +9 -0
  102. package/dist/memory/index.js.map +1 -0
  103. package/dist/memory/meta.d.ts +90 -0
  104. package/dist/memory/meta.d.ts.map +1 -0
  105. package/dist/memory/meta.js +362 -0
  106. package/dist/memory/meta.js.map +1 -0
  107. package/dist/memory/playbook.d.ts +133 -0
  108. package/dist/memory/playbook.d.ts.map +1 -0
  109. package/dist/memory/playbook.js +357 -0
  110. package/dist/memory/playbook.js.map +1 -0
  111. package/dist/memory/system.d.ts +167 -0
  112. package/dist/memory/system.d.ts.map +1 -0
  113. package/dist/memory/system.js +383 -0
  114. package/dist/memory/system.js.map +1 -0
  115. package/dist/runtime/backends/acp.d.ts +67 -0
  116. package/dist/runtime/backends/acp.d.ts.map +1 -0
  117. package/dist/runtime/backends/acp.js +290 -0
  118. package/dist/runtime/backends/acp.js.map +1 -0
  119. package/dist/runtime/backends/index.d.ts +5 -0
  120. package/dist/runtime/backends/index.d.ts.map +1 -0
  121. package/dist/runtime/backends/index.js +6 -0
  122. package/dist/runtime/backends/index.js.map +1 -0
  123. package/dist/runtime/backends/mock.d.ts +67 -0
  124. package/dist/runtime/backends/mock.d.ts.map +1 -0
  125. package/dist/runtime/backends/mock.js +153 -0
  126. package/dist/runtime/backends/mock.js.map +1 -0
  127. package/dist/runtime/backends/subprocess.d.ts +56 -0
  128. package/dist/runtime/backends/subprocess.d.ts.map +1 -0
  129. package/dist/runtime/backends/subprocess.js +260 -0
  130. package/dist/runtime/backends/subprocess.js.map +1 -0
  131. package/dist/runtime/flows/learning.d.ts +73 -0
  132. package/dist/runtime/flows/learning.d.ts.map +1 -0
  133. package/dist/runtime/flows/learning.js +116 -0
  134. package/dist/runtime/flows/learning.js.map +1 -0
  135. package/dist/runtime/flows/validation.d.ts +122 -0
  136. package/dist/runtime/flows/validation.d.ts.map +1 -0
  137. package/dist/runtime/flows/validation.js +223 -0
  138. package/dist/runtime/flows/validation.js.map +1 -0
  139. package/dist/runtime/index.d.ts +6 -0
  140. package/dist/runtime/index.d.ts.map +1 -0
  141. package/dist/runtime/index.js +8 -0
  142. package/dist/runtime/index.js.map +1 -0
  143. package/dist/runtime/manager.d.ts +116 -0
  144. package/dist/runtime/manager.d.ts.map +1 -0
  145. package/dist/runtime/manager.js +416 -0
  146. package/dist/runtime/manager.js.map +1 -0
  147. package/dist/runtime/types.d.ts +138 -0
  148. package/dist/runtime/types.d.ts.map +1 -0
  149. package/dist/runtime/types.js +2 -0
  150. package/dist/runtime/types.js.map +1 -0
  151. package/dist/search/evaluator.d.ts +102 -0
  152. package/dist/search/evaluator.d.ts.map +1 -0
  153. package/dist/search/evaluator.js +352 -0
  154. package/dist/search/evaluator.js.map +1 -0
  155. package/dist/search/index.d.ts +7 -0
  156. package/dist/search/index.d.ts.map +1 -0
  157. package/dist/search/index.js +11 -0
  158. package/dist/search/index.js.map +1 -0
  159. package/dist/search/refinement-loop.d.ts +73 -0
  160. package/dist/search/refinement-loop.d.ts.map +1 -0
  161. package/dist/search/refinement-loop.js +245 -0
  162. package/dist/search/refinement-loop.js.map +1 -0
  163. package/dist/search/refinement-types.d.ts +154 -0
  164. package/dist/search/refinement-types.d.ts.map +1 -0
  165. package/dist/search/refinement-types.js +99 -0
  166. package/dist/search/refinement-types.js.map +1 -0
  167. package/dist/search/router.d.ts +61 -0
  168. package/dist/search/router.d.ts.map +1 -0
  169. package/dist/search/router.js +197 -0
  170. package/dist/search/router.js.map +1 -0
  171. package/dist/search/solver.d.ts +75 -0
  172. package/dist/search/solver.d.ts.map +1 -0
  173. package/dist/search/solver.js +216 -0
  174. package/dist/search/solver.js.map +1 -0
  175. package/dist/search/verification-runner.d.ts +125 -0
  176. package/dist/search/verification-runner.d.ts.map +1 -0
  177. package/dist/search/verification-runner.js +440 -0
  178. package/dist/search/verification-runner.js.map +1 -0
  179. package/dist/surfacing/index.d.ts +2 -0
  180. package/dist/surfacing/index.d.ts.map +1 -0
  181. package/dist/surfacing/index.js +2 -0
  182. package/dist/surfacing/index.js.map +1 -0
  183. package/dist/surfacing/skill-library.d.ts +158 -0
  184. package/dist/surfacing/skill-library.d.ts.map +1 -0
  185. package/dist/surfacing/skill-library.js +429 -0
  186. package/dist/surfacing/skill-library.js.map +1 -0
  187. package/dist/types/config.d.ts +1113 -0
  188. package/dist/types/config.d.ts.map +1 -0
  189. package/dist/types/config.js +274 -0
  190. package/dist/types/config.js.map +1 -0
  191. package/dist/types/index.d.ts +9 -0
  192. package/dist/types/index.d.ts.map +1 -0
  193. package/dist/types/index.js +14 -0
  194. package/dist/types/index.js.map +1 -0
  195. package/dist/types/memory.d.ts +339 -0
  196. package/dist/types/memory.d.ts.map +1 -0
  197. package/dist/types/memory.js +207 -0
  198. package/dist/types/memory.js.map +1 -0
  199. package/dist/types/meta.d.ts +146 -0
  200. package/dist/types/meta.d.ts.map +1 -0
  201. package/dist/types/meta.js +51 -0
  202. package/dist/types/meta.js.map +1 -0
  203. package/dist/types/outcome.d.ts +42 -0
  204. package/dist/types/outcome.d.ts.map +1 -0
  205. package/dist/types/outcome.js +50 -0
  206. package/dist/types/outcome.js.map +1 -0
  207. package/dist/types/playbook.d.ts +119 -0
  208. package/dist/types/playbook.d.ts.map +1 -0
  209. package/dist/types/playbook.js +71 -0
  210. package/dist/types/playbook.js.map +1 -0
  211. package/dist/types/step.d.ts +44 -0
  212. package/dist/types/step.d.ts.map +1 -0
  213. package/dist/types/step.js +32 -0
  214. package/dist/types/step.js.map +1 -0
  215. package/dist/types/task.d.ts +91 -0
  216. package/dist/types/task.d.ts.map +1 -0
  217. package/dist/types/task.js +39 -0
  218. package/dist/types/task.js.map +1 -0
  219. package/dist/types/trajectory.d.ts +221 -0
  220. package/dist/types/trajectory.d.ts.map +1 -0
  221. package/dist/types/trajectory.js +60 -0
  222. package/dist/types/trajectory.js.map +1 -0
  223. package/dist/utils/index.d.ts +4 -0
  224. package/dist/utils/index.d.ts.map +1 -0
  225. package/dist/utils/index.js +4 -0
  226. package/dist/utils/index.js.map +1 -0
  227. package/dist/utils/similarity.d.ts +31 -0
  228. package/dist/utils/similarity.d.ts.map +1 -0
  229. package/dist/utils/similarity.js +107 -0
  230. package/dist/utils/similarity.js.map +1 -0
  231. package/dist/utils/storage.d.ts +106 -0
  232. package/dist/utils/storage.d.ts.map +1 -0
  233. package/dist/utils/storage.js +203 -0
  234. package/dist/utils/storage.js.map +1 -0
  235. package/dist/utils/validation.d.ts +129 -0
  236. package/dist/utils/validation.d.ts.map +1 -0
  237. package/dist/utils/validation.js +171 -0
  238. package/dist/utils/validation.js.map +1 -0
  239. package/package.json +50 -34
  240. package/scripts/migrate-to-playbooks.ts +307 -0
  241. package/src/agents/index.ts +14 -0
  242. package/src/agents/mock-provider.ts +93 -0
  243. package/src/agents/types.ts +137 -0
  244. package/src/atlas.ts +560 -0
  245. package/src/bin/cognitive-core.ts +470 -0
  246. package/src/embeddings/bm25.ts +337 -0
  247. package/src/embeddings/index.ts +39 -0
  248. package/src/embeddings/manager.ts +288 -0
  249. package/src/embeddings/provider.ts +311 -0
  250. package/src/embeddings/vector-store.ts +353 -0
  251. package/src/factory.ts +263 -0
  252. package/src/index.ts +246 -0
  253. package/src/learning/analyzer.ts +335 -0
  254. package/src/learning/effectiveness.ts +428 -0
  255. package/src/learning/index.ts +58 -0
  256. package/src/learning/llm-extractor.ts +542 -0
  257. package/src/learning/meta-learner.ts +516 -0
  258. package/src/learning/pipeline.ts +244 -0
  259. package/src/learning/playbook-extractor.ts +702 -0
  260. package/src/learning/usage-inference.ts +372 -0
  261. package/src/mcp/index.ts +12 -0
  262. package/src/mcp/playbook-server.ts +565 -0
  263. package/src/memory/curated-loader.ts +160 -0
  264. package/src/memory/experience.ts +515 -0
  265. package/src/memory/index.ts +27 -0
  266. package/src/memory/meta.ts +506 -0
  267. package/src/memory/playbook.ts +493 -0
  268. package/src/memory/system.ts +551 -0
  269. package/src/runtime/backends/acp.ts +378 -0
  270. package/src/runtime/backends/index.ts +24 -0
  271. package/src/runtime/backends/mock.ts +218 -0
  272. package/src/runtime/backends/subprocess.ts +356 -0
  273. package/src/runtime/flows/learning.ts +183 -0
  274. package/src/runtime/flows/validation.ts +381 -0
  275. package/src/runtime/index.ts +53 -0
  276. package/src/runtime/manager.ts +541 -0
  277. package/src/runtime/types.ts +157 -0
  278. package/src/search/evaluator.ts +474 -0
  279. package/src/search/index.ts +59 -0
  280. package/src/search/refinement-loop.ts +363 -0
  281. package/src/search/refinement-types.ts +159 -0
  282. package/src/search/router.ts +261 -0
  283. package/src/search/solver.ts +303 -0
  284. package/src/search/verification-runner.ts +570 -0
  285. package/src/surfacing/index.ts +6 -0
  286. package/src/surfacing/skill-library.ts +594 -0
  287. package/src/types/config.ts +333 -0
  288. package/src/types/index.ts +130 -0
  289. package/src/types/memory.ts +270 -0
  290. package/src/types/meta.ts +218 -0
  291. package/src/types/outcome.ts +66 -0
  292. package/src/types/playbook.ts +196 -0
  293. package/src/types/step.ts +40 -0
  294. package/src/types/task.ts +52 -0
  295. package/src/types/trajectory.ts +80 -0
  296. package/src/utils/index.ts +38 -0
  297. package/src/utils/similarity.ts +139 -0
  298. package/src/utils/storage.ts +249 -0
  299. package/src/utils/validation.ts +286 -0
  300. package/tests/embeddings/bm25.test.ts +130 -0
  301. package/tests/embeddings/manager.test.ts +205 -0
  302. package/tests/integration/atlas.test.ts +266 -0
  303. package/tests/integration/e2e.test.ts +929 -0
  304. package/tests/learning/analyzer.test.ts +426 -0
  305. package/tests/learning/effectiveness.test.ts +542 -0
  306. package/tests/learning/pipeline.test.ts +176 -0
  307. package/tests/learning/playbook-extractor-provenance.test.ts +114 -0
  308. package/tests/learning/usage-inference.test.ts +254 -0
  309. package/tests/mcp/playbook-server.test.ts +252 -0
  310. package/tests/memory/experience.test.ts +198 -0
  311. package/tests/memory/playbook.test.ts +338 -0
  312. package/tests/memory/provenance.test.ts +639 -0
  313. package/tests/memory/system.test.ts +325 -0
  314. package/tests/runtime/agent-manager.test.ts +512 -0
  315. package/tests/runtime/mock-backend.test.ts +248 -0
  316. package/tests/search/refinement-loop.test.ts +468 -0
  317. package/tests/search/refinement.test.ts +267 -0
  318. package/tests/search/router.test.ts +427 -0
  319. package/tests/surfacing/skill-library.test.ts +292 -0
  320. package/tests/types/outcome.test.ts +147 -0
  321. package/tests/types/step.test.ts +133 -0
  322. package/tests/types/task.test.ts +158 -0
  323. package/tests/types/trajectory.test.ts +253 -0
  324. package/tests/utils/similarity.test.ts +188 -0
  325. package/tests/utils/validation.test.ts +252 -0
  326. package/tsconfig.json +25 -0
  327. package/vitest.config.ts +22 -0
  328. package/dist/index.d.mts +0 -466
  329. package/dist/index.mjs +0 -478
@@ -0,0 +1,542 @@
1
+ /**
2
+ * LLM-Based Playbook Extractor
3
+ *
4
+ * Uses language models to generate higher-quality playbooks
5
+ * from trajectories. Complements the pattern-based extractor
6
+ * with deeper semantic analysis.
7
+ */
8
+
9
+ import type {
10
+ Playbook,
11
+ Trajectory,
12
+ Refinement,
13
+ } from '../types/index.js';
14
+ import { createPlaybook } from '../types/index.js';
15
+ import type { AnalysisResult } from './analyzer.js';
16
+ import type { LLMProvider } from '../agents/types.js';
17
+
18
+ /**
19
+ * Configuration for LLM-based extraction
20
+ */
21
+ export interface LLMExtractorConfig {
22
+ /** Temperature for LLM calls (default: 0.2 for determinism) */
23
+ temperature: number;
24
+ /** Maximum tokens for response */
25
+ maxTokens: number;
26
+ /** Whether to extract from single trajectories (vs only batches) */
27
+ extractFromSingle: boolean;
28
+ /** Minimum complexity for LLM extraction */
29
+ minComplexity: number;
30
+ }
31
+
32
+ const DEFAULT_CONFIG: LLMExtractorConfig = {
33
+ temperature: 0.2,
34
+ maxTokens: 2000,
35
+ extractFromSingle: true,
36
+ minComplexity: 3, // Minimum steps to warrant LLM extraction
37
+ };
38
+
39
+ /**
40
+ * Result from LLM extraction
41
+ */
42
+ export interface LLMExtractionResult {
43
+ playbooks: Playbook[];
44
+ refinements: Array<{
45
+ playbookId: string;
46
+ refinement: Refinement;
47
+ }>;
48
+ /** Raw LLM response for debugging */
49
+ rawResponse?: string;
50
+ }
51
+
52
+ /**
53
+ * LLM-Based Playbook Extractor
54
+ */
55
+ export class LLMPlaybookExtractor {
56
+ private provider: LLMProvider;
57
+ private config: LLMExtractorConfig;
58
+
59
+ constructor(provider: LLMProvider, config?: Partial<LLMExtractorConfig>) {
60
+ this.provider = provider;
61
+ this.config = { ...DEFAULT_CONFIG, ...config };
62
+ }
63
+
64
+ /**
65
+ * Extract playbooks from trajectories using LLM
66
+ */
67
+ async extract(
68
+ trajectories: Trajectory[],
69
+ analyses: AnalysisResult[],
70
+ existingPlaybooks: Playbook[] = []
71
+ ): Promise<LLMExtractionResult> {
72
+ // Filter to successful, complex enough trajectories
73
+ const candidates = trajectories.filter((t, i) => {
74
+ const analysis = analyses[i];
75
+ return (
76
+ analysis?.success &&
77
+ analysis.abstractable &&
78
+ t.steps.length >= this.config.minComplexity
79
+ );
80
+ });
81
+
82
+ if (candidates.length === 0) {
83
+ return { playbooks: [], refinements: [] };
84
+ }
85
+
86
+ // Extract playbooks from each candidate
87
+ const allResults: LLMExtractionResult = {
88
+ playbooks: [],
89
+ refinements: [],
90
+ };
91
+
92
+ // Process individually for better quality
93
+ if (this.config.extractFromSingle) {
94
+ for (let i = 0; i < candidates.length; i++) {
95
+ const trajectory = candidates[i];
96
+ const analysis = analyses.find(
97
+ (_, idx) => trajectories[idx] === trajectory
98
+ );
99
+
100
+ if (!analysis) continue;
101
+
102
+ const result = await this.extractFromSingleTrajectory(
103
+ trajectory,
104
+ analysis,
105
+ existingPlaybooks
106
+ );
107
+
108
+ allResults.playbooks.push(...result.playbooks);
109
+ allResults.refinements.push(...result.refinements);
110
+ }
111
+ }
112
+
113
+ // Also do batch extraction if we have multiple
114
+ if (candidates.length >= 2) {
115
+ const batchResult = await this.extractFromBatch(
116
+ candidates,
117
+ analyses.filter((_, i) => candidates.includes(trajectories[i])),
118
+ existingPlaybooks
119
+ );
120
+
121
+ // Merge with individual results (avoid duplicates)
122
+ for (const playbook of batchResult.playbooks) {
123
+ const isDuplicate = allResults.playbooks.some(
124
+ (p) => this.isSimilarPlaybook(p, playbook)
125
+ );
126
+ if (!isDuplicate) {
127
+ allResults.playbooks.push(playbook);
128
+ }
129
+ }
130
+
131
+ allResults.refinements.push(...batchResult.refinements);
132
+ }
133
+
134
+ return allResults;
135
+ }
136
+
137
+ /**
138
+ * Extract a playbook from a single trajectory
139
+ */
140
+ private async extractFromSingleTrajectory(
141
+ trajectory: Trajectory,
142
+ analysis: AnalysisResult,
143
+ existingPlaybooks: Playbook[]
144
+ ): Promise<LLMExtractionResult> {
145
+ const prompt = this.buildSingleExtractionPrompt(
146
+ trajectory,
147
+ analysis,
148
+ existingPlaybooks
149
+ );
150
+
151
+ const response = await this.provider.complete(
152
+ [{ role: 'user', content: prompt }],
153
+ {
154
+ temperature: this.config.temperature,
155
+ maxTokens: this.config.maxTokens,
156
+ }
157
+ );
158
+
159
+ return this.parseExtractionResponse(response, trajectory);
160
+ }
161
+
162
+ /**
163
+ * Extract playbooks from a batch of trajectories
164
+ */
165
+ private async extractFromBatch(
166
+ trajectories: Trajectory[],
167
+ analyses: AnalysisResult[],
168
+ existingPlaybooks: Playbook[]
169
+ ): Promise<LLMExtractionResult> {
170
+ const prompt = this.buildBatchExtractionPrompt(
171
+ trajectories,
172
+ analyses,
173
+ existingPlaybooks
174
+ );
175
+
176
+ const response = await this.provider.complete(
177
+ [{ role: 'user', content: prompt }],
178
+ {
179
+ temperature: this.config.temperature,
180
+ maxTokens: this.config.maxTokens * 2,
181
+ }
182
+ );
183
+
184
+ return this.parseExtractionResponse(response);
185
+ }
186
+
187
+ /**
188
+ * Build prompt for single trajectory extraction
189
+ */
190
+ private buildSingleExtractionPrompt(
191
+ trajectory: Trajectory,
192
+ analysis: AnalysisResult,
193
+ existingPlaybooks: Playbook[]
194
+ ): string {
195
+ const keyStepsDesc = analysis.keySteps
196
+ .map((idx) => {
197
+ const step = trajectory.steps[idx];
198
+ return step
199
+ ? ` - Step ${idx + 1}: ${step.action}${step.thought ? ` (reasoning: ${step.thought})` : ''}`
200
+ : '';
201
+ })
202
+ .filter(Boolean)
203
+ .join('\n');
204
+
205
+ const existingPlaybookNames = existingPlaybooks
206
+ .map((p) => `- ${p.name}: ${p.guidance.strategy.slice(0, 100)}`)
207
+ .slice(0, 5)
208
+ .join('\n');
209
+
210
+ return `Analyze this successful problem-solving trajectory and extract a reusable playbook.
211
+
212
+ ## Task
213
+ ${trajectory.task.description}
214
+ Domain: ${trajectory.task.domain}
215
+
216
+ ## Solution Steps
217
+ ${trajectory.steps.map((s, i) => `${i + 1}. ${s.action}${s.observation ? `\n Observation: ${s.observation.slice(0, 100)}` : ''}`).join('\n')}
218
+
219
+ ## Key Steps (most important for success)
220
+ ${keyStepsDesc}
221
+
222
+ ## Outcome
223
+ ${trajectory.outcome.success ? 'SUCCESS' : 'FAILURE'}: ${trajectory.outcome.solution ?? trajectory.outcome.errorInfo ?? 'No details'}
224
+
225
+ ${existingPlaybooks.length > 0 ? `## Existing Playbooks (avoid duplicates)
226
+ ${existingPlaybookNames}` : ''}
227
+
228
+ ## Instructions
229
+ Extract a reusable playbook that captures the essential approach. Focus on:
230
+ 1. What situations trigger this approach
231
+ 2. The core strategy/pattern used
232
+ 3. Key tactical steps
233
+ 4. Success/failure indicators
234
+
235
+ Respond in JSON format:
236
+ {
237
+ "playbook": {
238
+ "name": "kebab-case-name",
239
+ "situations": ["when X happens", "for Y type problems"],
240
+ "triggers": ["error messages", "signals that trigger this"],
241
+ "antiPatterns": ["when NOT to use this"],
242
+ "strategy": "High-level approach description",
243
+ "tactics": ["specific technique 1", "specific technique 2"],
244
+ "steps": ["step 1", "step 2", "step 3"],
245
+ "successIndicators": ["how to know it worked"],
246
+ "failureIndicators": ["how to know it failed"],
247
+ "complexity": "simple|moderate|complex",
248
+ "estimatedEffort": 5
249
+ },
250
+ "isRefinementOf": null
251
+ }
252
+
253
+ If this is better suited as a refinement to an existing playbook, set isRefinementOf to the playbook name and include only the refinement details.`;
254
+ }
255
+
256
+ /**
257
+ * Build prompt for batch extraction
258
+ */
259
+ private buildBatchExtractionPrompt(
260
+ trajectories: Trajectory[],
261
+ analyses: AnalysisResult[],
262
+ existingPlaybooks: Playbook[]
263
+ ): string {
264
+ const trajectorySummaries = trajectories
265
+ .map((t, i) => {
266
+ const analysis = analyses[i];
267
+ const keySteps = analysis?.keySteps ?? [];
268
+ return `### Trajectory ${i + 1}
269
+ Task: ${t.task.description}
270
+ Domain: ${t.task.domain}
271
+ Steps: ${t.steps.length}
272
+ Key steps: ${keySteps.map((idx) => t.steps[idx]?.action ?? '').join(' → ')}
273
+ Outcome: ${t.outcome.success ? 'SUCCESS' : 'FAILURE'}`;
274
+ })
275
+ .join('\n\n');
276
+
277
+ const existingPlaybookNames = existingPlaybooks
278
+ .map((p) => `- ${p.name}`)
279
+ .slice(0, 10)
280
+ .join('\n');
281
+
282
+ return `Analyze these successful trajectories and identify common patterns that can be extracted as reusable playbooks.
283
+
284
+ ## Trajectories
285
+ ${trajectorySummaries}
286
+
287
+ ${existingPlaybooks.length > 0 ? `## Existing Playbooks (avoid duplicates)
288
+ ${existingPlaybookNames}` : ''}
289
+
290
+ ## Instructions
291
+ Identify patterns that appear across multiple trajectories and extract them as playbooks.
292
+ Focus on generalizable approaches, not task-specific details.
293
+
294
+ Respond in JSON format:
295
+ {
296
+ "playbooks": [
297
+ {
298
+ "name": "kebab-case-name",
299
+ "situations": ["when X happens"],
300
+ "triggers": [],
301
+ "antiPatterns": [],
302
+ "strategy": "Description",
303
+ "tactics": ["technique 1"],
304
+ "steps": ["step 1", "step 2"],
305
+ "successIndicators": ["indicator"],
306
+ "failureIndicators": ["indicator"],
307
+ "complexity": "simple|moderate|complex",
308
+ "estimatedEffort": 5,
309
+ "sourceTrajectories": [1, 2]
310
+ }
311
+ ]
312
+ }`;
313
+ }
314
+
315
+ /**
316
+ * Parse LLM response into extraction result
317
+ */
318
+ private parseExtractionResponse(
319
+ response: string,
320
+ sourceTrajectory?: Trajectory
321
+ ): LLMExtractionResult {
322
+ const result: LLMExtractionResult = {
323
+ playbooks: [],
324
+ refinements: [],
325
+ rawResponse: response,
326
+ };
327
+
328
+ try {
329
+ // Extract JSON from response
330
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
331
+ if (!jsonMatch) {
332
+ return result;
333
+ }
334
+
335
+ const parsed = JSON.parse(jsonMatch[0]) as {
336
+ playbook?: LLMPlaybookData;
337
+ playbooks?: LLMPlaybookData[];
338
+ isRefinementOf?: string | null;
339
+ };
340
+
341
+ // Handle single playbook response
342
+ if (parsed.playbook && !parsed.isRefinementOf) {
343
+ const playbook = this.createPlaybookFromLLMData(
344
+ parsed.playbook,
345
+ sourceTrajectory
346
+ );
347
+ result.playbooks.push(playbook);
348
+ }
349
+
350
+ // Handle refinement response
351
+ if (parsed.playbook && parsed.isRefinementOf) {
352
+ result.refinements.push({
353
+ playbookId: parsed.isRefinementOf,
354
+ refinement: {
355
+ context: parsed.playbook.situations?.[0] ?? 'General refinement',
356
+ addition: parsed.playbook.strategy ?? '',
357
+ source: 'success',
358
+ addedAt: new Date(),
359
+ },
360
+ });
361
+ }
362
+
363
+ // Handle batch response
364
+ if (parsed.playbooks && Array.isArray(parsed.playbooks)) {
365
+ for (const pbData of parsed.playbooks) {
366
+ const playbook = this.createPlaybookFromLLMData(pbData);
367
+ result.playbooks.push(playbook);
368
+ }
369
+ }
370
+ } catch (error) {
371
+ // JSON parsing failed, return empty result
372
+ console.warn(
373
+ 'Failed to parse LLM extraction response:',
374
+ error instanceof Error ? error.message : error
375
+ );
376
+ }
377
+
378
+ return result;
379
+ }
380
+
381
+ /**
382
+ * Create a Playbook from LLM-extracted data
383
+ */
384
+ private createPlaybookFromLLMData(
385
+ data: LLMPlaybookData,
386
+ sourceTrajectory?: Trajectory
387
+ ): Playbook {
388
+ const domain = sourceTrajectory?.task.domain ?? 'general';
389
+ const sourceIds = sourceTrajectory ? [sourceTrajectory.id] : [];
390
+
391
+ return createPlaybook({
392
+ name: data.name ?? `llm-extracted-${Date.now()}`,
393
+ applicability: {
394
+ situations: data.situations ?? [],
395
+ triggers: data.triggers ?? [],
396
+ antiPatterns: data.antiPatterns ?? [],
397
+ domains: [domain],
398
+ },
399
+ guidance: {
400
+ strategy: data.strategy ?? '',
401
+ tactics: data.tactics ?? [],
402
+ steps: data.steps ?? [],
403
+ },
404
+ verification: {
405
+ successIndicators: data.successIndicators ?? [],
406
+ failureIndicators: data.failureIndicators ?? [],
407
+ },
408
+ evolution: {
409
+ version: '1.0.0',
410
+ createdFrom: sourceIds,
411
+ failures: [],
412
+ refinements: [],
413
+ successCount: 1,
414
+ failureCount: 0,
415
+ },
416
+ confidence: 0.6, // Start with moderate confidence for LLM-extracted
417
+ complexity: this.parseComplexity(data.complexity),
418
+ estimatedEffort: data.estimatedEffort ?? 5,
419
+ });
420
+ }
421
+
422
+ /**
423
+ * Parse complexity string
424
+ */
425
+ private parseComplexity(
426
+ complexity?: string
427
+ ): 'simple' | 'moderate' | 'complex' {
428
+ const normalized = complexity?.toLowerCase();
429
+ if (normalized === 'simple') return 'simple';
430
+ if (normalized === 'complex') return 'complex';
431
+ return 'moderate';
432
+ }
433
+
434
+ /**
435
+ * Check if two playbooks are similar
436
+ */
437
+ private isSimilarPlaybook(a: Playbook, b: Playbook): boolean {
438
+ // Simple name-based check
439
+ if (a.name === b.name) return true;
440
+
441
+ // Check situation overlap
442
+ const aSituations = new Set(a.applicability.situations);
443
+ const bSituations = b.applicability.situations;
444
+ const overlap = bSituations.filter((s) => aSituations.has(s)).length;
445
+
446
+ return overlap >= Math.min(aSituations.size, bSituations.length) * 0.8;
447
+ }
448
+
449
+ /**
450
+ * Generate a refinement for an existing playbook based on a new trajectory
451
+ */
452
+ async generateRefinement(
453
+ playbook: Playbook,
454
+ trajectory: Trajectory,
455
+ context: string
456
+ ): Promise<Refinement> {
457
+ const prompt = `Given this existing playbook and a new trajectory, generate a refinement.
458
+
459
+ ## Existing Playbook: ${playbook.name}
460
+ Strategy: ${playbook.guidance.strategy}
461
+ Steps: ${playbook.guidance.steps?.join(' → ') ?? 'None'}
462
+
463
+ ## New Trajectory
464
+ Task: ${trajectory.task.description}
465
+ Steps taken: ${trajectory.steps.map((s) => s.action).join(' → ')}
466
+ Outcome: ${trajectory.outcome.success ? 'SUCCESS' : 'FAILURE'}
467
+
468
+ ## Context
469
+ ${context}
470
+
471
+ ## Instructions
472
+ Generate a refinement that captures what's new or different in this trajectory.
473
+
474
+ Respond in JSON:
475
+ {
476
+ "context": "when/where this refinement applies",
477
+ "addition": "what to add/change in the approach"
478
+ }`;
479
+
480
+ const response = await this.provider.complete(
481
+ [{ role: 'user', content: prompt }],
482
+ {
483
+ temperature: this.config.temperature,
484
+ maxTokens: 500,
485
+ }
486
+ );
487
+
488
+ try {
489
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
490
+ if (jsonMatch) {
491
+ const parsed = JSON.parse(jsonMatch[0]) as {
492
+ context?: string;
493
+ addition?: string;
494
+ };
495
+
496
+ return {
497
+ context: parsed.context ?? context,
498
+ addition: parsed.addition ?? '',
499
+ source: trajectory.outcome.success ? 'success' : 'failure',
500
+ addedAt: new Date(),
501
+ };
502
+ }
503
+ } catch {
504
+ // Fall back to simple refinement
505
+ }
506
+
507
+ return {
508
+ context,
509
+ addition: `Additional approach from trajectory: ${trajectory.steps[0]?.action ?? ''}`,
510
+ source: trajectory.outcome.success ? 'success' : 'failure',
511
+ addedAt: new Date(),
512
+ };
513
+ }
514
+ }
515
+
516
+ /**
517
+ * Internal type for LLM-extracted playbook data
518
+ */
519
+ interface LLMPlaybookData {
520
+ name?: string;
521
+ situations?: string[];
522
+ triggers?: string[];
523
+ antiPatterns?: string[];
524
+ strategy?: string;
525
+ tactics?: string[];
526
+ steps?: string[];
527
+ successIndicators?: string[];
528
+ failureIndicators?: string[];
529
+ complexity?: string;
530
+ estimatedEffort?: number;
531
+ sourceTrajectories?: number[];
532
+ }
533
+
534
+ /**
535
+ * Create an LLM-based playbook extractor
536
+ */
537
+ export function createLLMExtractor(
538
+ provider: LLMProvider,
539
+ config?: Partial<LLMExtractorConfig>
540
+ ): LLMPlaybookExtractor {
541
+ return new LLMPlaybookExtractor(provider, config);
542
+ }