@haikeilabs/agentware 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -0
- package/dist/evals/cases/file_search.d.ts +4 -0
- package/dist/evals/cases/file_search.d.ts.map +1 -0
- package/dist/evals/cases/file_search.js +99 -0
- package/dist/evals/cases/general.d.ts +4 -0
- package/dist/evals/cases/general.d.ts.map +1 -0
- package/dist/evals/cases/general.js +113 -0
- package/dist/evals/index.d.ts +5 -0
- package/dist/evals/index.d.ts.map +1 -0
- package/dist/evals/index.js +4 -0
- package/dist/evals/main.d.ts +2 -0
- package/dist/evals/main.d.ts.map +1 -0
- package/dist/evals/main.js +109 -0
- package/dist/evals/models.d.ts +38 -0
- package/dist/evals/models.d.ts.map +1 -0
- package/dist/evals/models.js +69 -0
- package/dist/evals/runner.d.ts +40 -0
- package/dist/evals/runner.d.ts.map +1 -0
- package/dist/evals/runner.js +131 -0
- package/dist/executor/executor.d.ts +42 -0
- package/dist/executor/executor.d.ts.map +1 -0
- package/dist/executor/executor.js +63 -0
- package/dist/executor/index.d.ts +2 -0
- package/dist/executor/index.d.ts.map +1 -0
- package/dist/executor/index.js +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/jobs/index.d.ts +3 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +2 -0
- package/dist/jobs/job.d.ts +18 -0
- package/dist/jobs/job.d.ts.map +1 -0
- package/dist/jobs/job.js +20 -0
- package/dist/jobs/manager.d.ts +23 -0
- package/dist/jobs/manager.d.ts.map +1 -0
- package/dist/jobs/manager.js +63 -0
- package/dist/llm/backend.d.ts +9 -0
- package/dist/llm/backend.d.ts.map +1 -0
- package/dist/llm/backend.js +1 -0
- package/dist/llm/index.d.ts +4 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +1 -0
- package/dist/llm/request.d.ts +28 -0
- package/dist/llm/request.d.ts.map +1 -0
- package/dist/llm/request.js +7 -0
- package/dist/llm/response.d.ts +17 -0
- package/dist/llm/response.d.ts.map +1 -0
- package/dist/llm/response.js +1 -0
- package/dist/llmcontext/context_window.d.ts +36 -0
- package/dist/llmcontext/context_window.d.ts.map +1 -0
- package/dist/llmcontext/context_window.js +115 -0
- package/dist/llmcontext/index.d.ts +4 -0
- package/dist/llmcontext/index.d.ts.map +1 -0
- package/dist/llmcontext/index.js +3 -0
- package/dist/llmcontext/manager.d.ts +27 -0
- package/dist/llmcontext/manager.d.ts.map +1 -0
- package/dist/llmcontext/manager.js +27 -0
- package/dist/llmcontext/strategies.d.ts +21 -0
- package/dist/llmcontext/strategies.d.ts.map +1 -0
- package/dist/llmcontext/strategies.js +180 -0
- package/dist/memory/client.d.ts +107 -0
- package/dist/memory/client.d.ts.map +1 -0
- package/dist/memory/client.js +210 -0
- package/dist/memory/index.d.ts +5 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +2 -0
- package/dist/memory/tools.d.ts +22 -0
- package/dist/memory/tools.d.ts.map +1 -0
- package/dist/memory/tools.js +57 -0
- package/dist/middleware/audit.d.ts +27 -0
- package/dist/middleware/audit.d.ts.map +1 -0
- package/dist/middleware/audit.js +26 -0
- package/dist/middleware/guardrails/error_tracker.d.ts +34 -0
- package/dist/middleware/guardrails/error_tracker.d.ts.map +1 -0
- package/dist/middleware/guardrails/error_tracker.js +70 -0
- package/dist/middleware/guardrails/nudge.d.ts +17 -0
- package/dist/middleware/guardrails/nudge.d.ts.map +1 -0
- package/dist/middleware/guardrails/nudge.js +67 -0
- package/dist/middleware/guardrails/response_validator.d.ts +29 -0
- package/dist/middleware/guardrails/response_validator.d.ts.map +1 -0
- package/dist/middleware/guardrails/response_validator.js +145 -0
- package/dist/middleware/guardrails/step_enforcer.d.ts +20 -0
- package/dist/middleware/guardrails/step_enforcer.d.ts.map +1 -0
- package/dist/middleware/guardrails/step_enforcer.js +65 -0
- package/dist/middleware/index.d.ts +5 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +4 -0
- package/dist/middleware/inference.d.ts +28 -0
- package/dist/middleware/inference.d.ts.map +1 -0
- package/dist/middleware/inference.js +141 -0
- package/dist/middleware/middleware.d.ts +22 -0
- package/dist/middleware/middleware.d.ts.map +1 -0
- package/dist/middleware/middleware.js +51 -0
- package/dist/middleware/policy.d.ts +46 -0
- package/dist/middleware/policy.d.ts.map +1 -0
- package/dist/middleware/policy.js +122 -0
- package/dist/middleware/types.d.ts +42 -0
- package/dist/middleware/types.d.ts.map +1 -0
- package/dist/middleware/types.js +36 -0
- package/dist/prompts/generator.d.ts +10 -0
- package/dist/prompts/generator.d.ts.map +1 -0
- package/dist/prompts/generator.js +24 -0
- package/dist/prompts/index.d.ts +2 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +1 -0
- package/dist/toolformat/formatter.d.ts +20 -0
- package/dist/toolformat/formatter.d.ts.map +1 -0
- package/dist/toolformat/formatter.js +22 -0
- package/dist/toolformat/index.d.ts +2 -0
- package/dist/toolformat/index.d.ts.map +1 -0
- package/dist/toolformat/index.js +1 -0
- package/dist/tools/async.d.ts +42 -0
- package/dist/tools/async.d.ts.map +1 -0
- package/dist/tools/async.js +89 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +3 -0
- package/dist/tools/registry.d.ts +11 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +27 -0
- package/dist/tools/tool.d.ts +29 -0
- package/dist/tools/tool.d.ts.map +1 -0
- package/dist/tools/tool.js +31 -0
- package/package.json +49 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wiki memory - TypeScript client for the Go core's ontology-constrained
|
|
3
|
+
* wiki memory.
|
|
4
|
+
*
|
|
5
|
+
* WikiMemory spawns the Go MCP stdio server (`memctl serve`) scoped to one
|
|
6
|
+
* user. The subprocess owns enforcement: every call passes the Go
|
|
7
|
+
* middleware chain (declarative policy + ontology evaluator + audit), and
|
|
8
|
+
* in-band attempts to change user scope are denied. The API is async
|
|
9
|
+
* (subprocess I/O); inference stays in the Python SDK.
|
|
10
|
+
*
|
|
11
|
+
* ## Providing Your Own Ontology
|
|
12
|
+
*
|
|
13
|
+
* The T-box (schema) is fully composable — pass paths to your own TTL files.
|
|
14
|
+
* Multiple files are merged. Use absolute paths or paths relative to your
|
|
15
|
+
* working directory.
|
|
16
|
+
*
|
|
17
|
+
* Example TTL file (my-ontology.ttl):
|
|
18
|
+
* ```turtle
|
|
19
|
+
* @prefix ex: <http://example.org/> .
|
|
20
|
+
* @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
21
|
+
* @prefix owl: <http://www.w3.org/2002/07/owl#> .
|
|
22
|
+
*
|
|
23
|
+
* ex:Project a owl:Class ;
|
|
24
|
+
* rdfs:label "Project"@en ;
|
|
25
|
+
* rdfs:comment "A software project" .
|
|
26
|
+
*
|
|
27
|
+
* ex:Task a owl:Class ;
|
|
28
|
+
* rdfs:label "Task"@en ;
|
|
29
|
+
* rdfs:subClassOf ex:Project .
|
|
30
|
+
*
|
|
31
|
+
* ex:hasStatus a owl:ObjectProperty ;
|
|
32
|
+
* rdfs:domain ex:Project ;
|
|
33
|
+
* rdfs:range ex:Status .
|
|
34
|
+
*
|
|
35
|
+
* ex:Status a owl:Class ;
|
|
36
|
+
* rdfs:label "Status"@en .
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* Example usage:
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const wiki = new WikiMemory({
|
|
42
|
+
* userId: "alice",
|
|
43
|
+
* root: "./memory",
|
|
44
|
+
* tboxPaths: [
|
|
45
|
+
* "./my-ontology.ttl", // your custom ontology
|
|
46
|
+
* "./shared-skills.ttl", // another TTL file
|
|
47
|
+
* ],
|
|
48
|
+
* });
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* The repo includes example ontologies in `ontologies/`:
|
|
52
|
+
* - `ontologies/education/TBOX_LEARNING_SOFTWARE.ttl` (learning software concepts)
|
|
53
|
+
* - `ontologies/social/twitch_topics.ttl` (SKOS concepts)
|
|
54
|
+
* - `ontologies/thesaurus/*.ttl` (SKOS testing)
|
|
55
|
+
*/
|
|
56
|
+
import { spawn } from "node:child_process";
|
|
57
|
+
import { createInterface } from "node:readline";
|
|
58
|
+
export const MEMORY_TOOLS = [
|
|
59
|
+
"memory_ingest",
|
|
60
|
+
"memory_write_page",
|
|
61
|
+
"memory_query",
|
|
62
|
+
"memory_get_claims",
|
|
63
|
+
"memory_lint",
|
|
64
|
+
];
|
|
65
|
+
export const DIAGNOSTICS_MARKER = "diagnostics: ";
|
|
66
|
+
/** Extract structured violations from a deny reason, if present. */
|
|
67
|
+
export function parseDiagnostics(errorText) {
|
|
68
|
+
const idx = errorText.indexOf(DIAGNOSTICS_MARKER);
|
|
69
|
+
if (idx < 0)
|
|
70
|
+
return [];
|
|
71
|
+
try {
|
|
72
|
+
const raw = JSON.parse(errorText.slice(idx + DIAGNOSTICS_MARKER.length));
|
|
73
|
+
return raw.map((v) => ({
|
|
74
|
+
constraint: String(v.constraint ?? ""),
|
|
75
|
+
term: String(v.term ?? ""),
|
|
76
|
+
message: String(v.message ?? ""),
|
|
77
|
+
nearest: Array.isArray(v.nearest) ? v.nearest.map(String) : [],
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export class MemoryServerError extends Error {
|
|
85
|
+
}
|
|
86
|
+
export class WikiMemory {
|
|
87
|
+
userId;
|
|
88
|
+
proc;
|
|
89
|
+
lines;
|
|
90
|
+
pending = [];
|
|
91
|
+
nextId = 0;
|
|
92
|
+
ready;
|
|
93
|
+
constructor(options) {
|
|
94
|
+
if (!options.userId)
|
|
95
|
+
throw new MemoryServerError("userId is required");
|
|
96
|
+
if (!options.tboxPaths.length) {
|
|
97
|
+
throw new MemoryServerError("tboxPaths is required (the T-box is a parameter)");
|
|
98
|
+
}
|
|
99
|
+
const binary = options.memctlPath ?? process.env.PEDRO_MEMCTL ?? "memctl";
|
|
100
|
+
const args = [
|
|
101
|
+
"serve",
|
|
102
|
+
"-root", options.root,
|
|
103
|
+
"-user", options.userId,
|
|
104
|
+
"-session", options.sessionId ?? "typescript-sdk",
|
|
105
|
+
];
|
|
106
|
+
for (const path of options.tboxPaths)
|
|
107
|
+
args.push("-tbox", path);
|
|
108
|
+
this.userId = options.userId;
|
|
109
|
+
this.proc = spawn(binary, args, { stdio: ["pipe", "pipe", "pipe"] });
|
|
110
|
+
this.proc.on("error", (err) => this.failAll(new MemoryServerError(err.message)));
|
|
111
|
+
this.proc.on("exit", (code) => this.failAll(new MemoryServerError(`memory server exited (code=${code})`)));
|
|
112
|
+
this.lines = createInterface({ input: this.proc.stdout });
|
|
113
|
+
this.lines.on("line", (line) => this.onLine(line));
|
|
114
|
+
this.ready = this.request("initialize", {}).then(() => {
|
|
115
|
+
this.notify("notifications/initialized");
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
onLine(line) {
|
|
119
|
+
if (!line.trim())
|
|
120
|
+
return;
|
|
121
|
+
const next = this.pending.shift();
|
|
122
|
+
if (!next)
|
|
123
|
+
return;
|
|
124
|
+
let response;
|
|
125
|
+
try {
|
|
126
|
+
response = JSON.parse(line);
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
next.reject(new MemoryServerError(`bad response: ${String(err)}`));
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (response.error) {
|
|
133
|
+
next.reject(new MemoryServerError(`rpc ${response.error.code}: ${response.error.message}`));
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
next.resolve(response.result ?? {});
|
|
137
|
+
}
|
|
138
|
+
failAll(err) {
|
|
139
|
+
const waiting = this.pending;
|
|
140
|
+
this.pending = [];
|
|
141
|
+
for (const p of waiting)
|
|
142
|
+
p.reject(err);
|
|
143
|
+
}
|
|
144
|
+
notify(method) {
|
|
145
|
+
this.proc.stdin.write(JSON.stringify({ jsonrpc: "2.0", method }) + "\n");
|
|
146
|
+
}
|
|
147
|
+
request(method, params) {
|
|
148
|
+
this.nextId += 1;
|
|
149
|
+
const message = { jsonrpc: "2.0", id: this.nextId, method, params };
|
|
150
|
+
return new Promise((resolve, reject) => {
|
|
151
|
+
this.pending.push({ resolve, reject });
|
|
152
|
+
this.proc.stdin.write(JSON.stringify(message) + "\n");
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/** Execute a memory tool. Resolves to [outputText, success, error]. */
|
|
156
|
+
async execute(toolName, args) {
|
|
157
|
+
await this.ready;
|
|
158
|
+
const result = await this.request("tools/call", {
|
|
159
|
+
name: toolName,
|
|
160
|
+
arguments: args,
|
|
161
|
+
});
|
|
162
|
+
const blocks = (result.content ?? []);
|
|
163
|
+
const text = blocks
|
|
164
|
+
.filter((b) => b.type === "text")
|
|
165
|
+
.map((b) => b.text ?? "")
|
|
166
|
+
.join("");
|
|
167
|
+
if (result.isError)
|
|
168
|
+
return [null, false, text];
|
|
169
|
+
return [text, true, ""];
|
|
170
|
+
}
|
|
171
|
+
/** List the memory tools served by the core. */
|
|
172
|
+
async tools() {
|
|
173
|
+
await this.ready;
|
|
174
|
+
const result = await this.request("tools/list", {});
|
|
175
|
+
return (result.tools ?? []);
|
|
176
|
+
}
|
|
177
|
+
async ingest(sourceId, text) {
|
|
178
|
+
return this.execute("memory_ingest", { source_id: sourceId, text });
|
|
179
|
+
}
|
|
180
|
+
async writePage(content) {
|
|
181
|
+
return this.execute("memory_write_page", { content });
|
|
182
|
+
}
|
|
183
|
+
async query(question) {
|
|
184
|
+
return this.parsed(await this.execute("memory_query", { question }));
|
|
185
|
+
}
|
|
186
|
+
async getClaims(pageId) {
|
|
187
|
+
const args = {};
|
|
188
|
+
if (pageId)
|
|
189
|
+
args.page_id = pageId;
|
|
190
|
+
return this.parsed(await this.execute("memory_get_claims", args));
|
|
191
|
+
}
|
|
192
|
+
async lint() {
|
|
193
|
+
return this.parsed(await this.execute("memory_lint", {}));
|
|
194
|
+
}
|
|
195
|
+
parsed([output, ok, err]) {
|
|
196
|
+
if (!ok || typeof output !== "string" || output === "")
|
|
197
|
+
return [output, ok, err];
|
|
198
|
+
try {
|
|
199
|
+
return [JSON.parse(output), ok, err];
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return [output, ok, err];
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/** Terminate the memory server subprocess. */
|
|
206
|
+
close() {
|
|
207
|
+
this.proc.stdin.end();
|
|
208
|
+
this.proc.kill();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { DIAGNOSTICS_MARKER, MEMORY_TOOLS, MemoryServerError, WikiMemory, parseDiagnostics, } from "./client.js";
|
|
2
|
+
export type { DiagnosticViolation, ToolResult, WikiMemoryOptions } from "./client.js";
|
|
3
|
+
export { memoryTools } from "./tools.js";
|
|
4
|
+
export type { MemoryTool } from "./tools.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,mBAAmB,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework integration: expose wiki-memory tools in the Vercel AI SDK's
|
|
3
|
+
* tool shape ({ description, parameters, execute }).
|
|
4
|
+
*
|
|
5
|
+
* The returned record plugs directly into `generateText`/`streamText`:
|
|
6
|
+
*
|
|
7
|
+
* const memory = new WikiMemory({ userId: "alice", root, tboxPaths });
|
|
8
|
+
* const result = await generateText({ model, tools: memoryTools(memory), ... });
|
|
9
|
+
*
|
|
10
|
+
* Parameters are zod schemas (zod is already an SDK dependency). Denied
|
|
11
|
+
* writes resolve to "DENIED: ..." including the structured diagnostics
|
|
12
|
+
* payload, so the calling agent can self-correct and retry.
|
|
13
|
+
*/
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
import type { WikiMemory } from "./client.js";
|
|
16
|
+
export interface MemoryTool {
|
|
17
|
+
description: string;
|
|
18
|
+
parameters: z.ZodTypeAny;
|
|
19
|
+
execute: (args: Record<string, unknown>) => Promise<string>;
|
|
20
|
+
}
|
|
21
|
+
export declare function memoryTools(memory: WikiMemory): Record<string, MemoryTool>;
|
|
22
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/memory/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAc,UAAU,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC;IACzB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7D;AAQD,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAwC1E"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework integration: expose wiki-memory tools in the Vercel AI SDK's
|
|
3
|
+
* tool shape ({ description, parameters, execute }).
|
|
4
|
+
*
|
|
5
|
+
* The returned record plugs directly into `generateText`/`streamText`:
|
|
6
|
+
*
|
|
7
|
+
* const memory = new WikiMemory({ userId: "alice", root, tboxPaths });
|
|
8
|
+
* const result = await generateText({ model, tools: memoryTools(memory), ... });
|
|
9
|
+
*
|
|
10
|
+
* Parameters are zod schemas (zod is already an SDK dependency). Denied
|
|
11
|
+
* writes resolve to "DENIED: ..." including the structured diagnostics
|
|
12
|
+
* payload, so the calling agent can self-correct and retry.
|
|
13
|
+
*/
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
function render([output, ok, err]) {
|
|
16
|
+
if (!ok)
|
|
17
|
+
return `DENIED: ${err}`;
|
|
18
|
+
if (typeof output === "string")
|
|
19
|
+
return output;
|
|
20
|
+
return JSON.stringify(output, null, 2);
|
|
21
|
+
}
|
|
22
|
+
export function memoryTools(memory) {
|
|
23
|
+
return {
|
|
24
|
+
memory_ingest: {
|
|
25
|
+
description: "Store a raw source document in the user's memory vault.",
|
|
26
|
+
parameters: z.object({
|
|
27
|
+
source_id: z.string().describe("kebab-case source id, e.g. src-go-blog"),
|
|
28
|
+
text: z.string().describe("verbatim source text"),
|
|
29
|
+
}),
|
|
30
|
+
execute: async (args) => render(await memory.ingest(String(args.source_id), String(args.text))),
|
|
31
|
+
},
|
|
32
|
+
memory_write_page: {
|
|
33
|
+
description: "Create or update an ontology-validated wiki page. content is full " +
|
|
34
|
+
"page markdown with YAML frontmatter per the memory schema; on DENY " +
|
|
35
|
+
"the response includes structured diagnostics - fix and retry.",
|
|
36
|
+
parameters: z.object({
|
|
37
|
+
content: z.string().describe("full page markdown including frontmatter"),
|
|
38
|
+
}),
|
|
39
|
+
execute: async (args) => render(await memory.writePage(String(args.content))),
|
|
40
|
+
},
|
|
41
|
+
memory_query: {
|
|
42
|
+
description: "Query the user's wiki memory.",
|
|
43
|
+
parameters: z.object({ question: z.string() }),
|
|
44
|
+
execute: async (args) => render(await memory.query(String(args.question))),
|
|
45
|
+
},
|
|
46
|
+
memory_get_claims: {
|
|
47
|
+
description: "List claims tracked in the user's vault, optionally per page.",
|
|
48
|
+
parameters: z.object({ page_id: z.string().optional() }),
|
|
49
|
+
execute: async (args) => render(await memory.getClaims(args.page_id ? String(args.page_id) : undefined)),
|
|
50
|
+
},
|
|
51
|
+
memory_lint: {
|
|
52
|
+
description: "Report contract, ontology, and graph issues in the vault.",
|
|
53
|
+
parameters: z.object({}),
|
|
54
|
+
execute: async () => render(await memory.lint()),
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Decision } from "./types.js";
|
|
2
|
+
import { Action } from "./types.js";
|
|
3
|
+
export interface AuditRecord {
|
|
4
|
+
session_id: string;
|
|
5
|
+
tool_name: string;
|
|
6
|
+
args: Record<string, unknown>;
|
|
7
|
+
decision: Decision;
|
|
8
|
+
timestamp: Date;
|
|
9
|
+
}
|
|
10
|
+
export interface AuditFilter {
|
|
11
|
+
session_id?: string;
|
|
12
|
+
tool_name?: string;
|
|
13
|
+
action?: Action;
|
|
14
|
+
since?: Date;
|
|
15
|
+
limit?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface Auditor {
|
|
18
|
+
record(record: AuditRecord): void;
|
|
19
|
+
query(filter: AuditFilter): AuditRecord[];
|
|
20
|
+
}
|
|
21
|
+
export declare class InMemoryAuditor implements Auditor {
|
|
22
|
+
private records;
|
|
23
|
+
record(record: AuditRecord): void;
|
|
24
|
+
query(filter: AuditFilter): AuditRecord[];
|
|
25
|
+
clear(): void;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/middleware/audit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,EAAE,CAAC;CAC3C;AAED,qBAAa,eAAgB,YAAW,OAAO;IAC7C,OAAO,CAAC,OAAO,CAAqB;IAEpC,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAIjC,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,EAAE;IAazC,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export class InMemoryAuditor {
|
|
2
|
+
records = [];
|
|
3
|
+
record(record) {
|
|
4
|
+
this.records.push(record);
|
|
5
|
+
}
|
|
6
|
+
query(filter) {
|
|
7
|
+
const results = [];
|
|
8
|
+
for (const r of this.records) {
|
|
9
|
+
if (filter.session_id && r.session_id !== filter.session_id)
|
|
10
|
+
continue;
|
|
11
|
+
if (filter.tool_name && r.tool_name !== filter.tool_name)
|
|
12
|
+
continue;
|
|
13
|
+
if (filter.action && r.decision.action !== filter.action)
|
|
14
|
+
continue;
|
|
15
|
+
if (filter.since && r.timestamp < filter.since)
|
|
16
|
+
continue;
|
|
17
|
+
results.push(r);
|
|
18
|
+
if (filter.limit && results.length >= filter.limit)
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
return results;
|
|
22
|
+
}
|
|
23
|
+
clear() {
|
|
24
|
+
this.records = [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare enum ErrorCategory {
|
|
2
|
+
TIMEOUT = "timeout",
|
|
3
|
+
NOT_FOUND = "not_found",
|
|
4
|
+
INVALID_ARGS = "invalid_args",
|
|
5
|
+
PERMISSION = "permission",
|
|
6
|
+
RATE_LIMIT = "rate_limit",
|
|
7
|
+
UNKNOWN = "unknown"
|
|
8
|
+
}
|
|
9
|
+
export interface ToolError {
|
|
10
|
+
timestamp: Date;
|
|
11
|
+
tool: string;
|
|
12
|
+
args: Record<string, unknown>;
|
|
13
|
+
category: ErrorCategory;
|
|
14
|
+
message: string;
|
|
15
|
+
sessionId: string;
|
|
16
|
+
retryCount: number;
|
|
17
|
+
}
|
|
18
|
+
export declare class ErrorTracker {
|
|
19
|
+
private errors;
|
|
20
|
+
private maxErrorsPerTool;
|
|
21
|
+
private windowDurationMs;
|
|
22
|
+
constructor(maxErrorsPerTool?: number, windowDurationMinutes?: number);
|
|
23
|
+
setThresholds(maxErrors: number, windowMinutes: number): void;
|
|
24
|
+
recordError(sessionId: string, tool: string, args: Record<string, unknown>, err: Error, category: ErrorCategory): void;
|
|
25
|
+
private getRetryCount;
|
|
26
|
+
private pruneOldErrors;
|
|
27
|
+
getErrorCount(sessionId: string, tool: string): number;
|
|
28
|
+
getRecentErrors(sessionId: string): ToolError[];
|
|
29
|
+
getErrorsByCategory(sessionId: string, category: ErrorCategory): ToolError[];
|
|
30
|
+
isErrorRateExceeded(sessionId: string, tool: string): boolean;
|
|
31
|
+
resetSession(sessionId: string): void;
|
|
32
|
+
shouldBlockTool(sessionId: string, tool: string): boolean;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=error_tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error_tracker.d.ts","sourceRoot":"","sources":["../../../src/middleware/guardrails/error_tracker.ts"],"names":[],"mappings":"AAAA,oBAAY,aAAa;IACvB,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,YAAY,iBAAiB;IAC7B,UAAU,eAAe;IACzB,UAAU,eAAe;IACzB,OAAO,YAAY;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,gBAAgB,CAAS;gBAErB,gBAAgB,GAAE,MAAU,EAAE,qBAAqB,GAAE,MAAU;IAM3E,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAK7D,WAAW,CACT,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,GAAG,EAAE,KAAK,EACV,QAAQ,EAAE,aAAa,GACtB,IAAI;IAqBP,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,cAAc;IAatB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAItD,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE;IAK/C,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,SAAS,EAAE;IAI5E,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAI7D,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIrC,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;CAG1D"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export var ErrorCategory;
|
|
2
|
+
(function (ErrorCategory) {
|
|
3
|
+
ErrorCategory["TIMEOUT"] = "timeout";
|
|
4
|
+
ErrorCategory["NOT_FOUND"] = "not_found";
|
|
5
|
+
ErrorCategory["INVALID_ARGS"] = "invalid_args";
|
|
6
|
+
ErrorCategory["PERMISSION"] = "permission";
|
|
7
|
+
ErrorCategory["RATE_LIMIT"] = "rate_limit";
|
|
8
|
+
ErrorCategory["UNKNOWN"] = "unknown";
|
|
9
|
+
})(ErrorCategory || (ErrorCategory = {}));
|
|
10
|
+
export class ErrorTracker {
|
|
11
|
+
errors;
|
|
12
|
+
maxErrorsPerTool;
|
|
13
|
+
windowDurationMs;
|
|
14
|
+
constructor(maxErrorsPerTool = 5, windowDurationMinutes = 5) {
|
|
15
|
+
this.errors = new Map();
|
|
16
|
+
this.maxErrorsPerTool = maxErrorsPerTool;
|
|
17
|
+
this.windowDurationMs = windowDurationMinutes * 60 * 1000;
|
|
18
|
+
}
|
|
19
|
+
setThresholds(maxErrors, windowMinutes) {
|
|
20
|
+
this.maxErrorsPerTool = maxErrors;
|
|
21
|
+
this.windowDurationMs = windowMinutes * 60 * 1000;
|
|
22
|
+
}
|
|
23
|
+
recordError(sessionId, tool, args, err, category) {
|
|
24
|
+
if (!this.errors.has(sessionId)) {
|
|
25
|
+
this.errors.set(sessionId, []);
|
|
26
|
+
}
|
|
27
|
+
const retryCount = this.getRetryCount(sessionId, tool);
|
|
28
|
+
const toolErr = {
|
|
29
|
+
timestamp: new Date(),
|
|
30
|
+
tool,
|
|
31
|
+
args,
|
|
32
|
+
category,
|
|
33
|
+
message: err.message,
|
|
34
|
+
sessionId,
|
|
35
|
+
retryCount,
|
|
36
|
+
};
|
|
37
|
+
this.errors.get(sessionId).push(toolErr);
|
|
38
|
+
this.pruneOldErrors(sessionId);
|
|
39
|
+
}
|
|
40
|
+
getRetryCount(sessionId, tool) {
|
|
41
|
+
return (this.errors.get(sessionId) || []).filter((e) => e.tool === tool).length;
|
|
42
|
+
}
|
|
43
|
+
pruneOldErrors(sessionId) {
|
|
44
|
+
const errors = this.errors.get(sessionId);
|
|
45
|
+
if (!errors || errors.length <= this.maxErrorsPerTool) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const cutoff = new Date(Date.now() - this.windowDurationMs);
|
|
49
|
+
this.errors.set(sessionId, errors.filter((e) => e.timestamp > cutoff));
|
|
50
|
+
}
|
|
51
|
+
getErrorCount(sessionId, tool) {
|
|
52
|
+
return (this.errors.get(sessionId) || []).filter((e) => e.tool === tool).length;
|
|
53
|
+
}
|
|
54
|
+
getRecentErrors(sessionId) {
|
|
55
|
+
this.pruneOldErrors(sessionId);
|
|
56
|
+
return [...(this.errors.get(sessionId) || [])];
|
|
57
|
+
}
|
|
58
|
+
getErrorsByCategory(sessionId, category) {
|
|
59
|
+
return (this.errors.get(sessionId) || []).filter((e) => e.category === category);
|
|
60
|
+
}
|
|
61
|
+
isErrorRateExceeded(sessionId, tool) {
|
|
62
|
+
return this.getErrorCount(sessionId, tool) >= this.maxErrorsPerTool;
|
|
63
|
+
}
|
|
64
|
+
resetSession(sessionId) {
|
|
65
|
+
this.errors.delete(sessionId);
|
|
66
|
+
}
|
|
67
|
+
shouldBlockTool(sessionId, tool) {
|
|
68
|
+
return this.isErrorRateExceeded(sessionId, tool);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare enum NudgeKind {
|
|
2
|
+
RETRY = "retry",
|
|
3
|
+
UNKNOWN_TOOL = "unknown_tool",
|
|
4
|
+
STEP = "step",
|
|
5
|
+
PREREQUISITE = "prerequisite"
|
|
6
|
+
}
|
|
7
|
+
export interface Nudge {
|
|
8
|
+
role: string;
|
|
9
|
+
content: string;
|
|
10
|
+
kind: NudgeKind;
|
|
11
|
+
tier: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function retryNudge(_rawResponse: string, toolNames: string[]): Nudge;
|
|
14
|
+
export declare function unknownToolNudge(toolName: string, toolNames: string[]): Nudge;
|
|
15
|
+
export declare function stepNudge(terminalTool: string, pendingSteps: string[], tier?: number): Nudge;
|
|
16
|
+
export declare function prerequisiteNudge(toolName: string, missingPrereqs: string[]): Nudge;
|
|
17
|
+
//# sourceMappingURL=nudge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nudge.d.ts","sourceRoot":"","sources":["../../../src/middleware/guardrails/nudge.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,KAAK,UAAU;IACf,YAAY,iBAAiB;IAC7B,IAAI,SAAS;IACb,YAAY,iBAAiB;CAC9B;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAeD,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,KAAK,CAQ3E;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,KAAK,CAQ7E;AAED,wBAAgB,SAAS,CACvB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EAAE,EACtB,IAAI,GAAE,MAAU,GACf,KAAK,CAsBP;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EAAE,GACvB,KAAK,CAQP"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export var NudgeKind;
|
|
2
|
+
(function (NudgeKind) {
|
|
3
|
+
NudgeKind["RETRY"] = "retry";
|
|
4
|
+
NudgeKind["UNKNOWN_TOOL"] = "unknown_tool";
|
|
5
|
+
NudgeKind["STEP"] = "step";
|
|
6
|
+
NudgeKind["PREREQUISITE"] = "prerequisite";
|
|
7
|
+
})(NudgeKind || (NudgeKind = {}));
|
|
8
|
+
function joinToolNames(names) {
|
|
9
|
+
if (names.length === 0) {
|
|
10
|
+
return "(no tools available)";
|
|
11
|
+
}
|
|
12
|
+
if (names.length === 1) {
|
|
13
|
+
return names[0];
|
|
14
|
+
}
|
|
15
|
+
if (names.length === 2) {
|
|
16
|
+
return `${names[0]} and ${names[1]}`;
|
|
17
|
+
}
|
|
18
|
+
return names.slice(0, -1).join(", ") + `, and ${names[names.length - 1]}`;
|
|
19
|
+
}
|
|
20
|
+
export function retryNudge(_rawResponse, toolNames) {
|
|
21
|
+
const toolsList = joinToolNames(toolNames);
|
|
22
|
+
return {
|
|
23
|
+
role: "user",
|
|
24
|
+
content: `Your previous response was not a valid tool call. You must respond with a tool call, not free text. Available tools: ${toolsList}. Please try again with a valid tool call.`,
|
|
25
|
+
kind: NudgeKind.RETRY,
|
|
26
|
+
tier: 0,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function unknownToolNudge(toolName, toolNames) {
|
|
30
|
+
const toolsList = joinToolNames(toolNames);
|
|
31
|
+
return {
|
|
32
|
+
role: "user",
|
|
33
|
+
content: `Tool '${toolName}' does not exist. Available tools: ${toolsList}. Call one of them.`,
|
|
34
|
+
kind: NudgeKind.UNKNOWN_TOOL,
|
|
35
|
+
tier: 0,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function stepNudge(terminalTool, pendingSteps, tier = 1) {
|
|
39
|
+
const clampedTier = Math.max(1, Math.min(3, tier));
|
|
40
|
+
const steps = joinToolNames(pendingSteps);
|
|
41
|
+
let content;
|
|
42
|
+
switch (clampedTier) {
|
|
43
|
+
case 1:
|
|
44
|
+
content = `You cannot call ${terminalTool} yet. You must first complete these required steps: ${steps}. Call one of them now.`;
|
|
45
|
+
break;
|
|
46
|
+
case 2:
|
|
47
|
+
content = `You must call one of these tools now: ${steps}. Pick one.`;
|
|
48
|
+
break;
|
|
49
|
+
default:
|
|
50
|
+
content = `STOP. You MUST call one of: ${steps}. Do NOT call ${terminalTool}. Your next response MUST be a tool call to one of: ${steps}.`;
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
role: "user",
|
|
54
|
+
content,
|
|
55
|
+
kind: NudgeKind.STEP,
|
|
56
|
+
tier: clampedTier,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export function prerequisiteNudge(toolName, missingPrereqs) {
|
|
60
|
+
const prereqs = joinToolNames(missingPrereqs);
|
|
61
|
+
return {
|
|
62
|
+
role: "user",
|
|
63
|
+
content: `You cannot call ${toolName} yet. You must first call: ${prereqs}. Call the prerequisite tool now.`,
|
|
64
|
+
kind: NudgeKind.PREREQUISITE,
|
|
65
|
+
tier: 0,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Nudge } from "./nudge";
|
|
2
|
+
export interface ToolCall {
|
|
3
|
+
tool: string;
|
|
4
|
+
args: Record<string, unknown>;
|
|
5
|
+
}
|
|
6
|
+
export interface ValidationResult {
|
|
7
|
+
toolCalls: ToolCall[];
|
|
8
|
+
nudge: Nudge | null;
|
|
9
|
+
needsRetry: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare class ResponseValidator {
|
|
12
|
+
private toolNames;
|
|
13
|
+
private rescueEnabled;
|
|
14
|
+
private retryNudgeFn;
|
|
15
|
+
private thinkPattern;
|
|
16
|
+
private pythonTagPattern;
|
|
17
|
+
private codeFencePattern;
|
|
18
|
+
private rehearsalPattern;
|
|
19
|
+
private qwenFunctionPattern;
|
|
20
|
+
constructor(toolNames: string[], rescueEnabled?: boolean, retryNudgeFn?: (rawResponse: string, toolNames: string[]) => Nudge);
|
|
21
|
+
validateTextResponse(response: string): ValidationResult;
|
|
22
|
+
validateToolCalls(toolCalls: ToolCall[]): ValidationResult;
|
|
23
|
+
private rescueToolCall;
|
|
24
|
+
private extractJsonToolCalls;
|
|
25
|
+
private tryParseToolCall;
|
|
26
|
+
private extractRehearsalToolCalls;
|
|
27
|
+
private extractQwenXmlToolCalls;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=response_validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response_validator.d.ts","sourceRoot":"","sources":["../../../src/middleware/guardrails/response_validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAgC,MAAM,SAAS,CAAC;AAE9D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,aAAa,CAAU;IAC/B,OAAO,CAAC,YAAY,CAAsD;IAE1E,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,mBAAmB,CAAS;gBAGlC,SAAS,EAAE,MAAM,EAAE,EACnB,aAAa,GAAE,OAAc,EAC7B,YAAY,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,KAAK;IAapE,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB;IAYxD,iBAAiB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,gBAAgB;IAoB1D,OAAO,CAAC,cAAc;IAsBtB,OAAO,CAAC,oBAAoB;IAqC5B,OAAO,CAAC,gBAAgB;IAuBxB,OAAO,CAAC,yBAAyB;IA0BjC,OAAO,CAAC,uBAAuB;CAGhC"}
|