@warmdrift/kgauto-compiler 2.0.0-alpha.8 → 2.0.0-alpha.81

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.
Files changed (55) hide show
  1. package/README.md +176 -46
  2. package/dist/brain-proxy.d.mts +113 -0
  3. package/dist/brain-proxy.d.ts +113 -0
  4. package/dist/brain-proxy.js +193 -0
  5. package/dist/brain-proxy.mjs +6 -0
  6. package/dist/chunk-65ZMX5OT.mjs +169 -0
  7. package/dist/{chunk-5TI6PNSK.mjs → chunk-BVEXV5KC.mjs} +11 -0
  8. package/dist/chunk-NBO4R5PC.mjs +313 -0
  9. package/dist/chunk-OZNAGO4U.mjs +219 -0
  10. package/dist/chunk-P3TOAEG4.mjs +56 -0
  11. package/dist/chunk-RO22VFIF.mjs +29 -0
  12. package/dist/chunk-VVRDFE6T.mjs +1707 -0
  13. package/dist/chunk-XPD4I3Q5.mjs +832 -0
  14. package/dist/dialect.d.mts +41 -3
  15. package/dist/dialect.d.ts +41 -3
  16. package/dist/dialect.js +14 -2
  17. package/dist/dialect.mjs +5 -3
  18. package/dist/glassbox/index.d.mts +59 -0
  19. package/dist/glassbox/index.d.ts +59 -0
  20. package/dist/glassbox/index.js +312 -0
  21. package/dist/glassbox/index.mjs +12 -0
  22. package/dist/glassbox-routes/format.d.mts +24 -0
  23. package/dist/glassbox-routes/format.d.ts +24 -0
  24. package/dist/glassbox-routes/format.js +86 -0
  25. package/dist/glassbox-routes/format.mjs +18 -0
  26. package/dist/glassbox-routes/index.d.mts +191 -0
  27. package/dist/glassbox-routes/index.d.ts +191 -0
  28. package/dist/glassbox-routes/index.js +3063 -0
  29. package/dist/glassbox-routes/index.mjs +668 -0
  30. package/dist/glassbox-routes/react/index.d.mts +74 -0
  31. package/dist/glassbox-routes/react/index.d.ts +74 -0
  32. package/dist/glassbox-routes/react/index.js +819 -0
  33. package/dist/glassbox-routes/react/index.mjs +754 -0
  34. package/dist/index.d.mts +3455 -21
  35. package/dist/index.d.ts +3455 -21
  36. package/dist/index.js +10241 -1681
  37. package/dist/index.mjs +5905 -186
  38. package/dist/ir-BFwWhj2s.d.mts +1707 -0
  39. package/dist/ir-DZKS1tI7.d.ts +1707 -0
  40. package/dist/key-health.d.mts +166 -0
  41. package/dist/key-health.d.ts +166 -0
  42. package/dist/key-health.js +247 -0
  43. package/dist/key-health.mjs +12 -0
  44. package/dist/profiles.d.mts +302 -2
  45. package/dist/profiles.d.ts +302 -2
  46. package/dist/profiles.js +1320 -18
  47. package/dist/profiles.mjs +9 -1
  48. package/dist/types-B4kz3Vs0.d.ts +131 -0
  49. package/dist/types-D_fLt_Xv.d.ts +142 -0
  50. package/dist/types-DpcAMmk-.d.mts +131 -0
  51. package/dist/types-hjzSWxtv.d.mts +142 -0
  52. package/package.json +54 -8
  53. package/dist/chunk-MBEI5UOM.mjs +0 -409
  54. package/dist/profiles-B3eNQ2py.d.ts +0 -619
  55. package/dist/profiles-Py8c7zjJ.d.mts +0 -619
@@ -0,0 +1,313 @@
1
+ // src/glassbox/types.ts
2
+ var GLASSBOX_STREAM_TTL_MS = 6e4;
3
+
4
+ // src/glassbox/pubsub-upstash.ts
5
+ var UpstashPubSub = class {
6
+ url;
7
+ token;
8
+ fetchImpl;
9
+ blockMs;
10
+ maxLen;
11
+ constructor(cfg) {
12
+ this.url = cfg.url.replace(/\/$/, "");
13
+ this.token = cfg.token;
14
+ this.fetchImpl = cfg.fetchImpl ?? globalThis.fetch.bind(globalThis);
15
+ this.blockMs = cfg.blockMs ?? 100;
16
+ this.maxLen = cfg.maxLen ?? 100;
17
+ }
18
+ async publish(channelKey, event) {
19
+ const key = channelKey;
20
+ const payload = JSON.stringify(event);
21
+ await this.cmd([
22
+ "XADD",
23
+ key,
24
+ "MAXLEN",
25
+ "~",
26
+ String(this.maxLen),
27
+ "*",
28
+ "event",
29
+ payload
30
+ ]);
31
+ await this.cmd(["EXPIRE", key, String(Math.ceil(GLASSBOX_STREAM_TTL_MS / 1e3))]);
32
+ }
33
+ subscribe(channelKey) {
34
+ const key = channelKey;
35
+ const self = this;
36
+ let cursor = "$";
37
+ let cancelled = false;
38
+ let ttlDeadline = Date.now() + GLASSBOX_STREAM_TTL_MS;
39
+ return new ReadableStream({
40
+ async start(controller) {
41
+ try {
42
+ while (!cancelled && Date.now() < ttlDeadline) {
43
+ const resp = await self.cmd([
44
+ "XREAD",
45
+ "BLOCK",
46
+ String(self.blockMs),
47
+ "STREAMS",
48
+ key,
49
+ cursor
50
+ ]);
51
+ if (cancelled) break;
52
+ const parsed = parseXReadResult(resp.result);
53
+ if (parsed.entries.length === 0) {
54
+ continue;
55
+ }
56
+ for (const entry of parsed.entries) {
57
+ const evt = decodeEvent(entry.fields);
58
+ if (evt) {
59
+ try {
60
+ controller.enqueue(evt);
61
+ } catch {
62
+ cancelled = true;
63
+ break;
64
+ }
65
+ }
66
+ cursor = entry.id;
67
+ }
68
+ ttlDeadline = Date.now() + GLASSBOX_STREAM_TTL_MS;
69
+ }
70
+ } catch (err) {
71
+ if (!cancelled) {
72
+ try {
73
+ controller.error(err);
74
+ } catch {
75
+ }
76
+ return;
77
+ }
78
+ }
79
+ try {
80
+ controller.close();
81
+ } catch {
82
+ }
83
+ },
84
+ cancel() {
85
+ cancelled = true;
86
+ }
87
+ });
88
+ }
89
+ async cmd(args) {
90
+ const res = await this.fetchImpl(this.url, {
91
+ method: "POST",
92
+ headers: {
93
+ Authorization: `Bearer ${this.token}`,
94
+ "Content-Type": "application/json"
95
+ },
96
+ body: JSON.stringify(args)
97
+ });
98
+ if (!res.ok) {
99
+ throw new Error(`Upstash ${args[0]} failed: HTTP ${res.status}`);
100
+ }
101
+ const json = await res.json();
102
+ if (json.error) {
103
+ throw new Error(`Upstash ${args[0]} failed: ${json.error}`);
104
+ }
105
+ return json;
106
+ }
107
+ };
108
+ function traceChannel(traceId) {
109
+ return `glassbox:trace:${traceId}`;
110
+ }
111
+ function appChannel(appId) {
112
+ return `glassbox:app:${appId}`;
113
+ }
114
+ function decodeEvent(fields) {
115
+ const raw = fields["event"];
116
+ if (!raw) return void 0;
117
+ try {
118
+ const parsed = JSON.parse(raw);
119
+ if (typeof parsed.kind === "string" && typeof parsed.at === "number") {
120
+ return parsed;
121
+ }
122
+ return void 0;
123
+ } catch {
124
+ return void 0;
125
+ }
126
+ }
127
+ function parseXReadResult(raw) {
128
+ if (!Array.isArray(raw)) return { entries: [] };
129
+ const entries = [];
130
+ for (const stream of raw) {
131
+ if (!Array.isArray(stream) || stream.length < 2) continue;
132
+ const streamEntries = stream[1];
133
+ if (!Array.isArray(streamEntries)) continue;
134
+ for (const entry of streamEntries) {
135
+ if (!Array.isArray(entry) || entry.length < 2) continue;
136
+ const id = String(entry[0]);
137
+ const flat = entry[1];
138
+ if (!Array.isArray(flat)) continue;
139
+ const fields = {};
140
+ for (let i = 0; i < flat.length; i += 2) {
141
+ const k = flat[i];
142
+ const v = flat[i + 1];
143
+ if (typeof k === "string") fields[k] = String(v ?? "");
144
+ }
145
+ entries.push({ id, fields });
146
+ }
147
+ }
148
+ return { entries };
149
+ }
150
+
151
+ // src/glassbox/pubsub-memory.ts
152
+ var MemoryPubSub = class {
153
+ subscribers = /* @__PURE__ */ new Map();
154
+ async publish(channelKey, event) {
155
+ const subs = this.subscribers.get(channelKey);
156
+ if (!subs || subs.size === 0) return;
157
+ for (const sub of subs) {
158
+ if (sub.closed) continue;
159
+ try {
160
+ sub.controller.enqueue(event);
161
+ } catch {
162
+ sub.closed = true;
163
+ continue;
164
+ }
165
+ this.refreshTtl(channelKey, sub);
166
+ }
167
+ }
168
+ subscribe(channelKey) {
169
+ const self = this;
170
+ let sub;
171
+ return new ReadableStream({
172
+ start(controller) {
173
+ sub = {
174
+ controller,
175
+ ttlTimer: setTimeout(() => {
176
+ self.closeSubscriber(channelKey, sub);
177
+ }, GLASSBOX_STREAM_TTL_MS),
178
+ closed: false
179
+ };
180
+ let set = self.subscribers.get(channelKey);
181
+ if (!set) {
182
+ set = /* @__PURE__ */ new Set();
183
+ self.subscribers.set(channelKey, set);
184
+ }
185
+ set.add(sub);
186
+ },
187
+ cancel() {
188
+ if (sub) self.removeSubscriber(channelKey, sub);
189
+ }
190
+ });
191
+ }
192
+ /**
193
+ * Refresh the rolling TTL for a subscriber after an event lands. Replaces
194
+ * the existing timer with a fresh 60s one.
195
+ */
196
+ refreshTtl(channelKey, sub) {
197
+ clearTimeout(sub.ttlTimer);
198
+ sub.ttlTimer = setTimeout(() => {
199
+ this.closeSubscriber(channelKey, sub);
200
+ }, GLASSBOX_STREAM_TTL_MS);
201
+ }
202
+ /**
203
+ * Close the subscriber's stream cleanly and remove from the fan-out set.
204
+ * Idempotent — safe to call multiple times.
205
+ */
206
+ closeSubscriber(channelKey, sub) {
207
+ if (sub.closed) return;
208
+ sub.closed = true;
209
+ clearTimeout(sub.ttlTimer);
210
+ try {
211
+ sub.controller.close();
212
+ } catch {
213
+ }
214
+ this.removeSubscriber(channelKey, sub);
215
+ }
216
+ removeSubscriber(channelKey, sub) {
217
+ clearTimeout(sub.ttlTimer);
218
+ const set = this.subscribers.get(channelKey);
219
+ if (!set) return;
220
+ set.delete(sub);
221
+ if (set.size === 0) this.subscribers.delete(channelKey);
222
+ }
223
+ /**
224
+ * Test-only reset. Tears down all subscribers, clears all state. Calling
225
+ * outside of tests is harmless but cancels every active stream.
226
+ */
227
+ _reset() {
228
+ for (const [, set] of this.subscribers) {
229
+ for (const sub of set) {
230
+ this.closeSubscriber("", sub);
231
+ }
232
+ }
233
+ this.subscribers.clear();
234
+ }
235
+ };
236
+
237
+ // src/glassbox/emit.ts
238
+ var activePubSub;
239
+ function getPubSub() {
240
+ if (activePubSub) return activePubSub;
241
+ const url = readEnv("UPSTASH_REDIS_URL");
242
+ const token = readEnv("UPSTASH_REDIS_TOKEN");
243
+ if (url && token) {
244
+ activePubSub = new UpstashPubSub({ url, token });
245
+ } else {
246
+ activePubSub = new MemoryPubSub();
247
+ }
248
+ return activePubSub;
249
+ }
250
+ function readEnv(key) {
251
+ try {
252
+ if (typeof process !== "undefined" && process.env) {
253
+ const v = process.env[key];
254
+ return v && v.trim() !== "" ? v : void 0;
255
+ }
256
+ } catch {
257
+ }
258
+ return void 0;
259
+ }
260
+ function emitGlassboxEvent(traceId, appId, kind, data) {
261
+ if (!traceId) return;
262
+ const event = { kind, at: Date.now(), data };
263
+ const ps = getPubSub();
264
+ try {
265
+ const p1 = ps.publish(traceChannel(traceId), event);
266
+ if (p1 && typeof p1.then === "function") {
267
+ p1.catch(() => {
268
+ });
269
+ }
270
+ } catch {
271
+ }
272
+ if (appId) {
273
+ try {
274
+ const p2 = ps.publish(appChannel(appId), event);
275
+ if (p2 && typeof p2.then === "function") {
276
+ p2.catch(() => {
277
+ });
278
+ }
279
+ } catch {
280
+ }
281
+ }
282
+ }
283
+ function emitCompileStart(traceId, appId, data) {
284
+ emitGlassboxEvent(traceId, appId, "compile.start", data);
285
+ }
286
+ function emitCompileDone(traceId, appId, data) {
287
+ emitGlassboxEvent(traceId, appId, "compile.done", data);
288
+ }
289
+ function emitExecuteAttempt(traceId, appId, data) {
290
+ emitGlassboxEvent(traceId, appId, "execute.attempt", data);
291
+ }
292
+ function emitExecuteSuccess(traceId, appId, data) {
293
+ emitGlassboxEvent(traceId, appId, "execute.success", data);
294
+ }
295
+ function emitAdvisoryFired(traceId, appId, data) {
296
+ emitGlassboxEvent(traceId, appId, "advisory.fired", data);
297
+ }
298
+ function emitFallbackWalked(traceId, appId, data) {
299
+ emitGlassboxEvent(traceId, appId, "fallback.walked", data);
300
+ }
301
+
302
+ export {
303
+ GLASSBOX_STREAM_TTL_MS,
304
+ traceChannel,
305
+ appChannel,
306
+ getPubSub,
307
+ emitCompileStart,
308
+ emitCompileDone,
309
+ emitExecuteAttempt,
310
+ emitExecuteSuccess,
311
+ emitAdvisoryFired,
312
+ emitFallbackWalked
313
+ };
@@ -0,0 +1,219 @@
1
+ // src/version.ts
2
+ var LIBRARY_VERSION = "2.0.0-alpha.81";
3
+
4
+ // src/key-health.ts
5
+ var JSON_HEADERS = { "Content-Type": "application/json" };
6
+ var KEY_FINGERPRINT_DOMAIN = "kgauto-key-fingerprint-v1:";
7
+ var KEY_FINGERPRINT_LENGTH = 12;
8
+ async function keyFingerprint(key) {
9
+ const trimmed = key?.trim();
10
+ if (!trimmed) return void 0;
11
+ const subtle = globalThis.crypto?.subtle;
12
+ if (!subtle) return void 0;
13
+ const bytes = new TextEncoder().encode(KEY_FINGERPRINT_DOMAIN + trimmed);
14
+ const digest = await subtle.digest("SHA-256", bytes);
15
+ return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, KEY_FINGERPRINT_LENGTH);
16
+ }
17
+ function jsonResponse(status, body) {
18
+ return new Response(JSON.stringify(body), { status, headers: JSON_HEADERS });
19
+ }
20
+ function bearerOf(req) {
21
+ const header = req.headers.get("Authorization") ?? "";
22
+ const match = /^Bearer\s+(.+)$/i.exec(header);
23
+ return match?.[1]?.trim() ?? "";
24
+ }
25
+ function requireString(name, value) {
26
+ if (typeof value !== "string" || value.length === 0) {
27
+ throw new Error(`createKeyHealthRoute: ${name} is required`);
28
+ }
29
+ return value;
30
+ }
31
+ function envKey(env, name) {
32
+ const v = env[name];
33
+ if (typeof v !== "string") return void 0;
34
+ const trimmed = v.trim();
35
+ return trimmed.length > 0 ? trimmed : void 0;
36
+ }
37
+ var PROBE_SPECS = [
38
+ {
39
+ provider: "anthropic",
40
+ canonicalEnvName: "ANTHROPIC_API_KEY",
41
+ buildRequest: (key) => ({
42
+ url: "https://api.anthropic.com/v1/models?limit=1",
43
+ headers: { "x-api-key": key, "anthropic-version": "2023-06-01" }
44
+ })
45
+ },
46
+ {
47
+ provider: "deepseek",
48
+ canonicalEnvName: "DEEPSEEK_API_KEY",
49
+ buildRequest: (key) => ({
50
+ url: "https://api.deepseek.com/user/balance",
51
+ headers: { Authorization: `Bearer ${key}` }
52
+ }),
53
+ parseBalanceUsd: (body) => {
54
+ const infos = body?.balance_infos;
55
+ if (!Array.isArray(infos) || infos.length === 0) return void 0;
56
+ const first = infos[0];
57
+ if (first?.currency !== "USD") return void 0;
58
+ const n = Number(first.total_balance);
59
+ return Number.isFinite(n) ? n : void 0;
60
+ }
61
+ },
62
+ {
63
+ provider: "moonshot",
64
+ canonicalEnvName: "MOONSHOT_API_KEY",
65
+ buildRequest: (key) => ({
66
+ url: "https://api.moonshot.ai/v1/models",
67
+ headers: { Authorization: `Bearer ${key}` }
68
+ })
69
+ },
70
+ {
71
+ provider: "google",
72
+ canonicalEnvName: "GEMINI_API_KEY",
73
+ buildRequest: (key) => ({
74
+ url: `https://generativelanguage.googleapis.com/v1beta/models?pageSize=1&key=${encodeURIComponent(key)}`,
75
+ headers: {}
76
+ })
77
+ },
78
+ {
79
+ provider: "openai",
80
+ canonicalEnvName: "OPENAI_API_KEY",
81
+ buildRequest: (key) => ({
82
+ url: "https://api.openai.com/v1/models",
83
+ headers: { Authorization: `Bearer ${key}` }
84
+ })
85
+ }
86
+ ];
87
+ function createKeyHealthRoute(config) {
88
+ const appId = requireString("appId", config.appId);
89
+ const ingestSecret = requireString("ingestSecret", config.ingestSecret);
90
+ const fetchFn = config.fetchImpl ?? fetch;
91
+ const timeoutMs = config.timeoutMs ?? 3e3;
92
+ async function probeProvider(spec, env) {
93
+ let key;
94
+ let envName = spec.canonicalEnvName;
95
+ if (spec.provider === "google") {
96
+ const gemini = envKey(env, "GEMINI_API_KEY");
97
+ const google = envKey(env, "GOOGLE_API_KEY");
98
+ const aiSdk = envKey(env, "GOOGLE_GENERATIVE_AI_API_KEY");
99
+ key = gemini ?? google ?? aiSdk;
100
+ envName = gemini ? "GEMINI_API_KEY" : google ? "GOOGLE_API_KEY" : aiSdk ? "GOOGLE_GENERATIVE_AI_API_KEY" : "GEMINI_API_KEY";
101
+ } else if (spec.provider === "moonshot") {
102
+ const moonshot = envKey(env, "MOONSHOT_API_KEY");
103
+ const kimi = envKey(env, "KIMI_API_KEY");
104
+ key = moonshot ?? kimi;
105
+ envName = moonshot ? "MOONSHOT_API_KEY" : kimi ? "KIMI_API_KEY" : "MOONSHOT_API_KEY";
106
+ } else {
107
+ key = envKey(env, spec.canonicalEnvName);
108
+ }
109
+ if (!key) {
110
+ return {
111
+ provider: spec.provider,
112
+ env: envName,
113
+ present: false,
114
+ valid: null,
115
+ detail: "key_absent"
116
+ };
117
+ }
118
+ const fingerprint = await keyFingerprint(key);
119
+ const base = {
120
+ provider: spec.provider,
121
+ env: envName,
122
+ present: true,
123
+ valid: null,
124
+ ...fingerprint ? { key_fingerprint: fingerprint } : {}
125
+ };
126
+ const { url, headers } = spec.buildRequest(key);
127
+ const started = Date.now();
128
+ let res;
129
+ try {
130
+ res = await fetchFn(url, {
131
+ method: "GET",
132
+ headers,
133
+ signal: AbortSignal.timeout(timeoutMs)
134
+ });
135
+ } catch (err) {
136
+ const isTimeout = err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError");
137
+ return {
138
+ ...base,
139
+ latency_ms: Date.now() - started,
140
+ // NEVER echo err.message — provider errors could theoretically carry
141
+ // request context; a fixed vocabulary keeps key material impossible.
142
+ detail: isTimeout ? "timeout" : "network_error"
143
+ };
144
+ }
145
+ const latencyMs = Date.now() - started;
146
+ if (res.ok) {
147
+ const result = {
148
+ ...base,
149
+ valid: true,
150
+ status: res.status,
151
+ latency_ms: latencyMs
152
+ };
153
+ if (spec.parseBalanceUsd) {
154
+ try {
155
+ const body = await res.json();
156
+ const balance = spec.parseBalanceUsd(body);
157
+ if (balance !== void 0) result.balance_usd = balance;
158
+ } catch {
159
+ }
160
+ }
161
+ return result;
162
+ }
163
+ if (res.status === 401 || res.status === 403) {
164
+ return { ...base, valid: false, status: res.status, latency_ms: latencyMs };
165
+ }
166
+ return {
167
+ ...base,
168
+ valid: null,
169
+ status: res.status,
170
+ latency_ms: latencyMs,
171
+ detail: `http_${res.status}`
172
+ };
173
+ }
174
+ async function handle(req) {
175
+ try {
176
+ if (req.method !== "GET") {
177
+ return jsonResponse(405, { error: "method_not_allowed" });
178
+ }
179
+ if (bearerOf(req) !== ingestSecret) {
180
+ return jsonResponse(401, { error: "unauthorized" });
181
+ }
182
+ const env = config.env ?? process.env;
183
+ const settled = await Promise.allSettled(
184
+ PROBE_SPECS.map((spec) => probeProvider(spec, env))
185
+ );
186
+ const keys = settled.map((s, i) => {
187
+ if (s.status === "fulfilled") return s.value;
188
+ const spec = PROBE_SPECS[i];
189
+ return {
190
+ provider: spec.provider,
191
+ env: spec.canonicalEnvName,
192
+ present: true,
193
+ valid: null,
194
+ detail: "probe_failed"
195
+ };
196
+ });
197
+ keys.sort((a, b) => a.provider.localeCompare(b.provider));
198
+ const body = {
199
+ app_id: appId,
200
+ checked_at: (/* @__PURE__ */ new Date()).toISOString(),
201
+ library_version: LIBRARY_VERSION,
202
+ keys
203
+ };
204
+ return jsonResponse(200, body);
205
+ } catch (err) {
206
+ void err;
207
+ return jsonResponse(500, { error: "key_health_internal_error" });
208
+ }
209
+ }
210
+ return { handle };
211
+ }
212
+
213
+ export {
214
+ LIBRARY_VERSION,
215
+ KEY_FINGERPRINT_DOMAIN,
216
+ KEY_FINGERPRINT_LENGTH,
217
+ keyFingerprint,
218
+ createKeyHealthRoute
219
+ };
@@ -0,0 +1,56 @@
1
+ // src/glassbox-routes/format.ts
2
+ function formatAgo(iso, now = Date.now()) {
3
+ const t = Date.parse(iso);
4
+ if (Number.isNaN(t)) return iso;
5
+ const sec = Math.max(0, Math.floor((now - t) / 1e3));
6
+ if (sec < 60) return `${sec}s ago`;
7
+ if (sec < 3600) return `${Math.floor(sec / 60)}m ago`;
8
+ if (sec < 86400) return `${Math.floor(sec / 3600)}h ago`;
9
+ return `${Math.floor(sec / 86400)}d ago`;
10
+ }
11
+ function shortTraceId(traceId) {
12
+ return traceId.slice(-6);
13
+ }
14
+ function formatCost(usd) {
15
+ if (usd === void 0 || usd === null || Number.isNaN(usd)) return "\u2014";
16
+ if (usd === 0) return "$0.0000";
17
+ if (usd < 0.01) return `$${usd.toFixed(4)}`;
18
+ return `$${usd.toFixed(3)}`;
19
+ }
20
+ function formatMs(ms) {
21
+ if (ms === void 0 || ms === null) return "\u2014";
22
+ if (ms < 1e3) return `${ms}ms`;
23
+ return `${(ms / 1e3).toFixed(1)}s`;
24
+ }
25
+ function formatOrDash(v) {
26
+ if (v === void 0 || v === null) return "\u2014";
27
+ if (typeof v === "number") return v.toLocaleString();
28
+ return v;
29
+ }
30
+ function inputRatioLabel(status) {
31
+ switch (status) {
32
+ case "green":
33
+ return "healthy";
34
+ case "yellow":
35
+ return "borderline";
36
+ case "red":
37
+ return "input-heavy";
38
+ }
39
+ }
40
+ function formatMutation(mutation) {
41
+ const m = /^(.*)-(\d+)-to-(\d+)$/.exec(mutation);
42
+ if (m) {
43
+ return `${m[1]} (${m[2]} \u2192 ${m[3]})`;
44
+ }
45
+ return mutation;
46
+ }
47
+
48
+ export {
49
+ formatAgo,
50
+ shortTraceId,
51
+ formatCost,
52
+ formatMs,
53
+ formatOrDash,
54
+ inputRatioLabel,
55
+ formatMutation
56
+ };
@@ -0,0 +1,29 @@
1
+ import {
2
+ appChannel,
3
+ getPubSub,
4
+ traceChannel
5
+ } from "./chunk-NBO4R5PC.mjs";
6
+
7
+ // src/glassbox/subscribe.ts
8
+ function emptyStream() {
9
+ return new ReadableStream({
10
+ start(controller) {
11
+ controller.close();
12
+ }
13
+ });
14
+ }
15
+ function subscribe(traceId) {
16
+ if (!traceId) return emptyStream();
17
+ return getPubSub().subscribe(traceChannel(traceId));
18
+ }
19
+ function subscribeApp({
20
+ appId
21
+ }) {
22
+ if (!appId) return emptyStream();
23
+ return getPubSub().subscribe(appChannel(appId));
24
+ }
25
+
26
+ export {
27
+ subscribe,
28
+ subscribeApp
29
+ };