@directive-run/cli 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.
package/dist/index.js ADDED
@@ -0,0 +1,642 @@
1
+ import { getAllKnowledge, getAllExamples, getKnowledge } from '@directive-run/knowledge';
2
+ export { getAllExamples, getAllKnowledge, getExample, getExampleFiles, getKnowledge, getKnowledgeFiles } from '@directive-run/knowledge';
3
+ import { existsSync, readFileSync } from 'fs';
4
+ import { join, resolve, dirname } from 'path';
5
+ import pc from 'picocolors';
6
+
7
+ // src/lib/knowledge.ts
8
+
9
+ // src/templates/claude.ts
10
+ function generateClaudeRules() {
11
+ const corePatterns = getKnowledge("core-patterns");
12
+ const antiPatterns = getKnowledge("anti-patterns");
13
+ const naming = getKnowledge("naming");
14
+ const schemaTypes = getKnowledge("schema-types");
15
+ return `# Directive \u2014 Complete AI Coding Rules
16
+
17
+ > Constraint-driven runtime for TypeScript. Declare requirements, let the runtime resolve them.
18
+ > https://directive.run | \`npm install @directive-run/core\`
19
+ > Full reference with examples: https://directive.run/llms.txt
20
+
21
+ ## Core Patterns
22
+
23
+ ${corePatterns}
24
+
25
+ ---
26
+
27
+ ## Anti-Patterns (All 36)
28
+
29
+ ${antiPatterns}
30
+
31
+ ### AI Package Anti-Patterns (21-36)
32
+
33
+ | # | WRONG | CORRECT |
34
+ |---|-------|---------|
35
+ | 21 | TS types for factsSchema: \`{ confidence: number }\` | Use \`{ confidence: t.number() }\` |
36
+ | 22 | \`facts.cache.push(item)\` in orchestrator | \`facts.cache = [...facts.cache, item]\` |
37
+ | 23 | Returning data from orchestrator \`resolve\` | Resolvers return \`void\` \u2014 mutate \`context.facts\` |
38
+ | 24 | Forgetting \`orchestrator.start()\` multi-agent | Single: implicit. Multi: must call \`start()\` |
39
+ | 25 | Catching \`Error\` not \`GuardrailError\` | \`GuardrailError\` has \`.guardrailName\`, \`.errorCode\` |
40
+ | 26 | \`from '@directive-run/ai'\` for adapters | Subpath: \`from '@directive-run/ai/openai'\` |
41
+ | 27 | Assuming \`{ input_tokens }\` structure | Normalized: \`{ inputTokens, outputTokens }\` |
42
+ | 28 | Same CircuitBreaker across agents | Create separate instances per dependency |
43
+ | 29 | \`budgetWarningThreshold: 1.5\` | Must be 0-1 (percentage) |
44
+ | 30 | \`race\` minSuccess > agents.length | Must be \`1 \u2264 minSuccess \u2264 agents.length\` |
45
+ | 31 | Async summarizer with autoManage: true | Use \`autoManage: false\` for sync control |
46
+ | 32 | Side effects in reflect \`evaluator\` | Evaluator must be pure |
47
+ | 33 | Task calling \`runSingleAgent\` | Tasks can't call agents \u2014 separate node |
48
+ | 34 | Task expecting object input | Input is always \`string\` \u2014 \`JSON.parse(input)\` |
49
+ | 35 | Task ID same as agent ID | IDs share namespace \u2014 distinct names |
50
+ | 36 | \`from '@directive-run/ai/mcp'\` | \`from '@directive-run/ai'\` (main export) |
51
+
52
+ ---
53
+
54
+ ## Naming Conventions
55
+
56
+ ${naming}
57
+
58
+ ---
59
+
60
+ ## Schema Type Builders
61
+
62
+ ${schemaTypes}
63
+
64
+ ---
65
+
66
+ ## Multi-Module Quick Reference
67
+
68
+ \`\`\`typescript
69
+ // Two modules with cross-module dependency
70
+ const authSchema = { facts: { token: t.string(), isAuth: t.boolean() } };
71
+ const authModule = createModule("auth", { schema: authSchema, /* ... */ });
72
+
73
+ const cartModule = createModule("cart", {
74
+ schema: { facts: { items: t.array<CartItem>() } },
75
+ crossModuleDeps: { auth: authSchema }, // Declare dependency
76
+ constraints: {
77
+ checkout: {
78
+ when: (facts) => facts.self.items.length > 0 && facts.auth.isAuth, // facts.self.* for own, facts.auth.* for cross
79
+ require: () => ({ type: "CHECKOUT" }),
80
+ },
81
+ },
82
+ // ...
83
+ });
84
+
85
+ const system = createSystem({ modules: { auth: authModule, cart: cartModule } });
86
+ // Access: system.facts.auth.token, system.events.cart.addItem({...})
87
+ \`\`\`
88
+
89
+ Key rules:
90
+ - \`facts.self.*\` for own module facts in constraints/resolvers
91
+ - \`facts.otherModule.*\` for cross-module reads
92
+ - \`crossModuleDeps\` must declare consumed schemas
93
+ - \`system.events.moduleName.eventName(payload)\` for namespaced events
94
+ - The \`::\` separator is internal \u2014 always use dot notation
95
+
96
+ ---
97
+
98
+ ## Constraints
99
+
100
+ - \`when(facts)\` \u2192 boolean. When true, requirement is emitted.
101
+ - \`require(facts)\` \u2192 \`{ type: "TYPE", ...data }\` object (never string literal)
102
+ - \`priority: number\` \u2014 higher evaluated first
103
+ - \`after: ["constraintName"]\` \u2014 ordering within same priority
104
+ - Async: \`async: true\` + \`deps: ['factName']\` (deps REQUIRED for async)
105
+ - Constraints DECLARE needs, resolvers FULFILL them \u2014 decoupled.
106
+
107
+ ---
108
+
109
+ ## Resolvers
110
+
111
+ - \`resolve(req, context)\` \u2014 async, returns \`void\`. Mutate \`context.facts.*\`.
112
+ - \`requirement: "TYPE"\` \u2014 which type this handles
113
+ - \`key: (req) => string\` \u2014 deduplication key
114
+ - \`retry: { attempts: 3, backoff: "exponential", initialDelay: 100 }\`
115
+ - \`batch: { maxSize: 10, windowMs: 50 }\` for N+1 prevention
116
+ - Always \`await system.settle()\` after start to wait for resolution
117
+
118
+ ---
119
+
120
+ ## System API
121
+
122
+ - \`system.facts.fieldName\` \u2014 read/write facts
123
+ - \`system.derive.derivationName\` \u2014 read derived values
124
+ - \`system.events.eventName(payload)\` \u2014 dispatch events
125
+ - \`system.subscribe(listener)\` \u2014 subscribe to all changes
126
+ - \`system.read(key)\` \u2014 read fact or derivation by string key
127
+ - \`system.inspect()\` \u2014 full state snapshot
128
+ - \`system.settle()\` \u2014 wait for async operations
129
+ - \`system.start()\` / \`system.stop()\` / \`system.destroy()\`
130
+
131
+ ---
132
+
133
+ ## React (\`@directive-run/react\`)
134
+
135
+ \`\`\`typescript
136
+ import { useSelector, useEvent } from "@directive-run/react";
137
+
138
+ const count = useSelector(system, (s) => s.facts.count);
139
+ const events = useEvent(system);
140
+ // onClick={() => events.increment()}
141
+ \`\`\`
142
+
143
+ **NO** \`useDirective()\` hook. Use \`useSelector\` + \`useEvent\`.
144
+
145
+ ---
146
+
147
+ ## Plugins (\`@directive-run/core/plugins\`)
148
+
149
+ \`devtoolsPlugin()\`, \`loggingPlugin()\`, \`persistencePlugin(config)\`,
150
+ \`createCircuitBreaker(config)\`, \`createObservability(config)\`
151
+
152
+ ---
153
+
154
+ ## AI Package (\`@directive-run/ai\`)
155
+
156
+ ### Single-Agent Orchestrator
157
+
158
+ \`\`\`typescript
159
+ import { createAgentOrchestrator, t } from '@directive-run/ai';
160
+ import { createAnthropicRunner } from '@directive-run/ai/anthropic';
161
+
162
+ const orchestrator = createAgentOrchestrator({
163
+ runner: createAnthropicRunner({ apiKey }),
164
+ factsSchema: { result: t.string(), confidence: t.number() },
165
+ init: (facts) => { facts.result = ""; facts.confidence = 0; },
166
+ maxTokenBudget: 100000,
167
+ budgetWarningThreshold: 0.8,
168
+ guardrails: { input: [...], output: [...] },
169
+ memory: createAgentMemory({ strategy: createSlidingWindowStrategy({ maxMessages: 30 }) }),
170
+ debug: true,
171
+ });
172
+
173
+ const result = await orchestrator.run(agent, "analyze this");
174
+ \`\`\`
175
+
176
+ ### Multi-Agent
177
+
178
+ \`\`\`typescript
179
+ import { createMultiAgentOrchestrator, parallel, sequential, dag } from '@directive-run/ai';
180
+
181
+ const orch = createMultiAgentOrchestrator({
182
+ agents: { researcher: agentA, writer: agentB },
183
+ patterns: {
184
+ pipeline: sequential(["researcher", "writer"]),
185
+ brainstorm: parallel(["researcher", "writer"], mergeResults),
186
+ workflow: dag([
187
+ { id: "research", handler: "researcher" },
188
+ { id: "write", handler: "writer", dependencies: ["research"] },
189
+ ]),
190
+ },
191
+ runner,
192
+ });
193
+ orch.start(); // Required for multi-agent!
194
+ \`\`\`
195
+
196
+ 8 patterns: \`parallel\`, \`sequential\`, \`supervisor\`, \`dag\`, \`reflect\`, \`race\`, \`debate\`, \`goal\`
197
+
198
+ ### Adapter Imports (Subpath!)
199
+
200
+ \`\`\`typescript
201
+ import { createAnthropicRunner } from '@directive-run/ai/anthropic';
202
+ import { createOpenAIRunner } from '@directive-run/ai/openai';
203
+ import { createOllamaRunner } from '@directive-run/ai/ollama';
204
+ import { createGeminiRunner } from '@directive-run/ai/gemini';
205
+ \`\`\`
206
+
207
+ ### Guardrails
208
+
209
+ \`createPIIGuardrail\`, \`createModerationGuardrail\`, \`createRateLimitGuardrail\`,
210
+ \`createToolGuardrail\`, \`createOutputSchemaGuardrail\`, \`createLengthGuardrail\`,
211
+ \`createContentFilterGuardrail\`
212
+
213
+ \`GuardrailResult: { passed: boolean, reason?: string, transformed?: unknown }\`
214
+
215
+ ### Memory
216
+
217
+ \`createAgentMemory({ strategy, summarizer?, autoManage? })\`
218
+ Strategies: \`createSlidingWindowStrategy\`, \`createTokenBasedStrategy\`, \`createHybridStrategy\`
219
+ Summarizers: \`createTruncationSummarizer\`, \`createKeyPointsSummarizer\`, \`createLLMSummarizer(runner)\`
220
+
221
+ ### Streaming
222
+
223
+ \`\`\`typescript
224
+ const streamResult = orchestrator.runStream(agent, "analyze");
225
+ for await (const chunk of streamResult.stream) {
226
+ switch (chunk.type) {
227
+ case "token": process.stdout.write(chunk.data); break;
228
+ case "done": console.log("Tokens:", chunk.totalTokens); break;
229
+ case "error": console.error(chunk.error); break;
230
+ }
231
+ }
232
+ \`\`\`
233
+
234
+ Backpressure: \`"buffer"\` (default), \`"block"\`, \`"drop"\`
235
+ `;
236
+ }
237
+
238
+ // src/templates/cursor.ts
239
+ function generateCursorRules() {
240
+ return `# Directive \u2014 AI Coding Rules
241
+
242
+ > Constraint-driven runtime for TypeScript. \`npm install @directive-run/core\`
243
+ > Full reference: https://directive.run/llms.txt
244
+
245
+ ## Schema Shape (CRITICAL)
246
+
247
+ \`\`\`typescript
248
+ import { createModule, createSystem, t } from "@directive-run/core";
249
+
250
+ const myModule = createModule("name", {
251
+ schema: {
252
+ facts: { count: t.number(), items: t.array<string>() },
253
+ derivations: { total: "number" },
254
+ events: { increment: "void", addItem: "string" },
255
+ requirements: { FETCH_DATA: { url: "string" } },
256
+ },
257
+ init: (facts) => { facts.count = 0; facts.items = []; },
258
+ derive: {
259
+ total: (facts) => facts.items.length + facts.count,
260
+ },
261
+ events: {
262
+ increment: (facts) => { facts.count += 1; },
263
+ addItem: (facts, item) => { facts.items = [...facts.items, item]; },
264
+ },
265
+ constraints: {
266
+ fetchWhenReady: {
267
+ when: (facts) => facts.count > 0 && facts.items.length === 0,
268
+ require: (facts) => ({ type: "FETCH_DATA", url: "/api/items" }),
269
+ },
270
+ },
271
+ resolvers: {
272
+ fetchData: {
273
+ requirement: "FETCH_DATA",
274
+ resolve: async (req, context) => {
275
+ const data = await fetch(req.url).then(r => r.json());
276
+ context.facts.items = data;
277
+ },
278
+ },
279
+ },
280
+ });
281
+
282
+ const system = createSystem({ module: myModule });
283
+ await system.settle();
284
+ \`\`\`
285
+
286
+ ## Top 10 Anti-Patterns
287
+
288
+ | # | WRONG | CORRECT |
289
+ |---|-------|---------|
290
+ | 1 | \`facts.profile as ResourceState<Profile>\` | Remove cast \u2014 schema provides types |
291
+ | 2 | \`{ phase: t.string() }\` flat schema | \`schema: { facts: { phase: t.string() } }\` |
292
+ | 3 | \`facts.items\` in multi-module | \`facts.self.items\` |
293
+ | 4 | \`t.map()\`, \`t.set()\`, \`t.promise()\` | Don't exist. Use \`t.object<Map<K,V>>()\` |
294
+ | 5 | \`(req, ctx)\` in resolver | \`(req, context)\` \u2014 never abbreviate |
295
+ | 6 | \`createModule("n", { phase: t.string() })\` | Must wrap: \`schema: { facts: { ... } }\` |
296
+ | 7 | \`system.dispatch('login', {...})\` | \`system.events.login({...})\` |
297
+ | 8 | \`facts.items.push(item)\` | \`facts.items = [...facts.items, item]\` |
298
+ | 9 | \`useDirective(system)\` | \`useSelector(system, s => s.facts.count)\` |
299
+ | 10 | \`facts['auth::status']\` | \`facts.auth.status\` dot notation |
300
+
301
+ ## Naming
302
+
303
+ - \`req\` = requirement (not request). Parameter: \`(req, context)\`
304
+ - \`derive\` / derivations \u2014 never "computed" or "selectors"
305
+ - Resolvers return \`void\` \u2014 mutate \`context.facts\` instead
306
+ - Always use braces for returns: \`if (x) { return y; }\`
307
+ - Multi-module: \`facts.self.fieldName\` for own module facts
308
+ - Events: \`system.events.eventName(payload)\` \u2014 not \`system.dispatch()\`
309
+ - Import from main: \`import { createModule } from '@directive-run/core'\`
310
+
311
+ ## Schema Types That Exist
312
+
313
+ \`t.string<T>()\`, \`t.number()\`, \`t.boolean()\`, \`t.array<T>()\`, \`t.object<T>()\`,
314
+ \`t.enum("a","b")\`, \`t.literal(value)\`, \`t.nullable(inner)\`, \`t.optional(inner)\`, \`t.union(...)\`
315
+
316
+ Chainable: \`.default()\`, \`.validate()\`, \`.transform()\`, \`.brand<>()\`, \`.refine()\`
317
+
318
+ **DO NOT USE** (hallucinations): \`t.map()\`, \`t.set()\`, \`t.date()\`, \`t.tuple()\`, \`t.record()\`, \`t.promise()\`, \`t.any()\`
319
+
320
+ ## Key Pattern: Constraint \u2192 Requirement \u2192 Resolver
321
+
322
+ When the user wants "do X when Y": create THREE things:
323
+ 1. **Constraint**: \`when: (facts) => Y_condition\` \u2192 \`require: { type: "DO_X" }\`
324
+ 2. **Resolver**: handles "DO_X", calls API, sets \`context.facts\`
325
+ 3. They are **decoupled**. Constraint declares need, resolver fulfills it.
326
+ `;
327
+ }
328
+
329
+ // src/templates/copilot.ts
330
+ function generateCopilotRules() {
331
+ const base = generateCursorRules();
332
+ const extraAntiPatterns = `
333
+ ## Anti-Patterns 11-20
334
+
335
+ | # | WRONG | CORRECT |
336
+ |---|-------|---------|
337
+ | 11 | \`module("name").schema({...}).build()\` | Prefer \`createModule("name", {...})\` object syntax |
338
+ | 12 | Returning data from \`resolve\` | Resolvers return \`void\` \u2014 mutate \`context.facts\` |
339
+ | 13 | Async logic in \`init\` | \`init\` is synchronous, facts assignment only |
340
+ | 14 | \`await system.start()\` without settle | Add \`await system.settle()\` after start |
341
+ | 15 | Missing \`crossModuleDeps\` | Declare \`crossModuleDeps: { auth: authSchema }\` |
342
+ | 16 | \`require: "TYPE"\` string literal | \`require: { type: "TYPE" }\` object form |
343
+ | 17 | Passthrough derivation \`(f) => f.count\` | Remove \u2014 read fact directly |
344
+ | 18 | \`from '@directive-run/core/module'\` | \`from '@directive-run/core'\` (main export) |
345
+ | 19 | \`async when()\` without \`deps\` | Add \`deps: ['factName']\` for async constraints |
346
+ | 20 | No error boundary on resolver | Use try-catch or module error boundary config |
347
+ `;
348
+ const multiModule = `
349
+ ## Multi-Module
350
+
351
+ \`\`\`typescript
352
+ const system = createSystem({
353
+ modules: { auth: authModule, cart: cartModule },
354
+ });
355
+
356
+ // Access: system.facts.auth.token, system.events.cart.addItem({...})
357
+ // In constraints/resolvers: use facts.self.* for own module
358
+ // Declare deps: crossModuleDeps: { auth: authSchema }
359
+ \`\`\`
360
+ `;
361
+ const aiBasics = `
362
+ ## AI Package Basics (\`@directive-run/ai\`)
363
+
364
+ \`\`\`typescript
365
+ import { createAgentOrchestrator, t } from '@directive-run/ai';
366
+ import { createAnthropicRunner } from '@directive-run/ai/anthropic'; // Subpath import!
367
+
368
+ const orchestrator = createAgentOrchestrator({
369
+ runner: createAnthropicRunner({ apiKey: process.env.ANTHROPIC_API_KEY }),
370
+ factsSchema: { result: t.string(), confidence: t.number() }, // Use t.*() !
371
+ init: (facts) => { facts.result = ""; facts.confidence = 0; },
372
+ });
373
+
374
+ const result = await orchestrator.run(agent, "analyze this");
375
+ \`\`\`
376
+
377
+ **AI Anti-Patterns:**
378
+ - Use \`t.number()\` not \`number\` for factsSchema
379
+ - Subpath imports: \`from '@directive-run/ai/anthropic'\` not \`from '@directive-run/ai'\`
380
+ - Token usage normalized: \`{ inputTokens, outputTokens }\` (not provider-specific)
381
+ - \`facts.cache = [...facts.cache, item]\` not \`facts.cache.push(item)\`
382
+ `;
383
+ return base + extraAntiPatterns + multiModule + aiBasics;
384
+ }
385
+
386
+ // src/templates/cline.ts
387
+ function generateClineRules() {
388
+ return generateCopilotRules();
389
+ }
390
+
391
+ // src/templates/llms-txt.ts
392
+ function generateLlmsTxt() {
393
+ const knowledge = getAllKnowledge();
394
+ const examples = getAllExamples();
395
+ const coreOrder = [
396
+ "core-patterns",
397
+ "anti-patterns",
398
+ "naming",
399
+ "multi-module",
400
+ "constraints",
401
+ "resolvers",
402
+ "error-boundaries",
403
+ "testing",
404
+ "time-travel",
405
+ "schema-types",
406
+ "system-api",
407
+ "react-adapter",
408
+ "plugins"
409
+ ];
410
+ const aiOrder = [
411
+ "ai-orchestrator",
412
+ "ai-multi-agent",
413
+ "ai-tasks",
414
+ "ai-agents-streaming",
415
+ "ai-guardrails-memory",
416
+ "ai-adapters",
417
+ "ai-budget-resilience",
418
+ "ai-mcp-rag",
419
+ "ai-communication",
420
+ "ai-debug-observability",
421
+ "ai-security",
422
+ "ai-testing-evals"
423
+ ];
424
+ const exampleOrder = [
425
+ "counter",
426
+ "auth-flow",
427
+ "shopping-cart",
428
+ "error-boundaries",
429
+ "ai-orchestrator",
430
+ "fraud-analysis",
431
+ "ai-checkpoint"
432
+ ];
433
+ const sections = [
434
+ "# Directive \u2014 Complete AI Reference (llms.txt)",
435
+ "",
436
+ "> Constraint-driven runtime for TypeScript.",
437
+ "> Declare requirements. Let the runtime resolve them.",
438
+ "> https://directive.run",
439
+ "",
440
+ "## Core API (@directive-run/core)",
441
+ ""
442
+ ];
443
+ for (const name of coreOrder) {
444
+ const content = knowledge.get(name);
445
+ if (content) {
446
+ sections.push(content, "", "---", "");
447
+ }
448
+ }
449
+ sections.push("## AI Package (@directive-run/ai)", "");
450
+ for (const name of aiOrder) {
451
+ const content = knowledge.get(name);
452
+ if (content) {
453
+ sections.push(content, "", "---", "");
454
+ }
455
+ }
456
+ const apiSkeleton = knowledge.get("api-skeleton");
457
+ if (apiSkeleton) {
458
+ sections.push("## API Reference (Auto-Generated)", "", apiSkeleton, "");
459
+ }
460
+ sections.push("## Complete Examples", "");
461
+ for (const name of exampleOrder) {
462
+ const content = examples.get(name);
463
+ if (content) {
464
+ sections.push(
465
+ `### ${name}`,
466
+ "",
467
+ "```typescript",
468
+ content,
469
+ "```",
470
+ ""
471
+ );
472
+ }
473
+ }
474
+ return sections.join("\n");
475
+ }
476
+
477
+ // src/templates/windsurf.ts
478
+ function generateWindsurfRules() {
479
+ return generateCopilotRules();
480
+ }
481
+
482
+ // src/templates/index.ts
483
+ var generators = {
484
+ cursor: generateCursorRules,
485
+ claude: generateClaudeRules,
486
+ copilot: generateCopilotRules,
487
+ windsurf: generateWindsurfRules,
488
+ cline: generateClineRules
489
+ };
490
+ function getTemplate(toolId) {
491
+ const generator = generators[toolId];
492
+ if (!generator) {
493
+ throw new Error(`No template for tool: ${toolId}`);
494
+ }
495
+ return generator();
496
+ }
497
+ var TOOL_SIGNALS = [
498
+ {
499
+ id: "cursor",
500
+ name: "Cursor",
501
+ signals: [".cursor", ".cursorrules"],
502
+ outputPath: ".cursorrules"
503
+ },
504
+ {
505
+ id: "claude",
506
+ name: "Claude Code",
507
+ signals: [".claude"],
508
+ outputPath: ".claude/CLAUDE.md"
509
+ },
510
+ {
511
+ id: "copilot",
512
+ name: "GitHub Copilot",
513
+ signals: [".github"],
514
+ outputPath: ".github/copilot-instructions.md"
515
+ },
516
+ {
517
+ id: "windsurf",
518
+ name: "Windsurf",
519
+ signals: [".windsurfrules"],
520
+ outputPath: ".windsurfrules"
521
+ },
522
+ {
523
+ id: "cline",
524
+ name: "Cline",
525
+ signals: [".clinerules"],
526
+ outputPath: ".clinerules"
527
+ }
528
+ ];
529
+ function detectTools(rootDir) {
530
+ const detected = [];
531
+ for (const tool of TOOL_SIGNALS) {
532
+ const hasSignal = tool.signals.some(
533
+ (signal) => existsSync(join(rootDir, signal))
534
+ );
535
+ if (hasSignal) {
536
+ detected.push({
537
+ name: tool.name,
538
+ id: tool.id,
539
+ outputPath: join(rootDir, tool.outputPath)
540
+ });
541
+ }
542
+ }
543
+ return detected;
544
+ }
545
+ var MONOREPO_SIGNALS = [
546
+ { file: "pnpm-workspace.yaml", tool: "pnpm" },
547
+ { file: "turbo.json", tool: "turbo" }
548
+ ];
549
+ function detectMonorepo(startDir) {
550
+ let dir = resolve(startDir);
551
+ while (dir !== dirname(dir)) {
552
+ for (const signal of MONOREPO_SIGNALS) {
553
+ if (existsSync(join(dir, signal.file))) {
554
+ return { isMonorepo: true, rootDir: dir, tool: signal.tool };
555
+ }
556
+ }
557
+ const pkgPath = join(dir, "package.json");
558
+ if (existsSync(pkgPath)) {
559
+ try {
560
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
561
+ if (pkg.workspaces) {
562
+ const tool = existsSync(join(dir, "yarn.lock")) ? "yarn" : "npm";
563
+ return { isMonorepo: true, rootDir: dir, tool };
564
+ }
565
+ } catch {
566
+ }
567
+ }
568
+ dir = dirname(dir);
569
+ }
570
+ return { isMonorepo: false, rootDir: startDir };
571
+ }
572
+
573
+ // src/lib/constants.ts
574
+ var CLI_NAME = "directive";
575
+ var PACKAGE_NAME = "@directive-run/cli";
576
+ var SECTION_START = "<!-- directive:start -->";
577
+ var SECTION_END = "<!-- directive:end -->";
578
+
579
+ // src/lib/merge.ts
580
+ function mergeSection(existingContent, newSection) {
581
+ const startIdx = existingContent.indexOf(SECTION_START);
582
+ const endIdx = existingContent.indexOf(SECTION_END);
583
+ const wrapped = `${SECTION_START}
584
+ ${newSection}
585
+ ${SECTION_END}`;
586
+ if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
587
+ return existingContent.slice(0, startIdx) + wrapped + existingContent.slice(endIdx + SECTION_END.length);
588
+ }
589
+ const separator = existingContent.endsWith("\n") ? "\n" : "\n\n";
590
+ return existingContent + separator + wrapped + "\n";
591
+ }
592
+ function hasDirectiveSection(content) {
593
+ return content.includes(SECTION_START) && content.includes(SECTION_END);
594
+ }
595
+ async function loadSystem(filePath) {
596
+ const resolved = resolve(filePath);
597
+ if (!existsSync(resolved)) {
598
+ throw new Error(`File not found: ${resolved}`);
599
+ }
600
+ try {
601
+ const mod = await import(resolved);
602
+ if (mod.default && isSystem(mod.default)) {
603
+ return mod.default;
604
+ }
605
+ if (mod.system && isSystem(mod.system)) {
606
+ return mod.system;
607
+ }
608
+ for (const key of Object.keys(mod)) {
609
+ if (isSystem(mod[key])) {
610
+ return mod[key];
611
+ }
612
+ }
613
+ throw new Error(
614
+ `No Directive system found in ${pc.dim(filePath)}
615
+ Export a system as default or named "system":
616
+
617
+ ${pc.cyan("export default")} createSystem({ module: myModule });
618
+ ${pc.cyan("export const system")} = createSystem({ module: myModule });`
619
+ );
620
+ } catch (err) {
621
+ if (err instanceof Error && err.message.includes("No Directive system")) {
622
+ throw err;
623
+ }
624
+ throw new Error(
625
+ `Failed to load ${pc.dim(filePath)}: ${err instanceof Error ? err.message : String(err)}
626
+
627
+ Make sure the file is valid TypeScript and tsx is installed:
628
+ ${pc.cyan("npm install -D tsx")}`
629
+ );
630
+ }
631
+ }
632
+ function isSystem(obj) {
633
+ if (typeof obj !== "object" || obj === null) {
634
+ return false;
635
+ }
636
+ const sys = obj;
637
+ return typeof sys.inspect === "function" && typeof sys.start === "function" && typeof sys.stop === "function" && "facts" in sys;
638
+ }
639
+
640
+ export { CLI_NAME, PACKAGE_NAME, SECTION_END, SECTION_START, detectMonorepo, detectTools, generateLlmsTxt, getTemplate, hasDirectiveSection, loadSystem, mergeSection };
641
+ //# sourceMappingURL=index.js.map
642
+ //# sourceMappingURL=index.js.map