@warmdrift/kgauto-compiler 2.0.0-alpha.16 → 2.0.0-alpha.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-NUTC7NUC.mjs +298 -0
- package/dist/chunk-VZGMWKRT.mjs +19 -0
- package/dist/glassbox/index.d.mts +42 -0
- package/dist/glassbox/index.d.ts +42 -0
- package/dist/glassbox/index.js +300 -0
- package/dist/glassbox/index.mjs +10 -0
- package/dist/glassbox-routes/index.d.mts +73 -0
- package/dist/glassbox-routes/index.d.ts +73 -0
- package/dist/glassbox-routes/index.js +560 -0
- package/dist/glassbox-routes/index.mjs +269 -0
- package/dist/index.d.mts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +357 -2
- package/dist/index.mjs +77 -2
- package/dist/{profiles-BoLYdl7F.d.mts → ir-C3P4gDt0.d.mts} +13 -134
- package/dist/{profiles-CVB2_5C8.d.ts → ir-CFHU3BUT.d.ts} +13 -134
- package/dist/profiles.d.mts +137 -2
- package/dist/profiles.d.ts +137 -2
- package/dist/types-DWF6mPGg.d.mts +122 -0
- package/dist/types-xeklorHU.d.ts +122 -0
- package/package.json +12 -2
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import {
|
|
2
|
+
subscribe
|
|
3
|
+
} from "../chunk-VZGMWKRT.mjs";
|
|
4
|
+
import "../chunk-NUTC7NUC.mjs";
|
|
5
|
+
|
|
6
|
+
// src/glassbox-routes/auth.ts
|
|
7
|
+
import { Buffer } from "buffer";
|
|
8
|
+
import { timingSafeEqual } from "crypto";
|
|
9
|
+
var JSON_HEADERS = { "Content-Type": "application/json" };
|
|
10
|
+
function jsonError(status, code) {
|
|
11
|
+
return new Response(JSON.stringify({ error: code }), {
|
|
12
|
+
status,
|
|
13
|
+
headers: JSON_HEADERS
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function tokensEqual(a, b) {
|
|
17
|
+
if (a.length !== b.length) return false;
|
|
18
|
+
const ab = Buffer.from(a, "utf8");
|
|
19
|
+
const bb = Buffer.from(b, "utf8");
|
|
20
|
+
if (ab.length !== bb.length) return false;
|
|
21
|
+
return timingSafeEqual(ab, bb);
|
|
22
|
+
}
|
|
23
|
+
function checkAuth(req, config) {
|
|
24
|
+
const authHeader = req.headers.get("Authorization") ?? "";
|
|
25
|
+
const match = /^Bearer\s+(.+)$/i.exec(authHeader);
|
|
26
|
+
const provided = match?.[1]?.trim() ?? "";
|
|
27
|
+
if (!provided || !tokensEqual(provided, config.installToken)) {
|
|
28
|
+
return jsonError(401, "unauthorized");
|
|
29
|
+
}
|
|
30
|
+
const origin = req.headers.get("Origin") ?? "";
|
|
31
|
+
const expected = `chrome-extension://${config.extensionId}`;
|
|
32
|
+
if (origin !== expected) {
|
|
33
|
+
return jsonError(403, "forbidden_origin");
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/glassbox-routes/proxy.ts
|
|
39
|
+
var JSON_HEADERS2 = {
|
|
40
|
+
"Content-Type": "application/json",
|
|
41
|
+
"Cache-Control": "no-store"
|
|
42
|
+
};
|
|
43
|
+
var DEFAULT_LIMIT = 20;
|
|
44
|
+
var MAX_LIMIT = 100;
|
|
45
|
+
function jsonResponse(status, body) {
|
|
46
|
+
return new Response(JSON.stringify(body), { status, headers: JSON_HEADERS2 });
|
|
47
|
+
}
|
|
48
|
+
function jsonError2(status, code) {
|
|
49
|
+
return jsonResponse(status, { error: code });
|
|
50
|
+
}
|
|
51
|
+
function applyScrub(row, scrub) {
|
|
52
|
+
if (!scrub || row == null || typeof row !== "object") return row;
|
|
53
|
+
try {
|
|
54
|
+
return scrub(row);
|
|
55
|
+
} catch {
|
|
56
|
+
return row;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function parseLimit(raw) {
|
|
60
|
+
if (!raw) return DEFAULT_LIMIT;
|
|
61
|
+
const n = Number.parseInt(raw, 10);
|
|
62
|
+
if (!Number.isFinite(n) || n <= 0) return DEFAULT_LIMIT;
|
|
63
|
+
return Math.min(n, MAX_LIMIT);
|
|
64
|
+
}
|
|
65
|
+
function createProxyHandler(config) {
|
|
66
|
+
const {
|
|
67
|
+
installToken,
|
|
68
|
+
extensionId,
|
|
69
|
+
brainEndpoint,
|
|
70
|
+
brainJwt,
|
|
71
|
+
appId,
|
|
72
|
+
scrub,
|
|
73
|
+
fetch: fetchImpl
|
|
74
|
+
} = config;
|
|
75
|
+
const doFetch = fetchImpl ?? ((...args) => globalThis.fetch(...args));
|
|
76
|
+
const base = brainEndpoint.replace(/\/+$/, "");
|
|
77
|
+
return async function proxy(req) {
|
|
78
|
+
const authFail = checkAuth(req, { installToken, extensionId });
|
|
79
|
+
if (authFail) return authFail;
|
|
80
|
+
const url = new URL(req.url);
|
|
81
|
+
const traceId = url.searchParams.get("traceId");
|
|
82
|
+
const limit = parseLimit(url.searchParams.get("limit"));
|
|
83
|
+
const qs = new URLSearchParams();
|
|
84
|
+
qs.set("app_id", `eq.${appId}`);
|
|
85
|
+
if (traceId) {
|
|
86
|
+
qs.set("trace_id", `eq.${traceId}`);
|
|
87
|
+
} else {
|
|
88
|
+
qs.set("order", "created_at.desc");
|
|
89
|
+
qs.set("limit", String(limit));
|
|
90
|
+
}
|
|
91
|
+
const brainUrl = `${base}/rest/v1/compile_outcomes?${qs.toString()}`;
|
|
92
|
+
let brainRes;
|
|
93
|
+
try {
|
|
94
|
+
brainRes = await doFetch(brainUrl, {
|
|
95
|
+
method: "GET",
|
|
96
|
+
headers: {
|
|
97
|
+
Authorization: `Bearer ${brainJwt}`,
|
|
98
|
+
apikey: brainJwt,
|
|
99
|
+
Accept: "application/json"
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
} catch {
|
|
103
|
+
return jsonError2(502, "brain_unavailable");
|
|
104
|
+
}
|
|
105
|
+
if (brainRes.status === 401 || brainRes.status === 403) {
|
|
106
|
+
return jsonError2(500, "brain_auth_misconfig");
|
|
107
|
+
}
|
|
108
|
+
if (brainRes.status >= 500) {
|
|
109
|
+
return jsonError2(502, "brain_unavailable");
|
|
110
|
+
}
|
|
111
|
+
if (!brainRes.ok) {
|
|
112
|
+
return jsonError2(400, "bad_request");
|
|
113
|
+
}
|
|
114
|
+
let rows;
|
|
115
|
+
try {
|
|
116
|
+
rows = await brainRes.json();
|
|
117
|
+
} catch {
|
|
118
|
+
return jsonError2(502, "brain_unavailable");
|
|
119
|
+
}
|
|
120
|
+
if (!Array.isArray(rows)) {
|
|
121
|
+
return jsonError2(502, "brain_unavailable");
|
|
122
|
+
}
|
|
123
|
+
const scrubbed = rows.map((row) => applyScrub(row, scrub));
|
|
124
|
+
return jsonResponse(200, scrubbed);
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/glassbox-routes/stream.ts
|
|
129
|
+
var SSE_HEADERS = {
|
|
130
|
+
"Content-Type": "text/event-stream",
|
|
131
|
+
"Cache-Control": "no-cache, no-transform",
|
|
132
|
+
Connection: "keep-alive",
|
|
133
|
+
"X-Accel-Buffering": "no"
|
|
134
|
+
};
|
|
135
|
+
var JSON_HEADERS3 = { "Content-Type": "application/json" };
|
|
136
|
+
function jsonError3(status, code) {
|
|
137
|
+
return new Response(JSON.stringify({ error: code }), {
|
|
138
|
+
status,
|
|
139
|
+
headers: JSON_HEADERS3
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
function applyScrub2(event, scrub) {
|
|
143
|
+
if (!scrub) return event;
|
|
144
|
+
try {
|
|
145
|
+
const out = scrub(event);
|
|
146
|
+
if (out && typeof out === "object" && typeof out.kind === "string" && typeof out.at === "number") {
|
|
147
|
+
return out;
|
|
148
|
+
}
|
|
149
|
+
return event;
|
|
150
|
+
} catch {
|
|
151
|
+
return event;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function sseFrame(eventName, data) {
|
|
155
|
+
const safeName = eventName.replace(/[\r\n]/g, "");
|
|
156
|
+
return `event: ${safeName}
|
|
157
|
+
data: ${JSON.stringify(data)}
|
|
158
|
+
|
|
159
|
+
`;
|
|
160
|
+
}
|
|
161
|
+
function createStreamHandler(config, subscribe2) {
|
|
162
|
+
const { installToken, extensionId, scrub } = config;
|
|
163
|
+
return async function stream(req) {
|
|
164
|
+
const authFail = checkAuth(req, { installToken, extensionId });
|
|
165
|
+
if (authFail) return authFail;
|
|
166
|
+
const url = new URL(req.url);
|
|
167
|
+
const traceId = url.searchParams.get("traceId");
|
|
168
|
+
if (!traceId) {
|
|
169
|
+
return jsonError3(400, "missing_trace_id");
|
|
170
|
+
}
|
|
171
|
+
const source = subscribe2(traceId);
|
|
172
|
+
const encoder = new TextEncoder();
|
|
173
|
+
let sourceReader;
|
|
174
|
+
let cancelled = false;
|
|
175
|
+
const body = new ReadableStream({
|
|
176
|
+
async start(controller) {
|
|
177
|
+
controller.enqueue(encoder.encode(sseFrame("ready", {})));
|
|
178
|
+
sourceReader = source.getReader();
|
|
179
|
+
const signal = req.signal;
|
|
180
|
+
if (signal) {
|
|
181
|
+
if (signal.aborted) {
|
|
182
|
+
cancelled = true;
|
|
183
|
+
await sourceReader.cancel();
|
|
184
|
+
try {
|
|
185
|
+
controller.close();
|
|
186
|
+
} catch {
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
signal.addEventListener(
|
|
191
|
+
"abort",
|
|
192
|
+
() => {
|
|
193
|
+
cancelled = true;
|
|
194
|
+
sourceReader?.cancel().catch(() => {
|
|
195
|
+
});
|
|
196
|
+
try {
|
|
197
|
+
controller.close();
|
|
198
|
+
} catch {
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
{ once: true }
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
while (!cancelled) {
|
|
206
|
+
const { value, done } = await sourceReader.read();
|
|
207
|
+
if (done) break;
|
|
208
|
+
const scrubbed = applyScrub2(value, scrub);
|
|
209
|
+
controller.enqueue(
|
|
210
|
+
encoder.encode(sseFrame(scrubbed.kind, scrubbed))
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
} catch {
|
|
214
|
+
} finally {
|
|
215
|
+
try {
|
|
216
|
+
controller.close();
|
|
217
|
+
} catch {
|
|
218
|
+
}
|
|
219
|
+
try {
|
|
220
|
+
sourceReader?.releaseLock();
|
|
221
|
+
} catch {
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
cancel() {
|
|
226
|
+
cancelled = true;
|
|
227
|
+
sourceReader?.cancel().catch(() => {
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
return new Response(body, { status: 200, headers: SSE_HEADERS });
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// src/glassbox-routes/index.ts
|
|
236
|
+
function requireString(name, value) {
|
|
237
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
238
|
+
throw new Error(`createGlassboxRoutes: ${name} is required`);
|
|
239
|
+
}
|
|
240
|
+
return value;
|
|
241
|
+
}
|
|
242
|
+
function createGlassboxRoutes(config) {
|
|
243
|
+
const installToken = requireString("installToken", config.installToken);
|
|
244
|
+
const extensionId = requireString("extensionId", config.extensionId);
|
|
245
|
+
const brainEndpoint = requireString("brainEndpoint", config.brainEndpoint);
|
|
246
|
+
const brainJwt = requireString("brainJwt", config.brainJwt);
|
|
247
|
+
const appId = requireString("appId", config.appId);
|
|
248
|
+
const proxy = createProxyHandler({
|
|
249
|
+
installToken,
|
|
250
|
+
extensionId,
|
|
251
|
+
brainEndpoint,
|
|
252
|
+
brainJwt,
|
|
253
|
+
appId,
|
|
254
|
+
scrub: config.scrub,
|
|
255
|
+
fetch: config.fetch
|
|
256
|
+
});
|
|
257
|
+
const stream = createStreamHandler(
|
|
258
|
+
{
|
|
259
|
+
installToken,
|
|
260
|
+
extensionId,
|
|
261
|
+
scrub: config.scrub
|
|
262
|
+
},
|
|
263
|
+
config.subscribe ?? subscribe
|
|
264
|
+
);
|
|
265
|
+
return { proxy, stream };
|
|
266
|
+
}
|
|
267
|
+
export {
|
|
268
|
+
createGlassboxRoutes
|
|
269
|
+
};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { g as
|
|
1
|
+
import { C as CompilePolicy, N as NormalizedResponse, A as ApiKeys, P as ProviderOverrides, a as CompiledRequest, b as PromptIR, c as CallOptions, d as CallResult, R as RecordInput, O as OracleScore, e as CompileResult, B as BestPracticeAdvisory, f as Provider } from './ir-C3P4gDt0.mjs';
|
|
2
|
+
export { g as CallAttempt, h as CallError, i as Constraints, F as FallbackReason, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, j as MutationApplied, k as NormalizedTokens, l as PromptSection, T as ToolCall, m as ToolDefinition } from './ir-C3P4gDt0.mjs';
|
|
3
|
+
import { ModelProfile } from './profiles.mjs';
|
|
4
|
+
export { ALIASES, CacheStrategy, CliffRule, LoweringSpec, RecoveryRule, StructuredOutputCapability, SystemPromptMode, allProfiles, getProfile, profilesByProvider, tryGetProfile } from './profiles.mjs';
|
|
3
5
|
import { IntentArchetypeName } from './dialect.mjs';
|
|
4
6
|
export { ALL_ARCHETYPES, ContextBucket, DIALECT_VERSION, HistoryDepth, INTENT_ARCHETYPES, OutputMode, ShapeSignature, ToolCountBucket, bucketContext, bucketHistory, bucketToolCount, hashShape, isArchetype, learningKey } from './dialect.mjs';
|
|
5
7
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { g as
|
|
1
|
+
import { C as CompilePolicy, N as NormalizedResponse, A as ApiKeys, P as ProviderOverrides, a as CompiledRequest, b as PromptIR, c as CallOptions, d as CallResult, R as RecordInput, O as OracleScore, e as CompileResult, B as BestPracticeAdvisory, f as Provider } from './ir-CFHU3BUT.js';
|
|
2
|
+
export { g as CallAttempt, h as CallError, i as Constraints, F as FallbackReason, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, j as MutationApplied, k as NormalizedTokens, l as PromptSection, T as ToolCall, m as ToolDefinition } from './ir-CFHU3BUT.js';
|
|
3
|
+
import { ModelProfile } from './profiles.js';
|
|
4
|
+
export { ALIASES, CacheStrategy, CliffRule, LoweringSpec, RecoveryRule, StructuredOutputCapability, SystemPromptMode, allProfiles, getProfile, profilesByProvider, tryGetProfile } from './profiles.js';
|
|
3
5
|
import { IntentArchetypeName } from './dialect.js';
|
|
4
6
|
export { ALL_ARCHETYPES, ContextBucket, DIALECT_VERSION, HistoryDepth, INTENT_ARCHETYPES, OutputMode, ShapeSignature, ToolCountBucket, bucketContext, bucketHistory, bucketToolCount, hashShape, isArchetype, learningKey } from './dialect.js';
|
|
5
7
|
|
package/dist/index.js
CHANGED
|
@@ -2925,9 +2925,321 @@ function ensureCrossProviderTail(opts) {
|
|
|
2925
2925
|
return { chain };
|
|
2926
2926
|
}
|
|
2927
2927
|
|
|
2928
|
+
// src/glassbox/types.ts
|
|
2929
|
+
var GLASSBOX_STREAM_TTL_MS = 6e4;
|
|
2930
|
+
|
|
2931
|
+
// src/glassbox/pubsub-memory.ts
|
|
2932
|
+
var MemoryPubSub = class {
|
|
2933
|
+
subscribers = /* @__PURE__ */ new Map();
|
|
2934
|
+
async publish(traceId, event) {
|
|
2935
|
+
const subs = this.subscribers.get(traceId);
|
|
2936
|
+
if (!subs || subs.size === 0) return;
|
|
2937
|
+
for (const sub of subs) {
|
|
2938
|
+
if (sub.closed) continue;
|
|
2939
|
+
try {
|
|
2940
|
+
sub.controller.enqueue(event);
|
|
2941
|
+
} catch {
|
|
2942
|
+
sub.closed = true;
|
|
2943
|
+
continue;
|
|
2944
|
+
}
|
|
2945
|
+
this.refreshTtl(traceId, sub);
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
subscribe(traceId) {
|
|
2949
|
+
const self = this;
|
|
2950
|
+
let sub;
|
|
2951
|
+
return new ReadableStream({
|
|
2952
|
+
start(controller) {
|
|
2953
|
+
sub = {
|
|
2954
|
+
controller,
|
|
2955
|
+
ttlTimer: setTimeout(() => {
|
|
2956
|
+
self.closeSubscriber(traceId, sub);
|
|
2957
|
+
}, GLASSBOX_STREAM_TTL_MS),
|
|
2958
|
+
closed: false
|
|
2959
|
+
};
|
|
2960
|
+
let set = self.subscribers.get(traceId);
|
|
2961
|
+
if (!set) {
|
|
2962
|
+
set = /* @__PURE__ */ new Set();
|
|
2963
|
+
self.subscribers.set(traceId, set);
|
|
2964
|
+
}
|
|
2965
|
+
set.add(sub);
|
|
2966
|
+
},
|
|
2967
|
+
cancel() {
|
|
2968
|
+
if (sub) self.removeSubscriber(traceId, sub);
|
|
2969
|
+
}
|
|
2970
|
+
});
|
|
2971
|
+
}
|
|
2972
|
+
/**
|
|
2973
|
+
* Refresh the rolling TTL for a subscriber after an event lands. Replaces
|
|
2974
|
+
* the existing timer with a fresh 60s one.
|
|
2975
|
+
*/
|
|
2976
|
+
refreshTtl(traceId, sub) {
|
|
2977
|
+
clearTimeout(sub.ttlTimer);
|
|
2978
|
+
sub.ttlTimer = setTimeout(() => {
|
|
2979
|
+
this.closeSubscriber(traceId, sub);
|
|
2980
|
+
}, GLASSBOX_STREAM_TTL_MS);
|
|
2981
|
+
}
|
|
2982
|
+
/**
|
|
2983
|
+
* Close the subscriber's stream cleanly and remove from the fan-out set.
|
|
2984
|
+
* Idempotent — safe to call multiple times.
|
|
2985
|
+
*/
|
|
2986
|
+
closeSubscriber(traceId, sub) {
|
|
2987
|
+
if (sub.closed) return;
|
|
2988
|
+
sub.closed = true;
|
|
2989
|
+
clearTimeout(sub.ttlTimer);
|
|
2990
|
+
try {
|
|
2991
|
+
sub.controller.close();
|
|
2992
|
+
} catch {
|
|
2993
|
+
}
|
|
2994
|
+
this.removeSubscriber(traceId, sub);
|
|
2995
|
+
}
|
|
2996
|
+
removeSubscriber(traceId, sub) {
|
|
2997
|
+
clearTimeout(sub.ttlTimer);
|
|
2998
|
+
const set = this.subscribers.get(traceId);
|
|
2999
|
+
if (!set) return;
|
|
3000
|
+
set.delete(sub);
|
|
3001
|
+
if (set.size === 0) this.subscribers.delete(traceId);
|
|
3002
|
+
}
|
|
3003
|
+
/**
|
|
3004
|
+
* Test-only reset. Tears down all subscribers, clears all state. Calling
|
|
3005
|
+
* outside of tests is harmless but cancels every active stream.
|
|
3006
|
+
*/
|
|
3007
|
+
_reset() {
|
|
3008
|
+
for (const [, set] of this.subscribers) {
|
|
3009
|
+
for (const sub of set) {
|
|
3010
|
+
this.closeSubscriber("", sub);
|
|
3011
|
+
}
|
|
3012
|
+
}
|
|
3013
|
+
this.subscribers.clear();
|
|
3014
|
+
}
|
|
3015
|
+
};
|
|
3016
|
+
|
|
3017
|
+
// src/glassbox/pubsub-upstash.ts
|
|
3018
|
+
var UpstashPubSub = class {
|
|
3019
|
+
url;
|
|
3020
|
+
token;
|
|
3021
|
+
fetchImpl;
|
|
3022
|
+
blockMs;
|
|
3023
|
+
maxLen;
|
|
3024
|
+
constructor(cfg) {
|
|
3025
|
+
this.url = cfg.url.replace(/\/$/, "");
|
|
3026
|
+
this.token = cfg.token;
|
|
3027
|
+
this.fetchImpl = cfg.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
3028
|
+
this.blockMs = cfg.blockMs ?? 100;
|
|
3029
|
+
this.maxLen = cfg.maxLen ?? 100;
|
|
3030
|
+
}
|
|
3031
|
+
async publish(traceId, event) {
|
|
3032
|
+
const key = streamKey(traceId);
|
|
3033
|
+
const payload = JSON.stringify(event);
|
|
3034
|
+
await this.cmd([
|
|
3035
|
+
"XADD",
|
|
3036
|
+
key,
|
|
3037
|
+
"MAXLEN",
|
|
3038
|
+
"~",
|
|
3039
|
+
String(this.maxLen),
|
|
3040
|
+
"*",
|
|
3041
|
+
"event",
|
|
3042
|
+
payload
|
|
3043
|
+
]);
|
|
3044
|
+
await this.cmd(["EXPIRE", key, String(Math.ceil(GLASSBOX_STREAM_TTL_MS / 1e3))]);
|
|
3045
|
+
}
|
|
3046
|
+
subscribe(traceId) {
|
|
3047
|
+
const key = streamKey(traceId);
|
|
3048
|
+
const self = this;
|
|
3049
|
+
let cursor = "$";
|
|
3050
|
+
let cancelled = false;
|
|
3051
|
+
let ttlDeadline = Date.now() + GLASSBOX_STREAM_TTL_MS;
|
|
3052
|
+
return new ReadableStream({
|
|
3053
|
+
async start(controller) {
|
|
3054
|
+
try {
|
|
3055
|
+
while (!cancelled && Date.now() < ttlDeadline) {
|
|
3056
|
+
const resp = await self.cmd([
|
|
3057
|
+
"XREAD",
|
|
3058
|
+
"BLOCK",
|
|
3059
|
+
String(self.blockMs),
|
|
3060
|
+
"STREAMS",
|
|
3061
|
+
key,
|
|
3062
|
+
cursor
|
|
3063
|
+
]);
|
|
3064
|
+
if (cancelled) break;
|
|
3065
|
+
const parsed = parseXReadResult(resp.result);
|
|
3066
|
+
if (parsed.entries.length === 0) {
|
|
3067
|
+
continue;
|
|
3068
|
+
}
|
|
3069
|
+
for (const entry of parsed.entries) {
|
|
3070
|
+
const evt = decodeEvent(entry.fields);
|
|
3071
|
+
if (evt) {
|
|
3072
|
+
try {
|
|
3073
|
+
controller.enqueue(evt);
|
|
3074
|
+
} catch {
|
|
3075
|
+
cancelled = true;
|
|
3076
|
+
break;
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3079
|
+
cursor = entry.id;
|
|
3080
|
+
}
|
|
3081
|
+
ttlDeadline = Date.now() + GLASSBOX_STREAM_TTL_MS;
|
|
3082
|
+
}
|
|
3083
|
+
} catch (err) {
|
|
3084
|
+
if (!cancelled) {
|
|
3085
|
+
try {
|
|
3086
|
+
controller.error(err);
|
|
3087
|
+
} catch {
|
|
3088
|
+
}
|
|
3089
|
+
return;
|
|
3090
|
+
}
|
|
3091
|
+
}
|
|
3092
|
+
try {
|
|
3093
|
+
controller.close();
|
|
3094
|
+
} catch {
|
|
3095
|
+
}
|
|
3096
|
+
},
|
|
3097
|
+
cancel() {
|
|
3098
|
+
cancelled = true;
|
|
3099
|
+
}
|
|
3100
|
+
});
|
|
3101
|
+
}
|
|
3102
|
+
async cmd(args) {
|
|
3103
|
+
const res = await this.fetchImpl(this.url, {
|
|
3104
|
+
method: "POST",
|
|
3105
|
+
headers: {
|
|
3106
|
+
Authorization: `Bearer ${this.token}`,
|
|
3107
|
+
"Content-Type": "application/json"
|
|
3108
|
+
},
|
|
3109
|
+
body: JSON.stringify(args)
|
|
3110
|
+
});
|
|
3111
|
+
if (!res.ok) {
|
|
3112
|
+
throw new Error(`Upstash ${args[0]} failed: HTTP ${res.status}`);
|
|
3113
|
+
}
|
|
3114
|
+
const json = await res.json();
|
|
3115
|
+
if (json.error) {
|
|
3116
|
+
throw new Error(`Upstash ${args[0]} failed: ${json.error}`);
|
|
3117
|
+
}
|
|
3118
|
+
return json;
|
|
3119
|
+
}
|
|
3120
|
+
};
|
|
3121
|
+
function streamKey(traceId) {
|
|
3122
|
+
return `glassbox:trace:${traceId}`;
|
|
3123
|
+
}
|
|
3124
|
+
function decodeEvent(fields) {
|
|
3125
|
+
const raw = fields["event"];
|
|
3126
|
+
if (!raw) return void 0;
|
|
3127
|
+
try {
|
|
3128
|
+
const parsed = JSON.parse(raw);
|
|
3129
|
+
if (typeof parsed.kind === "string" && typeof parsed.at === "number") {
|
|
3130
|
+
return parsed;
|
|
3131
|
+
}
|
|
3132
|
+
return void 0;
|
|
3133
|
+
} catch {
|
|
3134
|
+
return void 0;
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
function parseXReadResult(raw) {
|
|
3138
|
+
if (!Array.isArray(raw)) return { entries: [] };
|
|
3139
|
+
const entries = [];
|
|
3140
|
+
for (const stream of raw) {
|
|
3141
|
+
if (!Array.isArray(stream) || stream.length < 2) continue;
|
|
3142
|
+
const streamEntries = stream[1];
|
|
3143
|
+
if (!Array.isArray(streamEntries)) continue;
|
|
3144
|
+
for (const entry of streamEntries) {
|
|
3145
|
+
if (!Array.isArray(entry) || entry.length < 2) continue;
|
|
3146
|
+
const id = String(entry[0]);
|
|
3147
|
+
const flat = entry[1];
|
|
3148
|
+
if (!Array.isArray(flat)) continue;
|
|
3149
|
+
const fields = {};
|
|
3150
|
+
for (let i = 0; i < flat.length; i += 2) {
|
|
3151
|
+
const k = flat[i];
|
|
3152
|
+
const v = flat[i + 1];
|
|
3153
|
+
if (typeof k === "string") fields[k] = String(v ?? "");
|
|
3154
|
+
}
|
|
3155
|
+
entries.push({ id, fields });
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
return { entries };
|
|
3159
|
+
}
|
|
3160
|
+
|
|
3161
|
+
// src/glassbox/emit.ts
|
|
3162
|
+
var activePubSub;
|
|
3163
|
+
function getPubSub() {
|
|
3164
|
+
if (activePubSub) return activePubSub;
|
|
3165
|
+
const url = readEnv("UPSTASH_REDIS_URL");
|
|
3166
|
+
const token = readEnv("UPSTASH_REDIS_TOKEN");
|
|
3167
|
+
if (url && token) {
|
|
3168
|
+
activePubSub = new UpstashPubSub({ url, token });
|
|
3169
|
+
} else {
|
|
3170
|
+
activePubSub = new MemoryPubSub();
|
|
3171
|
+
}
|
|
3172
|
+
return activePubSub;
|
|
3173
|
+
}
|
|
3174
|
+
function readEnv(key) {
|
|
3175
|
+
try {
|
|
3176
|
+
if (typeof process !== "undefined" && process.env) {
|
|
3177
|
+
const v = process.env[key];
|
|
3178
|
+
return v && v.trim() !== "" ? v : void 0;
|
|
3179
|
+
}
|
|
3180
|
+
} catch {
|
|
3181
|
+
}
|
|
3182
|
+
return void 0;
|
|
3183
|
+
}
|
|
3184
|
+
function emitGlassboxEvent(traceId, kind, data) {
|
|
3185
|
+
if (!traceId) return;
|
|
3186
|
+
const event = { kind, at: Date.now(), data };
|
|
3187
|
+
const ps = getPubSub();
|
|
3188
|
+
try {
|
|
3189
|
+
const p = ps.publish(traceId, event);
|
|
3190
|
+
if (p && typeof p.then === "function") {
|
|
3191
|
+
p.catch(() => {
|
|
3192
|
+
});
|
|
3193
|
+
}
|
|
3194
|
+
} catch {
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3197
|
+
function emitCompileStart(traceId, data) {
|
|
3198
|
+
emitGlassboxEvent(traceId, "compile.start", data);
|
|
3199
|
+
}
|
|
3200
|
+
function emitCompileDone(traceId, data) {
|
|
3201
|
+
emitGlassboxEvent(traceId, "compile.done", data);
|
|
3202
|
+
}
|
|
3203
|
+
function emitExecuteAttempt(traceId, data) {
|
|
3204
|
+
emitGlassboxEvent(traceId, "execute.attempt", data);
|
|
3205
|
+
}
|
|
3206
|
+
function emitExecuteSuccess(traceId, data) {
|
|
3207
|
+
emitGlassboxEvent(traceId, "execute.success", data);
|
|
3208
|
+
}
|
|
3209
|
+
function emitAdvisoryFired(traceId, data) {
|
|
3210
|
+
emitGlassboxEvent(traceId, "advisory.fired", data);
|
|
3211
|
+
}
|
|
3212
|
+
function emitFallbackWalked(traceId, data) {
|
|
3213
|
+
emitGlassboxEvent(traceId, "fallback.walked", data);
|
|
3214
|
+
}
|
|
3215
|
+
|
|
2928
3216
|
// src/call.ts
|
|
2929
3217
|
async function call(ir, opts = {}) {
|
|
3218
|
+
const traceId = generateTraceId();
|
|
3219
|
+
safeEmit(
|
|
3220
|
+
() => emitCompileStart(traceId, {
|
|
3221
|
+
appId: ir.appId,
|
|
3222
|
+
archetype: ir.intent.archetype,
|
|
3223
|
+
models: ir.models
|
|
3224
|
+
})
|
|
3225
|
+
);
|
|
2930
3226
|
const initial = compileAndRegister(ir, opts);
|
|
3227
|
+
safeEmit(
|
|
3228
|
+
() => emitCompileDone(traceId, {
|
|
3229
|
+
target: initial.target,
|
|
3230
|
+
provider: initial.provider,
|
|
3231
|
+
fallbackChain: initial.fallbackChain,
|
|
3232
|
+
tokensIn: initial.tokensIn,
|
|
3233
|
+
estimatedCostUsd: initial.estimatedCostUsd,
|
|
3234
|
+
mutationsApplied: initial.mutationsApplied,
|
|
3235
|
+
advisories: initial.advisories
|
|
3236
|
+
})
|
|
3237
|
+
);
|
|
3238
|
+
for (const adv of initial.advisories) {
|
|
3239
|
+
safeEmit(
|
|
3240
|
+
() => emitAdvisoryFired(traceId, { code: adv.code, message: adv.message })
|
|
3241
|
+
);
|
|
3242
|
+
}
|
|
2931
3243
|
const start = Date.now();
|
|
2932
3244
|
const attempts = [];
|
|
2933
3245
|
const rawTargets = [initial.target, ...initial.fallbackChain];
|
|
@@ -3058,6 +3370,9 @@ async function call(ir, opts = {}) {
|
|
|
3058
3370
|
continue;
|
|
3059
3371
|
}
|
|
3060
3372
|
}
|
|
3373
|
+
safeEmit(
|
|
3374
|
+
() => emitExecuteAttempt(traceId, { model: targetModel, attemptIndex: i })
|
|
3375
|
+
);
|
|
3061
3376
|
const exec = await execute(activeCompile.request, {
|
|
3062
3377
|
apiKeys: opts.apiKeys,
|
|
3063
3378
|
fetchImpl: opts.fetchImpl,
|
|
@@ -3067,6 +3382,14 @@ async function call(ir, opts = {}) {
|
|
|
3067
3382
|
if (validated.ok) {
|
|
3068
3383
|
attempts.push({ model: targetModel, status: "success" });
|
|
3069
3384
|
const latencyMs2 = Date.now() - start;
|
|
3385
|
+
safeEmit(
|
|
3386
|
+
() => emitExecuteSuccess(traceId, {
|
|
3387
|
+
model: targetModel,
|
|
3388
|
+
tokensIn: validated.response.tokens.input,
|
|
3389
|
+
tokensOut: validated.response.tokens.output,
|
|
3390
|
+
latencyMs: latencyMs2
|
|
3391
|
+
})
|
|
3392
|
+
);
|
|
3070
3393
|
await record({
|
|
3071
3394
|
handle: initial.handle,
|
|
3072
3395
|
tokensIn: validated.response.tokens.input,
|
|
@@ -3083,6 +3406,20 @@ async function call(ir, opts = {}) {
|
|
|
3083
3406
|
cacheCreationInputTokens: validated.response.tokens.cacheCreated
|
|
3084
3407
|
});
|
|
3085
3408
|
const fellOver = targetModel !== initial.target;
|
|
3409
|
+
const fallbackReason = fellOver ? normalizeFallbackReason(attempts) : void 0;
|
|
3410
|
+
if (fellOver) {
|
|
3411
|
+
const firstFailed = attempts.find((a) => a.status !== "success");
|
|
3412
|
+
if (firstFailed) {
|
|
3413
|
+
safeEmit(
|
|
3414
|
+
() => emitFallbackWalked(traceId, {
|
|
3415
|
+
from: initial.target,
|
|
3416
|
+
to: targetModel,
|
|
3417
|
+
reason: fallbackReason ?? "unknown",
|
|
3418
|
+
attempt: firstFailed
|
|
3419
|
+
})
|
|
3420
|
+
);
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3086
3423
|
return {
|
|
3087
3424
|
handle: initial.handle,
|
|
3088
3425
|
actualModel: targetModel,
|
|
@@ -3094,9 +3431,10 @@ async function call(ir, opts = {}) {
|
|
|
3094
3431
|
attempts,
|
|
3095
3432
|
servedBy: targetModel,
|
|
3096
3433
|
fellOverFrom: fellOver ? initial.target : void 0,
|
|
3097
|
-
fallbackReason
|
|
3434
|
+
fallbackReason,
|
|
3098
3435
|
unreachableFiltered,
|
|
3099
|
-
policyBlockedFiltered
|
|
3436
|
+
policyBlockedFiltered,
|
|
3437
|
+
traceId
|
|
3100
3438
|
};
|
|
3101
3439
|
}
|
|
3102
3440
|
attempts.push({
|
|
@@ -3193,6 +3531,23 @@ function normalizeFallbackReason(attempts) {
|
|
|
3193
3531
|
if (code === "auth" || code === "auth_inferred") return "provider_auth_failed";
|
|
3194
3532
|
return "provider_error";
|
|
3195
3533
|
}
|
|
3534
|
+
function generateTraceId() {
|
|
3535
|
+
try {
|
|
3536
|
+
const g = globalThis;
|
|
3537
|
+
if (g.crypto && typeof g.crypto.randomUUID === "function") {
|
|
3538
|
+
return g.crypto.randomUUID();
|
|
3539
|
+
}
|
|
3540
|
+
} catch {
|
|
3541
|
+
}
|
|
3542
|
+
const hex = (n) => Math.floor(Math.random() * Math.pow(16, n)).toString(16).padStart(n, "0");
|
|
3543
|
+
return `${hex(8)}-${hex(4)}-${hex(4)}-${hex(4)}-${hex(12)}`;
|
|
3544
|
+
}
|
|
3545
|
+
function safeEmit(fn) {
|
|
3546
|
+
try {
|
|
3547
|
+
fn();
|
|
3548
|
+
} catch {
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3196
3551
|
|
|
3197
3552
|
// src/oracle.ts
|
|
3198
3553
|
var DEFAULT_DIMENSIONS = ["correctness", "completeness", "conciseness", "format"];
|