nolo-cli 0.1.52 → 0.1.54
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/index.js +1220 -514
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -9229,6 +9229,377 @@ var init_agentRecordHelpers = __esm({
|
|
|
9229
9229
|
}
|
|
9230
9230
|
});
|
|
9231
9231
|
|
|
9232
|
+
// packages/agent-runtime/antigravityOAuth.ts
|
|
9233
|
+
function getAntigravityUserAgent() {
|
|
9234
|
+
const version = process.env.NOLO_ANTIGRAVITY_VERSION || "2.1.4";
|
|
9235
|
+
const os2 = process.platform === "win32" ? "windows" : process.platform;
|
|
9236
|
+
const arch3 = process.arch === "x64" ? "amd64" : process.arch === "ia32" ? "386" : process.arch;
|
|
9237
|
+
return `antigravity/hub/${version} ${os2}/${arch3}`;
|
|
9238
|
+
}
|
|
9239
|
+
function resolveAntigravityCloudCodeBaseUrl(customProviderUrl) {
|
|
9240
|
+
const raw = (customProviderUrl ?? "").trim();
|
|
9241
|
+
if (!raw) return ANTIGRAVITY_CLOUD_CODE_BASE_URL;
|
|
9242
|
+
const trimmed = trimTrailingSlash(raw);
|
|
9243
|
+
if (trimmed.includes(ANTIGRAVITY_CLOUD_CODE_HOST)) {
|
|
9244
|
+
const base = trimmed.replace(/\/v1internal:.*$/i, "").replace(/\/$/, "");
|
|
9245
|
+
if (ANTIGRAVITY_LEGACY_GENERIC_BASE_RE.test(base)) {
|
|
9246
|
+
return ANTIGRAVITY_CLOUD_CODE_BASE_URL;
|
|
9247
|
+
}
|
|
9248
|
+
return base;
|
|
9249
|
+
}
|
|
9250
|
+
return ANTIGRAVITY_CLOUD_CODE_BASE_URL;
|
|
9251
|
+
}
|
|
9252
|
+
function isAntigravityOAuthAgent(agentConfig) {
|
|
9253
|
+
if (!agentConfig) return false;
|
|
9254
|
+
const apiKeyRef = (agentConfig.apiKeyRef ?? "").trim().toLowerCase();
|
|
9255
|
+
const provider = String(agentConfig.provider ?? "").trim().toLowerCase();
|
|
9256
|
+
const url = (agentConfig.customProviderUrl ?? "").trim().toLowerCase();
|
|
9257
|
+
return apiKeyRef === "antigravity" || provider === "google-antigravity" || url.includes(ANTIGRAVITY_CLOUD_CODE_HOST);
|
|
9258
|
+
}
|
|
9259
|
+
function readAntigravityProjectId(metadata) {
|
|
9260
|
+
const value = metadata?.projectId;
|
|
9261
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
9262
|
+
}
|
|
9263
|
+
var ANTIGRAVITY_CLOUD_CODE_BASE_URL, ANTIGRAVITY_CLOUD_CODE_HOST, ANTIGRAVITY_LEGACY_GENERIC_BASE_RE;
|
|
9264
|
+
var init_antigravityOAuth = __esm({
|
|
9265
|
+
"packages/agent-runtime/antigravityOAuth.ts"() {
|
|
9266
|
+
"use strict";
|
|
9267
|
+
init_providerResolution();
|
|
9268
|
+
ANTIGRAVITY_CLOUD_CODE_BASE_URL = "https://daily-cloudcode-pa.googleapis.com";
|
|
9269
|
+
ANTIGRAVITY_CLOUD_CODE_HOST = "cloudcode-pa.googleapis.com";
|
|
9270
|
+
ANTIGRAVITY_LEGACY_GENERIC_BASE_RE = /^https?:\/\/cloudcode-pa\.googleapis\.com$/i;
|
|
9271
|
+
}
|
|
9272
|
+
});
|
|
9273
|
+
|
|
9274
|
+
// packages/agent-runtime/antigravityWireModel.ts
|
|
9275
|
+
function resolveAntigravityWireModel(logicalModelId) {
|
|
9276
|
+
const id = logicalModelId.trim();
|
|
9277
|
+
const lower = id.toLowerCase();
|
|
9278
|
+
if (lower === "gemini-3.1-pro" || lower === "gemini-3.1-pro-preview") {
|
|
9279
|
+
const wireModelId = "gemini-3.1-pro-low";
|
|
9280
|
+
return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
|
|
9281
|
+
}
|
|
9282
|
+
if (WIRE_PROFILES[id]) {
|
|
9283
|
+
return { wireModelId: id, profile: WIRE_PROFILES[id] };
|
|
9284
|
+
}
|
|
9285
|
+
return { wireModelId: id };
|
|
9286
|
+
}
|
|
9287
|
+
var WIRE_PROFILES;
|
|
9288
|
+
var init_antigravityWireModel = __esm({
|
|
9289
|
+
"packages/agent-runtime/antigravityWireModel.ts"() {
|
|
9290
|
+
"use strict";
|
|
9291
|
+
WIRE_PROFILES = {
|
|
9292
|
+
"gemini-3.5-flash-extra-low": { modelEnum: "MODEL_PLACEHOLDER_M187", maxOutputTokens: 65536 },
|
|
9293
|
+
"gemini-3.5-flash-low": { modelEnum: "MODEL_PLACEHOLDER_M20", maxOutputTokens: 65536 },
|
|
9294
|
+
"gemini-3-flash-agent": { modelEnum: "MODEL_PLACEHOLDER_M132", maxOutputTokens: 65536 },
|
|
9295
|
+
"gemini-3.1-pro-low": { modelEnum: "MODEL_PLACEHOLDER_M36", maxOutputTokens: 65535 },
|
|
9296
|
+
"gemini-pro-agent": { modelEnum: "MODEL_PLACEHOLDER_M16", maxOutputTokens: 65535 },
|
|
9297
|
+
"claude-sonnet-4-6": { maxOutputTokens: 64e3 },
|
|
9298
|
+
"claude-opus-4-6-thinking": { maxOutputTokens: 64e3 },
|
|
9299
|
+
"gemini-2.5-flash": { maxOutputTokens: 65536 }
|
|
9300
|
+
};
|
|
9301
|
+
}
|
|
9302
|
+
});
|
|
9303
|
+
|
|
9304
|
+
// packages/agent-runtime/antigravityCloudCodeProvider.ts
|
|
9305
|
+
import { randomUUID } from "node:crypto";
|
|
9306
|
+
function isGemini3WireModel(modelId) {
|
|
9307
|
+
return modelId.includes("gemini-3");
|
|
9308
|
+
}
|
|
9309
|
+
function messageText(content) {
|
|
9310
|
+
if (typeof content === "string") return content;
|
|
9311
|
+
if (!Array.isArray(content)) return "";
|
|
9312
|
+
return content.filter((part) => part?.type === "text").map((part) => part.text).join("\n").trim();
|
|
9313
|
+
}
|
|
9314
|
+
function parseToolArguments2(raw) {
|
|
9315
|
+
if (!raw?.trim()) return {};
|
|
9316
|
+
try {
|
|
9317
|
+
const parsed = JSON.parse(raw);
|
|
9318
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
9319
|
+
} catch {
|
|
9320
|
+
return {};
|
|
9321
|
+
}
|
|
9322
|
+
}
|
|
9323
|
+
function convertOpenAiMessagesToCca(messages, options) {
|
|
9324
|
+
const contents = [];
|
|
9325
|
+
const systemTexts = [];
|
|
9326
|
+
const toolNamesById = /* @__PURE__ */ new Map();
|
|
9327
|
+
for (const raw of messages) {
|
|
9328
|
+
if (!raw || typeof raw !== "object" || !("role" in raw)) continue;
|
|
9329
|
+
const role = String(raw.role);
|
|
9330
|
+
const content = "content" in raw ? raw.content : null;
|
|
9331
|
+
if (role === "system") {
|
|
9332
|
+
const text = messageText(content);
|
|
9333
|
+
if (text) systemTexts.push(text);
|
|
9334
|
+
continue;
|
|
9335
|
+
}
|
|
9336
|
+
if (role === "user") {
|
|
9337
|
+
const text = messageText(content);
|
|
9338
|
+
if (!text) continue;
|
|
9339
|
+
contents.push({ role: "user", parts: [{ text }] });
|
|
9340
|
+
continue;
|
|
9341
|
+
}
|
|
9342
|
+
if (role === "assistant") {
|
|
9343
|
+
const parts = [];
|
|
9344
|
+
const text = messageText(content);
|
|
9345
|
+
if (text) parts.push({ text });
|
|
9346
|
+
const toolCalls = "tool_calls" in raw && Array.isArray(raw.tool_calls) ? raw.tool_calls ?? [] : [];
|
|
9347
|
+
for (const call of toolCalls) {
|
|
9348
|
+
const name = call?.function?.name?.trim();
|
|
9349
|
+
if (!name) continue;
|
|
9350
|
+
const id = call.id?.trim() || `${name}_${toolNamesById.size}`;
|
|
9351
|
+
toolNamesById.set(id, name);
|
|
9352
|
+
parts.push({
|
|
9353
|
+
functionCall: {
|
|
9354
|
+
name,
|
|
9355
|
+
args: parseToolArguments2(call.function?.arguments),
|
|
9356
|
+
id
|
|
9357
|
+
},
|
|
9358
|
+
...options.attachSkipThoughtSignature ? { thoughtSignature: SKIP_THOUGHT_SIGNATURE } : {}
|
|
9359
|
+
});
|
|
9360
|
+
}
|
|
9361
|
+
if (parts.length === 0) continue;
|
|
9362
|
+
contents.push({ role: "model", parts });
|
|
9363
|
+
continue;
|
|
9364
|
+
}
|
|
9365
|
+
if (role === "tool") {
|
|
9366
|
+
const toolCallId = "tool_call_id" in raw && typeof raw.tool_call_id === "string" ? raw.tool_call_id : "";
|
|
9367
|
+
const name = toolNamesById.get(toolCallId) ?? "tool";
|
|
9368
|
+
const output2 = messageText(content) || "{}";
|
|
9369
|
+
contents.push({
|
|
9370
|
+
role: "user",
|
|
9371
|
+
parts: [{ functionResponse: { name, response: { output: output2 } } }]
|
|
9372
|
+
});
|
|
9373
|
+
}
|
|
9374
|
+
}
|
|
9375
|
+
return { contents, systemTexts };
|
|
9376
|
+
}
|
|
9377
|
+
function convertOpenAiTools(tools) {
|
|
9378
|
+
if (!Array.isArray(tools) || tools.length === 0) return void 0;
|
|
9379
|
+
const declarations = [];
|
|
9380
|
+
for (const tool of tools) {
|
|
9381
|
+
if (!tool || typeof tool !== "object" || !("function" in tool)) continue;
|
|
9382
|
+
const fn = tool.function;
|
|
9383
|
+
const name = typeof fn.name === "string" ? fn.name : "";
|
|
9384
|
+
if (!name) continue;
|
|
9385
|
+
declarations.push({
|
|
9386
|
+
name,
|
|
9387
|
+
description: typeof fn.description === "string" ? fn.description : "",
|
|
9388
|
+
parameters: fn.parameters ?? { type: "object", properties: {} }
|
|
9389
|
+
});
|
|
9390
|
+
}
|
|
9391
|
+
if (declarations.length === 0) return void 0;
|
|
9392
|
+
return [{ functionDeclarations: declarations }];
|
|
9393
|
+
}
|
|
9394
|
+
function buildCloudCodeAssistPayload(args2) {
|
|
9395
|
+
const projectId = readAntigravityProjectId(args2.metadata);
|
|
9396
|
+
if (!projectId) {
|
|
9397
|
+
throw new Error(
|
|
9398
|
+
"Antigravity OAuth credential is missing metadata.projectId. Re-run `nolo auth antigravity`."
|
|
9399
|
+
);
|
|
9400
|
+
}
|
|
9401
|
+
const logicalModel = typeof args2.openAiBody.model === "string" && args2.openAiBody.model.trim() || args2.agentConfig.model?.trim() || "gemini-3.1-pro";
|
|
9402
|
+
const { wireModelId: model, profile } = resolveAntigravityWireModel(logicalModel);
|
|
9403
|
+
const rawMessages = Array.isArray(args2.openAiBody.messages) ? args2.openAiBody.messages : [];
|
|
9404
|
+
const { contents, systemTexts } = convertOpenAiMessagesToCca(rawMessages, {
|
|
9405
|
+
attachSkipThoughtSignature: isGemini3WireModel(model)
|
|
9406
|
+
});
|
|
9407
|
+
if (contents.length === 0) {
|
|
9408
|
+
throw new Error("Antigravity Cloud Code Assist request has no user/model contents.");
|
|
9409
|
+
}
|
|
9410
|
+
const prompt = args2.agentConfig.prompt?.trim();
|
|
9411
|
+
if (prompt) systemTexts.unshift(prompt);
|
|
9412
|
+
const request = { contents };
|
|
9413
|
+
if (systemTexts.length > 0) {
|
|
9414
|
+
request.systemInstruction = {
|
|
9415
|
+
role: "user",
|
|
9416
|
+
parts: systemTexts.map((text) => ({ text }))
|
|
9417
|
+
};
|
|
9418
|
+
}
|
|
9419
|
+
const tools = convertOpenAiTools(
|
|
9420
|
+
Array.isArray(args2.openAiBody.tools) ? args2.openAiBody.tools : void 0
|
|
9421
|
+
);
|
|
9422
|
+
if (tools) {
|
|
9423
|
+
request.tools = tools;
|
|
9424
|
+
request.toolConfig = { functionCallingConfig: { mode: "VALIDATED" } };
|
|
9425
|
+
}
|
|
9426
|
+
const generationConfig = {};
|
|
9427
|
+
if (profile?.maxOutputTokens) {
|
|
9428
|
+
generationConfig.maxOutputTokens = profile.maxOutputTokens;
|
|
9429
|
+
} else if (typeof args2.agentConfig.max_tokens === "number" && args2.agentConfig.max_tokens > 0) {
|
|
9430
|
+
generationConfig.maxOutputTokens = args2.agentConfig.max_tokens;
|
|
9431
|
+
}
|
|
9432
|
+
if (typeof args2.agentConfig.temperature === "number") {
|
|
9433
|
+
generationConfig.temperature = args2.agentConfig.temperature;
|
|
9434
|
+
}
|
|
9435
|
+
if (Object.keys(generationConfig).length > 0) {
|
|
9436
|
+
request.generationConfig = generationConfig;
|
|
9437
|
+
}
|
|
9438
|
+
const agentId = randomUUID();
|
|
9439
|
+
const trajectoryId = randomUUID();
|
|
9440
|
+
const step = 2;
|
|
9441
|
+
const requestId = `agent/${agentId}/${Date.now()}/${trajectoryId}/${step}`;
|
|
9442
|
+
const isClaude = model.toLowerCase().includes("claude");
|
|
9443
|
+
const labels = {
|
|
9444
|
+
trajectory_id: trajectoryId,
|
|
9445
|
+
last_step_index: String(step - 1),
|
|
9446
|
+
used_claude: String(isClaude),
|
|
9447
|
+
used_claude_conservative: String(isClaude)
|
|
9448
|
+
};
|
|
9449
|
+
if (profile?.modelEnum) {
|
|
9450
|
+
labels.model_enum = profile.modelEnum;
|
|
9451
|
+
}
|
|
9452
|
+
request.labels = labels;
|
|
9453
|
+
request.sessionId = `-${Math.floor(Math.random() * 9e15)}`;
|
|
9454
|
+
return {
|
|
9455
|
+
url: `${resolveAntigravityCloudCodeBaseUrl(args2.agentConfig.customProviderUrl)}${STREAM_PATH}`,
|
|
9456
|
+
envelope: {
|
|
9457
|
+
project: projectId,
|
|
9458
|
+
model,
|
|
9459
|
+
request,
|
|
9460
|
+
requestId,
|
|
9461
|
+
requestType: "agent",
|
|
9462
|
+
userAgent: "antigravity"
|
|
9463
|
+
}
|
|
9464
|
+
};
|
|
9465
|
+
}
|
|
9466
|
+
function extractJsonFromSseLine(line) {
|
|
9467
|
+
const trimmed = line.trim();
|
|
9468
|
+
if (!trimmed.startsWith("data:")) return null;
|
|
9469
|
+
const payload = trimmed.slice(5).trim();
|
|
9470
|
+
if (!payload || payload === "[DONE]") return null;
|
|
9471
|
+
try {
|
|
9472
|
+
return JSON.parse(payload);
|
|
9473
|
+
} catch {
|
|
9474
|
+
return null;
|
|
9475
|
+
}
|
|
9476
|
+
}
|
|
9477
|
+
function accumulateCcaChunks(chunks) {
|
|
9478
|
+
let text = "";
|
|
9479
|
+
const toolCalls = [];
|
|
9480
|
+
let usage2;
|
|
9481
|
+
for (const chunk of chunks) {
|
|
9482
|
+
if (!chunk || typeof chunk !== "object") continue;
|
|
9483
|
+
const response = "response" in chunk && chunk.response && typeof chunk.response === "object" ? chunk.response : chunk;
|
|
9484
|
+
if ("usageMetadata" in response && response.usageMetadata && typeof response.usageMetadata === "object") {
|
|
9485
|
+
const meta = response.usageMetadata;
|
|
9486
|
+
const prompt = typeof meta.promptTokenCount === "number" ? meta.promptTokenCount : 0;
|
|
9487
|
+
const candidates2 = typeof meta.candidatesTokenCount === "number" ? meta.candidatesTokenCount : 0;
|
|
9488
|
+
const total = typeof meta.totalTokenCount === "number" ? meta.totalTokenCount : prompt + candidates2;
|
|
9489
|
+
usage2 = {
|
|
9490
|
+
prompt_tokens: prompt,
|
|
9491
|
+
completion_tokens: candidates2,
|
|
9492
|
+
total_tokens: total
|
|
9493
|
+
};
|
|
9494
|
+
}
|
|
9495
|
+
const candidates = Array.isArray(response.candidates) ? response.candidates : [];
|
|
9496
|
+
for (const candidate of candidates) {
|
|
9497
|
+
if (!candidate || typeof candidate !== "object" || !("content" in candidate)) continue;
|
|
9498
|
+
const content = candidate.content;
|
|
9499
|
+
if (!content || typeof content !== "object" || !("parts" in content)) continue;
|
|
9500
|
+
const parts = content.parts;
|
|
9501
|
+
if (!Array.isArray(parts)) continue;
|
|
9502
|
+
for (const part of parts) {
|
|
9503
|
+
if (!part || typeof part !== "object") continue;
|
|
9504
|
+
if ("text" in part && typeof part.text === "string") {
|
|
9505
|
+
const piece = part.text;
|
|
9506
|
+
if (!part.thought) {
|
|
9507
|
+
text += piece;
|
|
9508
|
+
}
|
|
9509
|
+
}
|
|
9510
|
+
if ("functionCall" in part && part.functionCall) {
|
|
9511
|
+
const call = part.functionCall;
|
|
9512
|
+
const name = typeof call.name === "string" ? call.name : "tool";
|
|
9513
|
+
const id = typeof call.id === "string" ? call.id : `${name}_${toolCalls.length}`;
|
|
9514
|
+
const argsObj = call.args && typeof call.args === "object" && !Array.isArray(call.args) ? call.args : {};
|
|
9515
|
+
toolCalls.push({
|
|
9516
|
+
id,
|
|
9517
|
+
type: "function",
|
|
9518
|
+
function: { name, arguments: JSON.stringify(argsObj) }
|
|
9519
|
+
});
|
|
9520
|
+
}
|
|
9521
|
+
}
|
|
9522
|
+
}
|
|
9523
|
+
}
|
|
9524
|
+
return { text, toolCalls, usage: usage2 };
|
|
9525
|
+
}
|
|
9526
|
+
async function readSseJsonChunks(response) {
|
|
9527
|
+
const reader = response.body?.getReader();
|
|
9528
|
+
if (!reader) return [];
|
|
9529
|
+
const decoder = new TextDecoder();
|
|
9530
|
+
let buffer = "";
|
|
9531
|
+
const chunks = [];
|
|
9532
|
+
while (true) {
|
|
9533
|
+
const { done, value } = await reader.read();
|
|
9534
|
+
if (done) break;
|
|
9535
|
+
buffer += decoder.decode(value, { stream: true });
|
|
9536
|
+
const lines = buffer.split("\n");
|
|
9537
|
+
buffer = lines.pop() ?? "";
|
|
9538
|
+
for (const line of lines) {
|
|
9539
|
+
const parsed = extractJsonFromSseLine(line);
|
|
9540
|
+
if (parsed) chunks.push(parsed);
|
|
9541
|
+
}
|
|
9542
|
+
}
|
|
9543
|
+
if (buffer.trim()) {
|
|
9544
|
+
const parsed = extractJsonFromSseLine(buffer);
|
|
9545
|
+
if (parsed) chunks.push(parsed);
|
|
9546
|
+
}
|
|
9547
|
+
return chunks;
|
|
9548
|
+
}
|
|
9549
|
+
async function fetchAntigravityCloudCodeCompletion(args2) {
|
|
9550
|
+
const fetchImpl = args2.fetchImpl ?? fetch;
|
|
9551
|
+
const { url, envelope } = buildCloudCodeAssistPayload(args2);
|
|
9552
|
+
const response = await fetchImpl(url, {
|
|
9553
|
+
method: "POST",
|
|
9554
|
+
headers: {
|
|
9555
|
+
Authorization: `Bearer ${args2.accessToken}`,
|
|
9556
|
+
"Content-Type": "application/json",
|
|
9557
|
+
"User-Agent": getAntigravityUserAgent()
|
|
9558
|
+
},
|
|
9559
|
+
body: JSON.stringify(envelope),
|
|
9560
|
+
signal: args2.signal
|
|
9561
|
+
});
|
|
9562
|
+
if (!response.ok) {
|
|
9563
|
+
const errorText = await response.text();
|
|
9564
|
+
return {
|
|
9565
|
+
status: response.status,
|
|
9566
|
+
body: { error: { message: errorText || response.statusText } }
|
|
9567
|
+
};
|
|
9568
|
+
}
|
|
9569
|
+
const chunks = await readSseJsonChunks(response);
|
|
9570
|
+
const { text, toolCalls, usage: usage2 } = accumulateCcaChunks(chunks);
|
|
9571
|
+
const message = {
|
|
9572
|
+
role: "assistant",
|
|
9573
|
+
content: text || null
|
|
9574
|
+
};
|
|
9575
|
+
if (toolCalls.length > 0) {
|
|
9576
|
+
message.tool_calls = toolCalls;
|
|
9577
|
+
}
|
|
9578
|
+
return {
|
|
9579
|
+
status: 200,
|
|
9580
|
+
body: {
|
|
9581
|
+
choices: [
|
|
9582
|
+
{
|
|
9583
|
+
index: 0,
|
|
9584
|
+
message,
|
|
9585
|
+
finish_reason: toolCalls.length > 0 ? "tool_calls" : "stop"
|
|
9586
|
+
}
|
|
9587
|
+
],
|
|
9588
|
+
...usage2 ? { usage: usage2 } : {}
|
|
9589
|
+
}
|
|
9590
|
+
};
|
|
9591
|
+
}
|
|
9592
|
+
var STREAM_PATH, SKIP_THOUGHT_SIGNATURE;
|
|
9593
|
+
var init_antigravityCloudCodeProvider = __esm({
|
|
9594
|
+
"packages/agent-runtime/antigravityCloudCodeProvider.ts"() {
|
|
9595
|
+
"use strict";
|
|
9596
|
+
init_antigravityOAuth();
|
|
9597
|
+
init_antigravityWireModel();
|
|
9598
|
+
STREAM_PATH = "/v1internal:streamGenerateContent?alt=sse";
|
|
9599
|
+
SKIP_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
|
|
9600
|
+
}
|
|
9601
|
+
});
|
|
9602
|
+
|
|
9232
9603
|
// packages/cli/client/agentConfigResolver.ts
|
|
9233
9604
|
var init_agentConfigResolver = __esm({
|
|
9234
9605
|
"packages/cli/client/agentConfigResolver.ts"() {
|
|
@@ -9245,6 +9616,278 @@ var init_localProviderResolver = __esm({
|
|
|
9245
9616
|
}
|
|
9246
9617
|
});
|
|
9247
9618
|
|
|
9619
|
+
// packages/cli/oauth/flows/antigravity.ts
|
|
9620
|
+
function readProjectId(value) {
|
|
9621
|
+
if (typeof value === "string" && value.length > 0) {
|
|
9622
|
+
return value;
|
|
9623
|
+
}
|
|
9624
|
+
if (value && typeof value === "object" && typeof value.id === "string" && value.id.length > 0) {
|
|
9625
|
+
return value.id;
|
|
9626
|
+
}
|
|
9627
|
+
return void 0;
|
|
9628
|
+
}
|
|
9629
|
+
function getDefaultTierId(allowedTiers) {
|
|
9630
|
+
if (!allowedTiers || allowedTiers.length === 0) {
|
|
9631
|
+
return TIER_LEGACY;
|
|
9632
|
+
}
|
|
9633
|
+
const defaultTier = allowedTiers.find(
|
|
9634
|
+
(tier) => tier.isDefault && typeof tier.id === "string" && tier.id.length > 0
|
|
9635
|
+
);
|
|
9636
|
+
if (defaultTier?.id) {
|
|
9637
|
+
return defaultTier.id;
|
|
9638
|
+
}
|
|
9639
|
+
return TIER_LEGACY;
|
|
9640
|
+
}
|
|
9641
|
+
async function sleep2(ms) {
|
|
9642
|
+
const { promise, resolve: resolve8 } = Promise.withResolvers();
|
|
9643
|
+
setTimeout(resolve8, ms);
|
|
9644
|
+
return promise;
|
|
9645
|
+
}
|
|
9646
|
+
async function onboardProjectWithRetries(fetchImpl, endpoint, headers, onboardBody, onProgress) {
|
|
9647
|
+
for (let attempt = 1; attempt <= PROJECT_ONBOARD_MAX_ATTEMPTS; attempt += 1) {
|
|
9648
|
+
if (attempt > 1) {
|
|
9649
|
+
onProgress?.(
|
|
9650
|
+
`Waiting for project provisioning (attempt ${attempt}/${PROJECT_ONBOARD_MAX_ATTEMPTS})...`
|
|
9651
|
+
);
|
|
9652
|
+
await sleep2(PROJECT_ONBOARD_INTERVAL_MS);
|
|
9653
|
+
}
|
|
9654
|
+
const onboardResponse = await fetchImpl(
|
|
9655
|
+
`${endpoint}/v1internal:onboardUser`,
|
|
9656
|
+
{
|
|
9657
|
+
method: "POST",
|
|
9658
|
+
headers,
|
|
9659
|
+
body: JSON.stringify(onboardBody)
|
|
9660
|
+
}
|
|
9661
|
+
);
|
|
9662
|
+
if (!onboardResponse.ok) {
|
|
9663
|
+
const errorText = await onboardResponse.text();
|
|
9664
|
+
throw new Error(
|
|
9665
|
+
`onboardUser failed: ${onboardResponse.status} ${onboardResponse.statusText}: ${errorText}`
|
|
9666
|
+
);
|
|
9667
|
+
}
|
|
9668
|
+
const operation = await onboardResponse.json();
|
|
9669
|
+
if (!operation.done) {
|
|
9670
|
+
continue;
|
|
9671
|
+
}
|
|
9672
|
+
const projectId = readProjectId(operation.response?.cloudaicompanionProject);
|
|
9673
|
+
if (projectId) {
|
|
9674
|
+
return projectId;
|
|
9675
|
+
}
|
|
9676
|
+
}
|
|
9677
|
+
throw new Error(
|
|
9678
|
+
`onboardUser did not return a provisioned project id after ${PROJECT_ONBOARD_MAX_ATTEMPTS} attempts`
|
|
9679
|
+
);
|
|
9680
|
+
}
|
|
9681
|
+
async function discoverProject(fetchImpl, accessToken, onProgress) {
|
|
9682
|
+
const headers = {
|
|
9683
|
+
Authorization: `Bearer ${accessToken}`,
|
|
9684
|
+
"Content-Type": "application/json"
|
|
9685
|
+
};
|
|
9686
|
+
onProgress?.("Checking for existing project...");
|
|
9687
|
+
const endpoint = CLOUD_CODE_ENDPOINT;
|
|
9688
|
+
const loadResponse = await fetchImpl(`${endpoint}/v1internal:loadCodeAssist`, {
|
|
9689
|
+
method: "POST",
|
|
9690
|
+
headers,
|
|
9691
|
+
body: JSON.stringify({
|
|
9692
|
+
metadata: ANTIGRAVITY_LOAD_CODE_ASSIST_METADATA
|
|
9693
|
+
})
|
|
9694
|
+
});
|
|
9695
|
+
if (!loadResponse.ok) {
|
|
9696
|
+
const errorText = await loadResponse.text();
|
|
9697
|
+
throw new Error(
|
|
9698
|
+
`loadCodeAssist failed: ${loadResponse.status} ${loadResponse.statusText}: ${errorText}`
|
|
9699
|
+
);
|
|
9700
|
+
}
|
|
9701
|
+
const loadPayload = await loadResponse.json();
|
|
9702
|
+
const existingProject = readProjectId(loadPayload.cloudaicompanionProject);
|
|
9703
|
+
if (existingProject) {
|
|
9704
|
+
return existingProject;
|
|
9705
|
+
}
|
|
9706
|
+
const tierId = getDefaultTierId(loadPayload.allowedTiers);
|
|
9707
|
+
onProgress?.("Provisioning project...");
|
|
9708
|
+
const onboardBody = {
|
|
9709
|
+
tierId,
|
|
9710
|
+
metadata: ANTIGRAVITY_LOAD_CODE_ASSIST_METADATA
|
|
9711
|
+
};
|
|
9712
|
+
return onboardProjectWithRetries(
|
|
9713
|
+
fetchImpl,
|
|
9714
|
+
endpoint,
|
|
9715
|
+
headers,
|
|
9716
|
+
onboardBody,
|
|
9717
|
+
onProgress
|
|
9718
|
+
);
|
|
9719
|
+
}
|
|
9720
|
+
async function getUserEmail(fetchImpl, accessToken) {
|
|
9721
|
+
try {
|
|
9722
|
+
const response = await fetchImpl(USERINFO_URL, {
|
|
9723
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
9724
|
+
});
|
|
9725
|
+
if (!response.ok) return void 0;
|
|
9726
|
+
const data = await response.json();
|
|
9727
|
+
return typeof data.email === "string" ? data.email : void 0;
|
|
9728
|
+
} catch {
|
|
9729
|
+
return void 0;
|
|
9730
|
+
}
|
|
9731
|
+
}
|
|
9732
|
+
function generateState2() {
|
|
9733
|
+
const bytes = new Uint8Array(16);
|
|
9734
|
+
crypto.getRandomValues(bytes);
|
|
9735
|
+
return Array.from(bytes).map((value) => value.toString(16).padStart(2, "0")).join("");
|
|
9736
|
+
}
|
|
9737
|
+
async function runAntigravityOAuthLogin(deps = {}) {
|
|
9738
|
+
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
9739
|
+
const output2 = deps.output ?? console;
|
|
9740
|
+
const error = deps.error ?? console;
|
|
9741
|
+
const redirectUri = `http://127.0.0.1:${CALLBACK_PORT}${CALLBACK_PATH}`;
|
|
9742
|
+
let handle;
|
|
9743
|
+
try {
|
|
9744
|
+
handle = await startCallbackServer({
|
|
9745
|
+
port: CALLBACK_PORT,
|
|
9746
|
+
hostname: "127.0.0.1",
|
|
9747
|
+
timeoutMs: 5 * 6e4
|
|
9748
|
+
});
|
|
9749
|
+
} catch (err) {
|
|
9750
|
+
throw new Error(
|
|
9751
|
+
`Failed to start Antigravity OAuth callback server on ${CALLBACK_PORT}: ${err instanceof Error ? err.message : String(err)}`
|
|
9752
|
+
);
|
|
9753
|
+
}
|
|
9754
|
+
try {
|
|
9755
|
+
const state = generateState2();
|
|
9756
|
+
const pkce = await generatePkcePair();
|
|
9757
|
+
const authParams = new URLSearchParams({
|
|
9758
|
+
client_id: CLIENT_ID,
|
|
9759
|
+
response_type: "code",
|
|
9760
|
+
redirect_uri: redirectUri,
|
|
9761
|
+
scope: SCOPES.join(" "),
|
|
9762
|
+
state,
|
|
9763
|
+
access_type: "offline",
|
|
9764
|
+
prompt: "consent"
|
|
9765
|
+
});
|
|
9766
|
+
const authUrl = `${AUTH_URL}?${authParams.toString()}`;
|
|
9767
|
+
output2.log(
|
|
9768
|
+
`Open the following URL in your browser to log in to Antigravity:
|
|
9769
|
+
${authUrl}`
|
|
9770
|
+
);
|
|
9771
|
+
if (deps.openBrowser) {
|
|
9772
|
+
try {
|
|
9773
|
+
await deps.openBrowser(authUrl);
|
|
9774
|
+
} catch (err) {
|
|
9775
|
+
error.error(
|
|
9776
|
+
`Failed to open browser automatically: ${err instanceof Error ? err.message : String(err)}`
|
|
9777
|
+
);
|
|
9778
|
+
}
|
|
9779
|
+
}
|
|
9780
|
+
const callback = await handle.waitForCode();
|
|
9781
|
+
const tokenResponse = await fetchImpl(TOKEN_URL, {
|
|
9782
|
+
method: "POST",
|
|
9783
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
9784
|
+
body: new URLSearchParams({
|
|
9785
|
+
client_id: CLIENT_ID,
|
|
9786
|
+
client_secret: CLIENT_SECRET,
|
|
9787
|
+
code: callback.code,
|
|
9788
|
+
grant_type: "authorization_code",
|
|
9789
|
+
redirect_uri: redirectUri
|
|
9790
|
+
})
|
|
9791
|
+
});
|
|
9792
|
+
if (!tokenResponse.ok) {
|
|
9793
|
+
const body = await tokenResponse.text();
|
|
9794
|
+
throw new Error(`Antigravity token exchange failed: ${body}`);
|
|
9795
|
+
}
|
|
9796
|
+
const tokenData = await tokenResponse.json();
|
|
9797
|
+
if (!tokenData.refresh_token) {
|
|
9798
|
+
throw new Error("No refresh token received. Please try again.");
|
|
9799
|
+
}
|
|
9800
|
+
const email = await getUserEmail(fetchImpl, tokenData.access_token);
|
|
9801
|
+
const projectId = await discoverProject(
|
|
9802
|
+
fetchImpl,
|
|
9803
|
+
tokenData.access_token,
|
|
9804
|
+
(message) => output2.log(message)
|
|
9805
|
+
);
|
|
9806
|
+
const now = (deps.now ?? Date.now)();
|
|
9807
|
+
return {
|
|
9808
|
+
provider: "antigravity",
|
|
9809
|
+
accessToken: tokenData.access_token,
|
|
9810
|
+
refreshToken: tokenData.refresh_token,
|
|
9811
|
+
expiresAt: now + tokenData.expires_in * 1e3 - ACCESS_TOKEN_CLIENT_SKEW_MS2,
|
|
9812
|
+
scope: tokenData.scope,
|
|
9813
|
+
obtainedAt: now,
|
|
9814
|
+
metadata: {
|
|
9815
|
+
projectId,
|
|
9816
|
+
email
|
|
9817
|
+
}
|
|
9818
|
+
};
|
|
9819
|
+
} finally {
|
|
9820
|
+
await handle.close();
|
|
9821
|
+
}
|
|
9822
|
+
}
|
|
9823
|
+
async function refreshAntigravityOAuthToken(credential) {
|
|
9824
|
+
if (!credential.refreshToken) {
|
|
9825
|
+
throw new Error("Antigravity credential has no refresh_token");
|
|
9826
|
+
}
|
|
9827
|
+
const fetchImpl = fetch;
|
|
9828
|
+
const projectId = credential.metadata?.projectId ?? void 0;
|
|
9829
|
+
const response = await fetchImpl(TOKEN_URL, {
|
|
9830
|
+
method: "POST",
|
|
9831
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
9832
|
+
body: new URLSearchParams({
|
|
9833
|
+
client_id: CLIENT_ID,
|
|
9834
|
+
client_secret: CLIENT_SECRET,
|
|
9835
|
+
refresh_token: credential.refreshToken,
|
|
9836
|
+
grant_type: "refresh_token"
|
|
9837
|
+
})
|
|
9838
|
+
});
|
|
9839
|
+
if (!response.ok) {
|
|
9840
|
+
const body = await response.text();
|
|
9841
|
+
throw new Error(`Antigravity token refresh failed: ${body}`);
|
|
9842
|
+
}
|
|
9843
|
+
const data = await response.json();
|
|
9844
|
+
const now = Date.now();
|
|
9845
|
+
return {
|
|
9846
|
+
...credential,
|
|
9847
|
+
accessToken: data.access_token,
|
|
9848
|
+
refreshToken: data.refresh_token || credential.refreshToken,
|
|
9849
|
+
expiresAt: now + data.expires_in * 1e3 - ACCESS_TOKEN_CLIENT_SKEW_MS2,
|
|
9850
|
+
scope: data.scope ?? credential.scope,
|
|
9851
|
+
obtainedAt: now
|
|
9852
|
+
};
|
|
9853
|
+
}
|
|
9854
|
+
var decode, CLIENT_ID, CLIENT_SECRET, CALLBACK_PORT, CALLBACK_PATH, SCOPES, AUTH_URL, TOKEN_URL, USERINFO_URL, CLOUD_CODE_ENDPOINT, TIER_LEGACY, PROJECT_ONBOARD_MAX_ATTEMPTS, PROJECT_ONBOARD_INTERVAL_MS, ACCESS_TOKEN_CLIENT_SKEW_MS2, ANTIGRAVITY_LOAD_CODE_ASSIST_METADATA;
|
|
9855
|
+
var init_antigravity = __esm({
|
|
9856
|
+
"packages/cli/oauth/flows/antigravity.ts"() {
|
|
9857
|
+
"use strict";
|
|
9858
|
+
init_callback_server();
|
|
9859
|
+
init_pkce();
|
|
9860
|
+
init_token_store();
|
|
9861
|
+
decode = (s) => Buffer.from(s, "base64").toString("utf8");
|
|
9862
|
+
CLIENT_ID = decode(
|
|
9863
|
+
"MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ=="
|
|
9864
|
+
);
|
|
9865
|
+
CLIENT_SECRET = decode("R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY=");
|
|
9866
|
+
CALLBACK_PORT = 51121;
|
|
9867
|
+
CALLBACK_PATH = "/oauth-callback";
|
|
9868
|
+
SCOPES = [
|
|
9869
|
+
"https://www.googleapis.com/auth/cloud-platform",
|
|
9870
|
+
"https://www.googleapis.com/auth/userinfo.email",
|
|
9871
|
+
"https://www.googleapis.com/auth/userinfo.profile",
|
|
9872
|
+
"https://www.googleapis.com/auth/cclog",
|
|
9873
|
+
"https://www.googleapis.com/auth/experimentsandconfigs"
|
|
9874
|
+
];
|
|
9875
|
+
AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
9876
|
+
TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
9877
|
+
USERINFO_URL = "https://www.googleapis.com/oauth2/v1/userinfo?alt=json";
|
|
9878
|
+
CLOUD_CODE_ENDPOINT = "https://cloudcode-pa.googleapis.com";
|
|
9879
|
+
TIER_LEGACY = "legacy-tier";
|
|
9880
|
+
PROJECT_ONBOARD_MAX_ATTEMPTS = 5;
|
|
9881
|
+
PROJECT_ONBOARD_INTERVAL_MS = 2e3;
|
|
9882
|
+
ACCESS_TOKEN_CLIENT_SKEW_MS2 = 5 * 60 * 1e3;
|
|
9883
|
+
ANTIGRAVITY_LOAD_CODE_ASSIST_METADATA = Object.freeze({
|
|
9884
|
+
ideType: "ANTIGRAVITY",
|
|
9885
|
+
platform: "PLATFORM_UNSPECIFIED",
|
|
9886
|
+
pluginType: "GEMINI"
|
|
9887
|
+
});
|
|
9888
|
+
}
|
|
9889
|
+
});
|
|
9890
|
+
|
|
9248
9891
|
// packages/cli/oauth/flows/openai-codex.ts
|
|
9249
9892
|
import { createHash as createHash2 } from "node:crypto";
|
|
9250
9893
|
async function postJson(fetchImpl, url, body, deps) {
|
|
@@ -9597,6 +10240,265 @@ var init_openai_codex = __esm({
|
|
|
9597
10240
|
}
|
|
9598
10241
|
});
|
|
9599
10242
|
|
|
10243
|
+
// packages/cli/oauth/flows/xai.ts
|
|
10244
|
+
function validateXAIEndpoint(url, field) {
|
|
10245
|
+
let parsed;
|
|
10246
|
+
try {
|
|
10247
|
+
parsed = new URL(url);
|
|
10248
|
+
} catch {
|
|
10249
|
+
throw new Error(`Invalid xAI ${field}: ${url}`);
|
|
10250
|
+
}
|
|
10251
|
+
if (parsed.protocol !== "https:") {
|
|
10252
|
+
throw new Error(`Invalid xAI ${field}: ${url}`);
|
|
10253
|
+
}
|
|
10254
|
+
const host = parsed.hostname.toLowerCase();
|
|
10255
|
+
if (!host || host !== "x.ai" && !host.endsWith(".x.ai")) {
|
|
10256
|
+
throw new Error(`Invalid xAI ${field}: ${url}`);
|
|
10257
|
+
}
|
|
10258
|
+
return url;
|
|
10259
|
+
}
|
|
10260
|
+
async function xaiOAuthDiscovery(fetchImpl, timeoutMs = DISCOVERY_TIMEOUT_MS) {
|
|
10261
|
+
let response;
|
|
10262
|
+
try {
|
|
10263
|
+
response = await fetchImpl(XAI_OAUTH_DISCOVERY_URL, {
|
|
10264
|
+
method: "GET",
|
|
10265
|
+
headers: { Accept: "application/json" },
|
|
10266
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
10267
|
+
});
|
|
10268
|
+
} catch (error) {
|
|
10269
|
+
throw new Error(
|
|
10270
|
+
`xAI OIDC discovery failed: ${error instanceof Error ? error.message : String(error)}`
|
|
10271
|
+
);
|
|
10272
|
+
}
|
|
10273
|
+
if (response.status !== 200) {
|
|
10274
|
+
throw new Error(`xAI OIDC discovery returned status ${response.status}.`);
|
|
10275
|
+
}
|
|
10276
|
+
let payload;
|
|
10277
|
+
try {
|
|
10278
|
+
payload = await response.json();
|
|
10279
|
+
} catch (error) {
|
|
10280
|
+
throw new Error(
|
|
10281
|
+
`xAI OIDC discovery returned invalid JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
10282
|
+
);
|
|
10283
|
+
}
|
|
10284
|
+
if (!payload || typeof payload !== "object") {
|
|
10285
|
+
throw new Error("xAI OIDC discovery response was not a JSON object.");
|
|
10286
|
+
}
|
|
10287
|
+
const obj = payload;
|
|
10288
|
+
const authorizationEndpoint = typeof obj.authorization_endpoint === "string" ? obj.authorization_endpoint.trim() : "";
|
|
10289
|
+
const tokenEndpoint = typeof obj.token_endpoint === "string" ? obj.token_endpoint.trim() : "";
|
|
10290
|
+
if (!authorizationEndpoint || !tokenEndpoint) {
|
|
10291
|
+
throw new Error("xAI OIDC discovery response was missing required endpoints.");
|
|
10292
|
+
}
|
|
10293
|
+
validateXAIEndpoint(authorizationEndpoint, "authorization_endpoint");
|
|
10294
|
+
validateXAIEndpoint(tokenEndpoint, "token_endpoint");
|
|
10295
|
+
return {
|
|
10296
|
+
authorization_endpoint: authorizationEndpoint,
|
|
10297
|
+
token_endpoint: tokenEndpoint
|
|
10298
|
+
};
|
|
10299
|
+
}
|
|
10300
|
+
function buildXAIAuthorizeUrl(opts) {
|
|
10301
|
+
const params = new URLSearchParams({
|
|
10302
|
+
response_type: "code",
|
|
10303
|
+
client_id: XAI_OAUTH_CLIENT_ID,
|
|
10304
|
+
redirect_uri: opts.redirectUri,
|
|
10305
|
+
scope: XAI_OAUTH_SCOPE,
|
|
10306
|
+
code_challenge: opts.codeChallenge,
|
|
10307
|
+
code_challenge_method: "S256",
|
|
10308
|
+
state: opts.state,
|
|
10309
|
+
nonce: opts.nonce,
|
|
10310
|
+
plan: "generic",
|
|
10311
|
+
referrer: "nolo-cli"
|
|
10312
|
+
});
|
|
10313
|
+
return `${opts.authorizationEndpoint}?${params.toString()}`;
|
|
10314
|
+
}
|
|
10315
|
+
function generateState3() {
|
|
10316
|
+
const bytes = new Uint8Array(16);
|
|
10317
|
+
crypto.getRandomValues(bytes);
|
|
10318
|
+
return Array.from(bytes).map((value) => value.toString(16).padStart(2, "0")).join("");
|
|
10319
|
+
}
|
|
10320
|
+
async function exchangeXAIToken(fetchImpl, code, redirectUri, verifier) {
|
|
10321
|
+
const discovery = await xaiOAuthDiscovery(fetchImpl);
|
|
10322
|
+
const tokenEndpoint = validateXAIEndpoint(discovery.token_endpoint, "token_endpoint");
|
|
10323
|
+
const body = new URLSearchParams({
|
|
10324
|
+
grant_type: "authorization_code",
|
|
10325
|
+
client_id: XAI_OAUTH_CLIENT_ID,
|
|
10326
|
+
code,
|
|
10327
|
+
redirect_uri: redirectUri,
|
|
10328
|
+
code_verifier: verifier
|
|
10329
|
+
});
|
|
10330
|
+
const response = await fetchImpl(tokenEndpoint, {
|
|
10331
|
+
method: "POST",
|
|
10332
|
+
headers: {
|
|
10333
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
10334
|
+
Accept: "application/json"
|
|
10335
|
+
},
|
|
10336
|
+
body,
|
|
10337
|
+
signal: AbortSignal.timeout(TOKEN_REQUEST_TIMEOUT_MS2)
|
|
10338
|
+
});
|
|
10339
|
+
if (!response.ok) {
|
|
10340
|
+
let detail = "";
|
|
10341
|
+
try {
|
|
10342
|
+
detail = (await response.text()).trim();
|
|
10343
|
+
} catch {
|
|
10344
|
+
}
|
|
10345
|
+
throw new Error(
|
|
10346
|
+
`xAI token exchange failed: ${response.status}${detail ? ` ${detail}` : ""}`
|
|
10347
|
+
);
|
|
10348
|
+
}
|
|
10349
|
+
const data = await response.json();
|
|
10350
|
+
if (typeof data.access_token !== "string" || !data.access_token) {
|
|
10351
|
+
throw new Error("xAI token exchange response missing access_token");
|
|
10352
|
+
}
|
|
10353
|
+
if (typeof data.refresh_token !== "string" || !data.refresh_token) {
|
|
10354
|
+
throw new Error("xAI token exchange response missing refresh_token");
|
|
10355
|
+
}
|
|
10356
|
+
if (typeof data.expires_in !== "number" || !Number.isFinite(data.expires_in)) {
|
|
10357
|
+
throw new Error("xAI token exchange response missing expires_in");
|
|
10358
|
+
}
|
|
10359
|
+
return {
|
|
10360
|
+
accessToken: data.access_token,
|
|
10361
|
+
refreshToken: data.refresh_token,
|
|
10362
|
+
expiresIn: data.expires_in,
|
|
10363
|
+
scope: typeof data.scope === "string" ? data.scope : void 0,
|
|
10364
|
+
idToken: typeof data.id_token === "string" ? data.id_token : void 0
|
|
10365
|
+
};
|
|
10366
|
+
}
|
|
10367
|
+
async function runXaiOAuthLogin(deps = {}) {
|
|
10368
|
+
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
10369
|
+
const output2 = deps.output ?? console;
|
|
10370
|
+
const error = deps.error ?? console;
|
|
10371
|
+
const redirectUri = `http://${XAI_OAUTH_REDIRECT_HOST}:${XAI_OAUTH_REDIRECT_PORT}${XAI_OAUTH_REDIRECT_PATH}`;
|
|
10372
|
+
let handle;
|
|
10373
|
+
try {
|
|
10374
|
+
handle = await startCallbackServer({
|
|
10375
|
+
port: XAI_OAUTH_REDIRECT_PORT,
|
|
10376
|
+
hostname: XAI_OAUTH_REDIRECT_HOST,
|
|
10377
|
+
timeoutMs: 5 * 6e4
|
|
10378
|
+
});
|
|
10379
|
+
} catch (err) {
|
|
10380
|
+
throw new Error(
|
|
10381
|
+
`Failed to start xAI OAuth callback server on ${XAI_OAUTH_REDIRECT_PORT}: ${err instanceof Error ? err.message : String(err)}`
|
|
10382
|
+
);
|
|
10383
|
+
}
|
|
10384
|
+
try {
|
|
10385
|
+
const state = generateState3();
|
|
10386
|
+
const pkce = await generatePkcePair();
|
|
10387
|
+
const nonce = crypto.randomUUID().replace(/-/g, "");
|
|
10388
|
+
const discovery = await xaiOAuthDiscovery(fetchImpl);
|
|
10389
|
+
const authUrl = buildXAIAuthorizeUrl({
|
|
10390
|
+
authorizationEndpoint: discovery.authorization_endpoint,
|
|
10391
|
+
redirectUri,
|
|
10392
|
+
codeChallenge: pkce.challenge,
|
|
10393
|
+
state,
|
|
10394
|
+
nonce
|
|
10395
|
+
});
|
|
10396
|
+
output2.log(
|
|
10397
|
+
`Open the following URL in your browser to log in to xAI Grok (SuperGrok):
|
|
10398
|
+
${authUrl}
|
|
10399
|
+
|
|
10400
|
+
Docs: ${XAI_OAUTH_DOCS_URL}`
|
|
10401
|
+
);
|
|
10402
|
+
if (deps.openBrowser) {
|
|
10403
|
+
try {
|
|
10404
|
+
await deps.openBrowser(authUrl);
|
|
10405
|
+
} catch (err) {
|
|
10406
|
+
error.error(
|
|
10407
|
+
`Failed to open browser automatically: ${err instanceof Error ? err.message : String(err)}`
|
|
10408
|
+
);
|
|
10409
|
+
}
|
|
10410
|
+
}
|
|
10411
|
+
const callback = await handle.waitForCode();
|
|
10412
|
+
const token = await exchangeXAIToken(
|
|
10413
|
+
fetchImpl,
|
|
10414
|
+
callback.code,
|
|
10415
|
+
redirectUri,
|
|
10416
|
+
pkce.verifier
|
|
10417
|
+
);
|
|
10418
|
+
const now = (deps.now ?? Date.now)();
|
|
10419
|
+
const expiresIn = token.expiresIn;
|
|
10420
|
+
return {
|
|
10421
|
+
provider: "xai",
|
|
10422
|
+
accessToken: token.accessToken,
|
|
10423
|
+
refreshToken: token.refreshToken,
|
|
10424
|
+
expiresAt: now + expiresIn * 1e3 - ACCESS_TOKEN_CLIENT_SKEW_MS3,
|
|
10425
|
+
scope: token.scope,
|
|
10426
|
+
idToken: token.idToken,
|
|
10427
|
+
obtainedAt: now
|
|
10428
|
+
};
|
|
10429
|
+
} finally {
|
|
10430
|
+
await handle.close();
|
|
10431
|
+
}
|
|
10432
|
+
}
|
|
10433
|
+
async function refreshXaiOAuthToken(credential) {
|
|
10434
|
+
if (!credential.refreshToken) {
|
|
10435
|
+
throw new Error("xAI credential has no refresh_token");
|
|
10436
|
+
}
|
|
10437
|
+
const fetchImpl = fetch;
|
|
10438
|
+
const discovery = await xaiOAuthDiscovery(fetchImpl);
|
|
10439
|
+
const tokenEndpoint = validateXAIEndpoint(discovery.token_endpoint, "token_endpoint");
|
|
10440
|
+
const body = new URLSearchParams({
|
|
10441
|
+
grant_type: "refresh_token",
|
|
10442
|
+
client_id: XAI_OAUTH_CLIENT_ID,
|
|
10443
|
+
refresh_token: credential.refreshToken
|
|
10444
|
+
});
|
|
10445
|
+
const response = await fetchImpl(tokenEndpoint, {
|
|
10446
|
+
method: "POST",
|
|
10447
|
+
headers: {
|
|
10448
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
10449
|
+
Accept: "application/json"
|
|
10450
|
+
},
|
|
10451
|
+
body,
|
|
10452
|
+
signal: AbortSignal.timeout(TOKEN_REQUEST_TIMEOUT_MS2)
|
|
10453
|
+
});
|
|
10454
|
+
if (!response.ok) {
|
|
10455
|
+
let detail = "";
|
|
10456
|
+
try {
|
|
10457
|
+
detail = (await response.text()).trim();
|
|
10458
|
+
} catch {
|
|
10459
|
+
}
|
|
10460
|
+
throw new Error(
|
|
10461
|
+
`xAI token refresh failed: ${response.status}${detail ? ` ${detail}` : ""}`
|
|
10462
|
+
);
|
|
10463
|
+
}
|
|
10464
|
+
const data = await response.json();
|
|
10465
|
+
if (typeof data.access_token !== "string" || !data.access_token) {
|
|
10466
|
+
throw new Error("xAI token refresh response missing access_token");
|
|
10467
|
+
}
|
|
10468
|
+
if (typeof data.expires_in !== "number" || !Number.isFinite(data.expires_in)) {
|
|
10469
|
+
throw new Error("xAI token refresh response missing expires_in");
|
|
10470
|
+
}
|
|
10471
|
+
const newRefresh = typeof data.refresh_token === "string" && data.refresh_token ? data.refresh_token : credential.refreshToken;
|
|
10472
|
+
const now = Date.now();
|
|
10473
|
+
return {
|
|
10474
|
+
...credential,
|
|
10475
|
+
accessToken: data.access_token,
|
|
10476
|
+
refreshToken: newRefresh,
|
|
10477
|
+
expiresAt: now + data.expires_in * 1e3 - ACCESS_TOKEN_CLIENT_SKEW_MS3,
|
|
10478
|
+
obtainedAt: now
|
|
10479
|
+
};
|
|
10480
|
+
}
|
|
10481
|
+
var XAI_OAUTH_ISSUER, XAI_OAUTH_DISCOVERY_URL, XAI_OAUTH_CLIENT_ID, XAI_OAUTH_SCOPE, XAI_OAUTH_REDIRECT_HOST, XAI_OAUTH_REDIRECT_PORT, XAI_OAUTH_REDIRECT_PATH, XAI_OAUTH_DOCS_URL, ACCESS_TOKEN_CLIENT_SKEW_MS3, DISCOVERY_TIMEOUT_MS, TOKEN_REQUEST_TIMEOUT_MS2;
|
|
10482
|
+
var init_xai = __esm({
|
|
10483
|
+
"packages/cli/oauth/flows/xai.ts"() {
|
|
10484
|
+
"use strict";
|
|
10485
|
+
init_callback_server();
|
|
10486
|
+
init_pkce();
|
|
10487
|
+
init_token_store();
|
|
10488
|
+
XAI_OAUTH_ISSUER = "https://auth.x.ai";
|
|
10489
|
+
XAI_OAUTH_DISCOVERY_URL = `${XAI_OAUTH_ISSUER}/.well-known/openid-configuration`;
|
|
10490
|
+
XAI_OAUTH_CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828";
|
|
10491
|
+
XAI_OAUTH_SCOPE = "openid profile email offline_access grok-cli:access api:access";
|
|
10492
|
+
XAI_OAUTH_REDIRECT_HOST = "127.0.0.1";
|
|
10493
|
+
XAI_OAUTH_REDIRECT_PORT = 56121;
|
|
10494
|
+
XAI_OAUTH_REDIRECT_PATH = "/callback";
|
|
10495
|
+
XAI_OAUTH_DOCS_URL = "https://hermes-agent.nousresearch.com/docs/guides/xai-grok-oauth";
|
|
10496
|
+
ACCESS_TOKEN_CLIENT_SKEW_MS3 = 5 * 60 * 1e3;
|
|
10497
|
+
DISCOVERY_TIMEOUT_MS = 15e3;
|
|
10498
|
+
TOKEN_REQUEST_TIMEOUT_MS2 = 2e4;
|
|
10499
|
+
}
|
|
10500
|
+
});
|
|
10501
|
+
|
|
9600
10502
|
// packages/cli/oauth/apiKeyRefResolver.ts
|
|
9601
10503
|
function isOAuthProvider(value) {
|
|
9602
10504
|
return value === "chatgpt" || value === "xai" || value === "antigravity";
|
|
@@ -9606,11 +10508,20 @@ function createOAuthApiKeyRefResolver(options = {}) {
|
|
|
9606
10508
|
const provider = ref.trim();
|
|
9607
10509
|
if (!isOAuthProvider(provider)) return null;
|
|
9608
10510
|
const refresh = REFRESH_BY_PROVIDER[provider];
|
|
9609
|
-
|
|
10511
|
+
const token = await resolveFreshAccessToken({
|
|
9610
10512
|
provider,
|
|
9611
10513
|
...options.homeDir ? { homeDir: options.homeDir } : {},
|
|
9612
10514
|
...refresh ? { refresh } : {}
|
|
9613
10515
|
});
|
|
10516
|
+
if (token) return token;
|
|
10517
|
+
const store = createOAuthTokenStore(options.homeDir);
|
|
10518
|
+
const credential = store.read(provider);
|
|
10519
|
+
if (credential && isTokenExpired(credential)) {
|
|
10520
|
+
throw new Error(
|
|
10521
|
+
`OAuth credential for "${provider}" is expired and could not be refreshed. Run \`nolo auth ${provider}\` (or \`nolo auth ${provider} --sync-to-server\` for server-side runs).`
|
|
10522
|
+
);
|
|
10523
|
+
}
|
|
10524
|
+
return null;
|
|
9614
10525
|
};
|
|
9615
10526
|
}
|
|
9616
10527
|
var REFRESH_BY_PROVIDER;
|
|
@@ -9618,9 +10529,16 @@ var init_apiKeyRefResolver = __esm({
|
|
|
9618
10529
|
"packages/cli/oauth/apiKeyRefResolver.ts"() {
|
|
9619
10530
|
"use strict";
|
|
9620
10531
|
init_token_store();
|
|
10532
|
+
init_antigravity();
|
|
9621
10533
|
init_openai_codex();
|
|
10534
|
+
init_xai();
|
|
9622
10535
|
REFRESH_BY_PROVIDER = {
|
|
9623
|
-
chatgpt: refreshOpenAiCodexToken
|
|
10536
|
+
chatgpt: refreshOpenAiCodexToken,
|
|
10537
|
+
// Previously only chatgpt was wired; expired antigravity/xai tokens then
|
|
10538
|
+
// surfaced as "OAuth credential not found" even when ~/.nolo/credentials
|
|
10539
|
+
// still held a valid refresh_token.
|
|
10540
|
+
antigravity: refreshAntigravityOAuthToken,
|
|
10541
|
+
xai: refreshXaiOAuthToken
|
|
9624
10542
|
};
|
|
9625
10543
|
}
|
|
9626
10544
|
});
|
|
@@ -19152,13 +20070,13 @@ var init_env = __esm({
|
|
|
19152
20070
|
});
|
|
19153
20071
|
|
|
19154
20072
|
// packages/app/utils/retryFetch.ts
|
|
19155
|
-
var TRANSIENT_READ_RETRY_STATUSES, DEFAULT_RETRY_DELAYS_MS,
|
|
20073
|
+
var TRANSIENT_READ_RETRY_STATUSES, DEFAULT_RETRY_DELAYS_MS, sleep3, getRequestMethod, isRetryableReadMethod, isAbortError, fetchWithTransientReadRetry;
|
|
19156
20074
|
var init_retryFetch = __esm({
|
|
19157
20075
|
"packages/app/utils/retryFetch.ts"() {
|
|
19158
20076
|
"use strict";
|
|
19159
20077
|
TRANSIENT_READ_RETRY_STATUSES = /* @__PURE__ */ new Set([502, 503, 504]);
|
|
19160
20078
|
DEFAULT_RETRY_DELAYS_MS = [300, 1e3];
|
|
19161
|
-
|
|
20079
|
+
sleep3 = (ms) => new Promise((resolve8) => {
|
|
19162
20080
|
setTimeout(resolve8, ms);
|
|
19163
20081
|
});
|
|
19164
20082
|
getRequestMethod = (input2, init) => {
|
|
@@ -19176,7 +20094,7 @@ var init_retryFetch = __esm({
|
|
|
19176
20094
|
const delaysMs = options.delaysMs ?? DEFAULT_RETRY_DELAYS_MS;
|
|
19177
20095
|
const retryStatuses = options.retryStatuses ?? TRANSIENT_READ_RETRY_STATUSES;
|
|
19178
20096
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
19179
|
-
const wait = options.sleep ??
|
|
20097
|
+
const wait = options.sleep ?? sleep3;
|
|
19180
20098
|
for (let attempt = 0; ; attempt += 1) {
|
|
19181
20099
|
try {
|
|
19182
20100
|
const response = await fetchImpl(input2, init);
|
|
@@ -25122,12 +26040,12 @@ function dataURLtoFile(dataUrl, filename) {
|
|
|
25122
26040
|
return null;
|
|
25123
26041
|
}
|
|
25124
26042
|
}
|
|
25125
|
-
var BYTES_PER_MB,
|
|
26043
|
+
var BYTES_PER_MB, sleep4, parseDataUrl, appendNoCacheQuery, tryLoadImage, waitForFileReady;
|
|
25126
26044
|
var init_imageUtils = __esm({
|
|
25127
26045
|
"packages/app/utils/imageUtils.ts"() {
|
|
25128
26046
|
"use strict";
|
|
25129
26047
|
BYTES_PER_MB = 1024 * 1024;
|
|
25130
|
-
|
|
26048
|
+
sleep4 = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
25131
26049
|
parseDataUrl = (dataUrl) => {
|
|
25132
26050
|
const trimmed = dataUrl.trim();
|
|
25133
26051
|
const parts = trimmed.split(",");
|
|
@@ -25180,7 +26098,7 @@ var init_imageUtils = __esm({
|
|
|
25180
26098
|
console.debug("[imageUtils] waitForFileReady: image loaded for", url);
|
|
25181
26099
|
return true;
|
|
25182
26100
|
}
|
|
25183
|
-
await
|
|
26101
|
+
await sleep4(intervalMs);
|
|
25184
26102
|
}
|
|
25185
26103
|
console.warn("[imageUtils] waitForFileReady: timeout for", url);
|
|
25186
26104
|
return false;
|
|
@@ -40795,24 +41713,6 @@ var init_generateResponseRequestBody = __esm({
|
|
|
40795
41713
|
}
|
|
40796
41714
|
});
|
|
40797
41715
|
|
|
40798
|
-
// packages/agent-runtime/antigravityOAuth.ts
|
|
40799
|
-
function isAntigravityOAuthAgent(agentConfig) {
|
|
40800
|
-
if (!agentConfig) return false;
|
|
40801
|
-
const apiKeyRef = (agentConfig.apiKeyRef ?? "").trim().toLowerCase();
|
|
40802
|
-
const provider = String(agentConfig.provider ?? "").trim().toLowerCase();
|
|
40803
|
-
const url = (agentConfig.customProviderUrl ?? "").trim().toLowerCase();
|
|
40804
|
-
return apiKeyRef === "antigravity" || provider === "google-antigravity" || url.includes(ANTIGRAVITY_CLOUD_CODE_HOST);
|
|
40805
|
-
}
|
|
40806
|
-
var ANTIGRAVITY_CLOUD_CODE_BASE_URL, ANTIGRAVITY_CLOUD_CODE_HOST;
|
|
40807
|
-
var init_antigravityOAuth = __esm({
|
|
40808
|
-
"packages/agent-runtime/antigravityOAuth.ts"() {
|
|
40809
|
-
"use strict";
|
|
40810
|
-
init_providerResolution();
|
|
40811
|
-
ANTIGRAVITY_CLOUD_CODE_BASE_URL = "https://daily-cloudcode-pa.googleapis.com";
|
|
40812
|
-
ANTIGRAVITY_CLOUD_CODE_HOST = "cloudcode-pa.googleapis.com";
|
|
40813
|
-
}
|
|
40814
|
-
});
|
|
40815
|
-
|
|
40816
41716
|
// packages/agent-runtime/agentCallPlan.ts
|
|
40817
41717
|
function resolveClientWire(plan) {
|
|
40818
41718
|
if (plan.upstreamWire === "gemini-cca") return "chat.completions";
|
|
@@ -51769,7 +52669,7 @@ ${emailPreview(match)}
|
|
|
51769
52669
|
${emailText(match).slice(0, 4e3)}`
|
|
51770
52670
|
};
|
|
51771
52671
|
}
|
|
51772
|
-
await
|
|
52672
|
+
await sleep5(pollIntervalMs);
|
|
51773
52673
|
}
|
|
51774
52674
|
throw new Error(`\u7B49\u5F85\u90AE\u4EF6\u8D85\u65F6\uFF1A${Math.ceil(timeoutMs / 1e3)} \u79D2\u5185\u6CA1\u6709\u5339\u914D\u90AE\u4EF6`);
|
|
51775
52675
|
}
|
|
@@ -51828,7 +52728,7 @@ async function emailArchiveFunc(args2, thunkApi) {
|
|
|
51828
52728
|
displayData: `\u5DF2\u5F52\u6863\u90AE\u4EF6\uFF1A${email?.subject || email?.dbKey}`
|
|
51829
52729
|
};
|
|
51830
52730
|
}
|
|
51831
|
-
var emailPreview,
|
|
52731
|
+
var emailPreview, sleep5, normalizeContains, clampNumber, participantList, emailText, matchesWaitFilters, stripHtml, cleanUrl, extractEmailVerificationArtifacts, emailSearchFunctionSchema, emailReadFunctionSchema, emailUpdateTagsFunctionSchema, emailArchiveFunctionSchema, emailProvisionIdentityFunctionSchema, emailSendFunctionSchema, emailWaitForFunctionSchema, emailExtractVerificationFunctionSchema;
|
|
51832
52732
|
var init_emailTools = __esm({
|
|
51833
52733
|
"packages/ai/tools/emailTools.ts"() {
|
|
51834
52734
|
"use strict";
|
|
@@ -51839,7 +52739,7 @@ var init_emailTools = __esm({
|
|
|
51839
52739
|
const tags = Array.isArray(email?.tags) && email.tags.length > 0 ? ` #${email.tags.join(" #")}` : "";
|
|
51840
52740
|
return `- ${subject} | from: ${from} | ${email?.mailbox ?? "mailbox?"}${tags} | ${email?.dbKey ?? ""}`;
|
|
51841
52741
|
};
|
|
51842
|
-
|
|
52742
|
+
sleep5 = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
51843
52743
|
normalizeContains = (value) => typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
51844
52744
|
clampNumber = (value, fallback, min, max) => {
|
|
51845
52745
|
const parsed = Number(value);
|
|
@@ -61131,7 +62031,7 @@ async function pollAppDeployJob(thunkApi, args2, toolRunId, jobId, options) {
|
|
|
61131
62031
|
);
|
|
61132
62032
|
throw repairError;
|
|
61133
62033
|
}
|
|
61134
|
-
await
|
|
62034
|
+
await sleep6(Math.min(400 + attempt * 50, 2e3));
|
|
61135
62035
|
}
|
|
61136
62036
|
throw new Error("\u90E8\u7F72\u4EFB\u52A1\u4ECD\u5728\u670D\u52A1\u7AEF\u6267\u884C\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u67E5\u770B\u7ED3\u679C\u3002");
|
|
61137
62037
|
} finally {
|
|
@@ -61727,7 +62627,7 @@ async function appFileReplaceFunc(args2, thunkApi) {
|
|
|
61727
62627
|
\u4E0B\u4E00\u6B65\uFF1A\u5148 appPreflight\uFF0C\u518D appDeploy\u3002`
|
|
61728
62628
|
};
|
|
61729
62629
|
}
|
|
61730
|
-
var normalizeOptionalString, TOOL_STEP_STATUS_RANK, APP_DEPLOY_STEP_LABELS,
|
|
62630
|
+
var normalizeOptionalString, TOOL_STEP_STATUS_RANK, APP_DEPLOY_STEP_LABELS, sleep6, appDeployFunctionSchema, appPreflightFunctionSchema, appListFunctionSchema, appDeleteFunctionSchema, appReadFunctionSchema, appFileListFunctionSchema, appFileReadFunctionSchema, appFileSearchFunctionSchema, appFileWriteFunctionSchema, appFileReplaceFunctionSchema;
|
|
61731
62631
|
var init_appTools = __esm({
|
|
61732
62632
|
"packages/ai/tools/appTools.ts"() {
|
|
61733
62633
|
"use strict";
|
|
@@ -61757,7 +62657,7 @@ var init_appTools = __esm({
|
|
|
61757
62657
|
deploy: "\u53D1\u5E03\u7AD9\u70B9",
|
|
61758
62658
|
verify: "\u9A8C\u8BC1\u8BBF\u95EE"
|
|
61759
62659
|
};
|
|
61760
|
-
|
|
62660
|
+
sleep6 = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
61761
62661
|
appDeployFunctionSchema = {
|
|
61762
62662
|
name: "appDeploy",
|
|
61763
62663
|
description: "\u5C06 JavaScript/TypeScript \u4EE3\u7801\u90E8\u7F72\u4E3A Web \u5E94\u7528\u3002\u9ED8\u8BA4\u90E8\u7F72\u5230\u5E73\u53F0\u670D\u52A1\u5668\uFF08nolo.chat/apps/{appId}/\uFF09\uFF0C\u65E0\u9700\u7528\u6237\u914D\u7F6E\u4EFB\u4F55\u989D\u5916\u8D26\u53F7\uFF0C\u7ACB\u5373\u53EF\u8BBF\u95EE\u3002\u4EE3\u7801\u5FC5\u987B\u662F ES Module \u683C\u5F0F\uFF08export default { fetch(req) {} }\uFF09\u3002\u652F\u6301\u591A\u6587\u4EF6\u9879\u76EE\uFF1A\u901A\u8FC7 files \u6570\u7EC4\u4F20\u5165\uFF0C\u670D\u52A1\u7AEF\u81EA\u52A8\u6253\u5305\u3002\u65B0\u5EFA\u5E94\u7528\u65F6\u4F7F\u7528 name\uFF1B\u66F4\u65B0\u5DF2\u6709\u5E94\u7528\u65F6\u5FC5\u987B\u4F18\u5148\u4F20 appId\uFF0C\u907F\u514D\u56E0\u4E3A\u540D\u79F0\u91CD\u590D\u800C\u8BEF\u5EFA\u65B0\u5E94\u7528\u3002",
|
|
@@ -65380,7 +66280,7 @@ __export(cliExecutor_exports, {
|
|
|
65380
66280
|
startCliSession: () => startCliSession
|
|
65381
66281
|
});
|
|
65382
66282
|
import { exec, execSync, spawn as spawn3 } from "child_process";
|
|
65383
|
-
import { randomUUID } from "node:crypto";
|
|
66283
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
65384
66284
|
import { mkdtempSync, readFileSync as readFileSync5, rmSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
65385
66285
|
import { isAbsolute, join as join5, resolve as resolve3 } from "node:path";
|
|
65386
66286
|
import { tmpdir } from "node:os";
|
|
@@ -66530,7 +67430,7 @@ function startCliSession(provider, options = {}) {
|
|
|
66530
67430
|
if (!EXECUTORS[provider]) {
|
|
66531
67431
|
throw new Error(`Unknown CLI provider: "${provider}". Supported: ${Object.keys(EXECUTORS).join(", ")}`);
|
|
66532
67432
|
}
|
|
66533
|
-
const sessionId =
|
|
67433
|
+
const sessionId = randomUUID2();
|
|
66534
67434
|
cliSessions.set(sessionId, {
|
|
66535
67435
|
sessionId,
|
|
66536
67436
|
provider,
|
|
@@ -67846,6 +68746,92 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
67846
68746
|
};
|
|
67847
68747
|
}
|
|
67848
68748
|
const apiKeyRefResolver = createOAuthApiKeyRefResolver();
|
|
68749
|
+
if (isAntigravityOAuthAgent(agentConfig)) {
|
|
68750
|
+
const accessToken = await apiKeyRefResolver("antigravity");
|
|
68751
|
+
if (!accessToken) {
|
|
68752
|
+
throw new Error(
|
|
68753
|
+
'OAuth credential for "antigravity" not found locally. Run `nolo auth antigravity`.'
|
|
68754
|
+
);
|
|
68755
|
+
}
|
|
68756
|
+
const credential = readOAuthCredential("antigravity");
|
|
68757
|
+
const { requestedToolNames: requestedToolNames2, tools: tools2 } = resolveProviderOpenAiToolBundle(
|
|
68758
|
+
agentConfig,
|
|
68759
|
+
deps.env,
|
|
68760
|
+
buildProviderOpenAiTools
|
|
68761
|
+
);
|
|
68762
|
+
logLocalRuntimeDiagnostic("provider.selected", {
|
|
68763
|
+
agentKey: agentConfig.key,
|
|
68764
|
+
transport: "antigravity-cloud-code",
|
|
68765
|
+
apiSource: agentConfig.apiSource ?? null,
|
|
68766
|
+
provider: agentConfig.provider ?? "google-antigravity",
|
|
68767
|
+
model: agentConfig.model ?? null,
|
|
68768
|
+
customProviderEndpoint: summarizeEndpoint(agentConfig.customProviderUrl) ?? null,
|
|
68769
|
+
hasApiKey: true,
|
|
68770
|
+
hasProjectId: Boolean(credential?.metadata?.projectId)
|
|
68771
|
+
});
|
|
68772
|
+
return {
|
|
68773
|
+
model: agentConfig.model || "gemini-3.1-pro",
|
|
68774
|
+
complete: async (messages, options) => {
|
|
68775
|
+
const timeoutSignal = buildRequestTimeoutSignal(options?.timeoutMs);
|
|
68776
|
+
const openAiBody = {
|
|
68777
|
+
model: agentConfig.model || "gemini-3.1-pro",
|
|
68778
|
+
messages,
|
|
68779
|
+
stream: false,
|
|
68780
|
+
...tools2.length > 0 ? { tools: tools2 } : {}
|
|
68781
|
+
};
|
|
68782
|
+
logLocalRuntimeDiagnostic("provider.request.start", {
|
|
68783
|
+
agentKey: agentConfig.key,
|
|
68784
|
+
transport: "antigravity-cloud-code",
|
|
68785
|
+
model: openAiBody.model,
|
|
68786
|
+
messageCount: messages.length,
|
|
68787
|
+
toolCount: tools2.length,
|
|
68788
|
+
requestedToolNames: requestedToolNames2,
|
|
68789
|
+
openAiToolNames: summarizeOpenAiToolNames(tools2),
|
|
68790
|
+
timeoutMs: options?.timeoutMs ?? null
|
|
68791
|
+
});
|
|
68792
|
+
try {
|
|
68793
|
+
const result = await fetchAntigravityCloudCodeCompletion({
|
|
68794
|
+
agentConfig,
|
|
68795
|
+
accessToken,
|
|
68796
|
+
metadata: credential?.metadata ?? null,
|
|
68797
|
+
openAiBody,
|
|
68798
|
+
signal: timeoutSignal?.signal,
|
|
68799
|
+
fetchImpl: (url, init) => fetchWithTransientRetry(fetchImpl, url, init, {
|
|
68800
|
+
sleep: deps.sleep,
|
|
68801
|
+
loopbackRequest
|
|
68802
|
+
})
|
|
68803
|
+
});
|
|
68804
|
+
if (result.status < 200 || result.status >= 300) {
|
|
68805
|
+
const errMsg = result.body && typeof result.body === "object" && result.body.error && typeof result.body.error.message === "string" ? result.body.error.message : JSON.stringify(result.body);
|
|
68806
|
+
throw new Error(`local antigravity provider failed: HTTP ${result.status} ${errMsg}`);
|
|
68807
|
+
}
|
|
68808
|
+
const choice = Array.isArray(result.body.choices) ? result.body.choices[0] : void 0;
|
|
68809
|
+
const message = choice?.message ?? {};
|
|
68810
|
+
const content = typeof message.content === "string" ? message.content : message.content == null ? "" : String(message.content);
|
|
68811
|
+
const tool_calls = Array.isArray(message.tool_calls) ? message.tool_calls : void 0;
|
|
68812
|
+
if (content && options?.onTextDelta) {
|
|
68813
|
+
options.onTextDelta(content);
|
|
68814
|
+
}
|
|
68815
|
+
logLocalRuntimeDiagnostic("provider.request.result", {
|
|
68816
|
+
agentKey: agentConfig.key,
|
|
68817
|
+
transport: "antigravity-cloud-code",
|
|
68818
|
+
ok: true,
|
|
68819
|
+
contentChars: content.length,
|
|
68820
|
+
toolCallCount: tool_calls?.length ?? 0
|
|
68821
|
+
});
|
|
68822
|
+
return {
|
|
68823
|
+
content,
|
|
68824
|
+
model: agentConfig.model || "gemini-3.1-pro",
|
|
68825
|
+
provider: agentConfig.provider || "google-antigravity",
|
|
68826
|
+
...tool_calls ? { tool_calls } : {},
|
|
68827
|
+
trace: messages
|
|
68828
|
+
};
|
|
68829
|
+
} finally {
|
|
68830
|
+
timeoutSignal?.clear();
|
|
68831
|
+
}
|
|
68832
|
+
}
|
|
68833
|
+
};
|
|
68834
|
+
}
|
|
67849
68835
|
if (shouldUsePlatformChatProvider(deps.env, agentConfig)) {
|
|
67850
68836
|
const providerConfig2 = await resolvePlatformChatProviderConfig({
|
|
67851
68837
|
agentConfig,
|
|
@@ -68075,6 +69061,9 @@ var init_localRuntimeAdapter = __esm({
|
|
|
68075
69061
|
"packages/cli/client/localRuntimeAdapter.ts"() {
|
|
68076
69062
|
"use strict";
|
|
68077
69063
|
init_agentRuntimeLocal();
|
|
69064
|
+
init_antigravityCloudCodeProvider();
|
|
69065
|
+
init_antigravityOAuth();
|
|
69066
|
+
init_oauthTokenStore();
|
|
68078
69067
|
init_localRuntimeDb();
|
|
68079
69068
|
init_agentConfigResolver();
|
|
68080
69069
|
init_localProviderResolver();
|
|
@@ -69170,7 +70159,7 @@ __export(machineInfo_exports, {
|
|
|
69170
70159
|
import { existsSync as existsSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3 } from "node:fs";
|
|
69171
70160
|
import { dirname as dirname4, join as join8 } from "node:path";
|
|
69172
70161
|
import { arch as arch2, hostname as hostname2, homedir as homedir5, platform } from "node:os";
|
|
69173
|
-
import { randomUUID as
|
|
70162
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
69174
70163
|
function defaultMachineIdPath() {
|
|
69175
70164
|
return join8(homedir5(), ".nolo", "machine-id");
|
|
69176
70165
|
}
|
|
@@ -69180,7 +70169,7 @@ function resolveMachineId(path8 = defaultMachineIdPath()) {
|
|
|
69180
70169
|
const existing = readFileSync7(path8, "utf8").trim();
|
|
69181
70170
|
if (existing) return existing;
|
|
69182
70171
|
}
|
|
69183
|
-
const next = `machine-${
|
|
70172
|
+
const next = `machine-${randomUUID3()}`;
|
|
69184
70173
|
mkdirSync3(dirname4(path8), { recursive: true });
|
|
69185
70174
|
writeFileSync4(path8, `${next}
|
|
69186
70175
|
`, "utf8");
|
|
@@ -69576,22 +70565,22 @@ async function runHttpAgentTurn(options, authToken) {
|
|
|
69576
70565
|
options.output.write(`[nolo] Agent request failed: HTTP ${res.status}
|
|
69577
70566
|
`);
|
|
69578
70567
|
const errorText = typeof data?.error === "string" ? data.error.trim() : "";
|
|
69579
|
-
const
|
|
70568
|
+
const messageText2 = typeof data?.message === "string" ? data.message.trim() : "";
|
|
69580
70569
|
const reasonText = typeof data?.reason === "string" ? data.reason.trim() : "";
|
|
69581
70570
|
const codeText = typeof data?.code === "string" ? data.code.trim() : "";
|
|
69582
70571
|
const dialogIdText = typeof data?.dialogId === "string" ? data.dialogId.trim() : "";
|
|
69583
|
-
if (errorText ||
|
|
69584
|
-
options.output.write(`${errorText ||
|
|
70572
|
+
if (errorText || messageText2) {
|
|
70573
|
+
options.output.write(`${errorText || messageText2}
|
|
69585
70574
|
`);
|
|
69586
|
-
if (
|
|
69587
|
-
options.output.write(`${
|
|
70575
|
+
if (messageText2 && messageText2 !== errorText) {
|
|
70576
|
+
options.output.write(`${messageText2}
|
|
69588
70577
|
`);
|
|
69589
70578
|
}
|
|
69590
|
-
if (codeText && codeText !== errorText && codeText !==
|
|
70579
|
+
if (codeText && codeText !== errorText && codeText !== messageText2) {
|
|
69591
70580
|
options.output.write(`code=${codeText}
|
|
69592
70581
|
`);
|
|
69593
70582
|
}
|
|
69594
|
-
if (reasonText && reasonText !== errorText && reasonText !==
|
|
70583
|
+
if (reasonText && reasonText !== errorText && reasonText !== messageText2) {
|
|
69595
70584
|
options.output.write(`reason=${reasonText}
|
|
69596
70585
|
`);
|
|
69597
70586
|
}
|
|
@@ -70008,10 +70997,12 @@ ${this.text}
|
|
|
70008
70997
|
// packages/cli/agentRunControl.ts
|
|
70009
70998
|
var agentRunControl_exports = {};
|
|
70010
70999
|
__export(agentRunControl_exports, {
|
|
71000
|
+
checkStaleRun: () => checkStaleRun,
|
|
70011
71001
|
defaultGenerateRunId: () => defaultGenerateRunId,
|
|
70012
71002
|
finalizeRunRecord: () => finalizeRunRecord,
|
|
70013
71003
|
findRunRecord: () => findRunRecord,
|
|
70014
71004
|
findRunRecordByPid: () => findRunRecordByPid,
|
|
71005
|
+
isPidGone: () => isPidGone,
|
|
70015
71006
|
listRunRecords: () => listRunRecords,
|
|
70016
71007
|
readRunRecord: () => readRunRecord,
|
|
70017
71008
|
resolveNoloHome: () => resolveNoloHome2,
|
|
@@ -70054,7 +71045,7 @@ function defaultGenerateRunId() {
|
|
|
70054
71045
|
function writeRunRecord(record, deps = {}) {
|
|
70055
71046
|
const fs5 = deps.fs ?? nodeFs;
|
|
70056
71047
|
const path8 = resolveRunRecordPath(record.runId, deps.env, deps.homedir);
|
|
70057
|
-
fs5.mkdirSync(
|
|
71048
|
+
fs5.mkdirSync(resolveRunsDir(deps.env, deps.homedir), { recursive: true });
|
|
70058
71049
|
fs5.writeFileSync(path8, JSON.stringify(record, null, 2));
|
|
70059
71050
|
}
|
|
70060
71051
|
function readRunRecord(runId, deps = {}) {
|
|
@@ -70172,6 +71163,29 @@ function finalizeRunRecord(runId, update, deps = {}) {
|
|
|
70172
71163
|
record.endedAt = now().toISOString();
|
|
70173
71164
|
writeRunRecord(record, deps);
|
|
70174
71165
|
}
|
|
71166
|
+
function isPidGone(pid, deps = {}) {
|
|
71167
|
+
const kill = deps.kill ?? ((p, s) => process.kill(p, s));
|
|
71168
|
+
try {
|
|
71169
|
+
kill(pid, "0");
|
|
71170
|
+
return false;
|
|
71171
|
+
} catch (error) {
|
|
71172
|
+
const code = error.code;
|
|
71173
|
+
return code === "ESRCH";
|
|
71174
|
+
}
|
|
71175
|
+
}
|
|
71176
|
+
function checkStaleRun(runId, deps = {}) {
|
|
71177
|
+
const record = readRunRecord(runId, deps);
|
|
71178
|
+
if (!record) return null;
|
|
71179
|
+
if (record.status !== "running") return record;
|
|
71180
|
+
if (typeof record.pid !== "number") return record;
|
|
71181
|
+
if (!isPidGone(record.pid, deps)) return record;
|
|
71182
|
+
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
71183
|
+
record.status = "failed";
|
|
71184
|
+
record.note = "process gone: pid no longer exists";
|
|
71185
|
+
record.endedAt = now().toISOString();
|
|
71186
|
+
writeRunRecord(record, deps);
|
|
71187
|
+
return record;
|
|
71188
|
+
}
|
|
70175
71189
|
function formatDuration(startedAt, endedAt) {
|
|
70176
71190
|
const start = new Date(startedAt).getTime();
|
|
70177
71191
|
const end = endedAt ? new Date(endedAt).getTime() : Date.now();
|
|
@@ -70213,14 +71227,48 @@ function readLogContent(logPath, tailCount, deps) {
|
|
|
70213
71227
|
return "";
|
|
70214
71228
|
}
|
|
70215
71229
|
}
|
|
70216
|
-
|
|
71230
|
+
function isRunningStatus(status) {
|
|
71231
|
+
return RUNNING_STATUSES.has(status);
|
|
71232
|
+
}
|
|
71233
|
+
function parseJsonFlag(args2) {
|
|
71234
|
+
let json = false;
|
|
71235
|
+
const rest = [];
|
|
71236
|
+
for (const arg of args2) {
|
|
71237
|
+
if (arg === "--json") {
|
|
71238
|
+
json = true;
|
|
71239
|
+
continue;
|
|
71240
|
+
}
|
|
71241
|
+
if (arg.startsWith("--json=")) {
|
|
71242
|
+
const value = arg.slice("--json=".length);
|
|
71243
|
+
json = value === "" || value === "true" || value === "1";
|
|
71244
|
+
continue;
|
|
71245
|
+
}
|
|
71246
|
+
rest.push(arg);
|
|
71247
|
+
}
|
|
71248
|
+
return { json, rest };
|
|
71249
|
+
}
|
|
71250
|
+
function defaultSleep2(ms) {
|
|
71251
|
+
return new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
71252
|
+
}
|
|
71253
|
+
async function runAgentPsCommand(args2, deps) {
|
|
71254
|
+
const { json } = parseJsonFlag(args2);
|
|
70217
71255
|
const records = listRunRecords(deps);
|
|
70218
|
-
|
|
71256
|
+
for (const record of records) {
|
|
71257
|
+
if (record.status === "running" && typeof record.pid === "number") {
|
|
71258
|
+
checkStaleRun(record.runId, deps);
|
|
71259
|
+
}
|
|
71260
|
+
}
|
|
71261
|
+
const refreshed = records.map((r) => readRunRecord(r.runId, deps)).filter(Boolean);
|
|
71262
|
+
if (json) {
|
|
71263
|
+
deps.output.write(JSON.stringify(refreshed) + "\n");
|
|
71264
|
+
return 0;
|
|
71265
|
+
}
|
|
71266
|
+
if (refreshed.length === 0) {
|
|
70219
71267
|
deps.output.write("No local runs found.\n");
|
|
70220
71268
|
return 0;
|
|
70221
71269
|
}
|
|
70222
71270
|
deps.output.write("RUN ID STATUS PID AGENT\n");
|
|
70223
|
-
for (const record of
|
|
71271
|
+
for (const record of refreshed) {
|
|
70224
71272
|
const pid = record.pid?.toString() ?? "-";
|
|
70225
71273
|
deps.output.write(
|
|
70226
71274
|
`${record.runId.padEnd(32)} ${record.status.padEnd(8)} ${pid.padEnd(8)} ${record.agentKey}
|
|
@@ -70229,18 +71277,83 @@ async function runAgentPsCommand(_args, deps) {
|
|
|
70229
71277
|
}
|
|
70230
71278
|
return 0;
|
|
70231
71279
|
}
|
|
71280
|
+
function parseStatusArgs(args2) {
|
|
71281
|
+
let target = "";
|
|
71282
|
+
let json = false;
|
|
71283
|
+
let watch = false;
|
|
71284
|
+
let intervalMs = 2e3;
|
|
71285
|
+
for (let i = 0; i < args2.length; i++) {
|
|
71286
|
+
const arg = args2[i];
|
|
71287
|
+
if (arg === "--json") {
|
|
71288
|
+
json = true;
|
|
71289
|
+
continue;
|
|
71290
|
+
}
|
|
71291
|
+
if (arg.startsWith("--json=")) {
|
|
71292
|
+
const value = arg.slice("--json=".length);
|
|
71293
|
+
json = value === "" || value === "true" || value === "1";
|
|
71294
|
+
continue;
|
|
71295
|
+
}
|
|
71296
|
+
if (arg === "--watch") {
|
|
71297
|
+
watch = true;
|
|
71298
|
+
continue;
|
|
71299
|
+
}
|
|
71300
|
+
if (arg.startsWith("--watch=")) {
|
|
71301
|
+
const value = arg.slice("--watch=".length);
|
|
71302
|
+
watch = value === "" || value === "true" || value === "1";
|
|
71303
|
+
continue;
|
|
71304
|
+
}
|
|
71305
|
+
if (arg === "--interval-ms") {
|
|
71306
|
+
const next = args2[i + 1];
|
|
71307
|
+
if (next && /^\d+$/.test(next)) {
|
|
71308
|
+
intervalMs = Number(next);
|
|
71309
|
+
i += 1;
|
|
71310
|
+
}
|
|
71311
|
+
continue;
|
|
71312
|
+
}
|
|
71313
|
+
if (arg.startsWith("--interval-ms=")) {
|
|
71314
|
+
const value = arg.slice("--interval-ms=".length);
|
|
71315
|
+
if (/^\d+$/.test(value)) intervalMs = Number(value);
|
|
71316
|
+
continue;
|
|
71317
|
+
}
|
|
71318
|
+
if (!arg.startsWith("-") && !target) {
|
|
71319
|
+
target = arg;
|
|
71320
|
+
}
|
|
71321
|
+
}
|
|
71322
|
+
return { target, json, watch, intervalMs };
|
|
71323
|
+
}
|
|
71324
|
+
function printStatusTick(record, deps) {
|
|
71325
|
+
const elapsed = formatDuration(record.startedAt, record.endedAt);
|
|
71326
|
+
const note = record.note ? ` (${record.note})` : "";
|
|
71327
|
+
deps.output.write(
|
|
71328
|
+
`[${(/* @__PURE__ */ new Date()).toISOString()}] ${record.runId} status=${record.status} elapsed=${elapsed}${note}
|
|
71329
|
+
`
|
|
71330
|
+
);
|
|
71331
|
+
}
|
|
70232
71332
|
async function runAgentStatusCommand(args2, deps) {
|
|
70233
|
-
const target = args2
|
|
71333
|
+
const { target, json, watch, intervalMs } = parseStatusArgs(args2);
|
|
70234
71334
|
if (!target) {
|
|
70235
|
-
deps.output.write("Usage: nolo agent status <runId|pid
|
|
71335
|
+
deps.output.write("Usage: nolo agent status <runId|pid> [--json] [--watch] [--interval-ms N]\n");
|
|
70236
71336
|
return 1;
|
|
70237
71337
|
}
|
|
70238
|
-
const
|
|
70239
|
-
if (!
|
|
71338
|
+
const initial = findRunRecord(target, deps);
|
|
71339
|
+
if (!initial) {
|
|
70240
71340
|
deps.output.write(`Run not found: ${target}
|
|
70241
71341
|
`);
|
|
70242
71342
|
return 1;
|
|
70243
71343
|
}
|
|
71344
|
+
const reconciled = checkStaleRun(initial.runId, deps) ?? initial;
|
|
71345
|
+
if (json) {
|
|
71346
|
+
const record = readRunRecord(reconciled.runId, deps) ?? reconciled;
|
|
71347
|
+
deps.output.write(JSON.stringify(record) + "\n");
|
|
71348
|
+
return 0;
|
|
71349
|
+
}
|
|
71350
|
+
if (!watch) {
|
|
71351
|
+
const record = readRunRecord(reconciled.runId, deps) ?? reconciled;
|
|
71352
|
+
return printStatusOnce(record, deps);
|
|
71353
|
+
}
|
|
71354
|
+
return runStatusWatch(reconciled.runId, intervalMs, deps);
|
|
71355
|
+
}
|
|
71356
|
+
function printStatusOnce(record, deps) {
|
|
70244
71357
|
deps.output.write(`runId: ${record.runId}
|
|
70245
71358
|
`);
|
|
70246
71359
|
deps.output.write(`status: ${record.status}
|
|
@@ -70260,6 +71373,8 @@ async function runAgentStatusCommand(args2, deps) {
|
|
|
70260
71373
|
if (typeof record.exitCode === "number") deps.output.write(`exitCode: ${record.exitCode}
|
|
70261
71374
|
`);
|
|
70262
71375
|
if (record.dialogId) deps.output.write(`dialog: ${record.dialogId}
|
|
71376
|
+
`);
|
|
71377
|
+
if (record.note) deps.output.write(`note: ${record.note}
|
|
70263
71378
|
`);
|
|
70264
71379
|
deps.output.write(`log: ${record.logPath}
|
|
70265
71380
|
`);
|
|
@@ -70273,6 +71388,47 @@ async function runAgentStatusCommand(args2, deps) {
|
|
|
70273
71388
|
}
|
|
70274
71389
|
return 0;
|
|
70275
71390
|
}
|
|
71391
|
+
async function runStatusWatch(runId, intervalMs, deps) {
|
|
71392
|
+
const sleep7 = deps.sleep ?? defaultSleep2;
|
|
71393
|
+
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
71394
|
+
let stopped = false;
|
|
71395
|
+
const setSignalHandler = deps.setSignalHandler ?? ((handler) => {
|
|
71396
|
+
process.once("SIGINT", handler);
|
|
71397
|
+
});
|
|
71398
|
+
const clearSignalHandler = deps.clearSignalHandler ?? (() => {
|
|
71399
|
+
process.removeAllListeners("SIGINT");
|
|
71400
|
+
});
|
|
71401
|
+
setSignalHandler(() => {
|
|
71402
|
+
stopped = true;
|
|
71403
|
+
});
|
|
71404
|
+
try {
|
|
71405
|
+
let record = readRunRecord(runId, deps);
|
|
71406
|
+
if (!record) {
|
|
71407
|
+
deps.output.write(`Run not found: ${runId}
|
|
71408
|
+
`);
|
|
71409
|
+
return 1;
|
|
71410
|
+
}
|
|
71411
|
+
printStatusTick(record, deps);
|
|
71412
|
+
while (!stopped && isRunningStatus(record.status)) {
|
|
71413
|
+
await sleep7(intervalMs);
|
|
71414
|
+
if (stopped) break;
|
|
71415
|
+
record = checkStaleRun(runId, deps);
|
|
71416
|
+
if (!record) {
|
|
71417
|
+
deps.output.write(`Run not found: ${runId}
|
|
71418
|
+
`);
|
|
71419
|
+
return 1;
|
|
71420
|
+
}
|
|
71421
|
+
printStatusTick(record, deps);
|
|
71422
|
+
}
|
|
71423
|
+
if (stopped) {
|
|
71424
|
+
deps.output.write(`watch stopped by signal
|
|
71425
|
+
`);
|
|
71426
|
+
}
|
|
71427
|
+
return 0;
|
|
71428
|
+
} finally {
|
|
71429
|
+
clearSignalHandler();
|
|
71430
|
+
}
|
|
71431
|
+
}
|
|
70276
71432
|
function parseLogsArgs(args2, onTail) {
|
|
70277
71433
|
let runId = "";
|
|
70278
71434
|
for (let i = 0; i < args2.length; i++) {
|
|
@@ -70364,10 +71520,12 @@ async function runAgentStopCommand(args2, deps) {
|
|
|
70364
71520
|
async function runAgentKillCommand(args2, deps) {
|
|
70365
71521
|
return runSignalCommand(args2, "SIGKILL", "kill", deps);
|
|
70366
71522
|
}
|
|
71523
|
+
var RUNNING_STATUSES;
|
|
70367
71524
|
var init_agentRunControl = __esm({
|
|
70368
71525
|
"packages/cli/agentRunControl.ts"() {
|
|
70369
71526
|
"use strict";
|
|
70370
71527
|
init_cliEnvHelpers();
|
|
71528
|
+
RUNNING_STATUSES = /* @__PURE__ */ new Set(["running"]);
|
|
70371
71529
|
}
|
|
70372
71530
|
});
|
|
70373
71531
|
|
|
@@ -76502,458 +77660,6 @@ var init_spaceCommands = __esm({
|
|
|
76502
77660
|
}
|
|
76503
77661
|
});
|
|
76504
77662
|
|
|
76505
|
-
// packages/cli/oauth/flows/antigravity.ts
|
|
76506
|
-
function readProjectId(value) {
|
|
76507
|
-
if (typeof value === "string" && value.length > 0) {
|
|
76508
|
-
return value;
|
|
76509
|
-
}
|
|
76510
|
-
if (value && typeof value === "object" && typeof value.id === "string" && value.id.length > 0) {
|
|
76511
|
-
return value.id;
|
|
76512
|
-
}
|
|
76513
|
-
return void 0;
|
|
76514
|
-
}
|
|
76515
|
-
function getDefaultTierId(allowedTiers) {
|
|
76516
|
-
if (!allowedTiers || allowedTiers.length === 0) {
|
|
76517
|
-
return TIER_LEGACY;
|
|
76518
|
-
}
|
|
76519
|
-
const defaultTier = allowedTiers.find(
|
|
76520
|
-
(tier) => tier.isDefault && typeof tier.id === "string" && tier.id.length > 0
|
|
76521
|
-
);
|
|
76522
|
-
if (defaultTier?.id) {
|
|
76523
|
-
return defaultTier.id;
|
|
76524
|
-
}
|
|
76525
|
-
return TIER_LEGACY;
|
|
76526
|
-
}
|
|
76527
|
-
async function sleep6(ms) {
|
|
76528
|
-
const { promise, resolve: resolve8 } = Promise.withResolvers();
|
|
76529
|
-
setTimeout(resolve8, ms);
|
|
76530
|
-
return promise;
|
|
76531
|
-
}
|
|
76532
|
-
async function onboardProjectWithRetries(fetchImpl, endpoint, headers, onboardBody, onProgress) {
|
|
76533
|
-
for (let attempt = 1; attempt <= PROJECT_ONBOARD_MAX_ATTEMPTS; attempt += 1) {
|
|
76534
|
-
if (attempt > 1) {
|
|
76535
|
-
onProgress?.(
|
|
76536
|
-
`Waiting for project provisioning (attempt ${attempt}/${PROJECT_ONBOARD_MAX_ATTEMPTS})...`
|
|
76537
|
-
);
|
|
76538
|
-
await sleep6(PROJECT_ONBOARD_INTERVAL_MS);
|
|
76539
|
-
}
|
|
76540
|
-
const onboardResponse = await fetchImpl(
|
|
76541
|
-
`${endpoint}/v1internal:onboardUser`,
|
|
76542
|
-
{
|
|
76543
|
-
method: "POST",
|
|
76544
|
-
headers,
|
|
76545
|
-
body: JSON.stringify(onboardBody)
|
|
76546
|
-
}
|
|
76547
|
-
);
|
|
76548
|
-
if (!onboardResponse.ok) {
|
|
76549
|
-
const errorText = await onboardResponse.text();
|
|
76550
|
-
throw new Error(
|
|
76551
|
-
`onboardUser failed: ${onboardResponse.status} ${onboardResponse.statusText}: ${errorText}`
|
|
76552
|
-
);
|
|
76553
|
-
}
|
|
76554
|
-
const operation = await onboardResponse.json();
|
|
76555
|
-
if (!operation.done) {
|
|
76556
|
-
continue;
|
|
76557
|
-
}
|
|
76558
|
-
const projectId = readProjectId(operation.response?.cloudaicompanionProject);
|
|
76559
|
-
if (projectId) {
|
|
76560
|
-
return projectId;
|
|
76561
|
-
}
|
|
76562
|
-
}
|
|
76563
|
-
throw new Error(
|
|
76564
|
-
`onboardUser did not return a provisioned project id after ${PROJECT_ONBOARD_MAX_ATTEMPTS} attempts`
|
|
76565
|
-
);
|
|
76566
|
-
}
|
|
76567
|
-
async function discoverProject(fetchImpl, accessToken, onProgress) {
|
|
76568
|
-
const headers = {
|
|
76569
|
-
Authorization: `Bearer ${accessToken}`,
|
|
76570
|
-
"Content-Type": "application/json"
|
|
76571
|
-
};
|
|
76572
|
-
onProgress?.("Checking for existing project...");
|
|
76573
|
-
const endpoint = CLOUD_CODE_ENDPOINT;
|
|
76574
|
-
const loadResponse = await fetchImpl(`${endpoint}/v1internal:loadCodeAssist`, {
|
|
76575
|
-
method: "POST",
|
|
76576
|
-
headers,
|
|
76577
|
-
body: JSON.stringify({
|
|
76578
|
-
metadata: ANTIGRAVITY_LOAD_CODE_ASSIST_METADATA
|
|
76579
|
-
})
|
|
76580
|
-
});
|
|
76581
|
-
if (!loadResponse.ok) {
|
|
76582
|
-
const errorText = await loadResponse.text();
|
|
76583
|
-
throw new Error(
|
|
76584
|
-
`loadCodeAssist failed: ${loadResponse.status} ${loadResponse.statusText}: ${errorText}`
|
|
76585
|
-
);
|
|
76586
|
-
}
|
|
76587
|
-
const loadPayload = await loadResponse.json();
|
|
76588
|
-
const existingProject = readProjectId(loadPayload.cloudaicompanionProject);
|
|
76589
|
-
if (existingProject) {
|
|
76590
|
-
return existingProject;
|
|
76591
|
-
}
|
|
76592
|
-
const tierId = getDefaultTierId(loadPayload.allowedTiers);
|
|
76593
|
-
onProgress?.("Provisioning project...");
|
|
76594
|
-
const onboardBody = {
|
|
76595
|
-
tierId,
|
|
76596
|
-
metadata: ANTIGRAVITY_LOAD_CODE_ASSIST_METADATA
|
|
76597
|
-
};
|
|
76598
|
-
return onboardProjectWithRetries(
|
|
76599
|
-
fetchImpl,
|
|
76600
|
-
endpoint,
|
|
76601
|
-
headers,
|
|
76602
|
-
onboardBody,
|
|
76603
|
-
onProgress
|
|
76604
|
-
);
|
|
76605
|
-
}
|
|
76606
|
-
async function getUserEmail(fetchImpl, accessToken) {
|
|
76607
|
-
try {
|
|
76608
|
-
const response = await fetchImpl(USERINFO_URL, {
|
|
76609
|
-
headers: { Authorization: `Bearer ${accessToken}` }
|
|
76610
|
-
});
|
|
76611
|
-
if (!response.ok) return void 0;
|
|
76612
|
-
const data = await response.json();
|
|
76613
|
-
return typeof data.email === "string" ? data.email : void 0;
|
|
76614
|
-
} catch {
|
|
76615
|
-
return void 0;
|
|
76616
|
-
}
|
|
76617
|
-
}
|
|
76618
|
-
function generateState2() {
|
|
76619
|
-
const bytes = new Uint8Array(16);
|
|
76620
|
-
crypto.getRandomValues(bytes);
|
|
76621
|
-
return Array.from(bytes).map((value) => value.toString(16).padStart(2, "0")).join("");
|
|
76622
|
-
}
|
|
76623
|
-
async function runAntigravityOAuthLogin(deps = {}) {
|
|
76624
|
-
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
76625
|
-
const output2 = deps.output ?? console;
|
|
76626
|
-
const error = deps.error ?? console;
|
|
76627
|
-
const redirectUri = `http://127.0.0.1:${CALLBACK_PORT}${CALLBACK_PATH}`;
|
|
76628
|
-
let handle;
|
|
76629
|
-
try {
|
|
76630
|
-
handle = await startCallbackServer({
|
|
76631
|
-
port: CALLBACK_PORT,
|
|
76632
|
-
hostname: "127.0.0.1",
|
|
76633
|
-
timeoutMs: 5 * 6e4
|
|
76634
|
-
});
|
|
76635
|
-
} catch (err) {
|
|
76636
|
-
throw new Error(
|
|
76637
|
-
`Failed to start Antigravity OAuth callback server on ${CALLBACK_PORT}: ${err instanceof Error ? err.message : String(err)}`
|
|
76638
|
-
);
|
|
76639
|
-
}
|
|
76640
|
-
try {
|
|
76641
|
-
const state = generateState2();
|
|
76642
|
-
const pkce = await generatePkcePair();
|
|
76643
|
-
const authParams = new URLSearchParams({
|
|
76644
|
-
client_id: CLIENT_ID,
|
|
76645
|
-
response_type: "code",
|
|
76646
|
-
redirect_uri: redirectUri,
|
|
76647
|
-
scope: SCOPES.join(" "),
|
|
76648
|
-
state,
|
|
76649
|
-
access_type: "offline",
|
|
76650
|
-
prompt: "consent"
|
|
76651
|
-
});
|
|
76652
|
-
const authUrl = `${AUTH_URL}?${authParams.toString()}`;
|
|
76653
|
-
output2.log(
|
|
76654
|
-
`Open the following URL in your browser to log in to Antigravity:
|
|
76655
|
-
${authUrl}`
|
|
76656
|
-
);
|
|
76657
|
-
if (deps.openBrowser) {
|
|
76658
|
-
try {
|
|
76659
|
-
await deps.openBrowser(authUrl);
|
|
76660
|
-
} catch (err) {
|
|
76661
|
-
error.error(
|
|
76662
|
-
`Failed to open browser automatically: ${err instanceof Error ? err.message : String(err)}`
|
|
76663
|
-
);
|
|
76664
|
-
}
|
|
76665
|
-
}
|
|
76666
|
-
const callback = await handle.waitForCode();
|
|
76667
|
-
const tokenResponse = await fetchImpl(TOKEN_URL, {
|
|
76668
|
-
method: "POST",
|
|
76669
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
76670
|
-
body: new URLSearchParams({
|
|
76671
|
-
client_id: CLIENT_ID,
|
|
76672
|
-
client_secret: CLIENT_SECRET,
|
|
76673
|
-
code: callback.code,
|
|
76674
|
-
grant_type: "authorization_code",
|
|
76675
|
-
redirect_uri: redirectUri
|
|
76676
|
-
})
|
|
76677
|
-
});
|
|
76678
|
-
if (!tokenResponse.ok) {
|
|
76679
|
-
const body = await tokenResponse.text();
|
|
76680
|
-
throw new Error(`Antigravity token exchange failed: ${body}`);
|
|
76681
|
-
}
|
|
76682
|
-
const tokenData = await tokenResponse.json();
|
|
76683
|
-
if (!tokenData.refresh_token) {
|
|
76684
|
-
throw new Error("No refresh token received. Please try again.");
|
|
76685
|
-
}
|
|
76686
|
-
const email = await getUserEmail(fetchImpl, tokenData.access_token);
|
|
76687
|
-
const projectId = await discoverProject(
|
|
76688
|
-
fetchImpl,
|
|
76689
|
-
tokenData.access_token,
|
|
76690
|
-
(message) => output2.log(message)
|
|
76691
|
-
);
|
|
76692
|
-
const now = (deps.now ?? Date.now)();
|
|
76693
|
-
return {
|
|
76694
|
-
provider: "antigravity",
|
|
76695
|
-
accessToken: tokenData.access_token,
|
|
76696
|
-
refreshToken: tokenData.refresh_token,
|
|
76697
|
-
expiresAt: now + tokenData.expires_in * 1e3 - ACCESS_TOKEN_CLIENT_SKEW_MS2,
|
|
76698
|
-
scope: tokenData.scope,
|
|
76699
|
-
obtainedAt: now,
|
|
76700
|
-
metadata: {
|
|
76701
|
-
projectId,
|
|
76702
|
-
email
|
|
76703
|
-
}
|
|
76704
|
-
};
|
|
76705
|
-
} finally {
|
|
76706
|
-
await handle.close();
|
|
76707
|
-
}
|
|
76708
|
-
}
|
|
76709
|
-
var decode, CLIENT_ID, CLIENT_SECRET, CALLBACK_PORT, CALLBACK_PATH, SCOPES, AUTH_URL, TOKEN_URL, USERINFO_URL, CLOUD_CODE_ENDPOINT, TIER_LEGACY, PROJECT_ONBOARD_MAX_ATTEMPTS, PROJECT_ONBOARD_INTERVAL_MS, ACCESS_TOKEN_CLIENT_SKEW_MS2, ANTIGRAVITY_LOAD_CODE_ASSIST_METADATA;
|
|
76710
|
-
var init_antigravity = __esm({
|
|
76711
|
-
"packages/cli/oauth/flows/antigravity.ts"() {
|
|
76712
|
-
"use strict";
|
|
76713
|
-
init_callback_server();
|
|
76714
|
-
init_pkce();
|
|
76715
|
-
init_token_store();
|
|
76716
|
-
decode = (s) => Buffer.from(s, "base64").toString("utf8");
|
|
76717
|
-
CLIENT_ID = decode(
|
|
76718
|
-
"MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ=="
|
|
76719
|
-
);
|
|
76720
|
-
CLIENT_SECRET = decode("R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY=");
|
|
76721
|
-
CALLBACK_PORT = 51121;
|
|
76722
|
-
CALLBACK_PATH = "/oauth-callback";
|
|
76723
|
-
SCOPES = [
|
|
76724
|
-
"https://www.googleapis.com/auth/cloud-platform",
|
|
76725
|
-
"https://www.googleapis.com/auth/userinfo.email",
|
|
76726
|
-
"https://www.googleapis.com/auth/userinfo.profile",
|
|
76727
|
-
"https://www.googleapis.com/auth/cclog",
|
|
76728
|
-
"https://www.googleapis.com/auth/experimentsandconfigs"
|
|
76729
|
-
];
|
|
76730
|
-
AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
76731
|
-
TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
76732
|
-
USERINFO_URL = "https://www.googleapis.com/oauth2/v1/userinfo?alt=json";
|
|
76733
|
-
CLOUD_CODE_ENDPOINT = "https://cloudcode-pa.googleapis.com";
|
|
76734
|
-
TIER_LEGACY = "legacy-tier";
|
|
76735
|
-
PROJECT_ONBOARD_MAX_ATTEMPTS = 5;
|
|
76736
|
-
PROJECT_ONBOARD_INTERVAL_MS = 2e3;
|
|
76737
|
-
ACCESS_TOKEN_CLIENT_SKEW_MS2 = 5 * 60 * 1e3;
|
|
76738
|
-
ANTIGRAVITY_LOAD_CODE_ASSIST_METADATA = Object.freeze({
|
|
76739
|
-
ideType: "ANTIGRAVITY",
|
|
76740
|
-
platform: "PLATFORM_UNSPECIFIED",
|
|
76741
|
-
pluginType: "GEMINI"
|
|
76742
|
-
});
|
|
76743
|
-
}
|
|
76744
|
-
});
|
|
76745
|
-
|
|
76746
|
-
// packages/cli/oauth/flows/xai.ts
|
|
76747
|
-
function validateXAIEndpoint(url, field) {
|
|
76748
|
-
let parsed;
|
|
76749
|
-
try {
|
|
76750
|
-
parsed = new URL(url);
|
|
76751
|
-
} catch {
|
|
76752
|
-
throw new Error(`Invalid xAI ${field}: ${url}`);
|
|
76753
|
-
}
|
|
76754
|
-
if (parsed.protocol !== "https:") {
|
|
76755
|
-
throw new Error(`Invalid xAI ${field}: ${url}`);
|
|
76756
|
-
}
|
|
76757
|
-
const host = parsed.hostname.toLowerCase();
|
|
76758
|
-
if (!host || host !== "x.ai" && !host.endsWith(".x.ai")) {
|
|
76759
|
-
throw new Error(`Invalid xAI ${field}: ${url}`);
|
|
76760
|
-
}
|
|
76761
|
-
return url;
|
|
76762
|
-
}
|
|
76763
|
-
async function xaiOAuthDiscovery(fetchImpl, timeoutMs = DISCOVERY_TIMEOUT_MS) {
|
|
76764
|
-
let response;
|
|
76765
|
-
try {
|
|
76766
|
-
response = await fetchImpl(XAI_OAUTH_DISCOVERY_URL, {
|
|
76767
|
-
method: "GET",
|
|
76768
|
-
headers: { Accept: "application/json" },
|
|
76769
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
76770
|
-
});
|
|
76771
|
-
} catch (error) {
|
|
76772
|
-
throw new Error(
|
|
76773
|
-
`xAI OIDC discovery failed: ${error instanceof Error ? error.message : String(error)}`
|
|
76774
|
-
);
|
|
76775
|
-
}
|
|
76776
|
-
if (response.status !== 200) {
|
|
76777
|
-
throw new Error(`xAI OIDC discovery returned status ${response.status}.`);
|
|
76778
|
-
}
|
|
76779
|
-
let payload;
|
|
76780
|
-
try {
|
|
76781
|
-
payload = await response.json();
|
|
76782
|
-
} catch (error) {
|
|
76783
|
-
throw new Error(
|
|
76784
|
-
`xAI OIDC discovery returned invalid JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
76785
|
-
);
|
|
76786
|
-
}
|
|
76787
|
-
if (!payload || typeof payload !== "object") {
|
|
76788
|
-
throw new Error("xAI OIDC discovery response was not a JSON object.");
|
|
76789
|
-
}
|
|
76790
|
-
const obj = payload;
|
|
76791
|
-
const authorizationEndpoint = typeof obj.authorization_endpoint === "string" ? obj.authorization_endpoint.trim() : "";
|
|
76792
|
-
const tokenEndpoint = typeof obj.token_endpoint === "string" ? obj.token_endpoint.trim() : "";
|
|
76793
|
-
if (!authorizationEndpoint || !tokenEndpoint) {
|
|
76794
|
-
throw new Error("xAI OIDC discovery response was missing required endpoints.");
|
|
76795
|
-
}
|
|
76796
|
-
validateXAIEndpoint(authorizationEndpoint, "authorization_endpoint");
|
|
76797
|
-
validateXAIEndpoint(tokenEndpoint, "token_endpoint");
|
|
76798
|
-
return {
|
|
76799
|
-
authorization_endpoint: authorizationEndpoint,
|
|
76800
|
-
token_endpoint: tokenEndpoint
|
|
76801
|
-
};
|
|
76802
|
-
}
|
|
76803
|
-
function buildXAIAuthorizeUrl(opts) {
|
|
76804
|
-
const params = new URLSearchParams({
|
|
76805
|
-
response_type: "code",
|
|
76806
|
-
client_id: XAI_OAUTH_CLIENT_ID,
|
|
76807
|
-
redirect_uri: opts.redirectUri,
|
|
76808
|
-
scope: XAI_OAUTH_SCOPE,
|
|
76809
|
-
code_challenge: opts.codeChallenge,
|
|
76810
|
-
code_challenge_method: "S256",
|
|
76811
|
-
state: opts.state,
|
|
76812
|
-
nonce: opts.nonce,
|
|
76813
|
-
plan: "generic",
|
|
76814
|
-
referrer: "nolo-cli"
|
|
76815
|
-
});
|
|
76816
|
-
return `${opts.authorizationEndpoint}?${params.toString()}`;
|
|
76817
|
-
}
|
|
76818
|
-
function generateState3() {
|
|
76819
|
-
const bytes = new Uint8Array(16);
|
|
76820
|
-
crypto.getRandomValues(bytes);
|
|
76821
|
-
return Array.from(bytes).map((value) => value.toString(16).padStart(2, "0")).join("");
|
|
76822
|
-
}
|
|
76823
|
-
async function exchangeXAIToken(fetchImpl, code, redirectUri, verifier) {
|
|
76824
|
-
const discovery = await xaiOAuthDiscovery(fetchImpl);
|
|
76825
|
-
const tokenEndpoint = validateXAIEndpoint(discovery.token_endpoint, "token_endpoint");
|
|
76826
|
-
const body = new URLSearchParams({
|
|
76827
|
-
grant_type: "authorization_code",
|
|
76828
|
-
client_id: XAI_OAUTH_CLIENT_ID,
|
|
76829
|
-
code,
|
|
76830
|
-
redirect_uri: redirectUri,
|
|
76831
|
-
code_verifier: verifier
|
|
76832
|
-
});
|
|
76833
|
-
const response = await fetchImpl(tokenEndpoint, {
|
|
76834
|
-
method: "POST",
|
|
76835
|
-
headers: {
|
|
76836
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
76837
|
-
Accept: "application/json"
|
|
76838
|
-
},
|
|
76839
|
-
body,
|
|
76840
|
-
signal: AbortSignal.timeout(TOKEN_REQUEST_TIMEOUT_MS2)
|
|
76841
|
-
});
|
|
76842
|
-
if (!response.ok) {
|
|
76843
|
-
let detail = "";
|
|
76844
|
-
try {
|
|
76845
|
-
detail = (await response.text()).trim();
|
|
76846
|
-
} catch {
|
|
76847
|
-
}
|
|
76848
|
-
throw new Error(
|
|
76849
|
-
`xAI token exchange failed: ${response.status}${detail ? ` ${detail}` : ""}`
|
|
76850
|
-
);
|
|
76851
|
-
}
|
|
76852
|
-
const data = await response.json();
|
|
76853
|
-
if (typeof data.access_token !== "string" || !data.access_token) {
|
|
76854
|
-
throw new Error("xAI token exchange response missing access_token");
|
|
76855
|
-
}
|
|
76856
|
-
if (typeof data.refresh_token !== "string" || !data.refresh_token) {
|
|
76857
|
-
throw new Error("xAI token exchange response missing refresh_token");
|
|
76858
|
-
}
|
|
76859
|
-
if (typeof data.expires_in !== "number" || !Number.isFinite(data.expires_in)) {
|
|
76860
|
-
throw new Error("xAI token exchange response missing expires_in");
|
|
76861
|
-
}
|
|
76862
|
-
return {
|
|
76863
|
-
accessToken: data.access_token,
|
|
76864
|
-
refreshToken: data.refresh_token,
|
|
76865
|
-
expiresIn: data.expires_in,
|
|
76866
|
-
scope: typeof data.scope === "string" ? data.scope : void 0,
|
|
76867
|
-
idToken: typeof data.id_token === "string" ? data.id_token : void 0
|
|
76868
|
-
};
|
|
76869
|
-
}
|
|
76870
|
-
async function runXaiOAuthLogin(deps = {}) {
|
|
76871
|
-
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
76872
|
-
const output2 = deps.output ?? console;
|
|
76873
|
-
const error = deps.error ?? console;
|
|
76874
|
-
const redirectUri = `http://${XAI_OAUTH_REDIRECT_HOST}:${XAI_OAUTH_REDIRECT_PORT}${XAI_OAUTH_REDIRECT_PATH}`;
|
|
76875
|
-
let handle;
|
|
76876
|
-
try {
|
|
76877
|
-
handle = await startCallbackServer({
|
|
76878
|
-
port: XAI_OAUTH_REDIRECT_PORT,
|
|
76879
|
-
hostname: XAI_OAUTH_REDIRECT_HOST,
|
|
76880
|
-
timeoutMs: 5 * 6e4
|
|
76881
|
-
});
|
|
76882
|
-
} catch (err) {
|
|
76883
|
-
throw new Error(
|
|
76884
|
-
`Failed to start xAI OAuth callback server on ${XAI_OAUTH_REDIRECT_PORT}: ${err instanceof Error ? err.message : String(err)}`
|
|
76885
|
-
);
|
|
76886
|
-
}
|
|
76887
|
-
try {
|
|
76888
|
-
const state = generateState3();
|
|
76889
|
-
const pkce = await generatePkcePair();
|
|
76890
|
-
const nonce = crypto.randomUUID().replace(/-/g, "");
|
|
76891
|
-
const discovery = await xaiOAuthDiscovery(fetchImpl);
|
|
76892
|
-
const authUrl = buildXAIAuthorizeUrl({
|
|
76893
|
-
authorizationEndpoint: discovery.authorization_endpoint,
|
|
76894
|
-
redirectUri,
|
|
76895
|
-
codeChallenge: pkce.challenge,
|
|
76896
|
-
state,
|
|
76897
|
-
nonce
|
|
76898
|
-
});
|
|
76899
|
-
output2.log(
|
|
76900
|
-
`Open the following URL in your browser to log in to xAI Grok (SuperGrok):
|
|
76901
|
-
${authUrl}
|
|
76902
|
-
|
|
76903
|
-
Docs: ${XAI_OAUTH_DOCS_URL}`
|
|
76904
|
-
);
|
|
76905
|
-
if (deps.openBrowser) {
|
|
76906
|
-
try {
|
|
76907
|
-
await deps.openBrowser(authUrl);
|
|
76908
|
-
} catch (err) {
|
|
76909
|
-
error.error(
|
|
76910
|
-
`Failed to open browser automatically: ${err instanceof Error ? err.message : String(err)}`
|
|
76911
|
-
);
|
|
76912
|
-
}
|
|
76913
|
-
}
|
|
76914
|
-
const callback = await handle.waitForCode();
|
|
76915
|
-
const token = await exchangeXAIToken(
|
|
76916
|
-
fetchImpl,
|
|
76917
|
-
callback.code,
|
|
76918
|
-
redirectUri,
|
|
76919
|
-
pkce.verifier
|
|
76920
|
-
);
|
|
76921
|
-
const now = (deps.now ?? Date.now)();
|
|
76922
|
-
const expiresIn = token.expiresIn;
|
|
76923
|
-
return {
|
|
76924
|
-
provider: "xai",
|
|
76925
|
-
accessToken: token.accessToken,
|
|
76926
|
-
refreshToken: token.refreshToken,
|
|
76927
|
-
expiresAt: now + expiresIn * 1e3 - ACCESS_TOKEN_CLIENT_SKEW_MS3,
|
|
76928
|
-
scope: token.scope,
|
|
76929
|
-
idToken: token.idToken,
|
|
76930
|
-
obtainedAt: now
|
|
76931
|
-
};
|
|
76932
|
-
} finally {
|
|
76933
|
-
await handle.close();
|
|
76934
|
-
}
|
|
76935
|
-
}
|
|
76936
|
-
var XAI_OAUTH_ISSUER, XAI_OAUTH_DISCOVERY_URL, XAI_OAUTH_CLIENT_ID, XAI_OAUTH_SCOPE, XAI_OAUTH_REDIRECT_HOST, XAI_OAUTH_REDIRECT_PORT, XAI_OAUTH_REDIRECT_PATH, XAI_OAUTH_DOCS_URL, ACCESS_TOKEN_CLIENT_SKEW_MS3, DISCOVERY_TIMEOUT_MS, TOKEN_REQUEST_TIMEOUT_MS2;
|
|
76937
|
-
var init_xai = __esm({
|
|
76938
|
-
"packages/cli/oauth/flows/xai.ts"() {
|
|
76939
|
-
"use strict";
|
|
76940
|
-
init_callback_server();
|
|
76941
|
-
init_pkce();
|
|
76942
|
-
init_token_store();
|
|
76943
|
-
XAI_OAUTH_ISSUER = "https://auth.x.ai";
|
|
76944
|
-
XAI_OAUTH_DISCOVERY_URL = `${XAI_OAUTH_ISSUER}/.well-known/openid-configuration`;
|
|
76945
|
-
XAI_OAUTH_CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828";
|
|
76946
|
-
XAI_OAUTH_SCOPE = "openid profile email offline_access grok-cli:access api:access";
|
|
76947
|
-
XAI_OAUTH_REDIRECT_HOST = "127.0.0.1";
|
|
76948
|
-
XAI_OAUTH_REDIRECT_PORT = 56121;
|
|
76949
|
-
XAI_OAUTH_REDIRECT_PATH = "/callback";
|
|
76950
|
-
XAI_OAUTH_DOCS_URL = "https://hermes-agent.nousresearch.com/docs/guides/xai-grok-oauth";
|
|
76951
|
-
ACCESS_TOKEN_CLIENT_SKEW_MS3 = 5 * 60 * 1e3;
|
|
76952
|
-
DISCOVERY_TIMEOUT_MS = 15e3;
|
|
76953
|
-
TOKEN_REQUEST_TIMEOUT_MS2 = 2e4;
|
|
76954
|
-
}
|
|
76955
|
-
});
|
|
76956
|
-
|
|
76957
77663
|
// packages/cli/client/profileConfig.ts
|
|
76958
77664
|
import { existsSync as existsSync10, mkdirSync as mkdirSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "node:fs";
|
|
76959
77665
|
import { dirname as dirname5, join as join11 } from "node:path";
|
|
@@ -77218,7 +77924,7 @@ async function runLoginCommand(args2, deps = {}) {
|
|
|
77218
77924
|
serverUrl,
|
|
77219
77925
|
fetchImpl: deps.fetchImpl ?? fetch,
|
|
77220
77926
|
openBrowser: deps.openBrowser ?? defaultOpenBrowser,
|
|
77221
|
-
sleep: deps.sleep ??
|
|
77927
|
+
sleep: deps.sleep ?? defaultSleep3,
|
|
77222
77928
|
now: deps.now ?? Date.now,
|
|
77223
77929
|
output: outputTarget,
|
|
77224
77930
|
error: errorTarget,
|
|
@@ -77286,7 +77992,7 @@ function runLogoutCommand(deps = {}) {
|
|
|
77286
77992
|
}
|
|
77287
77993
|
return 0;
|
|
77288
77994
|
}
|
|
77289
|
-
var LOGIN_HELP_TEXT, LOGOUT_HELP_TEXT, WHOAMI_HELP_TEXT, postJson2,
|
|
77995
|
+
var LOGIN_HELP_TEXT, LOGOUT_HELP_TEXT, WHOAMI_HELP_TEXT, postJson2, defaultSleep3, defaultOpenBrowser;
|
|
77290
77996
|
var init_authCommands = __esm({
|
|
77291
77997
|
"packages/cli/authCommands.ts"() {
|
|
77292
77998
|
"use strict";
|
|
@@ -77326,7 +78032,7 @@ Usage:
|
|
|
77326
78032
|
headers: { "Content-Type": "application/json" },
|
|
77327
78033
|
body: JSON.stringify(body)
|
|
77328
78034
|
});
|
|
77329
|
-
|
|
78035
|
+
defaultSleep3 = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
77330
78036
|
defaultOpenBrowser = async (url) => {
|
|
77331
78037
|
const command2 = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
77332
78038
|
const args2 = process.platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
@@ -77654,7 +78360,7 @@ ${SYNC_HELP_LINE}
|
|
|
77654
78360
|
|
|
77655
78361
|
// packages/connector-experimental/heartbeatLoop.ts
|
|
77656
78362
|
async function runHeartbeatLoop(options) {
|
|
77657
|
-
const sleep7 = options.sleep ??
|
|
78363
|
+
const sleep7 = options.sleep ?? defaultSleep4;
|
|
77658
78364
|
let beats = 0;
|
|
77659
78365
|
while (!options.signal?.aborted) {
|
|
77660
78366
|
await options.sendHeartbeat();
|
|
@@ -77664,11 +78370,11 @@ async function runHeartbeatLoop(options) {
|
|
|
77664
78370
|
await sleep7(options.intervalMs);
|
|
77665
78371
|
}
|
|
77666
78372
|
}
|
|
77667
|
-
var
|
|
78373
|
+
var defaultSleep4;
|
|
77668
78374
|
var init_heartbeatLoop = __esm({
|
|
77669
78375
|
"packages/connector-experimental/heartbeatLoop.ts"() {
|
|
77670
78376
|
"use strict";
|
|
77671
|
-
|
|
78377
|
+
defaultSleep4 = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
77672
78378
|
}
|
|
77673
78379
|
});
|
|
77674
78380
|
|
|
@@ -78281,7 +78987,7 @@ ${text}`);
|
|
|
78281
78987
|
return 1;
|
|
78282
78988
|
}
|
|
78283
78989
|
const maxAttempts = deps.maxConnectorAttempts ?? Infinity;
|
|
78284
|
-
const sleep7 = deps.sleep ??
|
|
78990
|
+
const sleep7 = deps.sleep ?? defaultSleep5;
|
|
78285
78991
|
const reconnectDelayMs = resolveConnectorReconnectDelayMs(env);
|
|
78286
78992
|
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
78287
78993
|
if (deps.signal?.aborted) {
|
|
@@ -78351,7 +79057,7 @@ ${text}`);
|
|
|
78351
79057
|
sendHeartbeat
|
|
78352
79058
|
});
|
|
78353
79059
|
}
|
|
78354
|
-
var
|
|
79060
|
+
var defaultSleep5;
|
|
78355
79061
|
var init_machineCommands = __esm({
|
|
78356
79062
|
"packages/cli/machineCommands.ts"() {
|
|
78357
79063
|
"use strict";
|
|
@@ -78366,7 +79072,7 @@ var init_machineCommands = __esm({
|
|
|
78366
79072
|
init_machineWsRunDispatch();
|
|
78367
79073
|
init_machineWsSession();
|
|
78368
79074
|
init_machineStatusCommands();
|
|
78369
|
-
|
|
79075
|
+
defaultSleep5 = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
78370
79076
|
}
|
|
78371
79077
|
});
|
|
78372
79078
|
|
|
@@ -80283,11 +80989,11 @@ function getAgentInternalCommandEntries() {
|
|
|
80283
80989
|
return runAgentReadCommand2(args2, deps);
|
|
80284
80990
|
}),
|
|
80285
80991
|
createAgentRunCommand(["agent", "run"], "Run an agent"),
|
|
80286
|
-
createEnvCommand(["agent", "ps"], "List active and recent local agent runs", async (_args, deps) => {
|
|
80992
|
+
createEnvCommand(["agent", "ps"], "List active and recent local agent runs (--json for machine-readable output)", async (_args, deps) => {
|
|
80287
80993
|
const { runAgentPsCommand: runAgentPsCommand2 } = await Promise.resolve().then(() => (init_agentRunControl(), agentRunControl_exports));
|
|
80288
80994
|
return runAgentPsCommand2(_args, { ...deps, output: process.stdout });
|
|
80289
80995
|
}),
|
|
80290
|
-
createEnvCommand(["agent", "status"], "Show status of a local agent run", async (args2, deps) => {
|
|
80996
|
+
createEnvCommand(["agent", "status"], "Show status of a local agent run (--json, --watch, --interval-ms N)", async (args2, deps) => {
|
|
80291
80997
|
const { runAgentStatusCommand: runAgentStatusCommand2 } = await Promise.resolve().then(() => (init_agentRunControl(), agentRunControl_exports));
|
|
80292
80998
|
return runAgentStatusCommand2(args2, { ...deps, output: process.stdout });
|
|
80293
80999
|
}),
|