@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.
- package/LICENSE +21 -0
- package/README.md +63 -0
- package/ai/ai-adapters.md +250 -0
- package/ai/ai-agents-streaming.md +269 -0
- package/ai/ai-budget-resilience.md +235 -0
- package/ai/ai-communication.md +281 -0
- package/ai/ai-debug-observability.md +243 -0
- package/ai/ai-guardrails-memory.md +332 -0
- package/ai/ai-mcp-rag.md +288 -0
- package/ai/ai-multi-agent.md +274 -0
- package/ai/ai-orchestrator.md +227 -0
- package/ai/ai-security.md +293 -0
- package/ai/ai-tasks.md +261 -0
- package/ai/ai-testing-evals.md +378 -0
- package/api-skeleton.md +5 -0
- package/core/anti-patterns.md +382 -0
- package/core/constraints.md +263 -0
- package/core/core-patterns.md +228 -0
- package/core/error-boundaries.md +322 -0
- package/core/multi-module.md +315 -0
- package/core/naming.md +283 -0
- package/core/plugins.md +344 -0
- package/core/react-adapter.md +262 -0
- package/core/resolvers.md +357 -0
- package/core/schema-types.md +262 -0
- package/core/system-api.md +271 -0
- package/core/testing.md +257 -0
- package/core/time-travel.md +238 -0
- package/dist/index.cjs +111 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +102 -0
- package/dist/index.js.map +1 -0
- package/examples/ab-testing.ts +385 -0
- package/examples/ai-checkpoint.ts +509 -0
- package/examples/ai-guardrails.ts +319 -0
- package/examples/ai-orchestrator.ts +589 -0
- package/examples/async-chains.ts +287 -0
- package/examples/auth-flow.ts +371 -0
- package/examples/batch-resolver.ts +341 -0
- package/examples/checkers.ts +589 -0
- package/examples/contact-form.ts +176 -0
- package/examples/counter.ts +393 -0
- package/examples/dashboard-loader.ts +512 -0
- package/examples/debounce-constraints.ts +105 -0
- package/examples/dynamic-modules.ts +293 -0
- package/examples/error-boundaries.ts +430 -0
- package/examples/feature-flags.ts +220 -0
- package/examples/form-wizard.ts +347 -0
- package/examples/fraud-analysis.ts +663 -0
- package/examples/goal-heist.ts +341 -0
- package/examples/multi-module.ts +57 -0
- package/examples/newsletter.ts +241 -0
- package/examples/notifications.ts +210 -0
- package/examples/optimistic-updates.ts +317 -0
- package/examples/pagination.ts +260 -0
- package/examples/permissions.ts +337 -0
- package/examples/provider-routing.ts +403 -0
- package/examples/server.ts +316 -0
- package/examples/shopping-cart.ts +422 -0
- package/examples/sudoku.ts +630 -0
- package/examples/theme-locale.ts +204 -0
- package/examples/time-machine.ts +225 -0
- package/examples/topic-guard.ts +306 -0
- package/examples/url-sync.ts +333 -0
- package/examples/websocket.ts +404 -0
- package/package.json +65 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
// Example: ai-guardrails
|
|
2
|
+
// Source: examples/ai-guardrails/src/main.ts
|
|
3
|
+
// Extracted for AI rules — DOM wiring stripped
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* AI Safety Shield — Prompt Injection & PII Detection
|
|
7
|
+
*
|
|
8
|
+
* Chat interface where every message passes through prompt injection detection,
|
|
9
|
+
* PII detection, and compliance checks. All run locally using built-in patterns.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
type InjectionDetectionResult,
|
|
14
|
+
type PIIDetectionResult,
|
|
15
|
+
detectPII,
|
|
16
|
+
detectPromptInjection,
|
|
17
|
+
} from "@directive-run/ai";
|
|
18
|
+
import {
|
|
19
|
+
type ModuleSchema,
|
|
20
|
+
createModule,
|
|
21
|
+
createSystem,
|
|
22
|
+
t,
|
|
23
|
+
} from "@directive-run/core";
|
|
24
|
+
import { devtoolsPlugin, emitDevToolsEvent } from "@directive-run/core/plugins";
|
|
25
|
+
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Types
|
|
28
|
+
// ============================================================================
|
|
29
|
+
|
|
30
|
+
interface ChatMessage {
|
|
31
|
+
id: string;
|
|
32
|
+
text: string;
|
|
33
|
+
blocked: boolean;
|
|
34
|
+
redactedText: string;
|
|
35
|
+
injectionResult: InjectionDetectionResult | null;
|
|
36
|
+
piiResult: PIIDetectionResult | null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface TimelineEntry {
|
|
40
|
+
time: number;
|
|
41
|
+
event: string;
|
|
42
|
+
detail: string;
|
|
43
|
+
type: "pass" | "injection" | "pii" | "compliance" | "info";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type ComplianceMode = "standard" | "gdpr" | "hipaa";
|
|
47
|
+
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// Timeline
|
|
50
|
+
// ============================================================================
|
|
51
|
+
|
|
52
|
+
const timeline: TimelineEntry[] = [];
|
|
53
|
+
|
|
54
|
+
function addTimeline(
|
|
55
|
+
event: string,
|
|
56
|
+
detail: string,
|
|
57
|
+
type: TimelineEntry["type"],
|
|
58
|
+
) {
|
|
59
|
+
timeline.unshift({ time: Date.now(), event, detail, type });
|
|
60
|
+
if (timeline.length > 50) {
|
|
61
|
+
timeline.length = 50;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ============================================================================
|
|
66
|
+
// Schema
|
|
67
|
+
// ============================================================================
|
|
68
|
+
|
|
69
|
+
const schema = {
|
|
70
|
+
facts: {
|
|
71
|
+
messages: t.object<ChatMessage[]>(),
|
|
72
|
+
complianceMode: t.string<ComplianceMode>(),
|
|
73
|
+
redactionEnabled: t.boolean(),
|
|
74
|
+
blockedCount: t.number(),
|
|
75
|
+
injectionAttempts: t.number(),
|
|
76
|
+
piiDetections: t.number(),
|
|
77
|
+
complianceBlocks: t.number(),
|
|
78
|
+
},
|
|
79
|
+
derivations: {
|
|
80
|
+
messageCount: t.number(),
|
|
81
|
+
blockRate: t.string(),
|
|
82
|
+
piiTypeCounts: t.string(),
|
|
83
|
+
},
|
|
84
|
+
events: {
|
|
85
|
+
setComplianceMode: { value: t.string() },
|
|
86
|
+
toggleRedaction: {},
|
|
87
|
+
clearHistory: {},
|
|
88
|
+
},
|
|
89
|
+
requirements: {},
|
|
90
|
+
} satisfies ModuleSchema;
|
|
91
|
+
|
|
92
|
+
// ============================================================================
|
|
93
|
+
// Module
|
|
94
|
+
// ============================================================================
|
|
95
|
+
|
|
96
|
+
const guardrailModule = createModule("guardrails", {
|
|
97
|
+
schema,
|
|
98
|
+
|
|
99
|
+
init: (facts) => {
|
|
100
|
+
facts.messages = [];
|
|
101
|
+
facts.complianceMode = "standard";
|
|
102
|
+
facts.redactionEnabled = true;
|
|
103
|
+
facts.blockedCount = 0;
|
|
104
|
+
facts.injectionAttempts = 0;
|
|
105
|
+
facts.piiDetections = 0;
|
|
106
|
+
facts.complianceBlocks = 0;
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
derive: {
|
|
110
|
+
messageCount: (facts) => facts.messages.length,
|
|
111
|
+
blockRate: (facts) => {
|
|
112
|
+
if (facts.messages.length === 0) {
|
|
113
|
+
return "0%";
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const blocked = (facts.messages as ChatMessage[]).filter(
|
|
117
|
+
(m) => m.blocked,
|
|
118
|
+
).length;
|
|
119
|
+
|
|
120
|
+
return `${Math.round((blocked / facts.messages.length) * 100)}%`;
|
|
121
|
+
},
|
|
122
|
+
piiTypeCounts: (facts) => {
|
|
123
|
+
const counts: Record<string, number> = {};
|
|
124
|
+
for (const msg of facts.messages as ChatMessage[]) {
|
|
125
|
+
if (msg.piiResult?.detected) {
|
|
126
|
+
for (const item of msg.piiResult.items) {
|
|
127
|
+
counts[item.type] = (counts[item.type] ?? 0) + 1;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
Object.entries(counts)
|
|
134
|
+
.map(([k, v]) => `${k}:${v}`)
|
|
135
|
+
.join(", ") || "none"
|
|
136
|
+
);
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
events: {
|
|
141
|
+
setComplianceMode: (facts, { value }) => {
|
|
142
|
+
facts.complianceMode = value as ComplianceMode;
|
|
143
|
+
},
|
|
144
|
+
toggleRedaction: (facts) => {
|
|
145
|
+
facts.redactionEnabled = !facts.redactionEnabled;
|
|
146
|
+
},
|
|
147
|
+
clearHistory: (facts) => {
|
|
148
|
+
facts.messages = [];
|
|
149
|
+
facts.blockedCount = 0;
|
|
150
|
+
facts.injectionAttempts = 0;
|
|
151
|
+
facts.piiDetections = 0;
|
|
152
|
+
facts.complianceBlocks = 0;
|
|
153
|
+
timeline.length = 0;
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// ============================================================================
|
|
159
|
+
// System
|
|
160
|
+
// ============================================================================
|
|
161
|
+
|
|
162
|
+
const system = createSystem({
|
|
163
|
+
module: guardrailModule,
|
|
164
|
+
debug: { runHistory: true },
|
|
165
|
+
plugins: [devtoolsPlugin({ name: "ai-guardrails" })],
|
|
166
|
+
});
|
|
167
|
+
system.start();
|
|
168
|
+
|
|
169
|
+
// ============================================================================
|
|
170
|
+
// Analysis Functions
|
|
171
|
+
// ============================================================================
|
|
172
|
+
|
|
173
|
+
function analyzeMessage(text: string): ChatMessage {
|
|
174
|
+
const id = `msg-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
|
175
|
+
let blocked = false;
|
|
176
|
+
|
|
177
|
+
// 1. Prompt injection detection
|
|
178
|
+
const injectionResult = detectPromptInjection(text);
|
|
179
|
+
if (injectionResult.detected) {
|
|
180
|
+
blocked = true;
|
|
181
|
+
system.facts.injectionAttempts =
|
|
182
|
+
(system.facts.injectionAttempts as number) + 1;
|
|
183
|
+
for (const p of injectionResult.patterns) {
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
emitDevToolsEvent({
|
|
188
|
+
type: "guardrail_check",
|
|
189
|
+
guardrailName: "prompt-injection",
|
|
190
|
+
guardrailType: "input",
|
|
191
|
+
passed: !injectionResult.detected,
|
|
192
|
+
inputLength: text.length,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// 2. PII detection
|
|
196
|
+
const piiResult = detectPII(text, {
|
|
197
|
+
redact: system.facts.redactionEnabled as boolean,
|
|
198
|
+
redactionStyle: "typed",
|
|
199
|
+
});
|
|
200
|
+
if (piiResult.detected) {
|
|
201
|
+
system.facts.piiDetections = (system.facts.piiDetections as number) + 1;
|
|
202
|
+
for (const item of piiResult.items) {
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
emitDevToolsEvent({
|
|
207
|
+
type: "guardrail_check",
|
|
208
|
+
guardrailName: "pii-detection",
|
|
209
|
+
guardrailType: "input",
|
|
210
|
+
passed: !piiResult.detected,
|
|
211
|
+
inputLength: text.length,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// 3. Compliance check
|
|
215
|
+
const mode = system.facts.complianceMode as ComplianceMode;
|
|
216
|
+
if (mode !== "standard" && piiResult.detected) {
|
|
217
|
+
const hasPHI = piiResult.items.some(
|
|
218
|
+
(i) =>
|
|
219
|
+
i.type === "medical_id" ||
|
|
220
|
+
i.type === "ssn" ||
|
|
221
|
+
i.type === "date_of_birth",
|
|
222
|
+
);
|
|
223
|
+
const hasContactInfo = piiResult.items.some(
|
|
224
|
+
(i) => i.type === "email" || i.type === "phone" || i.type === "name",
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
if (mode === "hipaa" && hasPHI) {
|
|
228
|
+
blocked = true;
|
|
229
|
+
system.facts.complianceBlocks =
|
|
230
|
+
(system.facts.complianceBlocks as number) + 1;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (mode === "gdpr" && hasContactInfo) {
|
|
234
|
+
blocked = true;
|
|
235
|
+
system.facts.complianceBlocks =
|
|
236
|
+
(system.facts.complianceBlocks as number) + 1;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
emitDevToolsEvent({
|
|
241
|
+
type: "guardrail_check",
|
|
242
|
+
guardrailName: `compliance-${mode}`,
|
|
243
|
+
guardrailType: "input",
|
|
244
|
+
passed: !blocked || !piiResult.detected,
|
|
245
|
+
inputLength: text.length,
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
if (blocked) {
|
|
249
|
+
system.facts.blockedCount = (system.facts.blockedCount as number) + 1;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (!blocked && !piiResult.detected) {
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
id,
|
|
258
|
+
text,
|
|
259
|
+
blocked,
|
|
260
|
+
redactedText,
|
|
261
|
+
injectionResult: injectionResult.detected ? injectionResult : null,
|
|
262
|
+
piiResult: piiResult.detected ? piiResult : null,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// ============================================================================
|
|
267
|
+
// DOM References
|
|
268
|
+
// ============================================================================
|
|
269
|
+
|
|
270
|
+
"gs-compliance",
|
|
271
|
+
"gs-redaction",
|
|
272
|
+
|
|
273
|
+
// Timeline
|
|
274
|
+
|
|
275
|
+
// Pre-built test buttons
|
|
276
|
+
|
|
277
|
+
// ============================================================================
|
|
278
|
+
// Render
|
|
279
|
+
// ============================================================================
|
|
280
|
+
|
|
281
|
+
function escapeHtml(text: string): string {
|
|
282
|
+
|
|
283
|
+
return div.innerHTML;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
// ============================================================================
|
|
288
|
+
// Subscribe
|
|
289
|
+
// ============================================================================
|
|
290
|
+
|
|
291
|
+
const allKeys = [
|
|
292
|
+
...Object.keys(schema.facts),
|
|
293
|
+
...Object.keys(schema.derivations),
|
|
294
|
+
];
|
|
295
|
+
system.subscribe(allKeys, render);
|
|
296
|
+
|
|
297
|
+
// ============================================================================
|
|
298
|
+
// Controls
|
|
299
|
+
// ============================================================================
|
|
300
|
+
|
|
301
|
+
function sendMessage(text: string) {
|
|
302
|
+
if (!text.trim()) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const msg = analyzeMessage(text);
|
|
307
|
+
const messages = [...(system.facts.messages as ChatMessage[]), msg];
|
|
308
|
+
system.facts.messages = messages;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
// Test buttons
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
// ============================================================================
|
|
316
|
+
// Initial Render
|
|
317
|
+
// ============================================================================
|
|
318
|
+
|
|
319
|
+
render();
|