@directive-run/knowledge 1.15.0 → 1.16.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/ai/ai-adapters.md +5 -0
- package/ai/ai-agents-streaming.md +5 -0
- package/ai/ai-budget-resilience.md +6 -0
- package/ai/ai-communication.md +5 -0
- package/ai/ai-debug-observability.md +6 -0
- package/ai/ai-guardrails-memory.md +6 -0
- package/ai/ai-mcp-rag.md +5 -0
- package/ai/ai-multi-agent.md +7 -0
- package/ai/ai-orchestrator.md +9 -0
- package/ai/ai-security.md +5 -0
- package/ai/ai-tasks.md +5 -0
- package/ai/ai-testing-evals.md +6 -0
- package/core/anti-patterns.md +9 -0
- package/core/constraints.md +7 -0
- package/core/core-patterns.md +10 -0
- package/core/error-boundaries.md +6 -0
- package/core/history.md +5 -0
- package/core/multi-module.md +7 -0
- package/core/naming.md +120 -91
- package/core/plugins.md +5 -0
- package/core/react-adapter.md +6 -0
- package/core/resolvers.md +8 -0
- package/core/schema-types.md +6 -0
- package/core/system-api.md +8 -0
- package/core/testing.md +6 -0
- package/package.json +3 -3
package/ai/ai-adapters.md
CHANGED
|
@@ -250,3 +250,8 @@ const orchestrator = createAgentOrchestrator({ runner });
|
|
|
250
250
|
| Gemini | `@directive-run/ai/gemini` | `apiKey`, `defaultModel` |
|
|
251
251
|
|
|
252
252
|
All adapters support: `baseURL`, `defaultHeaders`, `hooks`, streaming variant.
|
|
253
|
+
|
|
254
|
+
## See also
|
|
255
|
+
|
|
256
|
+
- [`ai-orchestrator.md`](./ai-orchestrator.md) — where the `AgentRunner` an adapter produces gets consumed
|
|
257
|
+
- [`ai-agents-streaming.md`](./ai-agents-streaming.md) — the `StreamingCallbackRunner` shape each adapter's streaming variant satisfies
|
|
@@ -300,3 +300,8 @@ case "guardrail_triggered":
|
|
|
300
300
|
| `orchestrator.runStream(agent, input, opts?)` | instance method | Returns `{ stream, result, abort }` |
|
|
301
301
|
| `createStreamingRunner(baseRunner, opts?)` | `@directive-run/ai` | Wrap a `StreamingCallbackRunner` into a `StreamRunner` |
|
|
302
302
|
| `createSSETransport(config?)` | `@directive-run/ai` | `{ toResponse, toStream }` for piping a stream to SSE |
|
|
303
|
+
|
|
304
|
+
## See also
|
|
305
|
+
|
|
306
|
+
- [`ai-adapters.md`](./ai-adapters.md) — provider runners that produce the streams this file consumes
|
|
307
|
+
- [`ai-orchestrator.md`](./ai-orchestrator.md) — `orchestrator.runStream(agent, input)` returns the `{ stream, result, abort }` triple this file documents
|
|
@@ -400,3 +400,9 @@ const orchestrator = createAgentOrchestrator({ runner: baseRunner, guardrails: {
|
|
|
400
400
|
| `createHealthMonitor(config?)` | returns `HealthMonitor`; push outcomes in via `recordSuccess/Failure` | — |
|
|
401
401
|
| `createSemanticCache(config)` | returns `SemanticCache`; use via `createSemanticCacheGuardrail({ cache })` | — |
|
|
402
402
|
| `createConstraintRouter(config)` | returns an `AgentRunner` that picks providers at call time | — |
|
|
403
|
+
|
|
404
|
+
## See also
|
|
405
|
+
|
|
406
|
+
- [`ai-orchestrator.md`](./ai-orchestrator.md) — `circuitBreaker` / `selfHealing` / `agentRetry` / `maxTokenBudget` options on `createAgentOrchestrator`
|
|
407
|
+
- [`ai-guardrails-memory.md`](./ai-guardrails-memory.md) — `createSemanticCacheGuardrail({ cache })` wires this file's `SemanticCache` into the orchestrator
|
|
408
|
+
- [`ai-debug-observability.md`](./ai-debug-observability.md) — recording retry storms, circuit-breaker state changes, and budget warnings in the debug timeline
|
package/ai/ai-communication.md
CHANGED
|
@@ -297,3 +297,8 @@ return JSON.stringify({ ...JSON.parse(input), researchData: data, timestamp: Dat
|
|
|
297
297
|
| `network.delegate(from, to, task, context)` | Delegated task with result | `Promise<DelegationResultMessage>` |
|
|
298
298
|
| `orchestrator.system.facts[agentId].x` | Cross-agent fact read | each agent is a namespaced module |
|
|
299
299
|
| `context.scratchpad` | Per-pattern ephemeral state | Readonly inside tasks/agents |
|
|
300
|
+
|
|
301
|
+
## See also
|
|
302
|
+
|
|
303
|
+
- [`ai-multi-agent.md`](./ai-multi-agent.md) — the orchestrator that owns the namespaced facts this file's primitives read
|
|
304
|
+
- [`ai-tasks.md`](./ai-tasks.md) — tasks share the scratchpad surface this file documents
|
|
@@ -321,3 +321,9 @@ timeline.subscribe((e) => {
|
|
|
321
321
|
| `createOtelPlugin(config)` | Plugin that emits spans for orchestrator activity |
|
|
322
322
|
| `createOTLPExporter(config)` | Returns `{ exportMetrics, exportTraces }` for OTel backends |
|
|
323
323
|
| `createDevtoolsServer({ timeline, port })` | WebSocket-bridged timeline for browser devtools |
|
|
324
|
+
|
|
325
|
+
## See also
|
|
326
|
+
|
|
327
|
+
- [`ai-orchestrator.md`](./ai-orchestrator.md) — `debug: { verboseTimeline }` config + `orchestrator.timeline` access + breakpoint surface
|
|
328
|
+
- [`ai-budget-resilience.md`](./ai-budget-resilience.md) — retry storms, circuit-breaker state changes, and budget warnings all flow through the debug timeline
|
|
329
|
+
- [`ai-testing-evals.md`](./ai-testing-evals.md) — `createTestTimeline` and `assertTimelineEvents` for asserting against recorded events
|
|
@@ -362,3 +362,9 @@ await memory.manage(); // awaits the async summarizer
|
|
|
362
362
|
| `createOutputTypeGuardrail` | output | `type` |
|
|
363
363
|
| `createLengthGuardrail` | output | one of `maxCharacters` or `maxTokens` |
|
|
364
364
|
| `createContentFilterGuardrail` | output | `blockedPatterns` |
|
|
365
|
+
|
|
366
|
+
## See also
|
|
367
|
+
|
|
368
|
+
- [`ai-orchestrator.md`](./ai-orchestrator.md) — `guardrails: { input, output, toolCall }` and `memory:` options on `createAgentOrchestrator`
|
|
369
|
+
- [`ai-security.md`](./ai-security.md) — `createPIIGuardrail`, `createPromptInjectionGuardrail`, `createAuditTrail`, `createCompliance` — the security-flavored guardrails
|
|
370
|
+
- [`ai-budget-resilience.md`](./ai-budget-resilience.md) — `createSemanticCache` pairs with `createSemanticCacheGuardrail` for caching-as-guardrail
|
package/ai/ai-mcp-rag.md
CHANGED
|
@@ -286,3 +286,8 @@ type EmbedderFn = (text: string) => Promise<number[]>;
|
|
|
286
286
|
| `createBatchedEmbedder(config)` | `@directive-run/ai` | `{ embed, flush, dispose }` | Wrap an EmbedderFn with batching |
|
|
287
287
|
| `createTestEmbedder(dim?)` | `@directive-run/ai` | `EmbedderFn` | Deterministic embedder for tests |
|
|
288
288
|
| `createJSONFileStore(options)` | `@directive-run/ai` | `RAGStorage` | File-backed vector store for prototyping |
|
|
289
|
+
|
|
290
|
+
## See also
|
|
291
|
+
|
|
292
|
+
- [`ai-orchestrator.md`](./ai-orchestrator.md) — where MCP-supplied tools and RAG-enriched runners flow into agent runs
|
|
293
|
+
- [`ai-security.md`](./ai-security.md) — `toolConstraints[…].requireApproval` and the per-tool approval workflow the MCP adapter exposes
|
package/ai/ai-multi-agent.md
CHANGED
|
@@ -366,3 +366,10 @@ orch.start();
|
|
|
366
366
|
| `race(handlers, options?)` | `string[], { timeout?, minSuccess?, extract? }` | — |
|
|
367
367
|
| `debate(config)` | `{ handlers, evaluator, maxRounds?, extract?, parseJudgement? }` | — (single arg) |
|
|
368
368
|
| `goal(nodes, when, options?)` | `Record<string, GoalNode>, (facts) => boolean, { maxSteps?, extract?, satisfaction? }` | when |
|
|
369
|
+
|
|
370
|
+
## See also
|
|
371
|
+
|
|
372
|
+
- [`ai-orchestrator.md`](./ai-orchestrator.md) — the single-agent flavor; covers options and lifecycle this file builds on
|
|
373
|
+
- [`ai-communication.md`](./ai-communication.md) — `createMessageBus` / `createAgentNetwork` for inter-agent messaging within a pattern
|
|
374
|
+
- [`ai-tasks.md`](./ai-tasks.md) — deterministic task handlers that compose with agents inside `dag` / `sequential` patterns
|
|
375
|
+
- [`ai-testing-evals.md`](./ai-testing-evals.md) — `createTestMultiAgentOrchestrator` and pattern-shape assertions
|
package/ai/ai-orchestrator.md
CHANGED
|
@@ -455,3 +455,12 @@ const final = await result;
|
|
|
455
455
|
| `orch.facts.agent.*` | Read built-in agent state |
|
|
456
456
|
| `orch.totalTokens` | Cumulative token count |
|
|
457
457
|
| `orch.timeline` | DebugTimeline (when `debug: true`); `null` otherwise |
|
|
458
|
+
|
|
459
|
+
## See also
|
|
460
|
+
|
|
461
|
+
- [`ai-multi-agent.md`](./ai-multi-agent.md) — the multi-agent flavor; 8 composition patterns and pattern factories
|
|
462
|
+
- [`ai-adapters.md`](./ai-adapters.md) — provider runners that produce the `runner` this orchestrator wraps
|
|
463
|
+
- [`ai-guardrails-memory.md`](./ai-guardrails-memory.md) — full surface of the `guardrails:` and `memory:` options on this orchestrator
|
|
464
|
+
- [`ai-budget-resilience.md`](./ai-budget-resilience.md) — full surface of the `circuitBreaker:`, `selfHealing:`, `agentRetry:`, `maxTokenBudget:` options
|
|
465
|
+
- [`ai-debug-observability.md`](./ai-debug-observability.md) — full surface of the `debug:`, `breakpoints:`, `onBreakpoint:` options + `orchestrator.timeline`
|
|
466
|
+
- [`ai-testing-evals.md`](./ai-testing-evals.md) — `createTestOrchestrator` for unit testing this surface
|
package/ai/ai-security.md
CHANGED
|
@@ -393,3 +393,8 @@ createCompliance({
|
|
|
393
393
|
| `createToolGuardrail` | `@directive-run/ai/guardrails` | guardrail | Tool allow/deny lists |
|
|
394
394
|
| `createContentFilterGuardrail` | `@directive-run/ai/guardrails` | guardrail | Block sensitive patterns (block-only — no redact) |
|
|
395
395
|
| `GuardrailError` / `isGuardrailError` | `@directive-run/ai` | error class + guard | Carries `code`, `guardrailName`, `userMessage` |
|
|
396
|
+
|
|
397
|
+
## See also
|
|
398
|
+
|
|
399
|
+
- [`ai-guardrails-memory.md`](./ai-guardrails-memory.md) — the broader guardrail surface (length, schema, content filter, tool allowlist) this file's security-flavored guardrails compose with
|
|
400
|
+
- [`ai-mcp-rag.md`](./ai-mcp-rag.md) — `toolConstraints[…].requireApproval` is where MCP tool calls thread into the approval workflow surfaced here
|
package/ai/ai-tasks.md
CHANGED
|
@@ -261,3 +261,8 @@ tasks: {
|
|
|
261
261
|
| Concurrency control | Via patterns | `maxConcurrent` |
|
|
262
262
|
| Scratchpad access | No | Yes |
|
|
263
263
|
| Works in all patterns | Yes | Yes |
|
|
264
|
+
|
|
265
|
+
## See also
|
|
266
|
+
|
|
267
|
+
- [`ai-multi-agent.md`](./ai-multi-agent.md) — tasks share the `handler:` namespace with agents inside `dag` / `sequential` / `parallel` patterns
|
|
268
|
+
- [`ai-communication.md`](./ai-communication.md) — tasks read the scratchpad this file's `context.scratchpad` surface exposes
|
package/ai/ai-testing-evals.md
CHANGED
|
@@ -477,3 +477,9 @@ const suite = createEvalSuite({
|
|
|
477
477
|
| `assertOrchestratorState` / `assertMultiAgentState` / `assertScratchpadState` / `assertDerivedValues` / `assertTimelineEvents` / `assertDagExecution` / `assertBreakpointHit` / `assertRerouted` / `assertAgentHealth` / `assertCheckpoint` / `assertMultiplexedStream` | `@directive-run/ai/testing` | State/topology/event assertions |
|
|
478
478
|
| `createEvalSuite` | `@directive-run/ai/evals` | Dataset-driven multi-criterion eval runner |
|
|
479
479
|
| `evalCost` / `evalLatency` / `evalOutputLength` / `evalSafety` / `evalStructure` / `evalMatch` / `evalJudge` / `evalFaithfulness` / `evalRelevance` / `evalCoherence` / `evalAssert` | `@directive-run/ai/evals` | Built-in criterion factories |
|
|
480
|
+
|
|
481
|
+
## See also
|
|
482
|
+
|
|
483
|
+
- [`ai-orchestrator.md`](./ai-orchestrator.md) — `createTestOrchestrator` wraps this orchestrator; the prod surface is what your tests are exercising
|
|
484
|
+
- [`ai-multi-agent.md`](./ai-multi-agent.md) — `createTestMultiAgentOrchestrator` for testing pattern execution
|
|
485
|
+
- [`ai-debug-observability.md`](./ai-debug-observability.md) — recorded debug events feed `assertTimelineEvents` / `assertDagExecution` / `assertBreakpointHit`
|
package/core/anti-patterns.md
CHANGED
|
@@ -371,3 +371,12 @@ Before generating any Directive code, verify:
|
|
|
371
371
|
8. Multi-module uses `facts.self.*` for own facts
|
|
372
372
|
9. Imports from `@directive-run/core`, not deep paths
|
|
373
373
|
10. `await system.settle()` after `system.start()`
|
|
374
|
+
|
|
375
|
+
## See also
|
|
376
|
+
|
|
377
|
+
- [`naming.md`](./naming.md) — the strict canonical-term rules AND the alias map for cross-paradigm searches
|
|
378
|
+
- [`constraints.md`](./constraints.md) — the constraint shape these anti-patterns reference (`facts` not in scope inside static `require:`, etc.)
|
|
379
|
+
- [`resolvers.md`](./resolvers.md) — the resolver shape these anti-patterns reference (return `void`, mutate `context.facts`, `(req, context)` not `(req, ctx)`)
|
|
380
|
+
- [`schema-types.md`](./schema-types.md) — the `t.*()` builders that exist and the hallucinated ones (`t.map`, `t.set`, `t.promise`, `t.date`) that don't
|
|
381
|
+
- [`react-adapter.md`](./react-adapter.md) — the React hooks that exist and the hallucinated ones (`useEvent`, `useSystem`, `DirectiveProvider`) that don't
|
|
382
|
+
- [`error-boundaries.md`](./error-boundaries.md) — error-handling shapes AI assistants sometimes invent
|
package/core/constraints.md
CHANGED
|
@@ -265,3 +265,10 @@ constraints: {
|
|
|
265
265
|
"Whenever X changes, log it" → Effect
|
|
266
266
|
"X is always facts.a + facts.b" → Derivation
|
|
267
267
|
```
|
|
268
|
+
|
|
269
|
+
## See also
|
|
270
|
+
|
|
271
|
+
- [`resolvers.md`](./resolvers.md) — the other half of the constraint-resolver loop; the supply side that fulfills the requirements constraints emit
|
|
272
|
+
- [`core-patterns.md`](./core-patterns.md) — how constraints fit into the module shape alongside facts, derivations, events, and effects
|
|
273
|
+
- [`multi-module.md`](./multi-module.md) — `crossModuleDeps` for constraints that fire on facts owned by another module
|
|
274
|
+
- [`anti-patterns.md`](./anti-patterns.md) — the constraint-shaped mistakes AI assistants reliably make
|
package/core/core-patterns.md
CHANGED
|
@@ -228,3 +228,13 @@ const typed = createModule("typed", {
|
|
|
228
228
|
},
|
|
229
229
|
});
|
|
230
230
|
```
|
|
231
|
+
|
|
232
|
+
## See also
|
|
233
|
+
|
|
234
|
+
- [`constraints.md`](./constraints.md) — the demand side of the constraint-resolver loop
|
|
235
|
+
- [`resolvers.md`](./resolvers.md) — the supply side that fulfills requirements
|
|
236
|
+
- [`schema-types.md`](./schema-types.md) — the `t.*()` builders that define fact and derivation types
|
|
237
|
+
- [`multi-module.md`](./multi-module.md) — when a single module isn't enough
|
|
238
|
+
- [`system-api.md`](./system-api.md) — `createSystem` and the runtime instance once your module is defined
|
|
239
|
+
- [`naming.md`](./naming.md) — terminology conventions every example here follows
|
|
240
|
+
- [`testing.md`](./testing.md) — `createTestSystem` for the modules you're learning to write
|
package/core/error-boundaries.md
CHANGED
|
@@ -322,3 +322,9 @@ try {
|
|
|
322
322
|
6. Add `onError` callback for logging/monitoring
|
|
323
323
|
7. Use `"throw"` for derivation errors (they indicate bugs)
|
|
324
324
|
8. Use `"skip"` for non-critical effects (logging, analytics)
|
|
325
|
+
|
|
326
|
+
## See also
|
|
327
|
+
|
|
328
|
+
- [`resolvers.md`](./resolvers.md) — retry policies and cancellation; the most common error source
|
|
329
|
+
- [`plugins.md`](./plugins.md) — `createCircuitBreaker` lives in `@directive-run/core/plugins`; pair it with error boundaries for cascading-failure isolation
|
|
330
|
+
- [`anti-patterns.md`](./anti-patterns.md) — common error-handling mistakes (catching the wrong type, swallowing recoverable errors)
|
package/core/history.md
CHANGED
|
@@ -344,3 +344,8 @@ const system = createSystem({
|
|
|
344
344
|
history: true,
|
|
345
345
|
});
|
|
346
346
|
```
|
|
347
|
+
|
|
348
|
+
## See also
|
|
349
|
+
|
|
350
|
+
- [`system-api.md`](./system-api.md) — `history` config in `createSystem` + the full `system.history.*` API
|
|
351
|
+
- [`testing.md`](./testing.md) — replay-driven testing patterns that pair with recorded snapshots
|
package/core/multi-module.md
CHANGED
|
@@ -318,3 +318,10 @@ system.events.cart.addItem({ id: "item-1", qty: 1 });
|
|
|
318
318
|
// object form is valid.
|
|
319
319
|
system.dispatch({ type: "login", token: "abc" });
|
|
320
320
|
```
|
|
321
|
+
|
|
322
|
+
## See also
|
|
323
|
+
|
|
324
|
+
- [`core-patterns.md`](./core-patterns.md) — start here for the single-module shape before going namespaced
|
|
325
|
+
- [`system-api.md`](./system-api.md) — `createSystem({ modules: { ... } })` and the namespaced facts proxy
|
|
326
|
+
- [`constraints.md`](./constraints.md) — `crossModuleDeps` for constraints that fire on facts owned by another module
|
|
327
|
+
- [`naming.md`](./naming.md) — `facts.self.*` convention; dot-notation vs bracket-notation rules
|
package/core/naming.md
CHANGED
|
@@ -2,81 +2,116 @@
|
|
|
2
2
|
|
|
3
3
|
> Covers all `@directive-run/*` packages — terminology, parameter names, return-style rules.
|
|
4
4
|
|
|
5
|
-
Directive
|
|
5
|
+
Directive uses precise vocabulary by design: each concept has one canonical name across every package, every language adapter, and every doc. The names are non-negotiable for code Directive ships, AND every term has a cross-paradigm alias so a developer coming from Redux / Zustand / XState / Jotai / React Query can find the right Directive concept on the first search.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
This file is both the rules and the bridge. Search for the term you already know; you'll land on the Directive equivalent.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
Resolver parameter names?
|
|
11
|
-
→ (req, context) req = requirement, NEVER "request"
|
|
12
|
-
→ NEVER (req, ctx) context is NEVER abbreviated
|
|
9
|
+
## Coming from another library? Start here
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
| If you call it… | (in this library) | Directive calls it… | Why the name |
|
|
12
|
+
|---|---|---|---|
|
|
13
|
+
| **state**, **store**, **atom**, **signal**, **observable** | Redux, Zustand, Jotai, Preact Signals, MobX | **facts** | "Facts about the world" — the system observes them. Same value-bag role as state, with a proxy that auto-tracks reads. |
|
|
14
|
+
| **selector**, **computed**, **getter**, **memo**, **derived store** | Redux, Vue/MobX, Zustand getters, Memoize, Svelte | **derivations** / `derive` | Auto-tracked computed values. No dep arrays. Directive's name aligns with "derived from facts." |
|
|
15
|
+
| **action**, **dispatch**, **reducer**, **command**, **intent** | Redux, Redux Toolkit, CQRS | **events** + **resolvers** | Events are the user-facing trigger; resolvers fulfill them. Reducers are split into the two halves Directive cares about. |
|
|
16
|
+
| **thunk**, **saga**, **effect**, **middleware**, **listener** | Redux Toolkit, redux-saga, redux-observable, NgRx | **resolvers** | Async logic that mutates state in response to a requirement. Same role as a thunk; declared once, run by the runtime. |
|
|
17
|
+
| **rule**, **condition**, **guard**, **trigger**, **policy** | XState guards, Cerbos, OPA, business-rule engines | **constraints** | Declarative "when X is true, Y must happen." Constraints emit requirements; resolvers fulfill them. |
|
|
18
|
+
| **request**, **query**, **side-effect spec** | React Query / TanStack Query queries, Apollo queries | **requirements** | The object a constraint emits. The runtime dedupes them, dispatches to resolvers, tracks status. |
|
|
19
|
+
| **subscription**, **listener**, **reaction**, **watcher** | Zustand subscribe, MobX reactions, Redux subscriptions | **effects** | Side-effects that run when watched facts change. Cleaner than `subscribe()` callbacks because effects auto-track. |
|
|
20
|
+
| **slice**, **feature**, **domain**, **bounded context** | Redux Toolkit slices, NgRx feature modules | **modules** | Encapsulates facts + derivations + constraints + resolvers + events for one bounded slice of the system. |
|
|
21
|
+
| **store**, **container**, **context**, **app state** | Redux Store, Pinia, React Context, NgRx Store | **system** | The runtime that wires modules together, evaluates constraints, dispatches resolvers, and exposes observation. |
|
|
22
|
+
| **state machine**, **statechart**, **xstate machine** | XState | (closest: **module** + **constraints**) | Directive isn't a state machine — but if your XState `states` model business rules (not UI flow), constraints + facts express the same logic declaratively with no transition functions. |
|
|
23
|
+
| **cache**, **query cache**, **stale-while-revalidate** | TanStack Query, SWR, Apollo cache | (closest: `@directive-run/query` + **constraints**) | Use `@directive-run/query` for the cache; constraints decide when refetches fire. Directive doesn't replace TanStack Query — it composes with it. |
|
|
24
|
+
| **agent**, **chain**, **graph**, **workflow** | LangChain, LangGraph, OpenAI Assistants | **agent** + **orchestrator** | `@directive-run/ai` keeps the names — agents are agents, orchestrators are orchestrators — but they run under the same constraint engine as the rest of Directive. |
|
|
25
|
+
| **guardrail**, **filter**, **safety check**, **moderation** | OpenAI moderation API, NVIDIA NeMo Guardrails | **guardrails** | Same name, same role; declarative input/output/tool-call checks. |
|
|
17
26
|
|
|
18
|
-
|
|
19
|
-
→ "facts" NEVER "state", "store", "atoms"
|
|
20
|
-
→ system.facts.count NEVER system.state.count
|
|
27
|
+
If your term isn't in the table, search the canonical name in this doc's [Terminology quick reference](#terminology-quick-reference) — both directions are listed.
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
→ "constraints" NEVER "rules", "conditions", "triggers"
|
|
24
|
-
→ when() + require() NEVER if/then, trigger/action
|
|
29
|
+
## Canonical terms (non-negotiable for code Directive ships)
|
|
25
30
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
Above is the bridge from your existing vocabulary. Below are the canonical names — the only ones that should appear in `@directive-run/*` source, tests, docs, and generated AI rules.
|
|
32
|
+
|
|
33
|
+
### `facts` — the value bag
|
|
34
|
+
|
|
35
|
+
Not state, not store, not atoms. **Facts.** Accessed at `system.facts.x`. Mutated through events and resolvers. Read through derivations, hooks, and `system.facts.$store`.
|
|
36
|
+
|
|
37
|
+
### `derivations` — auto-tracked computed values
|
|
38
|
+
|
|
39
|
+
Declared via `derive: { name: (facts) => … }`. Read at `system.derive.name`. The hook is `useDerived` (not `useComputed`, not `useSelector` — Directive's `useSelector` is a different, broader primitive that takes a selector function).
|
|
40
|
+
|
|
41
|
+
### `constraints` — when-then declarations
|
|
42
|
+
|
|
43
|
+
Declared via `constraints: { name: { when: …, require: … } }`. The `when` returns a boolean; the `require` returns a requirement.
|
|
44
|
+
|
|
45
|
+
### `resolvers` — requirement fulfillment
|
|
46
|
+
|
|
47
|
+
Declared via `resolvers: { name: { requirement: …, resolve: async (req, context) => … } }`. Mutate `context.facts`; never return data from `resolve`.
|
|
48
|
+
|
|
49
|
+
### `requirements` — what constraints emit
|
|
50
|
+
|
|
51
|
+
Tagged union `{ type: "FETCH_USER", … }`. Constraints emit them; the runtime dedupes by `type` + `key()`; resolvers fulfill them.
|
|
52
|
+
|
|
53
|
+
### `effects` — side effects from watched changes
|
|
54
|
+
|
|
55
|
+
Declared via `effects: { name: { run: (facts, prev) => … } }`. Run on relevant fact changes. The auto-tracking dependency model means no `deps` array unless you specifically need a partial dep set.
|
|
56
|
+
|
|
57
|
+
### `events` — typed mutation entry points
|
|
58
|
+
|
|
59
|
+
Declared via `events: { name: (facts, payload) => … }`. Called as `system.events.name(payload)`. The typed events accessor is the canonical way to dispatch — `system.dispatch({type, ...payload})` works but the typed accessor carries autocomplete.
|
|
30
60
|
|
|
31
|
-
|
|
61
|
+
### `module` — bounded slice
|
|
62
|
+
|
|
63
|
+
Created via `createModule(name, { schema, init, derive, effects, events, constraints, resolvers })`. Composes into systems.
|
|
64
|
+
|
|
65
|
+
### `system` — the runtime
|
|
66
|
+
|
|
67
|
+
Created via `createSystem({ module })` or `createSystem({ modules: { x, y } })`. Hosts the reconciliation loop.
|
|
68
|
+
|
|
69
|
+
## Parameter naming
|
|
32
70
|
|
|
33
71
|
### `req` = requirement (NOT request)
|
|
34
72
|
|
|
35
|
-
The `req` parameter in resolvers and constraint `key()` functions is short for **requirement**
|
|
73
|
+
The `req` parameter in resolvers and constraint `key()` functions is short for **requirement** — the object emitted by a constraint's `require` property.
|
|
36
74
|
|
|
37
75
|
```typescript
|
|
38
|
-
// CORRECT
|
|
76
|
+
// CORRECT — req is a requirement
|
|
39
77
|
resolvers: {
|
|
40
78
|
fetchUser: {
|
|
41
79
|
requirement: "FETCH_USER",
|
|
42
80
|
key: (req) => `fetch-${req.userId}`,
|
|
43
81
|
resolve: async (req, context) => {
|
|
44
82
|
// req.type === "FETCH_USER"
|
|
45
|
-
// req.userId from the requirement payload
|
|
46
83
|
const user = await fetchUser(req.userId);
|
|
47
84
|
context.facts.user = user;
|
|
48
85
|
},
|
|
49
86
|
},
|
|
50
87
|
},
|
|
51
88
|
|
|
52
|
-
// WRONG
|
|
89
|
+
// WRONG — never "request" or "r"
|
|
53
90
|
resolve: async (request, context) => { /* ... */ },
|
|
54
91
|
resolve: async (r, context) => { /* ... */ },
|
|
55
92
|
```
|
|
56
93
|
|
|
57
|
-
### `context` is
|
|
94
|
+
### `context` is never abbreviated
|
|
58
95
|
|
|
59
96
|
```typescript
|
|
60
97
|
// CORRECT
|
|
61
98
|
resolve: async (req, context) => {
|
|
62
99
|
context.facts.status = "loaded";
|
|
63
|
-
context.signal;
|
|
64
|
-
context.snapshot();
|
|
100
|
+
context.signal; // AbortSignal
|
|
101
|
+
context.snapshot(); // facts snapshot
|
|
65
102
|
},
|
|
66
103
|
|
|
67
|
-
// WRONG
|
|
104
|
+
// WRONG — never abbreviate to ctx
|
|
68
105
|
resolve: async (req, ctx) => { /* ... */ },
|
|
69
106
|
```
|
|
70
107
|
|
|
71
|
-
## Return
|
|
108
|
+
## Return style
|
|
72
109
|
|
|
73
|
-
###
|
|
110
|
+
### Braces for `if` blocks with `return` (NOT for arrow expressions)
|
|
74
111
|
|
|
75
112
|
The brace rule applies to control-flow blocks — not to arrow-expression bodies.
|
|
76
113
|
|
|
77
|
-
**Arrow expressions** (single-line derivations, predicates, computed
|
|
78
|
-
requirements): the concise form is preferred. No braces, no explicit
|
|
79
|
-
`return`.
|
|
114
|
+
**Arrow expressions** (single-line derivations, predicates, computed requirements): the concise form is preferred. No braces, no explicit `return`.
|
|
80
115
|
|
|
81
116
|
```typescript
|
|
82
117
|
// CORRECT — single-line arrow expressions stay concise
|
|
@@ -93,25 +128,24 @@ constraints: {
|
|
|
93
128
|
},
|
|
94
129
|
```
|
|
95
130
|
|
|
96
|
-
**Control-flow statements** (`if`, `for`, `while`): braces required, even
|
|
97
|
-
for single-line bodies. Single-line `if (x) return y` shapes are never used.
|
|
131
|
+
**Control-flow statements** (`if`, `for`, `while`): braces required, even for single-line bodies. Single-line `if (x) return y` shapes are never used.
|
|
98
132
|
|
|
99
133
|
```typescript
|
|
100
|
-
// WRONG
|
|
134
|
+
// WRONG — single-line if return
|
|
101
135
|
if (facts.user) return "ready";
|
|
102
136
|
|
|
103
|
-
// CORRECT
|
|
137
|
+
// CORRECT — always wrap the body in braces
|
|
104
138
|
if (facts.user) {
|
|
105
139
|
return "ready";
|
|
106
140
|
}
|
|
107
141
|
```
|
|
108
142
|
|
|
109
|
-
### Blank
|
|
143
|
+
### Blank line before `return`
|
|
110
144
|
|
|
111
145
|
Add a blank line before `return` when there is code above it. Skip the blank line when `return` is the first statement in a block.
|
|
112
146
|
|
|
113
147
|
```typescript
|
|
114
|
-
// CORRECT
|
|
148
|
+
// CORRECT — blank line before return when code precedes it
|
|
115
149
|
function getStatus(facts) {
|
|
116
150
|
const phase = facts.phase;
|
|
117
151
|
const hasUser = facts.user !== null;
|
|
@@ -119,12 +153,12 @@ function getStatus(facts) {
|
|
|
119
153
|
return phase === "ready" && hasUser;
|
|
120
154
|
}
|
|
121
155
|
|
|
122
|
-
// CORRECT
|
|
156
|
+
// CORRECT — no blank line when return is first statement
|
|
123
157
|
function isReady(facts) {
|
|
124
158
|
return facts.phase === "ready";
|
|
125
159
|
}
|
|
126
160
|
|
|
127
|
-
// CORRECT
|
|
161
|
+
// CORRECT — blank line after brace-style return block
|
|
128
162
|
function process(facts) {
|
|
129
163
|
if (!facts.ready) {
|
|
130
164
|
return null;
|
|
@@ -134,26 +168,20 @@ function process(facts) {
|
|
|
134
168
|
|
|
135
169
|
return result;
|
|
136
170
|
}
|
|
137
|
-
|
|
138
|
-
// WRONG – no blank line before return after code
|
|
139
|
-
function getStatus(facts) {
|
|
140
|
-
const phase = facts.phase;
|
|
141
|
-
return phase === "ready"; // Missing blank line
|
|
142
|
-
}
|
|
143
171
|
```
|
|
144
172
|
|
|
145
|
-
## Multi-
|
|
173
|
+
## Multi-line code formatting
|
|
146
174
|
|
|
147
175
|
Never put properties or statements on a single line inside braces. Always expand to one item per line with proper indentation. This applies everywhere: schema definitions, init functions, events, effects, requirement types, and any other object or block.
|
|
148
176
|
|
|
149
177
|
```typescript
|
|
150
|
-
// WRONG
|
|
178
|
+
// WRONG — properties crammed on one line
|
|
151
179
|
schema: {
|
|
152
180
|
facts: { phase: t.string(), count: t.number() },
|
|
153
181
|
requirements: { FETCH_USER: { id: t.string() }, RESET: {} },
|
|
154
182
|
},
|
|
155
183
|
|
|
156
|
-
// CORRECT
|
|
184
|
+
// CORRECT — one property per line, always expanded
|
|
157
185
|
schema: {
|
|
158
186
|
facts: {
|
|
159
187
|
phase: t.string(),
|
|
@@ -167,41 +195,31 @@ schema: {
|
|
|
167
195
|
},
|
|
168
196
|
},
|
|
169
197
|
|
|
170
|
-
// WRONG
|
|
198
|
+
// WRONG — statements crammed on one line
|
|
171
199
|
init: (facts) => { facts.phase = "idle"; facts.count = 0; },
|
|
172
200
|
|
|
173
|
-
// CORRECT
|
|
201
|
+
// CORRECT — one statement per line
|
|
174
202
|
init: (facts) => {
|
|
175
203
|
facts.phase = "idle";
|
|
176
204
|
facts.count = 0;
|
|
177
205
|
},
|
|
178
|
-
|
|
179
|
-
// WRONG
|
|
180
|
-
events: { reset: (facts) => { facts.count = 0; facts.phase = "idle"; } },
|
|
181
|
-
|
|
182
|
-
// CORRECT
|
|
183
|
-
events: {
|
|
184
|
-
reset: (facts) => {
|
|
185
|
-
facts.count = 0;
|
|
186
|
-
facts.phase = "idle";
|
|
187
|
-
},
|
|
188
|
-
},
|
|
189
206
|
```
|
|
190
207
|
|
|
191
208
|
Single-expression arrows (no braces) are fine on one line. Empty objects `{}` are fine inline.
|
|
209
|
+
|
|
192
210
|
```typescript
|
|
193
|
-
// OK
|
|
211
|
+
// OK — single expression, no braces
|
|
194
212
|
derive: {
|
|
195
213
|
isReady: (facts) => facts.phase === "ready",
|
|
196
214
|
},
|
|
197
215
|
|
|
198
|
-
// OK
|
|
216
|
+
// OK — empty object
|
|
199
217
|
RESET: {},
|
|
200
218
|
```
|
|
201
219
|
|
|
202
|
-
## Multi-
|
|
220
|
+
## Multi-module naming
|
|
203
221
|
|
|
204
|
-
### `facts.self.*` for
|
|
222
|
+
### `facts.self.*` for own module
|
|
205
223
|
|
|
206
224
|
In multi-module systems, constraints, effects, and derivations with `crossModuleDeps` receive namespaced facts. Own module facts are always at `facts.self.*`.
|
|
207
225
|
|
|
@@ -214,7 +232,7 @@ constraints: {
|
|
|
214
232
|
},
|
|
215
233
|
},
|
|
216
234
|
|
|
217
|
-
// WRONG
|
|
235
|
+
// WRONG — bare facts.* in multi-module context
|
|
218
236
|
constraints: {
|
|
219
237
|
loadWhenAuth: {
|
|
220
238
|
when: (facts) => facts.isAuthenticated && !facts.loaded,
|
|
@@ -223,48 +241,48 @@ constraints: {
|
|
|
223
241
|
},
|
|
224
242
|
```
|
|
225
243
|
|
|
226
|
-
### System-
|
|
244
|
+
### System-level access uses dot notation
|
|
227
245
|
|
|
228
246
|
```typescript
|
|
229
|
-
// CORRECT
|
|
247
|
+
// CORRECT — dot notation through namespace proxy
|
|
230
248
|
system.facts.auth.token;
|
|
231
249
|
system.facts.cart.items;
|
|
232
250
|
system.derive.auth.isLoggedIn;
|
|
233
251
|
system.events.auth.login({ token: "..." });
|
|
234
252
|
|
|
235
|
-
// WRONG
|
|
253
|
+
// WRONG — bracket notation with internal separator
|
|
236
254
|
system.facts["auth::token"];
|
|
237
255
|
system.facts["auth_token"];
|
|
238
256
|
```
|
|
239
257
|
|
|
240
|
-
## Type
|
|
258
|
+
## Type casting rules
|
|
241
259
|
|
|
242
|
-
### Never
|
|
260
|
+
### Never cast when reading
|
|
243
261
|
|
|
244
262
|
The schema provides all types. Do not add `as` casts when reading facts or derivations from the system.
|
|
245
263
|
|
|
246
264
|
```typescript
|
|
247
|
-
// CORRECT
|
|
265
|
+
// CORRECT — schema provides the type
|
|
248
266
|
const profile = system.facts.profile;
|
|
249
267
|
const isReady = system.derive.isReady;
|
|
250
268
|
|
|
251
|
-
// WRONG
|
|
269
|
+
// WRONG — unnecessary cast
|
|
252
270
|
const profile = system.facts.profile as UserProfile;
|
|
253
271
|
const isReady = system.derive.isReady as boolean;
|
|
254
272
|
```
|
|
255
273
|
|
|
256
|
-
### Cast
|
|
274
|
+
### Cast only in schema definition
|
|
257
275
|
|
|
258
|
-
Type assertions are only valid in schema definition using the `{} as {}` pattern:
|
|
276
|
+
Type assertions are only valid in schema definition using the `{} as {}` pattern, or via the `t.*` builders (preferred):
|
|
259
277
|
|
|
260
278
|
```typescript
|
|
261
|
-
// CORRECT
|
|
279
|
+
// CORRECT — cast in schema definition
|
|
262
280
|
schema: {
|
|
263
281
|
facts: {} as { profile: UserProfile; settings: AppSettings },
|
|
264
282
|
derivations: {} as { displayName: string },
|
|
265
283
|
},
|
|
266
284
|
|
|
267
|
-
//
|
|
285
|
+
// PREFERRED — t.* builders
|
|
268
286
|
schema: {
|
|
269
287
|
facts: {
|
|
270
288
|
profile: t.object<UserProfile>(),
|
|
@@ -276,17 +294,28 @@ schema: {
|
|
|
276
294
|
},
|
|
277
295
|
```
|
|
278
296
|
|
|
279
|
-
## Terminology
|
|
297
|
+
## Terminology quick reference
|
|
298
|
+
|
|
299
|
+
Two-way lookup. Search the term you know.
|
|
280
300
|
|
|
281
|
-
| Directive
|
|
301
|
+
| Directive term | Cross-paradigm aliases (use these to search) |
|
|
282
302
|
|---|---|
|
|
283
|
-
| facts | state, store, atoms, signals |
|
|
284
|
-
| derivations / derive | computed, selectors, getters, memos |
|
|
285
|
-
| constraints | rules, conditions, triggers, guards |
|
|
286
|
-
| resolvers | handlers, actions, reducers, sagas |
|
|
287
|
-
| requirements | requests, commands, intents |
|
|
288
|
-
| effects | watchers, subscriptions, reactions |
|
|
289
|
-
|
|
|
290
|
-
|
|
|
291
|
-
|
|
|
292
|
-
|
|
|
303
|
+
| **facts** | state, store, atoms, signals, observables, model |
|
|
304
|
+
| **derivations** / `derive` | computed, selectors, getters, memos, derived stores, $: blocks (Svelte) |
|
|
305
|
+
| **constraints** | rules, conditions, triggers, guards, policies, invariants |
|
|
306
|
+
| **resolvers** | handlers, actions, reducers, sagas, thunks, effects (Redux), middleware, listeners |
|
|
307
|
+
| **requirements** | requests, commands, intents, queries (TanStack), tasks |
|
|
308
|
+
| **effects** | watchers, subscriptions, reactions, autoruns, listeners |
|
|
309
|
+
| **events** | actions, intents, commands, methods (Pinia), signals (NgRx) |
|
|
310
|
+
| **module** | slice, feature, domain, bounded context, NgRx feature module |
|
|
311
|
+
| **system** | store, container, context, app state, app shell |
|
|
312
|
+
| **`req`** (parameter) | request, r, requirement (spelled out) |
|
|
313
|
+
| **`context`** (parameter) | ctx, c, resolverContext |
|
|
314
|
+
|
|
315
|
+
The forbidden direction is also non-negotiable: in code Directive ships, the columns reverse. Do NOT use `state`, `store`, `selectors`, `computed`, `actions`, `reducers`, `subscriptions`, `slices`, `request`, or `ctx` in `@directive-run/*` source. The alias map is for retrieval — the canonical names are for code.
|
|
316
|
+
|
|
317
|
+
## See also
|
|
318
|
+
|
|
319
|
+
- [`core-patterns.md`](./core-patterns.md) — the actual code shapes every naming rule here applies to
|
|
320
|
+
- [`multi-module.md`](./multi-module.md) — `facts.self.*` convention and dot-notation rules
|
|
321
|
+
- [`anti-patterns.md`](./anti-patterns.md) — naming-shaped mistakes (`request` for `req`, `ctx` for `context`, hallucinated TS schema types)
|
package/core/plugins.md
CHANGED
|
@@ -354,3 +354,8 @@ persistencePlugin({
|
|
|
354
354
|
exclude: ["authToken", "isLoading", "error"],
|
|
355
355
|
})
|
|
356
356
|
```
|
|
357
|
+
|
|
358
|
+
## See also
|
|
359
|
+
|
|
360
|
+
- [`system-api.md`](./system-api.md) — `plugins:` option on `createSystem` and the lifecycle hooks plugins observe
|
|
361
|
+
- [`error-boundaries.md`](./error-boundaries.md) — `createCircuitBreaker` and the resilience plugins that pair with error boundaries
|
package/core/react-adapter.md
CHANGED
|
@@ -368,3 +368,9 @@ const handleClick = useCallback(() => events.increment(), [events]);
|
|
|
368
368
|
const events = useEvents(system);
|
|
369
369
|
<button onClick={() => events.increment()}>+</button>
|
|
370
370
|
```
|
|
371
|
+
|
|
372
|
+
## See also
|
|
373
|
+
|
|
374
|
+
- [`system-api.md`](./system-api.md) — the system instance the hooks here read from + the SSR/hydration story
|
|
375
|
+
- [`core-patterns.md`](./core-patterns.md) — the module shape every React example here assumes you've built
|
|
376
|
+
- [`anti-patterns.md`](./anti-patterns.md) — the hallucinated React hooks (`useEvent`, `useSystem`, `DirectiveProvider`) that AI assistants reach for
|
package/core/resolvers.md
CHANGED
|
@@ -357,3 +357,11 @@ system.start();
|
|
|
357
357
|
await system.settle();
|
|
358
358
|
console.log(system.facts.data); // Resolved value
|
|
359
359
|
```
|
|
360
|
+
|
|
361
|
+
## See also
|
|
362
|
+
|
|
363
|
+
- [`constraints.md`](./constraints.md) — the demand side of the loop; what emits the requirements this resolver fulfills
|
|
364
|
+
- [`core-patterns.md`](./core-patterns.md) — how resolvers fit into the module shape
|
|
365
|
+
- [`error-boundaries.md`](./error-boundaries.md) — recovery strategies when a resolver throws (retry, fallback, circuit breaker)
|
|
366
|
+
- [`testing.md`](./testing.md) — mock resolvers via `mocks.resolvers` and the programmatic `mockResolver(type)` helper
|
|
367
|
+
- [`anti-patterns.md`](./anti-patterns.md) — the resolver-shaped mistakes (returning data from `resolve`, abbreviating `context` to `ctx`)
|
package/core/schema-types.md
CHANGED
|
@@ -265,3 +265,9 @@ const myModule = createModule("simple", {
|
|
|
265
265
|
```
|
|
266
266
|
|
|
267
267
|
This gives full TypeScript inference but skips runtime validation. Use `t.*()` when you want dev-mode validation, transforms, or self-documenting schemas.
|
|
268
|
+
|
|
269
|
+
## See also
|
|
270
|
+
|
|
271
|
+
- [`core-patterns.md`](./core-patterns.md) — where the schemas these builders define get attached (modules)
|
|
272
|
+
- [`system-api.md`](./system-api.md) — schema flows through `createSystem` and shows up on `system.facts.*`
|
|
273
|
+
- [`anti-patterns.md`](./anti-patterns.md) — hallucinated schema types (`t.map`, `t.set`, `t.date`, `t.promise`, `t.tuple`, `t.record`, `t.any`) that don't exist
|
package/core/system-api.md
CHANGED
|
@@ -453,3 +453,11 @@ system.start();
|
|
|
453
453
|
system.stop();
|
|
454
454
|
system.destroy();
|
|
455
455
|
```
|
|
456
|
+
|
|
457
|
+
## See also
|
|
458
|
+
|
|
459
|
+
- [`core-patterns.md`](./core-patterns.md) — the modules that go into `createSystem({ module: ... })`
|
|
460
|
+
- [`multi-module.md`](./multi-module.md) — `createSystem({ modules: { ... } })` for namespaced systems
|
|
461
|
+
- [`history.md`](./history.md) — the `history:` config and the `system.history.*` time-travel surface
|
|
462
|
+
- [`plugins.md`](./plugins.md) — the `plugins:` config and the lifecycle hooks plugins observe
|
|
463
|
+
- [`react-adapter.md`](./react-adapter.md) — consuming a system from React components
|
package/core/testing.md
CHANGED
|
@@ -404,3 +404,9 @@ resolve: (req, context) => { context.facts.x = 1; }
|
|
|
404
404
|
| `system.assertFactSet(key, value?)` | instance method | Assert a fact value |
|
|
405
405
|
| `system.assertFactChanges(key, n)` | instance method | Assert the change count for a fact |
|
|
406
406
|
| `system.waitForIdle(maxWait?)` | instance method | Wait for in-flight resolvers (default 5000ms) |
|
|
407
|
+
|
|
408
|
+
## See also
|
|
409
|
+
|
|
410
|
+
- [`resolvers.md`](./resolvers.md) — the resolver shape `mocks.resolvers` replaces and the retry/cancel semantics tests need to know about
|
|
411
|
+
- [`core-patterns.md`](./core-patterns.md) — the module shape `createTestSystem({ module })` is testing
|
|
412
|
+
- [`history.md`](./history.md) — recorded snapshots for replay-based testing patterns
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@directive-run/knowledge",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.0",
|
|
4
4
|
"description": "Knowledge files, examples, and validation for Directive — the constraint-driven TypeScript runtime.",
|
|
5
5
|
"license": "(MIT OR Apache-2.0)",
|
|
6
6
|
"author": "Jason Comes",
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
"tsx": "^4.19.2",
|
|
52
52
|
"typescript": "^5.7.2",
|
|
53
53
|
"vitest": "^3.0.0",
|
|
54
|
-
"@directive-run/core": "1.
|
|
55
|
-
"@directive-run/ai": "1.
|
|
54
|
+
"@directive-run/core": "1.16.0",
|
|
55
|
+
"@directive-run/ai": "1.16.0"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "tsx scripts/generate-api-skeleton.ts && tsx scripts/generate-sitemap.ts && tsx scripts/extract-examples.ts && tsup",
|