@warmdrift/kgauto-compiler 2.0.0-alpha.5 → 2.0.0-alpha.52
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 +140 -3
- package/dist/chunk-CXH7KC4D.mjs +1413 -0
- package/dist/chunk-HHWBB46W.mjs +694 -0
- package/dist/chunk-NBO4R5PC.mjs +313 -0
- package/dist/chunk-P3TOAEG4.mjs +56 -0
- package/dist/chunk-RO22VFIF.mjs +29 -0
- package/dist/glassbox/index.d.mts +59 -0
- package/dist/glassbox/index.d.ts +59 -0
- package/dist/glassbox/index.js +312 -0
- package/dist/glassbox/index.mjs +12 -0
- package/dist/glassbox-routes/format.d.mts +24 -0
- package/dist/glassbox-routes/format.d.ts +24 -0
- package/dist/glassbox-routes/format.js +86 -0
- package/dist/glassbox-routes/format.mjs +18 -0
- package/dist/glassbox-routes/index.d.mts +191 -0
- package/dist/glassbox-routes/index.d.ts +191 -0
- package/dist/glassbox-routes/index.js +2657 -0
- package/dist/glassbox-routes/index.mjs +663 -0
- package/dist/glassbox-routes/react/index.d.mts +74 -0
- package/dist/glassbox-routes/react/index.d.ts +74 -0
- package/dist/glassbox-routes/react/index.js +819 -0
- package/dist/glassbox-routes/react/index.mjs +754 -0
- package/dist/index.d.mts +2150 -14
- package/dist/index.d.ts +2150 -14
- package/dist/index.js +6367 -1085
- package/dist/index.mjs +3470 -175
- package/dist/ir-dDcG8Pvu.d.mts +1337 -0
- package/dist/ir-rUUojj0s.d.ts +1337 -0
- package/dist/profiles.d.mts +292 -2
- package/dist/profiles.d.ts +292 -2
- package/dist/profiles.js +1024 -16
- package/dist/profiles.mjs +9 -1
- package/dist/types-BTeRoSvM.d.mts +149 -0
- package/dist/types-B_pdPjxm.d.ts +149 -0
- package/dist/types-UXPxWabQ.d.ts +131 -0
- package/dist/types-vGo-h0tZ.d.mts +131 -0
- package/package.json +42 -6
- package/dist/chunk-MBEI5UOM.mjs +0 -409
- package/dist/profiles-DHdCRBVH.d.mts +0 -571
- package/dist/profiles-MGq5Tnjv.d.ts +0 -571
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @warmdrift/kgauto-compiler — v2.0.0-alpha.
|
|
1
|
+
# @warmdrift/kgauto-compiler — v2.0.0-alpha.6
|
|
2
2
|
|
|
3
3
|
> Prompt compiler + central learning brain for multi-model AI apps.
|
|
4
4
|
> **Swap models without rewriting prompts.**
|
|
@@ -18,8 +18,8 @@ mutations.
|
|
|
18
18
|
- **Package:** alpha — coexists with v1 (`@warmdrift/kgauto@1.2.0`) under
|
|
19
19
|
the temporary name `@warmdrift/kgauto-compiler`. Renames to v2 final once
|
|
20
20
|
v1 is fully retired from production.
|
|
21
|
-
- **Tests:**
|
|
22
|
-
- **Build:** clean (47KB ESM,
|
|
21
|
+
- **Tests:** 201/201 passing
|
|
22
|
+
- **Build:** clean (47KB ESM, 68KB CJS)
|
|
23
23
|
- **Brain:** schema ready (see `brain/migrations/001_initial_schema.sql`);
|
|
24
24
|
awaiting dedicated Supabase provisioning.
|
|
25
25
|
- **Mutation engine:** v2.1 (after enough outcome data accumulates).
|
|
@@ -89,6 +89,101 @@ await record({
|
|
|
89
89
|
});
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
+
### `probeShadow()` — measure a swap candidate from an AI-SDK route (alpha.48)
|
|
93
|
+
|
|
94
|
+
`call()` runs a full-IR shadow probe internally (`shadowProbe` option). AI-SDK consumers who drive `streamText()` themselves never call `call()`, so they reach the same probe via the standalone `probeShadow()` export — fire it from `onFinish`, passing the served leg you already have, wrapped in `waitUntil()`/`after()` so it never blocks the response.
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { probeShadow, configureBrain } from '@warmdrift/kgauto-compiler';
|
|
98
|
+
import { after } from 'next/server'; // or the platform's waitUntil()
|
|
99
|
+
|
|
100
|
+
configureBrain({ endpoint: 'https://your-app.com/api/kgauto/v2', apiKey: '...' });
|
|
101
|
+
|
|
102
|
+
const t0 = Date.now();
|
|
103
|
+
const result = streamText({
|
|
104
|
+
model, system, messages,
|
|
105
|
+
onFinish: ({ text, usage }) => {
|
|
106
|
+
after(() => probeShadow(ir, {
|
|
107
|
+
served: {
|
|
108
|
+
model: servedModelId,
|
|
109
|
+
responseText: text,
|
|
110
|
+
tokensIn: usage.promptTokens,
|
|
111
|
+
tokensOut: usage.completionTokens,
|
|
112
|
+
latencyMs: Date.now() - t0,
|
|
113
|
+
},
|
|
114
|
+
candidates: ['deepseek-v4-pro'], // what you'd consider swapping to
|
|
115
|
+
sampleRate: 0.05, // pin 1 for a dogfood window
|
|
116
|
+
}));
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
kgauto runs each candidate on the **same IR** and persists a `probe_outcomes` row (`replay_source='inline-full-ir'`, `prompt_fidelity=1.0`, both latency legs). Phase 1 is `judge:'off'` — rows accumulate for an offline verdict rollup; inline Opus judging is Phase 2. Fire-and-forget: never throws into your `onFinish`.
|
|
122
|
+
|
|
123
|
+
#### Sync-mode latency protection (`call()` + `BrainConfig.sync`)
|
|
124
|
+
|
|
125
|
+
A `probeShadow()` consumer fires from `after()`, so the probe is always off the user-facing path — slow candidates are fine there (it's the right place to evaluate a slow reasoner). But a **`call()`-inline** consumer that sets `BrainConfig.sync: true` (PB-class Edge routes, so the brain write reliably lands before teardown — L-086) *awaits* the probe, putting the candidate's latency on the user's critical path. A `latency_tier='slow'` candidate (deepseek-v4-pro ~78–84s) then blows the route's time budget and the user sees an empty response. Two knobs on `shadowProbe` protect the sync path — **both are no-ops off the critical path** (non-sync `call()` and every `probeShadow()` consumer):
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
await call(ir, {
|
|
129
|
+
shadowProbe: {
|
|
130
|
+
candidates: ['deepseek-v4-pro'],
|
|
131
|
+
sampleRate: 1,
|
|
132
|
+
maxLatencyMs: 15000, // default 15000. Sync-mode budget: if the probe
|
|
133
|
+
// overruns, abort the candidate, return the served
|
|
134
|
+
// response NOW, record outcome='aborted_latency_budget'.
|
|
135
|
+
skipSlowTierInSync: true, // default true. Don't even START a latency_tier='slow'
|
|
136
|
+
// candidate inline; record outcome='skipped_slow_tier_sync'.
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Aborted/skipped probes write a **diagnostic** `probe_outcomes` row (`outcome != 'completed'`, no candidate response, no verdict) so the offline rollup can tell "tried but too slow" from "never armed." A verdict rollup must filter `outcome='completed'`.
|
|
142
|
+
|
|
143
|
+
**The deeper rule: inline shadow-probe = FAST candidates only.** To evaluate a *slow* reasoner, use the offline/async probe path (the Phase-2 batch direction, off the response entirely) or `probeShadow()` from `after()` — never the inline sync probe.
|
|
144
|
+
|
|
145
|
+
## Structured advisories API (alpha.29+)
|
|
146
|
+
|
|
147
|
+
kgauto's compile-time advisories (`caching-off-on-claude`, `tool-bloat`,
|
|
148
|
+
`archetype-perf-floor-breach`, etc.) used to vanish after the consumer read
|
|
149
|
+
the compile result. alpha.29 ships a structured query + resolution surface
|
|
150
|
+
so Admin UIs can render "what's open right now?" without log-scraping.
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import {
|
|
154
|
+
getActionableAdvisories,
|
|
155
|
+
markAdvisoryResolved,
|
|
156
|
+
} from '@warmdrift/kgauto-compiler';
|
|
157
|
+
|
|
158
|
+
// Query open advisories for this app
|
|
159
|
+
const open = await getActionableAdvisories({
|
|
160
|
+
appId: 'playbacksam',
|
|
161
|
+
brainEndpoint: process.env.KGAUTO_BRAIN_ENDPOINT!,
|
|
162
|
+
brainJwt: process.env.KGAUTO_BRAIN_JWT!,
|
|
163
|
+
brainAnonKey: process.env.KGAUTO_BRAIN_ANON_KEY!,
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
for (const a of open) {
|
|
167
|
+
console.log(`[${a.severity}] ${a.rule} — ${a.observationCount} firings since ${a.openedAt}`);
|
|
168
|
+
console.log(` ${a.message}`);
|
|
169
|
+
if (a.suggestedFix?.docsLink) console.log(` ↳ ${a.suggestedFix.docsLink}`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// After the operator fixes the issue, mark it resolved:
|
|
173
|
+
const r = await markAdvisoryResolved({
|
|
174
|
+
id: open[0].id,
|
|
175
|
+
resolutionNote: 'wired historyCachePolicy in compile() — PR #99',
|
|
176
|
+
brainEndpoint: process.env.KGAUTO_BRAIN_ENDPOINT!,
|
|
177
|
+
brainJwt: process.env.KGAUTO_BRAIN_JWT!,
|
|
178
|
+
brainAnonKey: process.env.KGAUTO_BRAIN_ANON_KEY!,
|
|
179
|
+
});
|
|
180
|
+
if (!r.ok) console.error(r.reason);
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The view enforces server-side auto-resolution: advisories with no firing
|
|
184
|
+
in the last 14 days flip to `status='resolved'` automatically; the next
|
|
185
|
+
firing reopens the rule with a fresh stable `id`.
|
|
186
|
+
|
|
92
187
|
## Architecture
|
|
93
188
|
|
|
94
189
|
```
|
|
@@ -154,6 +249,48 @@ The 5 prod empty-responses in tt-intelligence's `gemini-2.5-flash` dashboard
|
|
|
154
249
|
calls? v2 catches those automatically — `expectedShortOutput` constraint plus
|
|
155
250
|
the `force_thinking_budget_zero` cliff guard.
|
|
156
251
|
|
|
252
|
+
## Tools
|
|
253
|
+
|
|
254
|
+
Tools are first-class IR fields. The compiler's tool-relevance pass drops
|
|
255
|
+
tools that don't apply to the current intent before lowering — saves
|
|
256
|
+
context budget on every call.
|
|
257
|
+
|
|
258
|
+
```ts
|
|
259
|
+
const tools: ToolDefinition[] = [
|
|
260
|
+
{
|
|
261
|
+
name: 'web_search',
|
|
262
|
+
description: 'Search the public web',
|
|
263
|
+
parameters: { type: 'object', properties: { q: { type: 'string' } } },
|
|
264
|
+
relevanceByIntent: {
|
|
265
|
+
ask: 0.9, // primary tool for ask
|
|
266
|
+
hunt: 0.9,
|
|
267
|
+
classify: 0.0, // never useful for classification
|
|
268
|
+
summarize: 0.0,
|
|
269
|
+
extract: 0.1,
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
// ...
|
|
273
|
+
];
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Each tool declares per-intent relevance scores 0..1. The pass keeps tools
|
|
277
|
+
where `relevanceByIntent[currentIntent] >= toolRelevanceThreshold` (default
|
|
278
|
+
`0.2`). Missing entries default to neutral (`0.5`) — kept by default. Set
|
|
279
|
+
explicit `0.0` to hard-exclude.
|
|
280
|
+
|
|
281
|
+
Tool definitions eat ~350 tokens of context per tool (L-051), so trimming
|
|
282
|
+
matters: 12 declared tools, only 3 relevant → 9 × 350 = 3150 tokens
|
|
283
|
+
recovered per call.
|
|
284
|
+
|
|
285
|
+
The `tool-bloat` advisory (alpha.6) fires when more than 10 tools survive
|
|
286
|
+
the relevance pass on a short-output archetype (`classify`, `extract`,
|
|
287
|
+
`summarize`, `transform`, `critique`) — those archetypes typically use
|
|
288
|
+
≤3 tools, so a kept-count >10 indicates either missing `relevanceByIntent`
|
|
289
|
+
or scores set too generously.
|
|
290
|
+
|
|
291
|
+
DeepSeek profiles cap tools to 1 (sequential-only). Other providers
|
|
292
|
+
inherit the count from the IR after the relevance pass.
|
|
293
|
+
|
|
157
294
|
## Brain provisioning
|
|
158
295
|
|
|
159
296
|
1. Create a NEW Supabase project (suggested name: `kgauto-brain`)
|