nolo-cli 0.107.0-alpha.4 → 0.108.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/{_executeModel-UDCSOTD2.js → _executeModel-BY3P5LBB.js} +12 -12
  2. package/{agentDeleteCommand-OWYHN6D6.js → agentDeleteCommand-66KXCSRR.js} +7 -6
  3. package/{agentEmailCommands-AU5I4M4W.js → agentEmailCommands-63UTONDK.js} +18 -17
  4. package/{agentListCommands-B2V4YAC4.js → agentListCommands-NXCOTTZL.js} +9 -8
  5. package/{agentMachineCommands-YMNME2L6.js → agentMachineCommands-Z6RGPZSG.js} +7 -6
  6. package/{agentProviderCommands-GNPTL5XR.js → agentProviderCommands-X3UNW77C.js} +1 -1
  7. package/{agentRecordCommands-G4KK4R7H.js → agentRecordCommands-JP54ZWND.js} +17 -16
  8. package/{agentRunCommand-UTZJA23G.js → agentRunCommand-RMQWWSHF.js} +17 -16
  9. package/{agentRuntimeLocal-KCMC2TBD.js → agentRuntimeLocal-E67CTV45.js} +5 -4
  10. package/{agentSlice-R7PR6KYM.js → agentSlice-DG5TIQHE.js} +1 -1
  11. package/{appDeleteCommands-JEPA3EWE.js → appDeleteCommands-Z36CLGUK.js} +8 -7
  12. package/{appDeployCommands-UTB76XFM.js → appDeployCommands-ECMUWG6S.js} +8 -7
  13. package/{appDeployStatusCommands-LGHF2SBD.js → appDeployStatusCommands-CL24TDMA.js} +8 -7
  14. package/{appGetCommands-PX2BFHOB.js → appGetCommands-ITHGOYGJ.js} +8 -7
  15. package/{appListCommands-BSMPTWKC.js → appListCommands-EEOSI6RC.js} +8 -7
  16. package/{authCommand-YW42YZA4.js → authCommand-HGP2XTKC.js} +99 -7
  17. package/{chatQueueReduxAdapter-2P6NFX64.js → chatQueueReduxAdapter-DKLWTT3G.js} +2 -2
  18. package/{chunk-PQFHGD77.js → chunk-2OASQKU2.js} +1 -1
  19. package/{chunk-62CATUYY.js → chunk-4NNTATRH.js} +12 -769
  20. package/{chunk-EEGDMATE.js → chunk-AODJ7WSF.js} +3 -3
  21. package/{chunk-UVA7OYO3.js → chunk-CW67PN7L.js} +3 -3
  22. package/{chunk-4CR5I7BD.js → chunk-DOTZ5GTO.js} +1 -1
  23. package/chunk-FV3JEYR3.js +870 -0
  24. package/{chunk-MS7TSPZR.js → chunk-G4VIHCGJ.js} +3 -3
  25. package/chunk-GMZLP5DV.js +82 -0
  26. package/{chunk-UZGQNTVW.js → chunk-GNCCNNZD.js} +3 -1
  27. package/{chunk-GO3Z72MT.js → chunk-H4AHY5BU.js} +3 -80
  28. package/{chunk-NA35QHCF.js → chunk-HSSRGGXJ.js} +1 -1
  29. package/{chunk-GEPUP7OO.js → chunk-IQPFGYO3.js} +1 -1
  30. package/{chunk-XT35TTFG.js → chunk-KZJP33ZK.js} +1 -1
  31. package/{chunk-GPCZ7UXG.js → chunk-LJ5VW2UJ.js} +1 -1
  32. package/{chunk-C3M4465B.js → chunk-LPIYPEME.js} +9 -9
  33. package/{chunk-AEOE4Z6Q.js → chunk-LWKP7AWH.js} +1 -1
  34. package/{chunk-3UZPUAES.js → chunk-P3GYTNDF.js} +1 -1
  35. package/{chunk-ETI2NYVF.js → chunk-PHXD6JTX.js} +1 -1
  36. package/{chunk-W7HLWAQ7.js → chunk-PWBDVI4R.js} +5 -5
  37. package/{chunk-KQ4ONNQD.js → chunk-QU7KDSZX.js} +1 -1
  38. package/{chunk-IBOZNTG2.js → chunk-RVE4DCV3.js} +2 -2
  39. package/{chunk-IBOOZVVD.js → chunk-RZGLXO2B.js} +26 -22
  40. package/{chunk-GL3EHUR4.js → chunk-SYXOBWOC.js} +4 -4
  41. package/{chunk-ASIFZ2WY.js → chunk-T3GEOSRJ.js} +2 -2
  42. package/{chunk-JDPFV2JV.js → chunk-TR22GEUU.js} +2 -2
  43. package/{chunk-FG3HKPQP.js → chunk-UDIIVXKA.js} +41 -28
  44. package/{chunk-NOF3HDSN.js → chunk-YTLRHRH3.js} +3 -3
  45. package/{chunk-T75QD6AB.js → chunk-YWIEQS6H.js} +513 -27
  46. package/{chunk-53HEEOTT.js → chunk-Z5625XML.js} +1 -1
  47. package/{contentThunks-IV2T3EJC.js → contentThunks-JHK6X2KU.js} +3 -3
  48. package/{createAgentAutomationAction-JCOIEYY4.js → createAgentAutomationAction-7HX7KBES.js} +3 -3
  49. package/{createDialogAction-NGG7YVNU.js → createDialogAction-VUUUZL54.js} +4 -4
  50. package/{createPageAction-D2VOOLP3.js → createPageAction-QWNMGO3O.js} +3 -3
  51. package/{dialogCommands-H7FPUYUQ.js → dialogCommands-EN7TYD3I.js} +8 -7
  52. package/{dialogSlice-6JZOOTDS.js → dialogSlice-P2K47T3P.js} +2 -2
  53. package/{docCreateCommands-WRG2JLGM.js → docCreateCommands-43JKQEIH.js} +7 -6
  54. package/{docDeleteCommands-SHWJIBJS.js → docDeleteCommands-RL6D46XE.js} +8 -7
  55. package/{docReadCommands-WJN3WT6O.js → docReadCommands-TOEUEQDG.js} +7 -6
  56. package/{docStore-HUPQ2FSS.js → docStore-3AHKTJRI.js} +1 -1
  57. package/{docUpdateCommands-IE32IL6O.js → docUpdateCommands-FWU5G2XB.js} +7 -6
  58. package/{handleSendMessageAction-DFPMQ7YM.js → handleSendMessageAction-ID5IKXUE.js} +2 -2
  59. package/index.js +51 -51
  60. package/{machineCommands-M2T2I5NF.js → machineCommands-TTKK4F7C.js} +16 -15
  61. package/{machineWsRunDispatch-ISBKOOD7.js → machineWsRunDispatch-RX64L3ET.js} +16 -15
  62. package/package.json +1 -1
  63. package/{providerPresetApply-FG6NZ57W.js → providerPresetApply-XI3WUPTI.js} +2 -2
  64. package/{providerRegistry-757OWH3O.js → providerRegistry-KEPWWGXD.js} +2 -2
  65. package/{readlineWorkspace-XQRDGWRZ.js → readlineWorkspace-KIMUDPPV.js} +20 -19
  66. package/{runAgentClientLoop-5ZA62FBA.js → runAgentClientLoop-AN4WIRPQ.js} +10 -10
  67. package/{spaceCommands-5GLCWZPO.js → spaceCommands-NA4JMIGT.js} +7 -6
  68. package/{streamAgentChatTurn-6UZJMYRB.js → streamAgentChatTurn-3TYTHZPJ.js} +11 -11
  69. package/{tools-KMGFWO43.js → tools-34SEJSLQ.js} +8 -8
  70. package/{tuiSummaryLlmCaller-OHHFTHMG.js → tuiSummaryLlmCaller-UFGFOIIW.js} +2 -1
  71. package/{updateDialogTitleAction-QTKNIURB.js → updateDialogTitleAction-RDHNT265.js} +3 -3
  72. package/chunk-Q5FJJ6XI.js +0 -103
@@ -0,0 +1,870 @@
1
+ import {
2
+ streamSseDataValues
3
+ } from "./chunk-GMZLP5DV.js";
4
+ import {
5
+ getAntigravityUserAgent,
6
+ readAntigravityProjectId,
7
+ resolveAntigravityCloudCodeBaseUrl
8
+ } from "./chunk-GNCCNNZD.js";
9
+ import {
10
+ asOptionalTrimmedString
11
+ } from "./chunk-G3SUCT4W.js";
12
+
13
+ // packages/core/chat/upstreamErrorBody.ts
14
+ function parseUpstreamErrorBody(errorText, statusText) {
15
+ if (errorText) {
16
+ try {
17
+ const parsed = JSON.parse(errorText);
18
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
19
+ const error = parsed.error;
20
+ if (error && typeof error === "object" && !Array.isArray(error)) {
21
+ return parsed;
22
+ }
23
+ }
24
+ } catch {
25
+ }
26
+ }
27
+ return { error: { message: errorText || statusText } };
28
+ }
29
+
30
+ // packages/agent-runtime/antigravityCloudCodeProvider.ts
31
+ import { randomUUID } from "node:crypto";
32
+
33
+ // packages/agent-runtime/antigravityWireModel.ts
34
+ var WIRE_PROFILES = {
35
+ // Antigravity discovery exposes 3.7 Flash as one tiered wire model.
36
+ // The UI labels its effort variants (Low/Medium/High), but the literal
37
+ // -medium/-high ids return 404 from streamGenerateContent.
38
+ "gemini-3.7-flash-tiered": { modelEnum: "MODEL_PLACEHOLDER_M301", maxOutputTokens: 65536 },
39
+ // Gemini 3.8 Flash 沿用 3.7 的 tiered 兼容策略:仓库内暂无 Antigravity discovery
40
+ // 证据确认 3.8 的 wire modelEnum,禁止虚构,先只声明同档输出上限;enum 待
41
+ // discovery 证据到位后补齐。
42
+ "gemini-3.8-flash-tiered": { maxOutputTokens: 65536 },
43
+ "gemini-3.6-flash-low": { maxOutputTokens: 65536 },
44
+ "gemini-3.6-flash-medium": { maxOutputTokens: 65536 },
45
+ "gemini-3.6-flash-high": { maxOutputTokens: 65536 },
46
+ // 旧模型 wire 映射保留:存量自定义 agent 仍可能引用(注册表已下线不影响此处)。
47
+ "gemini-3.5-flash-extra-low": { modelEnum: "MODEL_PLACEHOLDER_M187", maxOutputTokens: 65536 },
48
+ "gemini-3.5-flash-low": { modelEnum: "MODEL_PLACEHOLDER_M20", maxOutputTokens: 65536 },
49
+ "gemini-3-flash-agent": { modelEnum: "MODEL_PLACEHOLDER_M132", maxOutputTokens: 65536 },
50
+ "gemini-3.1-pro-low": { modelEnum: "MODEL_PLACEHOLDER_M36", maxOutputTokens: 65535 },
51
+ "gemini-pro-agent": { modelEnum: "MODEL_PLACEHOLDER_M16", maxOutputTokens: 65535 },
52
+ "claude-sonnet-5": { maxOutputTokens: 64e3 },
53
+ "claude-sonnet-4-6": { maxOutputTokens: 64e3 },
54
+ "claude-opus-4-6-thinking": { maxOutputTokens: 64e3 },
55
+ "gemini-2.5-flash": { maxOutputTokens: 65536 },
56
+ "gemini-2.5-pro": { maxOutputTokens: 65536 }
57
+ };
58
+ function resolveAntigravityWireModel(logicalModelId) {
59
+ const id = logicalModelId.trim();
60
+ const lower = id.toLowerCase();
61
+ if (lower === "gemini-3.5-flash") {
62
+ const wireModelId = "gemini-3.5-flash-low";
63
+ return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
64
+ }
65
+ if (lower === "gemini-3.7-flash" || ["gemini-3.7-flash-low", "gemini-3.7-flash-medium", "gemini-3.7-flash-high"].includes(lower)) {
66
+ const wireModelId = "gemini-3.7-flash-tiered";
67
+ return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
68
+ }
69
+ if (lower === "gemini-3.8-flash" || ["gemini-3.8-flash-low", "gemini-3.8-flash-medium", "gemini-3.8-flash-high"].includes(lower)) {
70
+ const wireModelId = "gemini-3.8-flash-tiered";
71
+ return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
72
+ }
73
+ if (lower === "gemini-3.6-flash") {
74
+ const wireModelId = "gemini-3.6-flash-low";
75
+ return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
76
+ }
77
+ if (lower === "gemini-3.1-pro" || lower === "gemini-3.1-pro-preview") {
78
+ const wireModelId = "gemini-3.1-pro-low";
79
+ return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
80
+ }
81
+ if (WIRE_PROFILES[id]) {
82
+ return { wireModelId: id, profile: WIRE_PROFILES[id] };
83
+ }
84
+ return { wireModelId: id };
85
+ }
86
+
87
+ // packages/agent-runtime/sseDataLine.ts
88
+ function parseSseDataLineJson(line) {
89
+ const trimmed = line.trim();
90
+ if (!trimmed.startsWith("data:")) return null;
91
+ const payload = trimmed.slice(5).trim();
92
+ if (!payload || payload === "[DONE]") return null;
93
+ try {
94
+ return JSON.parse(payload);
95
+ } catch {
96
+ return null;
97
+ }
98
+ }
99
+ function parseSseDataLineObject(line) {
100
+ const parsed = parseSseDataLineJson(line);
101
+ return parsed && typeof parsed === "object" ? parsed : null;
102
+ }
103
+
104
+ // packages/agent-runtime/geminiNativeShared.ts
105
+ var SKIP_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
106
+ function resolveGeminiModelQuirks(modelId) {
107
+ const lower = modelId.toLowerCase();
108
+ const isGemini3 = lower.includes("gemini-3");
109
+ const isStrictSignatureModel = lower.includes("gemini-3.5") || lower.includes("flash-preview");
110
+ const isClaude = lower.includes("claude");
111
+ return {
112
+ requiresThoughtSignature: isGemini3,
113
+ allowsThoughtSignatureSentinel: isGemini3 && !isStrictSignatureModel,
114
+ isClaudeCrossModel: isClaude
115
+ };
116
+ }
117
+ function isGemini3Model(modelId) {
118
+ return resolveGeminiModelQuirks(modelId).requiresThoughtSignature;
119
+ }
120
+ function messageText(content) {
121
+ if (typeof content === "string") return content;
122
+ if (!Array.isArray(content)) return "";
123
+ return content.filter(
124
+ (part) => part?.type === "text"
125
+ ).map((part) => part.text).join("\n").trim();
126
+ }
127
+ function parseDataUrlToInlineData(url) {
128
+ const match = /^data:([A-Za-z0-9.+-]+\/[A-Za-z0-9.+-]+);base64,([A-Za-z0-9+/=]*)$/.exec(
129
+ url
130
+ );
131
+ if (!match) return null;
132
+ return { mimeType: match[1], data: match[2] };
133
+ }
134
+ function extractInlineDataParts(content) {
135
+ if (!Array.isArray(content)) return [];
136
+ const parts = [];
137
+ for (const part of content) {
138
+ if (!part || typeof part !== "object") continue;
139
+ if (part.type !== "image_url") continue;
140
+ const url = part.image_url?.url;
141
+ if (typeof url !== "string" || !url.trim()) continue;
142
+ const inline = parseDataUrlToInlineData(url);
143
+ if (inline) parts.push({ inlineData: inline });
144
+ }
145
+ return parts;
146
+ }
147
+ function convertOpenAiMessagesToGemini(messages, options) {
148
+ const contents = [];
149
+ const systemTexts = [];
150
+ let toolCallIndex = 0;
151
+ let pendingFunctionCalls = [];
152
+ const pushOrMergeContent = (role, parts) => {
153
+ if (parts.length === 0) return;
154
+ const last = contents[contents.length - 1];
155
+ if (last && last.role === role) {
156
+ last.parts.push(...parts);
157
+ } else {
158
+ contents.push({ role, parts });
159
+ }
160
+ };
161
+ const flushPendingFunctionCalls = () => {
162
+ if (pendingFunctionCalls.length === 0) return;
163
+ const dummyResponses = pendingFunctionCalls.map(
164
+ ({ name, id }) => ({
165
+ functionResponse: {
166
+ name,
167
+ response: { output: "{}" },
168
+ ...id ? { id } : {}
169
+ }
170
+ })
171
+ );
172
+ pendingFunctionCalls = [];
173
+ pushOrMergeContent("user", dummyResponses);
174
+ };
175
+ for (const raw of messages) {
176
+ if (!raw || typeof raw !== "object" || !("role" in raw)) continue;
177
+ const role = String(raw.role);
178
+ const content = "content" in raw ? raw.content : null;
179
+ if (role === "system") {
180
+ const text = messageText(
181
+ content
182
+ );
183
+ if (text) systemTexts.push(text);
184
+ continue;
185
+ }
186
+ if (role === "user") {
187
+ flushPendingFunctionCalls();
188
+ const text = messageText(
189
+ content
190
+ );
191
+ const imageParts = extractInlineDataParts(
192
+ content
193
+ );
194
+ if (!text && imageParts.length === 0) continue;
195
+ const parts = [];
196
+ if (text) parts.push({ text });
197
+ for (const img of imageParts) parts.push(img);
198
+ pushOrMergeContent("user", parts);
199
+ continue;
200
+ }
201
+ if (role === "assistant") {
202
+ flushPendingFunctionCalls();
203
+ const text = messageText(
204
+ content
205
+ );
206
+ const toolCalls = "tool_calls" in raw && Array.isArray(raw.tool_calls) ? raw.tool_calls ?? [] : [];
207
+ const parts = [];
208
+ if (text) {
209
+ parts.push({ text });
210
+ }
211
+ for (const call of toolCalls) {
212
+ const name = call?.function?.name?.trim();
213
+ if (!name) continue;
214
+ const id = call.id?.trim() || `${name}_${toolCallIndex++}`;
215
+ pendingFunctionCalls.push({ name, id });
216
+ const realSignature = typeof call.thought_signature === "string" && call.thought_signature ? call.thought_signature : void 0;
217
+ const isFirstFunctionCallPart = !parts.some(
218
+ (p) => "functionCall" in p
219
+ );
220
+ const signature = realSignature ?? (options.attachSkipThoughtSignature && isFirstFunctionCallPart ? SKIP_THOUGHT_SIGNATURE : void 0);
221
+ const part = {
222
+ functionCall: {
223
+ name,
224
+ args: parseToolArgs(call.function?.arguments),
225
+ ...id ? { id } : {}
226
+ },
227
+ ...signature ? { thoughtSignature: signature } : {}
228
+ };
229
+ parts.push(part);
230
+ }
231
+ pushOrMergeContent("model", parts);
232
+ continue;
233
+ }
234
+ if (role === "tool") {
235
+ const toolCallId = "tool_call_id" in raw && typeof raw.tool_call_id === "string" ? raw.tool_call_id : "";
236
+ const rawName = "name" in raw && typeof raw.name === "string" ? raw.name.trim() : "";
237
+ const pendingIndex = pendingFunctionCalls.findIndex(
238
+ (p) => toolCallId ? p.id === toolCallId : rawName ? p.name === rawName : true
239
+ );
240
+ if (pendingIndex === -1) continue;
241
+ const [{ name, id }] = pendingFunctionCalls.splice(pendingIndex, 1);
242
+ const output = messageText(content) || "{}";
243
+ pushOrMergeContent("user", [
244
+ {
245
+ functionResponse: {
246
+ name,
247
+ response: { output },
248
+ // 保留 OpenAI tool_call_id:antigravity Cloud Code Assist 网关把
249
+ // Gemini contents 转成 Claude messages 时需要 functionResponse →
250
+ // tool_result 的 tool_use_id;缺 id 时网关报
251
+ // "tool_result.tool_use_id: Field required"(HTTP 400)。
252
+ ...id ? { id } : {}
253
+ }
254
+ }
255
+ ]);
256
+ }
257
+ }
258
+ flushPendingFunctionCalls();
259
+ if (contents.length > 0 && contents[0]?.role === "model") {
260
+ contents.unshift({
261
+ role: "user",
262
+ parts: [{ text: "Continue the conversation." }]
263
+ });
264
+ }
265
+ return { contents, systemTexts };
266
+ }
267
+ function parseToolArgs(raw) {
268
+ if (typeof raw === "string") {
269
+ try {
270
+ const parsed = JSON.parse(raw);
271
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
272
+ return parsed;
273
+ }
274
+ } catch {
275
+ }
276
+ }
277
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
278
+ return raw;
279
+ }
280
+ return {};
281
+ }
282
+ function sanitizeGeminiSchemaNode(node, active) {
283
+ const out = {};
284
+ if (!node || typeof node !== "object" || Array.isArray(node)) {
285
+ return { type: "string" };
286
+ }
287
+ if (active?.has(node)) {
288
+ return { type: "object", description: "(circular schema reference)" };
289
+ }
290
+ const seen = active ?? /* @__PURE__ */ new WeakSet();
291
+ seen.add(node);
292
+ try {
293
+ return sanitizeGeminiSchemaNodeInner(node, out, seen);
294
+ } finally {
295
+ seen.delete(node);
296
+ }
297
+ }
298
+ function sanitizeGeminiSchemaNodeInner(src, out, seen) {
299
+ if (Array.isArray(src.type)) {
300
+ const firstNonNull = src.type.find((t) => t !== "null");
301
+ if (typeof firstNonNull === "string") out.type = firstNonNull;
302
+ out.nullable = true;
303
+ } else if (typeof src.type === "string") {
304
+ out.type = src.type;
305
+ }
306
+ if (typeof src.description === "string") out.description = src.description;
307
+ if (typeof src.minimum === "number") out.minimum = src.minimum;
308
+ if (typeof src.maximum === "number") out.maximum = src.maximum;
309
+ if (Array.isArray(src.enum) && src.enum.length > 0) out.enum = src.enum;
310
+ if (src.nullable === true) out.nullable = true;
311
+ if ("const" in src && src.const !== void 0 && !out.enum) {
312
+ out.enum = [src.const];
313
+ }
314
+ const variantBranches = [
315
+ ...Array.isArray(src.oneOf) ? src.oneOf : [],
316
+ ...Array.isArray(src.anyOf) ? src.anyOf : []
317
+ ];
318
+ if (variantBranches.length > 0) {
319
+ const mergedProperties = {};
320
+ let requiredIntersection;
321
+ for (const branch of variantBranches) {
322
+ const sanitized = sanitizeGeminiSchemaNode(branch, seen);
323
+ const branchProperties = sanitized.properties ?? {};
324
+ for (const [key, value] of Object.entries(branchProperties)) {
325
+ const previous = mergedProperties[key];
326
+ const prevEnum = previous?.enum;
327
+ const nextEnum = value?.enum;
328
+ if (prevEnum && nextEnum) {
329
+ mergedProperties[key] = {
330
+ ...value,
331
+ enum: [.../* @__PURE__ */ new Set([...prevEnum, ...nextEnum])]
332
+ };
333
+ } else {
334
+ mergedProperties[key] = value;
335
+ }
336
+ }
337
+ const branchRequired = Array.isArray(sanitized.required) ? sanitized.required : [];
338
+ requiredIntersection = requiredIntersection === void 0 ? [...branchRequired] : requiredIntersection.filter((r) => branchRequired.includes(r));
339
+ }
340
+ out.properties = {
341
+ ...out.properties ?? {},
342
+ ...mergedProperties
343
+ };
344
+ if (requiredIntersection !== void 0 && requiredIntersection.length > 0) {
345
+ out.required = requiredIntersection;
346
+ }
347
+ if (typeof out.type !== "string") out.type = "object";
348
+ }
349
+ if (Array.isArray(src.allOf)) {
350
+ for (const branch of src.allOf) {
351
+ const sanitized = sanitizeGeminiSchemaNode(branch, seen);
352
+ out.properties = {
353
+ ...out.properties ?? {},
354
+ ...sanitized.properties ?? {}
355
+ };
356
+ if (Array.isArray(sanitized.required)) {
357
+ out.required = [
358
+ .../* @__PURE__ */ new Set([
359
+ ...out.required ?? [],
360
+ ...sanitized.required ?? []
361
+ ])
362
+ ];
363
+ }
364
+ }
365
+ if (typeof out.type !== "string") out.type = "object";
366
+ }
367
+ if (src.properties && typeof src.properties === "object") {
368
+ const properties = {};
369
+ for (const [key, value] of Object.entries(
370
+ src.properties
371
+ )) {
372
+ properties[key] = sanitizeGeminiSchemaNode(value, seen);
373
+ }
374
+ out.properties = properties;
375
+ if (typeof out.type !== "string") out.type = "object";
376
+ }
377
+ if (Array.isArray(src.required)) {
378
+ const properties = out.properties ?? {};
379
+ const required = [...new Set(src.required)].filter(
380
+ (r) => typeof r === "string" && r in properties
381
+ );
382
+ if (required.length > 0) out.required = required;
383
+ }
384
+ if (src.items !== void 0) {
385
+ out.items = sanitizeGeminiSchemaNode(src.items, seen);
386
+ if (typeof out.type !== "string") out.type = "array";
387
+ }
388
+ if (typeof out.type !== "string") out.type = "object";
389
+ return out;
390
+ }
391
+ function convertOpenAiToolsToGemini(tools) {
392
+ if (!Array.isArray(tools) || tools.length === 0) return void 0;
393
+ const declarations = [];
394
+ for (const tool of tools) {
395
+ if (!tool || typeof tool !== "object" || !("function" in tool)) continue;
396
+ const fn = tool.function;
397
+ const name = typeof fn.name === "string" ? fn.name : "";
398
+ if (!name) continue;
399
+ declarations.push({
400
+ name,
401
+ description: typeof fn.description === "string" ? fn.description : "",
402
+ parameters: sanitizeGeminiSchemaNode(
403
+ fn.parameters ?? { type: "object", properties: {} }
404
+ )
405
+ });
406
+ }
407
+ if (declarations.length === 0) return void 0;
408
+ return [{ functionDeclarations: declarations }];
409
+ }
410
+ function createGeminiAccumulatorState() {
411
+ return {
412
+ text: "",
413
+ toolCalls: [],
414
+ reasoning: "",
415
+ events: []
416
+ };
417
+ }
418
+ function applyGeminiChunk(chunk, state, options) {
419
+ if (!chunk || typeof chunk !== "object") return;
420
+ const response = "response" in chunk && chunk.response && typeof chunk.response === "object" ? chunk.response : chunk;
421
+ if ("usageMetadata" in response && response.usageMetadata && typeof response.usageMetadata === "object") {
422
+ const meta = response.usageMetadata;
423
+ const prompt = typeof meta.promptTokenCount === "number" ? meta.promptTokenCount : 0;
424
+ const candidates2 = typeof meta.candidatesTokenCount === "number" ? meta.candidatesTokenCount : 0;
425
+ const total = typeof meta.totalTokenCount === "number" ? meta.totalTokenCount : prompt + candidates2;
426
+ const cached = typeof meta.cachedContentTokenCount === "number" && Number.isFinite(meta.cachedContentTokenCount) ? (
427
+ // cached ⊆ prompt;对畸形上游防御性钳位,避免 cache_read > input 破坏归一化与计费
428
+ Math.min(Math.max(0, Math.floor(meta.cachedContentTokenCount)), prompt)
429
+ ) : 0;
430
+ state.usage = {
431
+ prompt_tokens: prompt,
432
+ completion_tokens: candidates2,
433
+ total_tokens: total,
434
+ ...cached > 0 ? { cache_read_input_tokens: cached } : {}
435
+ };
436
+ state.events.push({ kind: "usage", usage: state.usage });
437
+ }
438
+ const candidates = Array.isArray(response.candidates) ? response.candidates : [];
439
+ for (const candidate of candidates) {
440
+ if (!candidate || typeof candidate !== "object") continue;
441
+ const candidateFinishReason = candidate.finishReason;
442
+ if (typeof candidateFinishReason === "string" && candidateFinishReason.trim()) {
443
+ state.finishReason = candidateFinishReason.trim();
444
+ state.events.push({ kind: "finish", reason: state.finishReason });
445
+ }
446
+ const parts = Array.isArray(
447
+ candidate.content?.parts
448
+ ) ? candidate.content.parts : [];
449
+ for (const part of parts) {
450
+ if (!part || typeof part !== "object") continue;
451
+ const partSignature = part.thoughtSignature;
452
+ const isThought = Boolean(part.thought);
453
+ if ("text" in part && typeof part.text === "string") {
454
+ const piece = part.text;
455
+ if (!isThought) {
456
+ state.text += piece;
457
+ if (piece) {
458
+ state.events.push({ kind: "text", text: piece });
459
+ if (options?.onTextDelta) options.onTextDelta(piece);
460
+ }
461
+ } else {
462
+ state.reasoning += piece;
463
+ if (piece) {
464
+ state.events.push({ kind: "reasoning", text: piece });
465
+ if (options?.onReasoningDelta) options.onReasoningDelta(piece);
466
+ }
467
+ }
468
+ }
469
+ if (isThought && typeof partSignature === "string" && partSignature) {
470
+ state.pendingThoughtSignature = partSignature;
471
+ }
472
+ if ("functionCall" in part && part.functionCall) {
473
+ const call = part.functionCall;
474
+ const name = typeof call.name === "string" ? call.name : "tool";
475
+ const id = typeof call.id === "string" ? call.id : `${name}_${state.toolCalls.length}`;
476
+ const argsObj = call.args && typeof call.args === "object" ? call.args : {};
477
+ const resolvedSignature = typeof partSignature === "string" && partSignature ? partSignature : state.pendingThoughtSignature;
478
+ state.pendingThoughtSignature = void 0;
479
+ const toolCall = {
480
+ id,
481
+ type: "function",
482
+ function: { name, arguments: JSON.stringify(argsObj) },
483
+ ...typeof resolvedSignature === "string" && resolvedSignature ? { thought_signature: resolvedSignature } : {}
484
+ };
485
+ state.toolCalls.push(toolCall);
486
+ state.events.push({ kind: "tool_call", toolCall });
487
+ }
488
+ }
489
+ }
490
+ }
491
+ function accumulateGeminiChunks(chunks, options) {
492
+ const state = createGeminiAccumulatorState();
493
+ for (const chunk of chunks) {
494
+ applyGeminiChunk(chunk, state, options);
495
+ }
496
+ return {
497
+ text: state.text,
498
+ toolCalls: state.toolCalls,
499
+ usage: state.usage,
500
+ finishReason: state.finishReason,
501
+ reasoningContent: state.reasoning,
502
+ events: state.events
503
+ };
504
+ }
505
+ async function accumulateGeminiStream(stream, options) {
506
+ const state = createGeminiAccumulatorState();
507
+ for await (const chunk of stream) {
508
+ applyGeminiChunk(chunk, state, options);
509
+ }
510
+ return {
511
+ text: state.text,
512
+ toolCalls: state.toolCalls,
513
+ usage: state.usage,
514
+ finishReason: state.finishReason,
515
+ reasoningContent: state.reasoning,
516
+ events: state.events
517
+ };
518
+ }
519
+ function shouldUseGeminiNativeToolRoute(provider, model, tools, isImageModel) {
520
+ return provider === "google" && !isImageModel(model) && isGemini3Model(model) && Array.isArray(tools) && tools.length > 0;
521
+ }
522
+ function buildGeminiGenerateContentRequest(args) {
523
+ const { contents, systemTexts } = convertOpenAiMessagesToGemini(
524
+ args.messages,
525
+ { attachSkipThoughtSignature: args.attachSkipThoughtSignature }
526
+ );
527
+ const request = { contents };
528
+ if (systemTexts.length > 0) {
529
+ request.systemInstruction = {
530
+ role: "user",
531
+ parts: systemTexts.map((text) => ({ text }))
532
+ };
533
+ }
534
+ const toolsResult = convertOpenAiToolsToGemini(args.tools);
535
+ if (toolsResult) {
536
+ request.tools = toolsResult;
537
+ request.toolConfig = { functionCallingConfig: { mode: "AUTO" } };
538
+ }
539
+ const generationConfig = {};
540
+ if (typeof args.maxTokens === "number" && args.maxTokens > 0) {
541
+ generationConfig.maxOutputTokens = args.maxTokens;
542
+ }
543
+ if (typeof args.temperature === "number") {
544
+ generationConfig.temperature = args.temperature;
545
+ }
546
+ if (Object.keys(generationConfig).length > 0) {
547
+ request.generationConfig = generationConfig;
548
+ }
549
+ return request;
550
+ }
551
+
552
+ // packages/agent-runtime/antigravityCloudCodeProvider.ts
553
+ var STREAM_PATH = "/v1internal:streamGenerateContent?alt=sse";
554
+ function buildCloudCodeAssistPayload(args) {
555
+ const projectId = readAntigravityProjectId(args.metadata);
556
+ if (!projectId) {
557
+ throw new Error(
558
+ "Antigravity OAuth credential is missing metadata.projectId. Re-run `nolo auth antigravity`."
559
+ );
560
+ }
561
+ const logicalModel = asOptionalTrimmedString(args.openAiBody.model) ?? asOptionalTrimmedString(args.agentConfig.model) ?? "gemini-3.1-pro";
562
+ const { wireModelId: model, profile } = resolveAntigravityWireModel(logicalModel);
563
+ const rawMessages = Array.isArray(args.openAiBody.messages) ? args.openAiBody.messages : [];
564
+ const quirks = resolveGeminiModelQuirks(model);
565
+ const isClaude = quirks.isClaudeCrossModel;
566
+ const { contents, systemTexts } = convertOpenAiMessagesToGemini(rawMessages, {
567
+ attachSkipThoughtSignature: quirks.allowsThoughtSignatureSentinel
568
+ });
569
+ if (contents.length === 0) {
570
+ throw new Error("Antigravity Cloud Code Assist request has no user/model contents.");
571
+ }
572
+ const prompt = args.agentConfig.prompt?.trim();
573
+ if (prompt) systemTexts.unshift(prompt);
574
+ const request = { contents };
575
+ if (systemTexts.length > 0) {
576
+ request.systemInstruction = {
577
+ role: "user",
578
+ parts: systemTexts.map((text) => ({ text }))
579
+ };
580
+ }
581
+ const tools = convertOpenAiToolsToGemini(
582
+ Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools : void 0
583
+ );
584
+ if (tools) {
585
+ request.tools = tools;
586
+ request.toolConfig = { functionCallingConfig: { mode: "AUTO" } };
587
+ }
588
+ const generationConfig = {};
589
+ if (profile?.maxOutputTokens) {
590
+ generationConfig.maxOutputTokens = profile.maxOutputTokens;
591
+ } else if (typeof args.agentConfig.max_tokens === "number" && args.agentConfig.max_tokens > 0) {
592
+ generationConfig.maxOutputTokens = args.agentConfig.max_tokens;
593
+ }
594
+ if (typeof args.agentConfig.temperature === "number") {
595
+ generationConfig.temperature = args.agentConfig.temperature;
596
+ }
597
+ if (Object.keys(generationConfig).length > 0) {
598
+ request.generationConfig = generationConfig;
599
+ }
600
+ const agentId = randomUUID();
601
+ const trajectoryId = randomUUID();
602
+ const step = 2;
603
+ const requestId = `agent/${agentId}/${Date.now()}/${trajectoryId}/${step}`;
604
+ const labels = {
605
+ trajectory_id: trajectoryId,
606
+ last_step_index: String(step - 1),
607
+ used_claude: String(isClaude),
608
+ used_claude_conservative: String(isClaude)
609
+ };
610
+ if (profile?.modelEnum) {
611
+ labels.model_enum = profile.modelEnum;
612
+ }
613
+ request.labels = labels;
614
+ request.sessionId = `-${Math.floor(Math.random() * 9e15)}`;
615
+ return {
616
+ url: `${resolveAntigravityCloudCodeBaseUrl(args.agentConfig.customProviderUrl)}${STREAM_PATH}`,
617
+ envelope: {
618
+ project: projectId,
619
+ model,
620
+ request,
621
+ requestId,
622
+ requestType: "agent",
623
+ userAgent: "antigravity"
624
+ }
625
+ };
626
+ }
627
+ function resolveAntigravityFinishReason(upstream) {
628
+ const normalized = (upstream ?? "").trim().toUpperCase();
629
+ if (normalized === "MAX_TOKENS") return "length";
630
+ if (normalized === "SAFETY" || normalized === "RECITATION" || normalized === "PROHIBITED_CONTENT" || normalized === "BLOCKLIST") {
631
+ return "content_filter";
632
+ }
633
+ return "stop";
634
+ }
635
+ function normalizeAntigravityCompletion(decoded) {
636
+ const { text, toolCalls, usage, finishReason, reasoningContent, events } = decoded;
637
+ const normalizedFinishReason = (finishReason ?? "").trim().toUpperCase();
638
+ if (!text && !reasoningContent && toolCalls.length === 0 && !finishReason && !usage) {
639
+ const body = {
640
+ error: {
641
+ message: "antigravity upstream returned an empty stream (no content, finishReason or usage); channel degradation, not model emptiness"
642
+ },
643
+ provider_events: events
644
+ };
645
+ return {
646
+ status: 502,
647
+ text: "",
648
+ toolCalls: [],
649
+ providerEvents: events,
650
+ body
651
+ };
652
+ }
653
+ if (normalizedFinishReason === "MALFORMED_FUNCTION_CALL") {
654
+ const message2 = "antigravity upstream returned MALFORMED_FUNCTION_CALL (model generated an invalid function call or tool arguments were rejected by upstream)";
655
+ const providerFailure = {
656
+ kind: "provider_failure",
657
+ provider: "antigravity",
658
+ code: "MALFORMED_FUNCTION_CALL",
659
+ message: message2,
660
+ providerReason: "MALFORMED_FUNCTION_CALL",
661
+ retryable: false,
662
+ status: 502
663
+ };
664
+ return {
665
+ status: 502,
666
+ text: "",
667
+ toolCalls: [],
668
+ finishReason,
669
+ providerEvents: events,
670
+ providerFailure,
671
+ runtimeProviderFailure: {
672
+ message: providerFailure.message,
673
+ retryable: providerFailure.retryable
674
+ },
675
+ body: {
676
+ error: {
677
+ message: message2,
678
+ code: "MALFORMED_FUNCTION_CALL",
679
+ category: "malformed_function_call",
680
+ providerReason: "MALFORMED_FUNCTION_CALL",
681
+ retryable: false
682
+ },
683
+ provider_failure: providerFailure,
684
+ provider_events: events
685
+ }
686
+ };
687
+ }
688
+ const message = {
689
+ role: "assistant",
690
+ content: text || null
691
+ };
692
+ if (toolCalls.length > 0) message.tool_calls = toolCalls;
693
+ if (reasoningContent) message.reasoning_content = reasoningContent;
694
+ return {
695
+ status: 200,
696
+ text,
697
+ ...reasoningContent ? { reasoningContent } : {},
698
+ toolCalls,
699
+ ...usage ? { usage } : {},
700
+ ...finishReason ? { finishReason } : {},
701
+ providerEvents: events,
702
+ body: {
703
+ choices: [{
704
+ index: 0,
705
+ message,
706
+ finish_reason: toolCalls.length > 0 ? "tool_calls" : resolveAntigravityFinishReason(finishReason)
707
+ }],
708
+ ...usage ? { usage } : {},
709
+ provider_events: events
710
+ }
711
+ };
712
+ }
713
+ async function fetchAntigravityCloudCodeCompletion(args) {
714
+ const fetchImpl = args.fetchImpl ?? fetch;
715
+ const { url, envelope } = buildCloudCodeAssistPayload(args);
716
+ const response = await fetchImpl(url, {
717
+ method: "POST",
718
+ headers: {
719
+ Authorization: `Bearer ${args.accessToken}`,
720
+ "Content-Type": "application/json",
721
+ "User-Agent": getAntigravityUserAgent()
722
+ },
723
+ body: JSON.stringify(envelope),
724
+ signal: args.signal
725
+ });
726
+ if (!response.ok) {
727
+ const errorText = await response.text();
728
+ return {
729
+ status: response.status,
730
+ text: "",
731
+ toolCalls: [],
732
+ providerEvents: [],
733
+ // 保留上游结构:Antigravity 的限流 body 同样携带结构化的重置信息,
734
+ // 压成字符串会让冷却退化成 5 分钟默认值。
735
+ body: parseUpstreamErrorBody(errorText, response.statusText)
736
+ };
737
+ }
738
+ const chunkStream = streamSseDataValues(response, parseSseDataLineJson);
739
+ const { text, toolCalls, usage, finishReason, reasoningContent, events } = await accumulateGeminiStream(chunkStream, {
740
+ onTextDelta: args.onTextDelta,
741
+ onReasoningDelta: args.onReasoningDelta
742
+ });
743
+ const normalized = normalizeAntigravityCompletion({
744
+ text,
745
+ toolCalls,
746
+ usage,
747
+ finishReason,
748
+ reasoningContent,
749
+ events
750
+ });
751
+ if (normalized.status !== 200 || !text && toolCalls.length === 0) {
752
+ console.warn(
753
+ `[antigravity] empty completion: finishReason=${JSON.stringify(finishReason)} reasoningLen=${reasoningContent?.length ?? 0} usage=${JSON.stringify(usage) ?? "none"} model=${String(envelope.model)} base=${new URL(url).host}`
754
+ );
755
+ }
756
+ return normalized;
757
+ }
758
+
759
+ // packages/agent-runtime/devinOAuth.ts
760
+ import { existsSync, readFileSync } from "node:fs";
761
+ import { homedir } from "node:os";
762
+ import { join } from "node:path";
763
+ var DEVIN_CONNECT_URL = "https://server.codeium.com/exa.api_server_pb.ApiServerService/GetChatMessage";
764
+ function buildDevinAuthUrl(orgId) {
765
+ const cleanOrg = orgId?.trim();
766
+ if (cleanOrg) {
767
+ return `https://app.devin.ai/org/${encodeURIComponent(cleanOrg)}/settings/keys`;
768
+ }
769
+ return "https://app.devin.ai/settings/keys";
770
+ }
771
+ function extractDevinToken(input) {
772
+ const raw = input?.trim();
773
+ if (!raw) return null;
774
+ if (/^https?:\/\//i.test(raw)) {
775
+ try {
776
+ const url = new URL(raw);
777
+ const queryToken = url.searchParams.get("token") || url.searchParams.get("access_token") || url.searchParams.get("auth_token");
778
+ if (queryToken?.trim()) return queryToken.trim();
779
+ if (url.hash) {
780
+ const hashParams = new URLSearchParams(url.hash.replace(/^#/, ""));
781
+ const hashToken = hashParams.get("token") || hashParams.get("access_token") || hashParams.get("auth_token");
782
+ if (hashToken?.trim()) return hashToken.trim();
783
+ }
784
+ } catch {
785
+ }
786
+ }
787
+ return raw || null;
788
+ }
789
+ function parseDevinCredentialsToml(content) {
790
+ for (const line of content.split(/\r?\n/)) {
791
+ const cogMatch = line.match(/(cog_[A-Za-z0-9_-]+)/);
792
+ if (cogMatch?.[1]) {
793
+ return cogMatch[1].trim();
794
+ }
795
+ const match = line.match(
796
+ /^\s*(?:windsurf_api_key|devin_api_key|api_key|api_token|token)\s*=\s*"([^"]+)"\s*$/i
797
+ );
798
+ if (match?.[1]) {
799
+ return match[1].trim();
800
+ }
801
+ }
802
+ return null;
803
+ }
804
+ function detectLocalDevinCredentials(options) {
805
+ const baseHome = options?.homeDir || homedir();
806
+ const xdgData = process.env.XDG_DATA_HOME;
807
+ const candidateCliPaths = [
808
+ xdgData ? join(xdgData, "devin", "credentials.toml") : null,
809
+ join(baseHome, ".local", "share", "devin", "credentials.toml"),
810
+ process.env.APPDATA ? join(process.env.APPDATA, "devin", "credentials.toml") : null
811
+ ].filter((p) => Boolean(p));
812
+ for (const credPath of candidateCliPaths) {
813
+ if (existsSync(credPath)) {
814
+ try {
815
+ const content = readFileSync(credPath, "utf-8");
816
+ const token = parseDevinCredentialsToml(content);
817
+ if (token) {
818
+ return {
819
+ found: true,
820
+ token,
821
+ source: "devin-cli",
822
+ sourcePath: credPath
823
+ };
824
+ }
825
+ } catch {
826
+ }
827
+ }
828
+ }
829
+ const codeiumPath = join(baseHome, ".codeium", "config.json");
830
+ if (existsSync(codeiumPath)) {
831
+ try {
832
+ const parsed = JSON.parse(readFileSync(codeiumPath, "utf-8"));
833
+ const token = parsed.apiKey || parsed.api_key;
834
+ if (token?.trim()) {
835
+ return {
836
+ found: true,
837
+ token: token.trim(),
838
+ source: "codeium-config",
839
+ sourcePath: codeiumPath
840
+ };
841
+ }
842
+ } catch {
843
+ }
844
+ }
845
+ return { found: false };
846
+ }
847
+ function buildDevinOAuthCredential(token, now = Date.now()) {
848
+ return {
849
+ provider: "devin",
850
+ accessToken: token.trim(),
851
+ obtainedAt: now
852
+ };
853
+ }
854
+
855
+ export {
856
+ parseSseDataLineJson,
857
+ parseSseDataLineObject,
858
+ parseUpstreamErrorBody,
859
+ isGemini3Model,
860
+ accumulateGeminiChunks,
861
+ shouldUseGeminiNativeToolRoute,
862
+ buildGeminiGenerateContentRequest,
863
+ resolveAntigravityFinishReason,
864
+ fetchAntigravityCloudCodeCompletion,
865
+ DEVIN_CONNECT_URL,
866
+ buildDevinAuthUrl,
867
+ extractDevinToken,
868
+ detectLocalDevinCredentials,
869
+ buildDevinOAuthCredential
870
+ };