mu-agent 0.1.0 → 0.1.3

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.
@@ -0,0 +1,1248 @@
1
+ import { createRequire as __muCreateRequire } from "node:module"; const require = __muCreateRequire(import.meta.url);
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __esm = (fn, res, err) => function __init() {
4
+ if (err) throw err[0];
5
+ try {
6
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
7
+ } catch (e) {
8
+ throw err = [e], e;
9
+ }
10
+ };
11
+
12
+ // mu-auth-unused:cloud-code
13
+ var cloud_code_exports = {};
14
+ var init_cloud_code = __esm({
15
+ "mu-auth-unused:cloud-code"() {
16
+ "use strict";
17
+ }
18
+ });
19
+
20
+ // packages/kyrn-judge/src/auth/main.ts
21
+ import { join as join3 } from "node:path";
22
+ import { createInterface } from "node:readline";
23
+ import { defaultModelPerProvider, ModelRuntime } from "../../dist/bundle/index.js";
24
+
25
+ // packages/kyrn-judge/src/config.ts
26
+ import { readFileSync } from "node:fs";
27
+ import { join as join2 } from "node:path";
28
+
29
+ // packages/kyrn-judge/src/naming.ts
30
+ import { existsSync } from "node:fs";
31
+ import { homedir } from "node:os";
32
+ import { join } from "node:path";
33
+ function muEnv(name, env = process.env) {
34
+ return env[`MU_${name}`] || env[`KYRN_${name}`] || void 0;
35
+ }
36
+ var CONFIG_FILE = "mu.json";
37
+ var LEGACY_CONFIG_FILE = "kyrn.json";
38
+ function muHome(home = homedir()) {
39
+ const current = join(home, ".mu");
40
+ const legacy = join(home, ".kyrn");
41
+ return existsSync(current) || !existsSync(legacy) ? current : legacy;
42
+ }
43
+
44
+ // packages/kyrn-judge/src/config.ts
45
+ var DEFAULT_CONFIG = {
46
+ tiers: ["jev"],
47
+ judges: {},
48
+ modes: { default: "shadow" },
49
+ routes: {},
50
+ features: {},
51
+ recordState: false
52
+ };
53
+ var MODES = ["off", "shadow", "active"];
54
+ function isRecord(value) {
55
+ return typeof value === "object" && value !== null && !Array.isArray(value);
56
+ }
57
+ function readModes(value) {
58
+ const modes = {};
59
+ if (!isRecord(value)) return modes;
60
+ for (const [specId, mode] of Object.entries(value)) {
61
+ if (typeof mode === "string" && MODES.includes(mode)) modes[specId] = mode;
62
+ }
63
+ return modes;
64
+ }
65
+ function readTiers(value) {
66
+ const raw = Array.isArray(value) ? value : typeof value === "string" ? value.split(",") : [];
67
+ return raw.filter((tier) => typeof tier === "string").map((tier) => tier.trim()).filter(Boolean);
68
+ }
69
+ function readRoutes(value) {
70
+ const routes = {};
71
+ if (!isRecord(value)) return routes;
72
+ for (const [specId, tiers] of Object.entries(value)) {
73
+ const parsed = readTiers(tiers);
74
+ if (parsed.length > 0) routes[specId] = parsed;
75
+ }
76
+ return routes;
77
+ }
78
+ function readJudges(value) {
79
+ const judges = {};
80
+ if (!isRecord(value)) return judges;
81
+ for (const [name, config] of Object.entries(value)) {
82
+ if (!isRecord(config) || typeof config.type !== "string") continue;
83
+ if (!["jev", "typesafe", "gateway", "local", "http", "llm", "mock"].includes(config.type)) continue;
84
+ judges[name] = config;
85
+ }
86
+ return judges;
87
+ }
88
+ function parseConfig(value) {
89
+ if (!isRecord(value)) return DEFAULT_CONFIG;
90
+ const tiers = Array.isArray(value.tiers) ? value.tiers.filter((tier) => typeof tier === "string") : [];
91
+ return {
92
+ tiers: tiers.length > 0 ? tiers : DEFAULT_CONFIG.tiers,
93
+ judges: readJudges(value.judges),
94
+ modes: { ...DEFAULT_CONFIG.modes, ...readModes(value.modes) },
95
+ routes: readRoutes(value.routes),
96
+ features: isRecord(value.features) ? value.features : {},
97
+ mcp: isRecord(value.mcp) ? value.mcp : void 0,
98
+ writer: typeof value.writer === "string" ? value.writer : void 0,
99
+ recordState: value.recordState === true
100
+ };
101
+ }
102
+ function loadConfig(source = {}) {
103
+ const env = source.env ?? process.env;
104
+ let config = DEFAULT_CONFIG;
105
+ let problem;
106
+ for (const file of source.dir ? [CONFIG_FILE, LEGACY_CONFIG_FILE] : []) {
107
+ try {
108
+ config = parseConfig(JSON.parse(readFileSync(join2(source.dir, file), "utf8")));
109
+ break;
110
+ } catch (error) {
111
+ if (error.code === "ENOENT") continue;
112
+ problem = `${file} could not be read: ${error instanceof Error ? error.message : String(error)}`;
113
+ break;
114
+ }
115
+ }
116
+ const judge = muEnv("JUDGE", env)?.trim();
117
+ if (judge === "off") return { config, disabled: true, problem };
118
+ if (judge) {
119
+ const tiers = judge.split(",").map((tier) => tier.trim() === "gateway" ? "jev" : tier.trim());
120
+ config = { ...config, tiers: tiers.filter(Boolean) };
121
+ }
122
+ const mode = muEnv("JUDGE_MODE", env);
123
+ if (mode && MODES.includes(mode)) config = { ...config, modes: { ...config.modes, default: mode } };
124
+ const writer = muEnv("WRITER", env);
125
+ if (writer) config = { ...config, writer };
126
+ return { config, disabled: false, problem };
127
+ }
128
+ function featureOptions(config, name, defaults) {
129
+ const value = config.features[name];
130
+ if (value === false) return { ...defaults, enabled: false };
131
+ if (value === true) return { ...defaults, enabled: true };
132
+ if (isRecord(value)) return { ...defaults, ...value };
133
+ return defaults;
134
+ }
135
+
136
+ // node_modules/typebox/build/system/hashing/hash.mjs
137
+ var ByteMarker;
138
+ (function(ByteMarker2) {
139
+ ByteMarker2[ByteMarker2["Array"] = 0] = "Array";
140
+ ByteMarker2[ByteMarker2["BigInt"] = 1] = "BigInt";
141
+ ByteMarker2[ByteMarker2["Boolean"] = 2] = "Boolean";
142
+ ByteMarker2[ByteMarker2["Date"] = 3] = "Date";
143
+ ByteMarker2[ByteMarker2["Constructor"] = 4] = "Constructor";
144
+ ByteMarker2[ByteMarker2["Function"] = 5] = "Function";
145
+ ByteMarker2[ByteMarker2["Null"] = 6] = "Null";
146
+ ByteMarker2[ByteMarker2["Number"] = 7] = "Number";
147
+ ByteMarker2[ByteMarker2["Object"] = 8] = "Object";
148
+ ByteMarker2[ByteMarker2["RegExp"] = 9] = "RegExp";
149
+ ByteMarker2[ByteMarker2["String"] = 10] = "String";
150
+ ByteMarker2[ByteMarker2["Symbol"] = 11] = "Symbol";
151
+ ByteMarker2[ByteMarker2["TypeArray"] = 12] = "TypeArray";
152
+ ByteMarker2[ByteMarker2["Undefined"] = 13] = "Undefined";
153
+ })(ByteMarker || (ByteMarker = {}));
154
+ var Accumulator = BigInt("14695981039346656037");
155
+ var [Prime, Size] = [BigInt("1099511628211"), BigInt(
156
+ "18446744073709551616"
157
+ /* 2 ^ 64 */
158
+ )];
159
+ var Bytes = Array.from({ length: 256 }).map((_, i) => BigInt(i));
160
+ var F64 = new Float64Array(1);
161
+ var F64In = new DataView(F64.buffer);
162
+ var F64Out = new Uint8Array(F64.buffer);
163
+ var encoder = new TextEncoder();
164
+
165
+ // node_modules/typebox/build/type/types/integer.mjs
166
+ var IntegerPattern = "-?(?:0|[1-9][0-9]*)";
167
+
168
+ // node_modules/typebox/build/type/types/number.mjs
169
+ var NumberPattern = "-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?";
170
+
171
+ // node_modules/typebox/build/type/types/string.mjs
172
+ var StringPattern = ".*";
173
+
174
+ // node_modules/typebox/build/type/types/record.mjs
175
+ var IntegerKey = `^${IntegerPattern}$`;
176
+ var NumberKey = `^${NumberPattern}$`;
177
+ var StringKey = `^${StringPattern}$`;
178
+
179
+ // node_modules/typebox/build/type/script/token/internal/char.mjs
180
+ function Range(start, end) {
181
+ return Array.from({ length: end - start + 1 }, (_, i) => String.fromCharCode(start + i));
182
+ }
183
+ var Alpha = [
184
+ ...Range(97, 122),
185
+ // Lowercase
186
+ ...Range(65, 90)
187
+ // Uppercase
188
+ ];
189
+ var Zero = "0";
190
+ var NonZero = Range(49, 57);
191
+ var Digit = [Zero, ...NonZero];
192
+ var UnderScore = "_";
193
+ var DollarSign = "$";
194
+
195
+ // node_modules/typebox/build/type/script/token/unsigned_integer.mjs
196
+ var AllowedDigits = [...Digit, UnderScore];
197
+
198
+ // node_modules/typebox/build/type/script/token/ident.mjs
199
+ var Initial = [...Alpha, UnderScore, DollarSign];
200
+ var Remaining = [...Initial, ...Digit];
201
+
202
+ // node_modules/typebox/build/type/script/token/unsigned_number.mjs
203
+ var AllowedDigits2 = [...Digit, UnderScore];
204
+
205
+ // node_modules/typebox/build/type/engine/helpers/keys.mjs
206
+ var integerKeyPattern = new RegExp("^(?:0|[1-9][0-9]*)$");
207
+
208
+ // node_modules/typebox/build/type/engine/indexed/from_object.mjs
209
+ var NumericKeyPattern = new RegExp(IntegerKey);
210
+
211
+ // packages/ai/src/utils/event-stream.ts
212
+ var FifoQueue = class {
213
+ constructor() {
214
+ this.incoming = [];
215
+ this.outgoing = [];
216
+ }
217
+ get length() {
218
+ return this.incoming.length + this.outgoing.length;
219
+ }
220
+ enqueue(value) {
221
+ this.incoming.push(value);
222
+ }
223
+ dequeue() {
224
+ if (this.outgoing.length === 0) {
225
+ while (this.incoming.length > 0) {
226
+ this.outgoing.push(this.incoming.pop());
227
+ }
228
+ }
229
+ return this.outgoing.pop();
230
+ }
231
+ };
232
+ var EventStream = class {
233
+ constructor(isComplete, extractResult) {
234
+ this.queue = new FifoQueue();
235
+ this.waiting = new FifoQueue();
236
+ this.done = false;
237
+ this.isComplete = isComplete;
238
+ this.extractResult = extractResult;
239
+ this.finalResultPromise = new Promise((resolve) => {
240
+ this.resolveFinalResult = resolve;
241
+ });
242
+ }
243
+ push(event) {
244
+ if (this.done) return;
245
+ if (this.isComplete(event)) {
246
+ this.done = true;
247
+ this.resolveFinalResult(this.extractResult(event));
248
+ }
249
+ const waiter = this.waiting.dequeue();
250
+ if (waiter) {
251
+ waiter({ value: event, done: false });
252
+ } else {
253
+ this.queue.enqueue(event);
254
+ }
255
+ }
256
+ end(result) {
257
+ this.done = true;
258
+ if (result !== void 0) {
259
+ this.resolveFinalResult(result);
260
+ }
261
+ while (this.waiting.length > 0) {
262
+ const waiter = this.waiting.dequeue();
263
+ waiter({ value: void 0, done: true });
264
+ }
265
+ }
266
+ async *[Symbol.asyncIterator]() {
267
+ while (true) {
268
+ if (this.queue.length > 0) {
269
+ yield this.queue.dequeue();
270
+ } else if (this.done) {
271
+ return;
272
+ } else {
273
+ const result = await new Promise((resolve) => this.waiting.enqueue(resolve));
274
+ if (result.done) return;
275
+ yield result.value;
276
+ }
277
+ }
278
+ }
279
+ result() {
280
+ return this.finalResultPromise;
281
+ }
282
+ };
283
+ var AssistantMessageEventStream = class extends EventStream {
284
+ constructor() {
285
+ super(
286
+ (event) => event.type === "done" || event.type === "error",
287
+ (event) => {
288
+ if (event.type === "done") {
289
+ return event.message;
290
+ } else if (event.type === "error") {
291
+ return event.error;
292
+ }
293
+ throw new Error("Unexpected event type for final result");
294
+ }
295
+ );
296
+ }
297
+ };
298
+
299
+ // packages/ai/src/api/lazy.ts
300
+ function createSetupErrorMessage(model, error) {
301
+ return {
302
+ role: "assistant",
303
+ content: [],
304
+ api: model.api,
305
+ provider: model.provider,
306
+ model: model.id,
307
+ usage: {
308
+ input: 0,
309
+ output: 0,
310
+ cacheRead: 0,
311
+ cacheWrite: 0,
312
+ totalTokens: 0,
313
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
314
+ },
315
+ stopReason: "error",
316
+ errorMessage: error instanceof Error ? error.message : String(error),
317
+ timestamp: Date.now()
318
+ };
319
+ }
320
+ function hasResult(source) {
321
+ return typeof source.result === "function";
322
+ }
323
+ async function forwardStream(target, source) {
324
+ for await (const event of source) {
325
+ target.push(event);
326
+ }
327
+ target.end(hasResult(source) ? await source.result() : void 0);
328
+ }
329
+ function lazyStream(model, setup) {
330
+ const outer = new AssistantMessageEventStream();
331
+ setup().then((inner) => forwardStream(outer, inner)).catch((error) => {
332
+ const message = createSetupErrorMessage(model, error);
333
+ outer.push({ type: "error", reason: "error", error: message });
334
+ outer.end(message);
335
+ });
336
+ return outer;
337
+ }
338
+ function lazyApi(load, capabilities) {
339
+ const api = {
340
+ stream: (model, context, options) => lazyStream(model, async () => (await load()).stream(model, context, options)),
341
+ streamSimple: (model, context, options) => lazyStream(model, async () => (await load()).streamSimple(model, context, options))
342
+ };
343
+ if (capabilities?.fetchDeferred) {
344
+ api.fetchDeferred = (model, handle, options) => lazyStream(model, async () => {
345
+ const implementation = await load();
346
+ if (!implementation.fetchDeferred) throw new Error("API does not support deferred responses");
347
+ return implementation.fetchDeferred(model, handle, options);
348
+ });
349
+ }
350
+ if (capabilities?.cancelDeferred) {
351
+ api.cancelDeferred = async (model, handle, options) => {
352
+ const implementation = await load();
353
+ if (!implementation.cancelDeferred) throw new Error("API cannot cancel deferred responses");
354
+ await implementation.cancelDeferred(model, handle, options);
355
+ };
356
+ }
357
+ return api;
358
+ }
359
+
360
+ // packages/ai/src/auth/oauth/oauth-page.ts
361
+ var MU_MARK_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" fill="none" aria-hidden="true"><defs><linearGradient id="mu-tile" x1="0" y1="0" x2="100" y2="100" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#F3C6FA"/><stop offset="0.5" stop-color="#B79CF7"/><stop offset="1" stop-color="#8680EB"/></linearGradient></defs><rect width="100" height="100" rx="27" fill="url(#mu-tile)"/><path d="M41 32 L35 74.4 M38.9 47 C37.77 55 41 59.4 47.6 59.4 C54.8 59.4 61.05 54.5 61.9 48.5 M64.25 32 L61.35 52.5 C60.6 58 62.3 61.2 66.4 60.4" stroke="#FFFFFF" stroke-width="9.8" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
362
+ var MU_FAVICON = `data:image/svg+xml,${encodeURIComponent(MU_MARK_SVG)}`;
363
+ function escapeHtml(value) {
364
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
365
+ }
366
+ function renderPage(options) {
367
+ const title = escapeHtml(`${options.heading} \xB7 mu`);
368
+ const heading = escapeHtml(options.heading);
369
+ const message = escapeHtml(options.message);
370
+ const details = options.details ? escapeHtml(options.details) : void 0;
371
+ return `<!doctype html>
372
+ <html lang="en">
373
+ <head>
374
+ <meta charset="utf-8" />
375
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
376
+ <meta name="color-scheme" content="light dark" />
377
+ <title>${title}</title>
378
+ <link rel="icon" type="image/svg+xml" href="${MU_FAVICON}" />
379
+ <style>
380
+ :root {
381
+ color-scheme: light dark;
382
+ --text: #111111;
383
+ --text-dim: #6b6b70;
384
+ --page-bg: #ffffff;
385
+ --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
386
+ --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
387
+ }
388
+ @media (prefers-color-scheme: dark) {
389
+ :root {
390
+ --text: #f4f4f5;
391
+ --text-dim: #9a9aa1;
392
+ --page-bg: #000000;
393
+ }
394
+ }
395
+ * { box-sizing: border-box; }
396
+ body {
397
+ margin: 0;
398
+ min-height: 100vh;
399
+ display: flex;
400
+ align-items: center;
401
+ justify-content: center;
402
+ padding: 24px;
403
+ background: var(--page-bg);
404
+ color: var(--text);
405
+ font-family: var(--font-sans);
406
+ text-align: center;
407
+ }
408
+ main {
409
+ width: 100%;
410
+ max-width: 520px;
411
+ display: flex;
412
+ flex-direction: column;
413
+ align-items: center;
414
+ justify-content: center;
415
+ }
416
+ .mark {
417
+ width: 72px;
418
+ height: 72px;
419
+ display: block;
420
+ margin-bottom: 28px;
421
+ }
422
+ .mark svg { display: block; width: 100%; height: 100%; }
423
+ h1 {
424
+ margin: 0 0 10px;
425
+ font-size: 26px;
426
+ line-height: 1.2;
427
+ font-weight: 600;
428
+ letter-spacing: -0.01em;
429
+ color: var(--text);
430
+ }
431
+ p {
432
+ margin: 0;
433
+ line-height: 1.7;
434
+ color: var(--text-dim);
435
+ font-size: 15px;
436
+ }
437
+ .details {
438
+ margin-top: 16px;
439
+ font-family: var(--font-mono);
440
+ font-size: 13px;
441
+ color: var(--text-dim);
442
+ white-space: pre-wrap;
443
+ word-break: break-word;
444
+ }
445
+ </style>
446
+ </head>
447
+ <body>
448
+ <main>
449
+ <div class="mark">${MU_MARK_SVG}</div>
450
+ <h1>${heading}</h1>
451
+ <p>${message}</p>
452
+ ${details ? `<div class="details">${details}</div>` : ""}
453
+ </main>
454
+ </body>
455
+ </html>`;
456
+ }
457
+ function oauthSuccessHtml(message) {
458
+ return renderPage({ heading: "Signed in", message });
459
+ }
460
+ function oauthErrorHtml(message, details) {
461
+ return renderPage({ heading: "Sign-in did not complete", message, details });
462
+ }
463
+
464
+ // packages/ai/src/utils/diagnostics.ts
465
+ function formatThrownValue(value) {
466
+ if (value instanceof Error) return value.message || value.name;
467
+ if (typeof value === "string") return value;
468
+ return String(value);
469
+ }
470
+
471
+ // packages/ai/src/auth/resolve.ts
472
+ var ModelsError = class extends Error {
473
+ constructor(code, message, options) {
474
+ super(withCauseDetail(message, options?.cause), options);
475
+ this.name = "ModelsError";
476
+ this.code = code;
477
+ }
478
+ };
479
+ function withCauseDetail(message, cause) {
480
+ if (cause === void 0 || cause === null) return message;
481
+ const detail = formatThrownValue(cause).trim();
482
+ if (!detail || message.includes(detail)) return message;
483
+ return `${message}: ${detail}`;
484
+ }
485
+ var DEFAULT_OAUTH_MINIMUM_VALIDITY_MS = 5 * 60 * 1e3;
486
+
487
+ // packages/ai/src/models.ts
488
+ function createProvider(input) {
489
+ const baselineModels = input.models;
490
+ let dynamicModels = [];
491
+ const fetchModels = input.fetchModels;
492
+ const currentModels = () => {
493
+ const merged = [...baselineModels];
494
+ for (const model of dynamicModels) {
495
+ const index = merged.findIndex((entry) => entry.id === model.id);
496
+ if (index >= 0) merged[index] = model;
497
+ else merged.push(model);
498
+ }
499
+ return merged;
500
+ };
501
+ const single = typeof input.api.stream === "function" ? input.api : void 0;
502
+ const byApi = single ? void 0 : input.api;
503
+ const apiFor = (model) => single ?? byApi?.[model.api];
504
+ const dispatch = (model, run) => {
505
+ const streams2 = apiFor(model);
506
+ if (!streams2) {
507
+ return lazyStream(model, async () => {
508
+ throw new ModelsError("stream", `Provider ${input.id} has no API implementation for "${model.api}"`);
509
+ });
510
+ }
511
+ return run(streams2);
512
+ };
513
+ const provider = {
514
+ id: input.id,
515
+ name: input.name ?? input.id,
516
+ baseUrl: input.baseUrl,
517
+ headers: input.headers,
518
+ auth: input.auth,
519
+ getModels: currentModels,
520
+ refreshModels: fetchModels ? async (context) => {
521
+ if (context.stored) {
522
+ const restored = context.stored.models.filter((model) => model.provider === input.id).map((model) => model);
523
+ if (!await context.publish({
524
+ update: () => {
525
+ dynamicModels = restored;
526
+ }
527
+ })) {
528
+ return;
529
+ }
530
+ }
531
+ if (!context.allowNetwork || context.signal.aborted) return;
532
+ const refreshed = await fetchModels(context);
533
+ if (context.signal.aborted) return;
534
+ await context.publish({
535
+ persist: { models: refreshed, checkedAt: Date.now() },
536
+ update: () => {
537
+ dynamicModels = refreshed;
538
+ }
539
+ });
540
+ } : void 0,
541
+ filterModels: input.filterModels,
542
+ stream: (model, context, options) => dispatch(model, (streams2) => streams2.stream(model, context, options)),
543
+ streamSimple: (model, context, options) => dispatch(model, (streams2) => streams2.streamSimple(model, context, options))
544
+ };
545
+ const streams = single ? [single] : Object.values(byApi ?? {}).filter((entry) => entry !== void 0);
546
+ if (streams.some((entry) => entry.fetchDeferred !== void 0)) {
547
+ provider.fetchDeferred = (model, handle, options) => lazyStream(model, async () => {
548
+ const implementation = apiFor(model);
549
+ if (!implementation?.fetchDeferred) {
550
+ throw new ModelsError(
551
+ "provider",
552
+ `Provider ${input.id} does not support deferred responses for "${model.api}"`
553
+ );
554
+ }
555
+ return implementation.fetchDeferred(model, handle, options);
556
+ });
557
+ }
558
+ if (streams.some((entry) => entry.cancelDeferred !== void 0)) {
559
+ provider.cancelDeferred = async (model, handle, options) => {
560
+ const implementation = apiFor(model);
561
+ if (!implementation?.cancelDeferred) {
562
+ throw new ModelsError(
563
+ "provider",
564
+ `Provider ${input.id} cannot cancel deferred responses for "${model.api}"`
565
+ );
566
+ }
567
+ await implementation.cancelDeferred(model, handle, options);
568
+ };
569
+ }
570
+ return provider;
571
+ }
572
+
573
+ // packages/ai/src/providers/data/google.json
574
+ var google_default = { "google-generative-ai": { "deep-research-max-preview-04-2026": { id: "deep-research-max-preview-04-2026", name: "Deep Research Max Preview (Apr-21-2026)", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 65536 }, "deep-research-preview-04-2026": { id: "deep-research-preview-04-2026", name: "Deep Research Preview (Apr-21-2026)", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 65536 }, "gemini-2.5-computer-use-preview-10-2025": { id: "gemini-2.5-computer-use-preview-10-2025", name: "Gemini 2.5 Computer Use Preview 10-2025", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 65536 }, "gemini-2.5-flash": { id: "gemini-2.5-flash", name: "Gemini 2.5 Flash", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 2.5, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemini-2.5-flash-lite": { id: "gemini-2.5-flash-lite", name: "Gemini 2.5 Flash-Lite", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.4, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemini-2.5-pro": { id: "gemini-2.5-pro", name: "Gemini 2.5 Pro", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemini-3-flash-preview": { id: "gemini-3-flash-preview", name: "Gemini 3 Flash Preview", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 0.5, output: 3, cacheRead: 0.05, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemini-3.1-flash-lite": { id: "gemini-3.1-flash-lite", name: "Gemini 3.1 Flash Lite", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 0.25, output: 1.5, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemini-3.1-flash-lite-image": { id: "gemini-3.1-flash-lite-image", name: "Nano Banana 2 Lite", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: "minimal", low: null, medium: null, high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 0.25, output: 30, cacheRead: 0, cacheWrite: 0 }, contextWindow: 65536, maxTokens: 65536 }, "gemini-3.1-flash-lite-preview": { id: "gemini-3.1-flash-lite-preview", name: "Gemini 3.1 Flash Lite Preview", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 0.25, output: 1.5, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemini-3.1-flash-live-preview": { id: "gemini-3.1-flash-live-preview", name: "Gemini 3.1 Flash Live Preview", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 0.75, output: 4.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 65536 }, "gemini-3.1-pro-preview": { id: "gemini-3.1-pro-preview", name: "Gemini 3.1 Pro Preview", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemini-3.1-pro-preview-customtools": { id: "gemini-3.1-pro-preview-customtools", name: "Gemini 3.1 Pro Preview Custom Tools", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemini-3.5-flash": { id: "gemini-3.5-flash", name: "Gemini 3.5 Flash", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 1.5, output: 9, cacheRead: 0.15, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemini-3.5-flash-lite": { id: "gemini-3.5-flash-lite", name: "Gemini 3.5 Flash Lite", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 0.3, output: 2.5, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemini-3.6-flash": { id: "gemini-3.6-flash", name: "Gemini 3.6 Flash", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 0.75, output: 3.75, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemini-3.7-flash": { id: "gemini-3.7-flash", name: "Gemini 3.7 Flash", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 0.75, output: 3.75, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemini-3.8-flash": { id: "gemini-3.8-flash", name: "Gemini 3.8 Flash", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 0.75, output: 3.75, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemini-flash-latest": { id: "gemini-flash-latest", name: "Gemini Flash Latest", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 1.5, output: 9, cacheRead: 0.15, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemini-flash-lite-latest": { id: "gemini-flash-lite-latest", name: "Gemini Flash-Lite Latest", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 0.25, output: 1.5, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536 }, "gemma-4-26b-a4b-it": { id: "gemma-4-26b-a4b-it", name: "Gemma 4 26B A4B IT", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: "MINIMAL", low: null, medium: null, high: "HIGH" }, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768 }, "gemma-4-31b-it": { id: "gemma-4-31b-it", name: "Gemma 4 31B IT", api: "google-generative-ai", provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta", reasoning: true, thinkingLevelMap: { off: null, minimal: "MINIMAL", low: null, medium: null, high: "HIGH" }, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768 } } };
575
+
576
+ // packages/ai/src/model-catalog.ts
577
+ function flattenModelCatalog(_provider, groups) {
578
+ return Object.assign({}, ...Object.values(groups));
579
+ }
580
+
581
+ // packages/ai/src/providers/google.models.ts
582
+ var GOOGLE_MODELS = flattenModelCatalog("google", google_default);
583
+
584
+ // packages/kyrn-judge/src/google-login/endpoints.ts
585
+ var CLOUD_CODE_API = "google-cloud-code";
586
+ var GEMINI_CLI_PROVIDER = "google-gemini-cli";
587
+ var ANTIGRAVITY_PROVIDER = "google-antigravity";
588
+ var CLOUD_CODE_ENDPOINT = "https://cloudcode-pa.googleapis.com";
589
+ var ANTIGRAVITY_ENDPOINTS = [
590
+ "https://daily-cloudcode-pa.sandbox.googleapis.com",
591
+ "https://autopush-cloudcode-pa.sandbox.googleapis.com",
592
+ CLOUD_CODE_ENDPOINT
593
+ ];
594
+ var antigravityUserAgent = (env = (name) => process.env[name]) => `antigravity/${env("MU_ANTIGRAVITY_VERSION") || env("PI_AI_ANTIGRAVITY_VERSION") || "1.107.0"} darwin/arm64`;
595
+
596
+ // packages/kyrn-judge/src/google-login/oauth.ts
597
+ import { createServer } from "node:http";
598
+ var decode = (value) => atob(value);
599
+ var GOOGLE = {
600
+ authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
601
+ tokenUrl: "https://oauth2.googleapis.com/token",
602
+ userInfoUrl: "https://www.googleapis.com/oauth2/v1/userinfo?alt=json",
603
+ callbackHost: process.env.PI_OAUTH_CALLBACK_HOST || "127.0.0.1",
604
+ env: (name) => process.env[name]
605
+ };
606
+ var BASE_SCOPES = [
607
+ "https://www.googleapis.com/auth/cloud-platform",
608
+ "https://www.googleapis.com/auth/userinfo.email",
609
+ "https://www.googleapis.com/auth/userinfo.profile"
610
+ ];
611
+ var GEMINI_CLI_LOGIN = {
612
+ ...GOOGLE,
613
+ kind: "gemini-cli",
614
+ title: "Google Gemini CLI",
615
+ clientId: decode("NjgxMjU1ODA5Mzk1LW9vOGZ0Mm9wcmRybnA5ZTNhcWY2YXYzaG1kaWIxMzVqLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29t"),
616
+ clientSecret: decode("R09DU1BYLTR1SGdNUG0tMW83U2stZ2VWNkN1NWNsWEZzeGw="),
617
+ callbackPort: 8085,
618
+ callbackPath: "/oauth2callback",
619
+ scopes: BASE_SCOPES,
620
+ codeAssistEndpoints: [CLOUD_CODE_ENDPOINT]
621
+ };
622
+ var ANTIGRAVITY_LOGIN = {
623
+ ...GOOGLE,
624
+ kind: "antigravity",
625
+ title: "Google Antigravity",
626
+ clientId: decode(
627
+ "MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ=="
628
+ ),
629
+ clientSecret: decode("R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY="),
630
+ callbackPort: 51121,
631
+ callbackPath: "/oauth-callback",
632
+ scopes: [
633
+ ...BASE_SCOPES,
634
+ "https://www.googleapis.com/auth/cclog",
635
+ "https://www.googleapis.com/auth/experimentsandconfigs"
636
+ ],
637
+ codeAssistEndpoints: [CLOUD_CODE_ENDPOINT, ANTIGRAVITY_ENDPOINTS[0]]
638
+ };
639
+ var ANTIGRAVITY_DEFAULT_PROJECT = "rising-fact-p41fc";
640
+ function riskNotice(config) {
641
+ return `Experimental: this signs in through ${config.title}'s own login, not one Google made for mu. Google may treat that as against its terms and limit or suspend the account. Use an account you can afford to lose access to, or a Gemini API key (provider "google") instead.`;
642
+ }
643
+ function base64url(bytes) {
644
+ let binary = "";
645
+ for (const byte of bytes) binary += String.fromCharCode(byte);
646
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
647
+ }
648
+ async function pkce() {
649
+ const bytes = new Uint8Array(32);
650
+ crypto.getRandomValues(bytes);
651
+ const verifier = base64url(bytes);
652
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
653
+ return { verifier, challenge: base64url(new Uint8Array(digest)) };
654
+ }
655
+ function listen(config, state) {
656
+ return new Promise((resolve, reject) => {
657
+ let settle = () => {
658
+ };
659
+ const wait = new Promise((done) => {
660
+ let settled = false;
661
+ settle = (value) => {
662
+ if (settled) return;
663
+ settled = true;
664
+ done(value);
665
+ };
666
+ });
667
+ const server = createServer((request, response) => {
668
+ const url = new URL(request.url ?? "/", `http://localhost:${config.callbackPort}`);
669
+ const send = (status, html) => {
670
+ response.writeHead(status, { "Content-Type": "text/html; charset=utf-8" });
671
+ response.end(html);
672
+ };
673
+ if (url.pathname !== config.callbackPath) {
674
+ return send(404, oauthErrorHtml("This address is mu's sign-in callback; there is no page here."));
675
+ }
676
+ const given = url.searchParams.get("state");
677
+ const error = url.searchParams.get("error");
678
+ if (error) {
679
+ const said = error.replace(/[^\w.-]/g, "").slice(0, 80) || "an error";
680
+ send(400, oauthErrorHtml("Google did not complete the sign-in.", `Google said: ${said}`));
681
+ if (given === state) settle({ declined: said });
682
+ return;
683
+ }
684
+ const code = url.searchParams.get("code");
685
+ if (!code || !given) return send(400, oauthErrorHtml("The code or the state is missing."));
686
+ if (given !== state) {
687
+ return send(400, oauthErrorHtml("This address belongs to another sign-in. Use the tab mu opened last."));
688
+ }
689
+ send(200, oauthSuccessHtml("You can close this window and go back to mu."));
690
+ settle({ code, state: given });
691
+ });
692
+ server.once(
693
+ "error",
694
+ (error) => reject(
695
+ error.code === "EADDRINUSE" ? new Error(
696
+ `Port ${config.callbackPort} is taken (is ${config.title} itself signing in?). Close it and try again.`
697
+ ) : error
698
+ )
699
+ );
700
+ server.listen(
701
+ config.callbackPort,
702
+ config.callbackHost,
703
+ () => resolve({ server, wait, cancel: () => settle(void 0) })
704
+ );
705
+ });
706
+ }
707
+ function parsePasted(input) {
708
+ const value = input.trim();
709
+ if (!value) return {};
710
+ try {
711
+ const url = new URL(value);
712
+ return { code: url.searchParams.get("code") ?? void 0, state: url.searchParams.get("state") ?? void 0 };
713
+ } catch {
714
+ return { code: value };
715
+ }
716
+ }
717
+ async function tokenRequest(config, body, signal) {
718
+ const response = await fetch(config.tokenUrl, {
719
+ method: "POST",
720
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
721
+ body: new URLSearchParams({ client_id: config.clientId, client_secret: config.clientSecret, ...body }),
722
+ signal
723
+ });
724
+ const text = await response.text();
725
+ if (!response.ok) throw new Error(`Google token request failed (${response.status}): ${text.slice(0, 300)}`);
726
+ const data = JSON.parse(text);
727
+ if (!data.access_token || typeof data.expires_in !== "number") {
728
+ throw new Error("Google's token response has no access token");
729
+ }
730
+ return data;
731
+ }
732
+ var expiry = (seconds) => Date.now() + seconds * 1e3 - 5 * 60 * 1e3;
733
+ async function email(config, token, signal) {
734
+ try {
735
+ const response = await fetch(config.userInfoUrl, { headers: { Authorization: `Bearer ${token}` }, signal });
736
+ if (!response.ok) return void 0;
737
+ const data = await response.json();
738
+ return typeof data.email === "string" ? data.email : void 0;
739
+ } catch {
740
+ return void 0;
741
+ }
742
+ }
743
+ var CLIENT_METADATA = { ideType: "IDE_UNSPECIFIED", platform: "PLATFORM_UNSPECIFIED", pluginType: "GEMINI" };
744
+ var projectOf = (value) => typeof value === "string" ? value || void 0 : value?.id || void 0;
745
+ var NEEDS_PROJECT = "This account needs a Google Cloud project: set GOOGLE_CLOUD_PROJECT (see https://goo.gle/gemini-cli-auth-docs#workspace-gca).";
746
+ async function geminiProject(config, token, interaction) {
747
+ const own = config.env("GOOGLE_CLOUD_PROJECT") || config.env("GOOGLE_CLOUD_PROJECT_ID");
748
+ const endpoint = config.codeAssistEndpoints[0];
749
+ const headers = {
750
+ Authorization: `Bearer ${token}`,
751
+ "Content-Type": "application/json",
752
+ "User-Agent": "google-api-nodejs-client/9.15.1",
753
+ "X-Goog-Api-Client": "gl-node/22.17.0"
754
+ };
755
+ interaction.notify({ type: "progress", message: "Looking up the Cloud Code Assist project..." });
756
+ const loaded = await fetch(`${endpoint}/v1internal:loadCodeAssist`, {
757
+ method: "POST",
758
+ headers,
759
+ body: JSON.stringify({ cloudaicompanionProject: own, metadata: { ...CLIENT_METADATA, duetProject: own } }),
760
+ signal: interaction.signal
761
+ });
762
+ let data;
763
+ if (loaded.ok) data = await loaded.json();
764
+ else {
765
+ const text = await loaded.text();
766
+ if (!text.includes("SECURITY_POLICY_VIOLATED")) {
767
+ throw new Error(`loadCodeAssist failed (${loaded.status}): ${text.slice(0, 300)}`);
768
+ }
769
+ data = { currentTier: { id: "standard-tier" } };
770
+ }
771
+ if (data.currentTier) {
772
+ const found = projectOf(data.cloudaicompanionProject) ?? own;
773
+ if (!found) throw new Error(NEEDS_PROJECT);
774
+ return found;
775
+ }
776
+ const tier = data.allowedTiers?.find((candidate) => candidate.isDefault)?.id ?? "legacy-tier";
777
+ if (tier !== "free-tier" && !own) throw new Error(NEEDS_PROJECT);
778
+ interaction.notify({
779
+ type: "progress",
780
+ message: "Setting up a Cloud Code Assist project (this can take a minute)..."
781
+ });
782
+ const body = { tierId: tier, metadata: CLIENT_METADATA };
783
+ if (tier !== "free-tier" && own) {
784
+ body.cloudaicompanionProject = own;
785
+ body.metadata = { ...CLIENT_METADATA, duetProject: own };
786
+ }
787
+ const started = await fetch(`${endpoint}/v1internal:onboardUser`, {
788
+ method: "POST",
789
+ headers,
790
+ body: JSON.stringify(body),
791
+ signal: interaction.signal
792
+ });
793
+ if (!started.ok) throw new Error(`onboardUser failed (${started.status}): ${(await started.text()).slice(0, 300)}`);
794
+ let operation = await started.json();
795
+ for (let attempt = 0; !operation.done && operation.name && attempt < 60; attempt++) {
796
+ await new Promise((resolve) => setTimeout(resolve, attempt === 0 ? 1e3 : 5e3));
797
+ const polled = await fetch(`${endpoint}/v1internal/${operation.name}`, { headers, signal: interaction.signal });
798
+ if (!polled.ok) throw new Error(`Setting up the project failed (${polled.status})`);
799
+ operation = await polled.json();
800
+ }
801
+ const provisioned = operation.response?.cloudaicompanionProject?.id ?? own;
802
+ if (!provisioned) throw new Error(NEEDS_PROJECT);
803
+ return provisioned;
804
+ }
805
+ async function antigravityProject(config, token, interaction) {
806
+ interaction.notify({ type: "progress", message: "Looking up the Antigravity project..." });
807
+ for (const endpoint of config.codeAssistEndpoints) {
808
+ try {
809
+ const loaded = await fetch(`${endpoint}/v1internal:loadCodeAssist`, {
810
+ method: "POST",
811
+ headers: {
812
+ Authorization: `Bearer ${token}`,
813
+ "Content-Type": "application/json",
814
+ "User-Agent": "google-api-nodejs-client/9.15.1",
815
+ "Client-Metadata": JSON.stringify(CLIENT_METADATA)
816
+ },
817
+ body: JSON.stringify({ metadata: CLIENT_METADATA }),
818
+ signal: interaction.signal
819
+ });
820
+ if (!loaded.ok) continue;
821
+ const found = projectOf((await loaded.json()).cloudaicompanionProject);
822
+ if (found) return found;
823
+ } catch (error) {
824
+ if (interaction.signal.aborted) throw error;
825
+ }
826
+ }
827
+ return ANTIGRAVITY_DEFAULT_PROJECT;
828
+ }
829
+ async function consent(config, interaction) {
830
+ const answer = await interaction.prompt({
831
+ type: "select",
832
+ message: riskNotice(config),
833
+ options: [
834
+ { id: "continue", label: "I understand the risk, sign in" },
835
+ { id: "cancel", label: "Cancel" }
836
+ ]
837
+ });
838
+ if (answer !== "continue") throw new Error("Login cancelled");
839
+ }
840
+ async function login(config, interaction) {
841
+ await consent(config, interaction);
842
+ const { verifier, challenge } = await pkce();
843
+ const redirectUri = `http://localhost:${config.callbackPort}${config.callbackPath}`;
844
+ const callback = await listen(config, verifier);
845
+ const pasting = new AbortController();
846
+ const onAbort = () => callback.cancel();
847
+ interaction.signal.addEventListener("abort", onAbort, { once: true });
848
+ let pasted;
849
+ let pasteError;
850
+ try {
851
+ const query = new URLSearchParams({
852
+ client_id: config.clientId,
853
+ response_type: "code",
854
+ redirect_uri: redirectUri,
855
+ scope: config.scopes.join(" "),
856
+ code_challenge: challenge,
857
+ code_challenge_method: "S256",
858
+ state: verifier,
859
+ access_type: "offline",
860
+ prompt: "consent"
861
+ });
862
+ interaction.notify({
863
+ type: "auth_url",
864
+ url: `${config.authUrl}?${query.toString()}`,
865
+ instructions: "Sign in with Google in your browser. If the browser is on another machine, paste the address it ends on here."
866
+ });
867
+ const typed = interaction.prompt({
868
+ type: "manual_code",
869
+ message: "Sign in in your browser, or paste the address the browser ended on:",
870
+ placeholder: redirectUri,
871
+ signal: pasting.signal
872
+ }).then((value) => {
873
+ pasted = value;
874
+ callback.cancel();
875
+ }).catch((error) => {
876
+ pasteError = error instanceof Error ? error : new Error(String(error));
877
+ callback.cancel();
878
+ });
879
+ let code;
880
+ const received = await callback.wait;
881
+ if (received && "declined" in received) throw new Error(`Google sign-in was declined: ${received.declined}`);
882
+ if (received) {
883
+ if (received.state !== verifier) throw new Error("OAuth state mismatch");
884
+ code = received.code;
885
+ } else {
886
+ if (!pasted && !pasteError && !interaction.signal.aborted) await typed;
887
+ if (interaction.signal.aborted) throw new Error("Login cancelled");
888
+ if (pasteError) throw pasteError;
889
+ const parsed = parsePasted(pasted ?? "");
890
+ if (parsed.state && parsed.state !== verifier) throw new Error("OAuth state mismatch");
891
+ code = parsed.code;
892
+ }
893
+ if (!code) throw new Error("No authorization code came back");
894
+ interaction.notify({ type: "progress", message: "Exchanging the code for tokens..." });
895
+ const tokens = await tokenRequest(
896
+ config,
897
+ { code, grant_type: "authorization_code", redirect_uri: redirectUri, code_verifier: verifier },
898
+ interaction.signal
899
+ );
900
+ if (!tokens.refresh_token) throw new Error("Google sent no refresh token; sign in again");
901
+ const who = await email(config, tokens.access_token, interaction.signal);
902
+ const projectId = config.kind === "gemini-cli" ? await geminiProject(config, tokens.access_token, interaction) : await antigravityProject(config, tokens.access_token, interaction);
903
+ return {
904
+ type: "oauth",
905
+ access: tokens.access_token,
906
+ refresh: tokens.refresh_token,
907
+ expires: expiry(tokens.expires_in),
908
+ projectId,
909
+ ...who ? { email: who } : {}
910
+ };
911
+ } finally {
912
+ interaction.signal.removeEventListener("abort", onAbort);
913
+ pasting.abort();
914
+ callback.server.close();
915
+ callback.server.closeAllConnections();
916
+ }
917
+ }
918
+ async function refresh(config, credential, signal) {
919
+ const projectId = credential.projectId;
920
+ if (!projectId) throw new Error(`${config.title} credential has no project; sign in again`);
921
+ const tokens = await tokenRequest(
922
+ config,
923
+ { refresh_token: credential.refresh, grant_type: "refresh_token" },
924
+ signal
925
+ );
926
+ return {
927
+ ...credential,
928
+ type: "oauth",
929
+ access: tokens.access_token,
930
+ refresh: tokens.refresh_token || credential.refresh,
931
+ expires: expiry(tokens.expires_in),
932
+ projectId
933
+ };
934
+ }
935
+ function cloudCodeKey(credential) {
936
+ return JSON.stringify({ token: credential.access, projectId: credential.projectId });
937
+ }
938
+ function googleOAuth(config) {
939
+ return {
940
+ name: `${config.title} (experimental)`,
941
+ isSubscription: true,
942
+ loginLabel: `Sign in with Google through ${config.title} (experimental)`,
943
+ login: (interaction) => login(config, interaction),
944
+ refresh: (credential, signal) => refresh(config, credential, signal),
945
+ toAuth: async (credential) => ({ apiKey: cloudCodeKey(credential) })
946
+ };
947
+ }
948
+ var geminiCliOAuth = googleOAuth(GEMINI_CLI_LOGIN);
949
+ var antigravityOAuth = googleOAuth(ANTIGRAVITY_LOGIN);
950
+
951
+ // packages/kyrn-judge/src/google-login/providers.ts
952
+ var cloudCode = () => lazyApi(() => Promise.resolve().then(() => (init_cloud_code(), cloud_code_exports)));
953
+ var FREE = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
954
+ var NOT_CHAT = /image|live|computer-use|customtools|latest|deep-research|tts|embedding/;
955
+ function geminiCliModels() {
956
+ return Object.values(GOOGLE_MODELS).filter((model) => model.id.startsWith("gemini-") && !NOT_CHAT.test(model.id)).map((model) => ({
957
+ ...model,
958
+ api: CLOUD_CODE_API,
959
+ provider: GEMINI_CLI_PROVIDER,
960
+ baseUrl: CLOUD_CODE_ENDPOINT,
961
+ cost: FREE
962
+ }));
963
+ }
964
+ function geminiCliProvider() {
965
+ return createProvider({
966
+ id: GEMINI_CLI_PROVIDER,
967
+ name: "Google Gemini CLI (experimental)",
968
+ baseUrl: CLOUD_CODE_ENDPOINT,
969
+ auth: { oauth: geminiCliOAuth },
970
+ models: geminiCliModels(),
971
+ api: cloudCode()
972
+ });
973
+ }
974
+ var FLASH_LEVELS = {
975
+ off: null,
976
+ minimal: "minimal",
977
+ low: "low",
978
+ medium: "medium",
979
+ high: "high",
980
+ xhigh: null,
981
+ max: null
982
+ };
983
+ var PRO_LEVELS = { ...FLASH_LEVELS, minimal: null };
984
+ var levelsOf = (id) => /^gemini-3(?:\.\d+)?-pro/.test(id) ? PRO_LEVELS : /^gemini-3(?:\.\d+)?-flash/.test(id) ? FLASH_LEVELS : void 0;
985
+ var OPUS = { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 };
986
+ var SONNET = { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 };
987
+ var GEMINI_PRO = { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.375 };
988
+ var GEMINI_FLASH = { input: 0.5, output: 3, cacheRead: 0.5, cacheWrite: 0 };
989
+ var GPT_OSS = { input: 0.09, output: 0.36, cacheRead: 0, cacheWrite: 0 };
990
+ function antigravityModel(id, name, fields) {
991
+ const levels = levelsOf(id);
992
+ return {
993
+ id,
994
+ name: `${name} (Antigravity)`,
995
+ api: CLOUD_CODE_API,
996
+ provider: ANTIGRAVITY_PROVIDER,
997
+ baseUrl: ANTIGRAVITY_ENDPOINTS[0],
998
+ ...fields,
999
+ ...levels ? { thinkingLevelMap: levels } : {}
1000
+ };
1001
+ }
1002
+ var TEXT_AND_IMAGE = ["text", "image"];
1003
+ function antigravityBaseline() {
1004
+ const claude = (maxTokens, reasoning, cost) => ({ reasoning, input: TEXT_AND_IMAGE, cost, contextWindow: 2e5, maxTokens });
1005
+ const gemini = (cost) => ({ reasoning: true, input: TEXT_AND_IMAGE, cost, contextWindow: 1048576, maxTokens: 65535 });
1006
+ return [
1007
+ antigravityModel("claude-opus-4-5-thinking", "Claude Opus 4.5 Thinking", claude(64e3, true, OPUS)),
1008
+ antigravityModel("claude-opus-4-6-thinking", "Claude Opus 4.6 Thinking", claude(128e3, true, OPUS)),
1009
+ antigravityModel("claude-sonnet-4-5", "Claude Sonnet 4.5", claude(64e3, false, SONNET)),
1010
+ antigravityModel("claude-sonnet-4-5-thinking", "Claude Sonnet 4.5 Thinking", claude(64e3, true, SONNET)),
1011
+ antigravityModel("claude-sonnet-4-6", "Claude Sonnet 4.6", claude(64e3, true, SONNET)),
1012
+ antigravityModel("gemini-3-flash", "Gemini 3 Flash", gemini(GEMINI_FLASH)),
1013
+ antigravityModel("gemini-3.1-pro-high", "Gemini 3.1 Pro High", gemini(GEMINI_PRO)),
1014
+ antigravityModel("gemini-3.1-pro-low", "Gemini 3.1 Pro Low", gemini(GEMINI_PRO)),
1015
+ antigravityModel("gpt-oss-120b-medium", "GPT-OSS 120B Medium", {
1016
+ reasoning: false,
1017
+ input: ["text"],
1018
+ cost: GPT_OSS,
1019
+ contextWindow: 131072,
1020
+ maxTokens: 32768
1021
+ })
1022
+ ];
1023
+ }
1024
+ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1025
+ var positive = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : void 0;
1026
+ var SERVED = /^(?:gemini|claude|gpt-oss)-/;
1027
+ function antigravityModelsFrom(body) {
1028
+ const listed = isRecord2(body) ? body.models : void 0;
1029
+ const entries = Array.isArray(listed) ? listed.flatMap(
1030
+ (item) => isRecord2(item) && typeof item.id === "string" ? [[item.id, item]] : []
1031
+ ) : isRecord2(listed) ? Object.entries(listed).map(([id, info]) => [id, isRecord2(info) ? info : {}]) : [];
1032
+ const baseline = new Map(antigravityBaseline().map((model) => [model.id, model]));
1033
+ const models = /* @__PURE__ */ new Map();
1034
+ for (const [raw, info] of entries) {
1035
+ const id = raw.trim();
1036
+ if (!SERVED.test(id) || /image/.test(id) || models.has(id)) continue;
1037
+ const known = baseline.get(id);
1038
+ if (known) {
1039
+ models.set(id, known);
1040
+ continue;
1041
+ }
1042
+ const family = id.startsWith("claude-") ? "claude" : id.startsWith("gpt-oss-") ? "gpt-oss" : "gemini";
1043
+ const name = typeof info.displayName === "string" && info.displayName.trim() ? info.displayName.trim() : id;
1044
+ const images = typeof info.supportsImages === "boolean" ? info.supportsImages : family !== "gpt-oss";
1045
+ const reasoning = family === "gemini" ? true : typeof info.supportsThinking === "boolean" ? info.supportsThinking : /thinking/.test(id);
1046
+ models.set(
1047
+ id,
1048
+ antigravityModel(id, name, {
1049
+ reasoning,
1050
+ input: images ? TEXT_AND_IMAGE : ["text"],
1051
+ cost: FREE,
1052
+ contextWindow: family === "gemini" ? 1048576 : family === "claude" ? 2e5 : 131072,
1053
+ maxTokens: positive(info.maxOutputTokens) ?? (family === "gemini" ? 65535 : family === "claude" ? 64e3 : 32768)
1054
+ })
1055
+ );
1056
+ }
1057
+ return [...models.values()];
1058
+ }
1059
+ async function fetchAntigravityModels(context, fetcher = globalThis.fetch) {
1060
+ const credential = context.credential;
1061
+ if (credential?.type !== "oauth") return [];
1062
+ let failure = "no endpoint answered";
1063
+ for (const endpoint of ANTIGRAVITY_ENDPOINTS) {
1064
+ const response = await fetcher(`${endpoint}/v1internal:fetchAvailableModels`, {
1065
+ method: "POST",
1066
+ headers: {
1067
+ Authorization: `Bearer ${credential.access}`,
1068
+ "Content-Type": "application/json",
1069
+ "User-Agent": antigravityUserAgent()
1070
+ },
1071
+ body: "{}",
1072
+ signal: context.signal
1073
+ });
1074
+ if (response.ok) return antigravityModelsFrom(await response.json());
1075
+ failure = `${endpoint} answered ${response.status}`;
1076
+ }
1077
+ throw new Error(`Antigravity did not list its models: ${failure}`);
1078
+ }
1079
+ function antigravityProvider(fetcher) {
1080
+ return createProvider({
1081
+ id: ANTIGRAVITY_PROVIDER,
1082
+ name: "Google Antigravity (experimental)",
1083
+ baseUrl: ANTIGRAVITY_ENDPOINTS[0],
1084
+ auth: { oauth: antigravityOAuth },
1085
+ models: antigravityBaseline(),
1086
+ fetchModels: (context) => fetchAntigravityModels(context, fetcher),
1087
+ api: cloudCode()
1088
+ });
1089
+ }
1090
+
1091
+ // packages/kyrn-judge/src/auth/runner.ts
1092
+ var BUILT_IN_PROVIDERS = ["openai-codex", "anthropic", "xai"];
1093
+ var LISTED_BY_ACCOUNT = /* @__PURE__ */ new Set(["google-antigravity"]);
1094
+ var MODELS_READ_MS = 2e4;
1095
+ var BROWSER_METHOD = "browser";
1096
+ var USAGE = "usage: mu auth status | mu auth login <provider> | mu auth logout <provider>";
1097
+ var AUTH_COMMANDS = ["status", "login", "logout"];
1098
+ function modelsOf(runtime, provider, preferred) {
1099
+ const models = runtime.getModels(provider).map((model) => ({ id: model.id, name: model.name || model.id }));
1100
+ const first = models.findIndex((model) => model.id === preferred[provider]);
1101
+ return first > 0 ? [models[first], ...models.slice(0, first), ...models.slice(first + 1)] : models;
1102
+ }
1103
+ var isBrowserChoice = (prompt) => prompt.type === "select" && prompt.options.some((option) => option.id === BROWSER_METHOD);
1104
+ function shown(prompt) {
1105
+ return {
1106
+ type: prompt.type,
1107
+ message: prompt.message,
1108
+ placeholder: "placeholder" in prompt ? prompt.placeholder : void 0,
1109
+ options: prompt.type === "select" ? prompt.options : void 0
1110
+ };
1111
+ }
1112
+ async function runAuth(argv, options) {
1113
+ const { runtime, preferred, io } = options;
1114
+ try {
1115
+ const [mode, provider] = argv;
1116
+ if (!AUTH_COMMANDS.includes(mode ?? "")) throw new Error(USAGE);
1117
+ for (const extra of options.extra) runtime.registerNativeProvider(extra);
1118
+ if (options.extra.length > 0) {
1119
+ await runtime.refresh({ allowNetwork: false, providers: options.extra.map((extra) => extra.id) });
1120
+ }
1121
+ const offered = [...BUILT_IN_PROVIDERS, ...options.extra.map((extra) => extra.id)];
1122
+ const status = async () => ({
1123
+ type: "status",
1124
+ offered,
1125
+ signedIn: (await runtime.listCredentials()).filter((credential) => credential.type === "oauth" && offered.includes(credential.providerId)).map((credential) => ({
1126
+ provider: credential.providerId,
1127
+ models: modelsOf(runtime, credential.providerId, preferred)
1128
+ }))
1129
+ });
1130
+ if (mode === "status") {
1131
+ io.say(await status());
1132
+ return 0;
1133
+ }
1134
+ if (!provider) throw new Error(USAGE);
1135
+ if (!offered.includes(provider)) throw new Error(`Signing in to ${provider} is not available in this mu`);
1136
+ if (mode === "logout") {
1137
+ const stored = (await runtime.listCredentials()).find((credential) => credential.providerId === provider);
1138
+ if (stored?.type === "oauth") await runtime.logout(provider);
1139
+ io.say(await status());
1140
+ return 0;
1141
+ }
1142
+ await signIn(provider, options);
1143
+ return 0;
1144
+ } catch (error) {
1145
+ io.say({ type: "error", message: error instanceof Error ? error.message : String(error) });
1146
+ return 1;
1147
+ }
1148
+ }
1149
+ async function signIn(provider, { runtime, preferred, io, modelsReadMs }) {
1150
+ const controller = new AbortController();
1151
+ let pending;
1152
+ io.listen(
1153
+ (line) => {
1154
+ let message;
1155
+ try {
1156
+ message = JSON.parse(line);
1157
+ } catch {
1158
+ return;
1159
+ }
1160
+ if (message.type === "answer" && pending) {
1161
+ const waiting = pending;
1162
+ pending = void 0;
1163
+ waiting.resolve(typeof message.value === "string" ? message.value : "");
1164
+ } else if (message.type === "cancel") {
1165
+ controller.abort();
1166
+ pending?.reject(new Error("cancelled"));
1167
+ }
1168
+ },
1169
+ // The app went away: nobody is left to finish the sign-in.
1170
+ () => controller.abort()
1171
+ );
1172
+ await runtime.login(provider, "oauth", {
1173
+ signal: controller.signal,
1174
+ notify: (event) => io.say({ type: "event", event }),
1175
+ prompt: (prompt) => isBrowserChoice(prompt) ? Promise.resolve(BROWSER_METHOD) : new Promise((resolve, reject) => {
1176
+ const entry = { resolve, reject };
1177
+ pending = entry;
1178
+ prompt.signal?.addEventListener(
1179
+ "abort",
1180
+ () => {
1181
+ if (pending !== entry) return;
1182
+ pending = void 0;
1183
+ reject(new Error("withdrawn"));
1184
+ io.say({ type: "prompt_done" });
1185
+ },
1186
+ { once: true }
1187
+ );
1188
+ io.say({ type: "prompt", prompt: shown(prompt) });
1189
+ })
1190
+ });
1191
+ io.say({ type: "signed_in" });
1192
+ if (LISTED_BY_ACCOUNT.has(provider)) {
1193
+ const signal = AbortSignal.any([controller.signal, AbortSignal.timeout(modelsReadMs ?? MODELS_READ_MS)]);
1194
+ await runtime.refresh({ providers: [provider], allowNetwork: true, signal }).catch(() => {
1195
+ });
1196
+ }
1197
+ io.say({ type: "done", provider, models: modelsOf(runtime, provider, preferred) });
1198
+ }
1199
+
1200
+ // packages/kyrn-judge/src/auth/main.ts
1201
+ var agentDir = muEnv("AGENT_DIR") || join3(muHome(), "agent");
1202
+ var say = (message) => process.stdout.write(`${JSON.stringify(message)}
1203
+ `);
1204
+ function googleProviders() {
1205
+ try {
1206
+ const loaded = loadConfig({ dir: agentDir, env: process.env });
1207
+ if (loaded.disabled) return [];
1208
+ const options = featureOptions(loaded.config, "googleLogin", {
1209
+ enabled: true,
1210
+ geminiCli: true,
1211
+ antigravity: true
1212
+ });
1213
+ if (!options.enabled) return [];
1214
+ return [
1215
+ ...options.geminiCli ? [geminiCliProvider()] : [],
1216
+ ...options.antigravity ? [antigravityProvider()] : []
1217
+ ];
1218
+ } catch {
1219
+ return [];
1220
+ }
1221
+ }
1222
+ async function main() {
1223
+ const runtime = await ModelRuntime.create({
1224
+ authPath: join3(agentDir, "auth.json"),
1225
+ modelsPath: join3(agentDir, "models.json"),
1226
+ refreshOnCreate: false
1227
+ });
1228
+ return runAuth(process.argv.slice(2), {
1229
+ runtime,
1230
+ preferred: defaultModelPerProvider,
1231
+ extra: googleProviders(),
1232
+ io: {
1233
+ say,
1234
+ listen: (line, end) => {
1235
+ const lines = createInterface({ input: process.stdin });
1236
+ lines.on("line", line);
1237
+ lines.on("close", end);
1238
+ }
1239
+ }
1240
+ });
1241
+ }
1242
+ main().then(
1243
+ (code) => process.exit(code),
1244
+ (error) => {
1245
+ say({ type: "error", message: error instanceof Error ? error.message : String(error) });
1246
+ process.exit(1);
1247
+ }
1248
+ );