@directive-run/knowledge 0.2.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 (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +63 -0
  3. package/ai/ai-adapters.md +250 -0
  4. package/ai/ai-agents-streaming.md +269 -0
  5. package/ai/ai-budget-resilience.md +235 -0
  6. package/ai/ai-communication.md +281 -0
  7. package/ai/ai-debug-observability.md +243 -0
  8. package/ai/ai-guardrails-memory.md +332 -0
  9. package/ai/ai-mcp-rag.md +288 -0
  10. package/ai/ai-multi-agent.md +274 -0
  11. package/ai/ai-orchestrator.md +227 -0
  12. package/ai/ai-security.md +293 -0
  13. package/ai/ai-tasks.md +261 -0
  14. package/ai/ai-testing-evals.md +378 -0
  15. package/api-skeleton.md +5 -0
  16. package/core/anti-patterns.md +382 -0
  17. package/core/constraints.md +263 -0
  18. package/core/core-patterns.md +228 -0
  19. package/core/error-boundaries.md +322 -0
  20. package/core/multi-module.md +315 -0
  21. package/core/naming.md +283 -0
  22. package/core/plugins.md +344 -0
  23. package/core/react-adapter.md +262 -0
  24. package/core/resolvers.md +357 -0
  25. package/core/schema-types.md +262 -0
  26. package/core/system-api.md +271 -0
  27. package/core/testing.md +257 -0
  28. package/core/time-travel.md +238 -0
  29. package/dist/index.cjs +111 -0
  30. package/dist/index.cjs.map +1 -0
  31. package/dist/index.d.cts +10 -0
  32. package/dist/index.d.ts +10 -0
  33. package/dist/index.js +102 -0
  34. package/dist/index.js.map +1 -0
  35. package/examples/ab-testing.ts +385 -0
  36. package/examples/ai-checkpoint.ts +509 -0
  37. package/examples/ai-guardrails.ts +319 -0
  38. package/examples/ai-orchestrator.ts +589 -0
  39. package/examples/async-chains.ts +287 -0
  40. package/examples/auth-flow.ts +371 -0
  41. package/examples/batch-resolver.ts +341 -0
  42. package/examples/checkers.ts +589 -0
  43. package/examples/contact-form.ts +176 -0
  44. package/examples/counter.ts +393 -0
  45. package/examples/dashboard-loader.ts +512 -0
  46. package/examples/debounce-constraints.ts +105 -0
  47. package/examples/dynamic-modules.ts +293 -0
  48. package/examples/error-boundaries.ts +430 -0
  49. package/examples/feature-flags.ts +220 -0
  50. package/examples/form-wizard.ts +347 -0
  51. package/examples/fraud-analysis.ts +663 -0
  52. package/examples/goal-heist.ts +341 -0
  53. package/examples/multi-module.ts +57 -0
  54. package/examples/newsletter.ts +241 -0
  55. package/examples/notifications.ts +210 -0
  56. package/examples/optimistic-updates.ts +317 -0
  57. package/examples/pagination.ts +260 -0
  58. package/examples/permissions.ts +337 -0
  59. package/examples/provider-routing.ts +403 -0
  60. package/examples/server.ts +316 -0
  61. package/examples/shopping-cart.ts +422 -0
  62. package/examples/sudoku.ts +630 -0
  63. package/examples/theme-locale.ts +204 -0
  64. package/examples/time-machine.ts +225 -0
  65. package/examples/topic-guard.ts +306 -0
  66. package/examples/url-sync.ts +333 -0
  67. package/examples/websocket.ts +404 -0
  68. package/package.json +65 -0
@@ -0,0 +1,238 @@
1
+ # Time-Travel Debugging
2
+
3
+ Directive can record every fact change as a snapshot, enabling undo/redo, replay, and state export for bug reports.
4
+
5
+ ## Decision Tree: "Should I enable time-travel?"
6
+
7
+ ```
8
+ What's the use case?
9
+ ├── Debugging during development → Yes, enable with maxSnapshots cap
10
+ ├── Production app → No, disable for performance
11
+ ├── Bug reproduction → Enable, use exportHistory() to share
12
+ ├── Testing → Usually no — use assertFact/assertDerivation instead
13
+ └── Demo / presentation → Yes, great for showing state changes
14
+ ```
15
+
16
+ ## Enabling Time-Travel
17
+
18
+ ```typescript
19
+ import { createSystem } from "@directive-run/core";
20
+
21
+ const system = createSystem({
22
+ module: myModule,
23
+ debug: {
24
+ timeTravel: true, // Enable snapshot recording
25
+ maxSnapshots: 100, // Cap memory usage (default: 50)
26
+ },
27
+ });
28
+ ```
29
+
30
+ Time-travel is disabled by default. Snapshots are recorded automatically on every fact mutation.
31
+
32
+ ## The TimeTravelAPI
33
+
34
+ Access via `system.debug.timeTravel`:
35
+
36
+ ```typescript
37
+ const tt = system.debug.timeTravel;
38
+
39
+ // Navigation
40
+ tt.canUndo(); // boolean — is there a previous snapshot?
41
+ tt.canRedo(); // boolean — is there a next snapshot?
42
+ tt.undo(); // Restore previous snapshot
43
+ tt.redo(); // Restore next snapshot
44
+
45
+ // Direct access
46
+ tt.getSnapshots(); // Array of all snapshots
47
+ tt.goToSnapshot(index); // Jump to a specific snapshot by index
48
+
49
+ // Each snapshot contains:
50
+ // {
51
+ // facts: { ... }, — full fact state at that point
52
+ // timestamp: number, — when the snapshot was taken
53
+ // label?: string, — optional label from changeset
54
+ // changedKeys: string[], — which facts changed
55
+ // }
56
+ ```
57
+
58
+ ## Undo/Redo Pattern
59
+
60
+ ```typescript
61
+ const system = createSystem({
62
+ module: editorModule,
63
+ debug: { timeTravel: true, maxSnapshots: 200 },
64
+ });
65
+
66
+ system.start();
67
+
68
+ // User makes changes
69
+ system.facts.text = "Hello";
70
+ system.facts.text = "Hello, world";
71
+ system.facts.text = "Hello, world!";
72
+
73
+ // Undo last change
74
+ const tt = system.debug.timeTravel;
75
+ tt.undo();
76
+ console.log(system.facts.text); // "Hello, world"
77
+
78
+ tt.undo();
79
+ console.log(system.facts.text); // "Hello"
80
+
81
+ // Redo
82
+ tt.redo();
83
+ console.log(system.facts.text); // "Hello, world"
84
+
85
+ // Check navigation state
86
+ tt.canUndo(); // true
87
+ tt.canRedo(); // true
88
+ ```
89
+
90
+ ## Changesets: Grouping Related Changes
91
+
92
+ Multiple fact mutations can be grouped into a single undoable unit.
93
+
94
+ ```typescript
95
+ const tt = system.debug.timeTravel;
96
+
97
+ // Without changeset — each mutation is a separate snapshot
98
+ system.facts.firstName = "Alice";
99
+ system.facts.lastName = "Smith";
100
+ // Two snapshots, two undos needed
101
+
102
+ // With changeset — grouped into one snapshot
103
+ tt.beginChangeset("Update user name");
104
+ system.facts.firstName = "Alice";
105
+ system.facts.lastName = "Smith";
106
+ tt.endChangeset();
107
+ // One snapshot, one undo restores both
108
+
109
+ // Undo reverts the entire changeset
110
+ tt.undo();
111
+ // Both firstName and lastName are restored
112
+ ```
113
+
114
+ Use changesets for logically related mutations: form submissions, multi-field updates, resolver results.
115
+
116
+ ## Exporting and Importing History
117
+
118
+ Serialize the full snapshot history for bug reports or debugging.
119
+
120
+ ```typescript
121
+ const tt = system.debug.timeTravel;
122
+
123
+ // Export — returns a serializable object
124
+ const historyData = tt.exportHistory();
125
+ // Send to server, save to file, attach to bug report
126
+ console.log(JSON.stringify(historyData));
127
+
128
+ // Import — restore history from exported data
129
+ tt.importHistory(historyData);
130
+
131
+ // Now you can step through the user's exact state sequence
132
+ tt.goToSnapshot(0); // Start
133
+ tt.goToSnapshot(5); // When the bug occurred
134
+ ```
135
+
136
+ ## Snapshot Inspection
137
+
138
+ ```typescript
139
+ const tt = system.debug.timeTravel;
140
+ const snapshots = tt.getSnapshots();
141
+
142
+ // Walk through all snapshots
143
+ for (const snap of snapshots) {
144
+ console.log(`[${new Date(snap.timestamp).toISOString()}]`);
145
+ console.log(` Changed: ${snap.changedKeys.join(", ")}`);
146
+ if (snap.label) {
147
+ console.log(` Label: ${snap.label}`);
148
+ }
149
+ console.log(` Facts:`, snap.facts);
150
+ }
151
+
152
+ // Jump to a specific point
153
+ tt.goToSnapshot(3);
154
+ console.log(system.facts); // State as of snapshot 3
155
+ ```
156
+
157
+ ## Performance: maxSnapshots
158
+
159
+ Every fact mutation creates a snapshot. Cap the number to control memory:
160
+
161
+ ```typescript
162
+ // Low memory — keeps last 20 snapshots, discards oldest
163
+ debug: { timeTravel: true, maxSnapshots: 20 },
164
+
165
+ // Development — generous cap for deep debugging
166
+ debug: { timeTravel: true, maxSnapshots: 500 },
167
+
168
+ // Default if not specified
169
+ debug: { timeTravel: true }, // maxSnapshots defaults to 50
170
+ ```
171
+
172
+ When the cap is reached, the oldest snapshot is discarded (FIFO). Redo history beyond the cap is lost.
173
+
174
+ ## Common Mistakes
175
+
176
+ ### Enabling time-travel in production
177
+
178
+ ```typescript
179
+ // WRONG — snapshots consume memory on every mutation
180
+ const system = createSystem({
181
+ module: myModule,
182
+ debug: { timeTravel: true },
183
+ });
184
+
185
+ // CORRECT — gate on environment
186
+ const system = createSystem({
187
+ module: myModule,
188
+ debug: {
189
+ timeTravel: process.env.NODE_ENV === "development",
190
+ maxSnapshots: 100,
191
+ },
192
+ });
193
+ ```
194
+
195
+ ### Forgetting to end a changeset
196
+
197
+ ```typescript
198
+ // WRONG — changeset never closed, all subsequent mutations are grouped
199
+ tt.beginChangeset("update");
200
+ system.facts.name = "Alice";
201
+ // ... forgot endChangeset()
202
+ system.facts.unrelated = true; // Still part of the changeset!
203
+
204
+ // CORRECT — always close changesets
205
+ tt.beginChangeset("update");
206
+ system.facts.name = "Alice";
207
+ tt.endChangeset();
208
+ ```
209
+
210
+ ### Accessing time-travel when disabled
211
+
212
+ ```typescript
213
+ // WRONG — timeTravel not enabled, system.debug.timeTravel is null
214
+ const system = createSystem({ module: myModule });
215
+ system.debug.timeTravel.undo(); // TypeError!
216
+
217
+ // CORRECT — check before using
218
+ const tt = system.debug.timeTravel;
219
+ if (tt) {
220
+ tt.undo();
221
+ }
222
+
223
+ // Or enable it
224
+ const system = createSystem({
225
+ module: myModule,
226
+ debug: { timeTravel: true },
227
+ });
228
+ ```
229
+
230
+ ### No maxSnapshots cap with frequent mutations
231
+
232
+ ```typescript
233
+ // WRONG — unbounded snapshots in a high-frequency update loop
234
+ debug: { timeTravel: true }, // Default cap is 50, which is fine
235
+
236
+ // Be explicit when mutation rate is high
237
+ debug: { timeTravel: true, maxSnapshots: 30 },
238
+ ```
package/dist/index.cjs ADDED
@@ -0,0 +1,111 @@
1
+ 'use strict';
2
+
3
+ var fs = require('fs');
4
+ var path = require('path');
5
+ var url = require('url');
6
+
7
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
8
+ // src/index.ts
9
+ var __dirname$1 = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));
10
+ var PKG_ROOT = path.resolve(__dirname$1, "..");
11
+ function resolveAsset(name) {
12
+ const fromDist = path.join(PKG_ROOT, name);
13
+ if (fs.existsSync(fromDist)) {
14
+ return fromDist;
15
+ }
16
+ const fromSrc = path.join(PKG_ROOT, "..", name);
17
+ if (fs.existsSync(fromSrc)) {
18
+ return fromSrc;
19
+ }
20
+ return fromDist;
21
+ }
22
+ var CORE_DIR = resolveAsset("core");
23
+ var AI_DIR = resolveAsset("ai");
24
+ var EXAMPLES_DIR = resolveAsset("examples");
25
+ var API_SKELETON_PATH = resolveAsset("api-skeleton.md");
26
+ var knowledgeCache = null;
27
+ var exampleCache = null;
28
+ function loadDir(dir, map) {
29
+ try {
30
+ const files = fs.readdirSync(dir).filter(
31
+ (f) => f.endsWith(".md") || f.endsWith(".ts")
32
+ );
33
+ for (const file of files) {
34
+ const name = file.replace(/\.(md|ts)$/, "");
35
+ map.set(name, fs.readFileSync(path.join(dir, file), "utf-8"));
36
+ }
37
+ } catch (err) {
38
+ if (err.code !== "ENOENT") {
39
+ throw err;
40
+ }
41
+ }
42
+ }
43
+ function loadAllKnowledge() {
44
+ const map = /* @__PURE__ */ new Map();
45
+ loadDir(CORE_DIR, map);
46
+ loadDir(AI_DIR, map);
47
+ try {
48
+ map.set("api-skeleton", fs.readFileSync(API_SKELETON_PATH, "utf-8"));
49
+ } catch {
50
+ }
51
+ return map;
52
+ }
53
+ function loadAllExamples() {
54
+ const map = /* @__PURE__ */ new Map();
55
+ loadDir(EXAMPLES_DIR, map);
56
+ return map;
57
+ }
58
+ function getKnowledge(name) {
59
+ if (!knowledgeCache) {
60
+ knowledgeCache = loadAllKnowledge();
61
+ }
62
+ return knowledgeCache.get(name) ?? "";
63
+ }
64
+ function getAllKnowledge() {
65
+ if (!knowledgeCache) {
66
+ knowledgeCache = loadAllKnowledge();
67
+ }
68
+ return knowledgeCache;
69
+ }
70
+ function getExample(name) {
71
+ if (!exampleCache) {
72
+ exampleCache = loadAllExamples();
73
+ }
74
+ return exampleCache.get(name) ?? "";
75
+ }
76
+ function getAllExamples() {
77
+ if (!exampleCache) {
78
+ exampleCache = loadAllExamples();
79
+ }
80
+ return exampleCache;
81
+ }
82
+ function getKnowledgeFiles(names) {
83
+ return names.map((name) => getKnowledge(name)).filter(Boolean).join("\n\n---\n\n");
84
+ }
85
+ function getExampleFiles(names) {
86
+ return names.map((name) => {
87
+ const content = getExample(name);
88
+ if (!content) {
89
+ return "";
90
+ }
91
+ return `### Example: ${name}
92
+
93
+ \`\`\`typescript
94
+ ${content}
95
+ \`\`\``;
96
+ }).filter(Boolean).join("\n\n");
97
+ }
98
+ function clearCache() {
99
+ knowledgeCache = null;
100
+ exampleCache = null;
101
+ }
102
+
103
+ exports.clearCache = clearCache;
104
+ exports.getAllExamples = getAllExamples;
105
+ exports.getAllKnowledge = getAllKnowledge;
106
+ exports.getExample = getExample;
107
+ exports.getExampleFiles = getExampleFiles;
108
+ exports.getKnowledge = getKnowledge;
109
+ exports.getKnowledgeFiles = getKnowledgeFiles;
110
+ //# sourceMappingURL=index.cjs.map
111
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":["__dirname","dirname","fileURLToPath","resolve","join","existsSync","readdirSync","readFileSync"],"mappings":"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","file":"index.cjs","sourcesContent":["import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n// Resolve package root: works both in src/ (dev) and dist/ (bundled)\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\n/**\n * Resolve a path relative to the package root.\n * Tries dist-relative first (bundled), then src-relative (dev).\n */\nfunction resolveAsset(name: string): string {\n const fromDist = join(PKG_ROOT, name);\n if (existsSync(fromDist)) {\n return fromDist;\n }\n\n const fromSrc = join(PKG_ROOT, \"..\", name);\n if (existsSync(fromSrc)) {\n return fromSrc;\n }\n\n return fromDist; // default, will just return empty maps\n}\n\nconst CORE_DIR = resolveAsset(\"core\");\nconst AI_DIR = resolveAsset(\"ai\");\nconst EXAMPLES_DIR = resolveAsset(\"examples\");\nconst API_SKELETON_PATH = resolveAsset(\"api-skeleton.md\");\n\nlet knowledgeCache: Map<string, string> | null = null;\nlet exampleCache: Map<string, string> | null = null;\n\nfunction loadDir(dir: string, map: Map<string, string>): void {\n try {\n const files = readdirSync(dir).filter(\n (f) => f.endsWith(\".md\") || f.endsWith(\".ts\"),\n );\n for (const file of files) {\n const name = file.replace(/\\.(md|ts)$/, \"\");\n map.set(name, readFileSync(join(dir, file), \"utf-8\"));\n }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n // directory does not exist — expected during tests or incomplete installs\n }\n}\n\nfunction loadAllKnowledge(): Map<string, string> {\n const map = new Map<string, string>();\n loadDir(CORE_DIR, map);\n loadDir(AI_DIR, map);\n\n // Include api-skeleton\n try {\n map.set(\"api-skeleton\", readFileSync(API_SKELETON_PATH, \"utf-8\"));\n } catch {\n // may not exist yet\n }\n\n return map;\n}\n\nfunction loadAllExamples(): Map<string, string> {\n const map = new Map<string, string>();\n loadDir(EXAMPLES_DIR, map);\n\n return map;\n}\n\nexport function getKnowledge(name: string): string {\n if (!knowledgeCache) {\n knowledgeCache = loadAllKnowledge();\n }\n\n return knowledgeCache.get(name) ?? \"\";\n}\n\nexport function getAllKnowledge(): ReadonlyMap<string, string> {\n if (!knowledgeCache) {\n knowledgeCache = loadAllKnowledge();\n }\n\n return knowledgeCache;\n}\n\nexport function getExample(name: string): string {\n if (!exampleCache) {\n exampleCache = loadAllExamples();\n }\n\n return exampleCache.get(name) ?? \"\";\n}\n\nexport function getAllExamples(): ReadonlyMap<string, string> {\n if (!exampleCache) {\n exampleCache = loadAllExamples();\n }\n\n return exampleCache;\n}\n\nexport function getKnowledgeFiles(names: string[]): string {\n return names\n .map((name) => getKnowledge(name))\n .filter(Boolean)\n .join(\"\\n\\n---\\n\\n\");\n}\n\nexport function getExampleFiles(names: string[]): string {\n return names\n .map((name) => {\n const content = getExample(name);\n if (!content) {\n return \"\";\n }\n\n return `### Example: ${name}\\n\\n\\`\\`\\`typescript\\n${content}\\n\\`\\`\\``;\n })\n .filter(Boolean)\n .join(\"\\n\\n\");\n}\n\n/** Clear cached knowledge and examples. Useful for dev/watch mode. */\nexport function clearCache(): void {\n knowledgeCache = null;\n exampleCache = null;\n}\n"]}
@@ -0,0 +1,10 @@
1
+ declare function getKnowledge(name: string): string;
2
+ declare function getAllKnowledge(): ReadonlyMap<string, string>;
3
+ declare function getExample(name: string): string;
4
+ declare function getAllExamples(): ReadonlyMap<string, string>;
5
+ declare function getKnowledgeFiles(names: string[]): string;
6
+ declare function getExampleFiles(names: string[]): string;
7
+ /** Clear cached knowledge and examples. Useful for dev/watch mode. */
8
+ declare function clearCache(): void;
9
+
10
+ export { clearCache, getAllExamples, getAllKnowledge, getExample, getExampleFiles, getKnowledge, getKnowledgeFiles };
@@ -0,0 +1,10 @@
1
+ declare function getKnowledge(name: string): string;
2
+ declare function getAllKnowledge(): ReadonlyMap<string, string>;
3
+ declare function getExample(name: string): string;
4
+ declare function getAllExamples(): ReadonlyMap<string, string>;
5
+ declare function getKnowledgeFiles(names: string[]): string;
6
+ declare function getExampleFiles(names: string[]): string;
7
+ /** Clear cached knowledge and examples. Useful for dev/watch mode. */
8
+ declare function clearCache(): void;
9
+
10
+ export { clearCache, getAllExamples, getAllKnowledge, getExample, getExampleFiles, getKnowledge, getKnowledgeFiles };
package/dist/index.js ADDED
@@ -0,0 +1,102 @@
1
+ import { existsSync, readFileSync, readdirSync } from 'fs';
2
+ import { dirname, resolve, join } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ // src/index.ts
6
+ var __dirname$1 = dirname(fileURLToPath(import.meta.url));
7
+ var PKG_ROOT = resolve(__dirname$1, "..");
8
+ function resolveAsset(name) {
9
+ const fromDist = join(PKG_ROOT, name);
10
+ if (existsSync(fromDist)) {
11
+ return fromDist;
12
+ }
13
+ const fromSrc = join(PKG_ROOT, "..", name);
14
+ if (existsSync(fromSrc)) {
15
+ return fromSrc;
16
+ }
17
+ return fromDist;
18
+ }
19
+ var CORE_DIR = resolveAsset("core");
20
+ var AI_DIR = resolveAsset("ai");
21
+ var EXAMPLES_DIR = resolveAsset("examples");
22
+ var API_SKELETON_PATH = resolveAsset("api-skeleton.md");
23
+ var knowledgeCache = null;
24
+ var exampleCache = null;
25
+ function loadDir(dir, map) {
26
+ try {
27
+ const files = readdirSync(dir).filter(
28
+ (f) => f.endsWith(".md") || f.endsWith(".ts")
29
+ );
30
+ for (const file of files) {
31
+ const name = file.replace(/\.(md|ts)$/, "");
32
+ map.set(name, readFileSync(join(dir, file), "utf-8"));
33
+ }
34
+ } catch (err) {
35
+ if (err.code !== "ENOENT") {
36
+ throw err;
37
+ }
38
+ }
39
+ }
40
+ function loadAllKnowledge() {
41
+ const map = /* @__PURE__ */ new Map();
42
+ loadDir(CORE_DIR, map);
43
+ loadDir(AI_DIR, map);
44
+ try {
45
+ map.set("api-skeleton", readFileSync(API_SKELETON_PATH, "utf-8"));
46
+ } catch {
47
+ }
48
+ return map;
49
+ }
50
+ function loadAllExamples() {
51
+ const map = /* @__PURE__ */ new Map();
52
+ loadDir(EXAMPLES_DIR, map);
53
+ return map;
54
+ }
55
+ function getKnowledge(name) {
56
+ if (!knowledgeCache) {
57
+ knowledgeCache = loadAllKnowledge();
58
+ }
59
+ return knowledgeCache.get(name) ?? "";
60
+ }
61
+ function getAllKnowledge() {
62
+ if (!knowledgeCache) {
63
+ knowledgeCache = loadAllKnowledge();
64
+ }
65
+ return knowledgeCache;
66
+ }
67
+ function getExample(name) {
68
+ if (!exampleCache) {
69
+ exampleCache = loadAllExamples();
70
+ }
71
+ return exampleCache.get(name) ?? "";
72
+ }
73
+ function getAllExamples() {
74
+ if (!exampleCache) {
75
+ exampleCache = loadAllExamples();
76
+ }
77
+ return exampleCache;
78
+ }
79
+ function getKnowledgeFiles(names) {
80
+ return names.map((name) => getKnowledge(name)).filter(Boolean).join("\n\n---\n\n");
81
+ }
82
+ function getExampleFiles(names) {
83
+ return names.map((name) => {
84
+ const content = getExample(name);
85
+ if (!content) {
86
+ return "";
87
+ }
88
+ return `### Example: ${name}
89
+
90
+ \`\`\`typescript
91
+ ${content}
92
+ \`\`\``;
93
+ }).filter(Boolean).join("\n\n");
94
+ }
95
+ function clearCache() {
96
+ knowledgeCache = null;
97
+ exampleCache = null;
98
+ }
99
+
100
+ export { clearCache, getAllExamples, getAllKnowledge, getExample, getExampleFiles, getKnowledge, getKnowledgeFiles };
101
+ //# sourceMappingURL=index.js.map
102
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":["__dirname"],"mappings":"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","file":"index.js","sourcesContent":["import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n// Resolve package root: works both in src/ (dev) and dist/ (bundled)\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\n/**\n * Resolve a path relative to the package root.\n * Tries dist-relative first (bundled), then src-relative (dev).\n */\nfunction resolveAsset(name: string): string {\n const fromDist = join(PKG_ROOT, name);\n if (existsSync(fromDist)) {\n return fromDist;\n }\n\n const fromSrc = join(PKG_ROOT, \"..\", name);\n if (existsSync(fromSrc)) {\n return fromSrc;\n }\n\n return fromDist; // default, will just return empty maps\n}\n\nconst CORE_DIR = resolveAsset(\"core\");\nconst AI_DIR = resolveAsset(\"ai\");\nconst EXAMPLES_DIR = resolveAsset(\"examples\");\nconst API_SKELETON_PATH = resolveAsset(\"api-skeleton.md\");\n\nlet knowledgeCache: Map<string, string> | null = null;\nlet exampleCache: Map<string, string> | null = null;\n\nfunction loadDir(dir: string, map: Map<string, string>): void {\n try {\n const files = readdirSync(dir).filter(\n (f) => f.endsWith(\".md\") || f.endsWith(\".ts\"),\n );\n for (const file of files) {\n const name = file.replace(/\\.(md|ts)$/, \"\");\n map.set(name, readFileSync(join(dir, file), \"utf-8\"));\n }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n // directory does not exist — expected during tests or incomplete installs\n }\n}\n\nfunction loadAllKnowledge(): Map<string, string> {\n const map = new Map<string, string>();\n loadDir(CORE_DIR, map);\n loadDir(AI_DIR, map);\n\n // Include api-skeleton\n try {\n map.set(\"api-skeleton\", readFileSync(API_SKELETON_PATH, \"utf-8\"));\n } catch {\n // may not exist yet\n }\n\n return map;\n}\n\nfunction loadAllExamples(): Map<string, string> {\n const map = new Map<string, string>();\n loadDir(EXAMPLES_DIR, map);\n\n return map;\n}\n\nexport function getKnowledge(name: string): string {\n if (!knowledgeCache) {\n knowledgeCache = loadAllKnowledge();\n }\n\n return knowledgeCache.get(name) ?? \"\";\n}\n\nexport function getAllKnowledge(): ReadonlyMap<string, string> {\n if (!knowledgeCache) {\n knowledgeCache = loadAllKnowledge();\n }\n\n return knowledgeCache;\n}\n\nexport function getExample(name: string): string {\n if (!exampleCache) {\n exampleCache = loadAllExamples();\n }\n\n return exampleCache.get(name) ?? \"\";\n}\n\nexport function getAllExamples(): ReadonlyMap<string, string> {\n if (!exampleCache) {\n exampleCache = loadAllExamples();\n }\n\n return exampleCache;\n}\n\nexport function getKnowledgeFiles(names: string[]): string {\n return names\n .map((name) => getKnowledge(name))\n .filter(Boolean)\n .join(\"\\n\\n---\\n\\n\");\n}\n\nexport function getExampleFiles(names: string[]): string {\n return names\n .map((name) => {\n const content = getExample(name);\n if (!content) {\n return \"\";\n }\n\n return `### Example: ${name}\\n\\n\\`\\`\\`typescript\\n${content}\\n\\`\\`\\``;\n })\n .filter(Boolean)\n .join(\"\\n\\n\");\n}\n\n/** Clear cached knowledge and examples. Useful for dev/watch mode. */\nexport function clearCache(): void {\n knowledgeCache = null;\n exampleCache = null;\n}\n"]}