@sayknow-cli/coding-agent 0.3.0 → 0.3.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.
- package/bin/skc.js +4 -0
- package/dist/types/cli/mcp-cli.d.ts +25 -0
- package/dist/types/cli/notify-cli.d.ts +2 -0
- package/dist/types/cli/plugin-cli.d.ts +2 -0
- package/dist/types/cli.d.ts +6 -0
- package/dist/types/commands/mcp.d.ts +70 -0
- package/dist/types/commands/plugin.d.ts +6 -0
- package/dist/types/commands/session.d.ts +6 -0
- package/dist/types/config/keybindings.d.ts +2 -2
- package/dist/types/config/model-profile-activation.d.ts +8 -1
- package/dist/types/config/settings-schema.d.ts +39 -2
- package/dist/types/deep-interview/plaintext-gate-guard.d.ts +11 -0
- package/dist/types/defaults/skc-defaults.d.ts +2 -13
- package/dist/types/extensibility/shared-events.d.ts +1 -0
- package/dist/types/extensibility/skc-plugins/compiler.d.ts +19 -0
- package/dist/types/extensibility/skc-plugins/constrained-hooks.d.ts +29 -0
- package/dist/types/extensibility/skc-plugins/index.d.ts +9 -0
- package/dist/types/extensibility/skc-plugins/injection.d.ts +9 -0
- package/dist/types/extensibility/skc-plugins/installer.d.ts +13 -0
- package/dist/types/extensibility/skc-plugins/mcp-policy.d.ts +26 -0
- package/dist/types/extensibility/skc-plugins/observability.d.ts +27 -0
- package/dist/types/extensibility/skc-plugins/prompt-appendix.d.ts +16 -0
- package/dist/types/extensibility/skc-plugins/registry.d.ts +32 -0
- package/dist/types/extensibility/skc-plugins/runtime-adapters.d.ts +64 -0
- package/dist/types/extensibility/skc-plugins/session-validation.d.ts +42 -0
- package/dist/types/extensibility/skc-plugins/types.d.ts +158 -2
- package/dist/types/extensibility/skc-plugins/validation.d.ts +8 -1
- package/dist/types/lsp/types.d.ts +2 -0
- package/dist/types/main.d.ts +2 -0
- package/dist/types/modes/components/custom-editor.d.ts +1 -1
- package/dist/types/modes/components/model-selector.d.ts +8 -0
- package/dist/types/modes/components/status-line/git-utils.d.ts +6 -0
- package/dist/types/modes/theme/defaults/index.d.ts +99 -0
- package/dist/types/notifications/attachment-registry.d.ts +17 -0
- package/dist/types/notifications/chat-adapters.d.ts +9 -0
- package/dist/types/notifications/config.d.ts +9 -1
- package/dist/types/notifications/engine.d.ts +59 -0
- package/dist/types/notifications/html-format.d.ts +11 -0
- package/dist/types/notifications/index.d.ts +149 -1
- package/dist/types/notifications/lifecycle-commands.d.ts +60 -0
- package/dist/types/notifications/lifecycle-control-runtime.d.ts +98 -0
- package/dist/types/notifications/lifecycle-orchestrator.d.ts +144 -0
- package/dist/types/notifications/managed-daemon.d.ts +48 -0
- package/dist/types/notifications/operator-runtime.d.ts +52 -0
- package/dist/types/notifications/rate-limit-pool.d.ts +2 -0
- package/dist/types/notifications/recent-activity.d.ts +35 -0
- package/dist/types/notifications/telegram-daemon.d.ts +133 -16
- package/dist/types/notifications/telegram-reference.d.ts +3 -1
- package/dist/types/notifications/threaded-inbound.d.ts +19 -0
- package/dist/types/notifications/threaded-render.d.ts +6 -1
- package/dist/types/notifications/topic-registry.d.ts +12 -9
- package/dist/types/runtime-mcp/types.d.ts +7 -0
- package/dist/types/sdk.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +16 -4
- package/dist/types/session/blob-store.d.ts +25 -0
- package/dist/types/session/session-manager.d.ts +57 -0
- package/dist/types/skc-runtime/launch-tmux.d.ts +1 -0
- package/dist/types/skc-runtime/psmux-detect.d.ts +78 -0
- package/dist/types/skc-runtime/ralplan-runtime.d.ts +1 -1
- package/dist/types/skc-runtime/team-runtime.d.ts +2 -0
- package/dist/types/skc-runtime/tmux-common.d.ts +30 -2
- package/dist/types/skc-runtime/tmux-sessions.d.ts +18 -0
- package/dist/types/slash-commands/helpers/fast-status-report.d.ts +6 -0
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +9 -1
- package/dist/types/tools/composer-bash-policy.d.ts +14 -0
- package/dist/types/tools/fetch.d.ts +23 -0
- package/dist/types/tools/index.d.ts +4 -1
- package/dist/types/tools/telegram-send.d.ts +32 -0
- package/dist/types/utils/changelog.d.ts +1 -0
- package/dist/types/web/insane/bridge.d.ts +103 -0
- package/dist/types/web/insane/url-guard.d.ts +25 -0
- package/dist/types/web/scrapers/types.d.ts +5 -0
- package/dist/types/web/scrapers/utils.d.ts +7 -1
- package/dist/types/web/search/provider.d.ts +18 -1
- package/dist/types/web/search/providers/insane.d.ts +53 -0
- package/dist/types/web/search/providers/text-citations.d.ts +23 -0
- package/dist/types/web/search/types.d.ts +12 -4
- package/package.json +14 -10
- package/scripts/g004-tmux-smoke.ts +100 -0
- package/scripts/g005-daemon-smoke.ts +180 -0
- package/scripts/g011-daemon-path-smoke.ts +153 -0
- package/scripts/verify-insane-vendor.ts +132 -0
- package/src/cli/args.ts +1 -1
- package/src/cli/fast-help.ts +30 -2
- package/src/cli/mcp-cli.ts +272 -0
- package/src/cli/notify-cli.ts +152 -5
- package/src/cli/plugin-cli.ts +66 -3
- package/src/cli.ts +30 -12
- package/src/commands/mcp.ts +117 -0
- package/src/commands/plugin.ts +4 -0
- package/src/commands/session.ts +18 -0
- package/src/commands/team.ts +1 -1
- package/src/config/keybindings.ts +2 -2
- package/src/config/model-profile-activation.ts +55 -7
- package/src/config/settings-schema.ts +30 -1
- package/src/deep-interview/plaintext-gate-guard.ts +94 -0
- package/src/defaults/skc/extensions/grok-cli-vendor/biome.json +1 -1
- package/src/defaults/skc/skills/deep-interview/SKILL.md +7 -6
- package/src/defaults/skc/skills/ralplan/SKILL.md +11 -4
- package/src/defaults/skc/skills/team/SKILL.md +5 -3
- package/src/defaults/skc/skills/ultragoal/SKILL.md +41 -13
- package/src/defaults/skc-defaults.ts +2 -27
- package/src/export/html/index.ts +2 -2
- package/src/extensibility/extensions/runner.ts +1 -0
- package/src/extensibility/shared-events.ts +1 -0
- package/src/extensibility/skc-plugins/compiler.ts +351 -0
- package/src/extensibility/skc-plugins/constrained-hooks.ts +170 -0
- package/src/extensibility/skc-plugins/index.ts +9 -0
- package/src/extensibility/skc-plugins/injection.ts +109 -0
- package/src/extensibility/skc-plugins/installer.ts +434 -0
- package/src/extensibility/skc-plugins/loader.ts +3 -1
- package/src/extensibility/skc-plugins/mcp-policy.ts +239 -0
- package/src/extensibility/skc-plugins/observability.ts +84 -0
- package/src/extensibility/skc-plugins/paths.ts +1 -1
- package/src/extensibility/skc-plugins/prompt-appendix.ts +109 -0
- package/src/extensibility/skc-plugins/registry.ts +180 -0
- package/src/extensibility/skc-plugins/runtime-adapters.ts +234 -0
- package/src/extensibility/skc-plugins/schema.ts +250 -20
- package/src/extensibility/skc-plugins/session-validation.ts +147 -0
- package/src/extensibility/skc-plugins/types.ts +199 -3
- package/src/extensibility/skc-plugins/validation.ts +80 -0
- package/src/extensibility/skills.ts +15 -0
- package/src/hooks/skill-state.ts +57 -0
- package/src/internal-urls/docs-index.generated.ts +17 -13
- package/src/lsp/config.ts +16 -3
- package/src/lsp/defaults.json +7 -0
- package/src/lsp/types.ts +2 -0
- package/src/main.ts +14 -3
- package/src/modes/bridge/bridge-mode.ts +11 -0
- package/src/modes/components/assistant-message.ts +49 -1
- package/src/modes/components/custom-editor.ts +2 -0
- package/src/modes/components/footer.ts +2 -3
- package/src/modes/components/hook-editor.ts +1 -1
- package/src/modes/components/hook-selector.ts +67 -43
- package/src/modes/components/model-selector.ts +56 -11
- package/src/modes/components/status-line/git-utils.ts +25 -0
- package/src/modes/components/status-line.ts +10 -11
- package/src/modes/components/welcome.ts +2 -3
- package/src/modes/controllers/event-controller.ts +15 -0
- package/src/modes/controllers/extension-ui-controller.ts +0 -27
- package/src/modes/controllers/selector-controller.ts +53 -11
- package/src/modes/interactive-mode.ts +50 -3
- package/src/modes/shared/agent-wire/scopes.ts +1 -1
- package/src/modes/theme/defaults/gruvbox-dark.json +99 -0
- package/src/modes/theme/defaults/index.ts +2 -0
- package/src/modes/utils/context-usage.ts +2 -2
- package/src/modes/utils/hotkeys-markdown.ts +1 -1
- package/src/notifications/attachment-registry.ts +23 -0
- package/src/notifications/chat-adapters.ts +147 -0
- package/src/notifications/config.ts +23 -2
- package/src/notifications/engine.ts +100 -0
- package/src/notifications/html-format.ts +38 -0
- package/src/notifications/index.ts +417 -45
- package/src/notifications/lifecycle-commands.ts +238 -0
- package/src/notifications/lifecycle-control-runtime.ts +405 -0
- package/src/notifications/lifecycle-orchestrator.ts +358 -0
- package/src/notifications/managed-daemon.ts +163 -0
- package/src/notifications/operator-runtime.ts +171 -0
- package/src/notifications/rate-limit-pool.ts +19 -0
- package/src/notifications/recent-activity.ts +132 -0
- package/src/notifications/telegram-daemon.ts +984 -242
- package/src/notifications/telegram-reference.ts +25 -7
- package/src/notifications/threaded-inbound.ts +60 -4
- package/src/notifications/threaded-render.ts +20 -2
- package/src/notifications/topic-registry.ts +23 -9
- package/src/prompts/agents/executor.md +2 -2
- package/src/runtime-mcp/transports/stdio.ts +38 -4
- package/src/runtime-mcp/types.ts +7 -0
- package/src/sdk.ts +157 -10
- package/src/session/agent-session.ts +248 -125
- package/src/session/blob-store.ts +196 -8
- package/src/session/session-manager.ts +762 -12
- package/src/skc-runtime/launch-tmux.ts +85 -22
- package/src/skc-runtime/ledger-event-renderer.ts +1 -0
- package/src/skc-runtime/psmux-detect.ts +239 -0
- package/src/skc-runtime/ralplan-runtime.ts +2 -2
- package/src/skc-runtime/team-runtime.ts +56 -23
- package/src/skc-runtime/tmux-common.ts +88 -4
- package/src/skc-runtime/tmux-sessions.ts +111 -9
- package/src/skc-runtime/ultragoal-guard.ts +25 -8
- package/src/skc-runtime/ultragoal-runtime.ts +75 -15
- package/src/skc-runtime/workflow-manifest.generated.json +29 -0
- package/src/skc-runtime/workflow-manifest.ts +7 -2
- package/src/slash-commands/builtin-registry.ts +23 -3
- package/src/slash-commands/helpers/fast-status-report.ts +13 -3
- package/src/slash-commands/helpers/parse.ts +2 -1
- package/src/system-prompt.ts +9 -0
- package/src/task/executor.ts +31 -7
- package/src/task/index.ts +2 -0
- package/src/tools/ask.ts +5 -1
- package/src/tools/bash.ts +9 -0
- package/src/tools/composer-bash-policy.ts +96 -0
- package/src/tools/fetch.ts +94 -1
- package/src/tools/index.ts +6 -1
- package/src/tools/telegram-send.ts +137 -0
- package/src/utils/changelog.ts +8 -0
- package/src/web/insane/bridge.ts +350 -0
- package/src/web/insane/url-guard.ts +159 -0
- package/src/web/scrapers/types.ts +143 -45
- package/src/web/scrapers/utils.ts +70 -19
- package/src/web/search/provider.ts +77 -18
- package/src/web/search/providers/anthropic.ts +70 -3
- package/src/web/search/providers/codex.ts +1 -119
- package/src/web/search/providers/gemini.ts +99 -0
- package/src/web/search/providers/insane.ts +551 -0
- package/src/web/search/providers/openai-compatible.ts +66 -32
- package/src/web/search/providers/text-citations.ts +111 -0
- package/src/web/search/types.ts +13 -2
- package/vendor/insane-search/LICENSE +21 -0
- package/vendor/insane-search/MANIFEST.json +24 -0
- package/vendor/insane-search/engine/__init__.py +23 -0
- package/vendor/insane-search/engine/__main__.py +128 -0
- package/vendor/insane-search/engine/bias_check.py +183 -0
- package/vendor/insane-search/engine/executor.py +254 -0
- package/vendor/insane-search/engine/fetch_chain.py +725 -0
- package/vendor/insane-search/engine/learning.py +175 -0
- package/vendor/insane-search/engine/phase0.py +214 -0
- package/vendor/insane-search/engine/safety.py +91 -0
- package/vendor/insane-search/engine/templates/package.json +11 -0
- package/vendor/insane-search/engine/templates/playwright_mobile_chrome.js +188 -0
- package/vendor/insane-search/engine/templates/playwright_real_chrome.js +243 -0
- package/vendor/insane-search/engine/tests/test_hardening.py +57 -0
- package/vendor/insane-search/engine/tests/test_smoke.py +152 -0
- package/vendor/insane-search/engine/tests/test_u1.py +200 -0
- package/vendor/insane-search/engine/tests/test_u4.py +131 -0
- package/vendor/insane-search/engine/tests/test_u5.py +163 -0
- package/vendor/insane-search/engine/tests/test_u7.py +124 -0
- package/vendor/insane-search/engine/transport.py +211 -0
- package/vendor/insane-search/engine/url_transforms.py +98 -0
- package/vendor/insane-search/engine/validators.py +331 -0
- package/vendor/insane-search/engine/waf_detector.py +214 -0
- package/vendor/insane-search/engine/waf_profiles.yaml +162 -0
|
@@ -15,6 +15,7 @@ import type { SearchResponse, SearchSource } from "../../../web/search/types";
|
|
|
15
15
|
import { SearchProviderError } from "../../../web/search/types";
|
|
16
16
|
import type { SearchParams } from "./base";
|
|
17
17
|
import { SearchProvider } from "./base";
|
|
18
|
+
import { addSource, extractTextSources } from "./text-citations";
|
|
18
19
|
import { classifyProviderHttpError, withHardTimeout } from "./utils";
|
|
19
20
|
|
|
20
21
|
const CODEX_BASE_URL = "https://chatgpt.com/backend-api";
|
|
@@ -118,125 +119,6 @@ function isImagePlaceholderAnswer(text: string): boolean {
|
|
|
118
119
|
return text.trim().toLowerCase() === "(see attached image)";
|
|
119
120
|
}
|
|
120
121
|
|
|
121
|
-
function addSource(sources: SearchSource[], source: SearchSource): void {
|
|
122
|
-
if (!sources.some(existing => existing.url === source.url)) {
|
|
123
|
-
sources.push(source);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function countCharacter(text: string, target: string): number {
|
|
128
|
-
let count = 0;
|
|
129
|
-
for (const char of text) {
|
|
130
|
-
if (char === target) {
|
|
131
|
-
count += 1;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
return count;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Strips prose punctuation and unmatched closing delimiters from extracted URLs.
|
|
139
|
-
* OpenAI code backend often returns links in markdown or sentence text without structured annotations.
|
|
140
|
-
*/
|
|
141
|
-
function normalizeExtractedUrl(candidate: string): string | null {
|
|
142
|
-
let url = candidate.trim();
|
|
143
|
-
|
|
144
|
-
while (url.length > 0) {
|
|
145
|
-
const lastCharacter = url.at(-1);
|
|
146
|
-
if (!lastCharacter) break;
|
|
147
|
-
if (/[.,!?;:'"]/u.test(lastCharacter)) {
|
|
148
|
-
url = url.slice(0, -1);
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
if (lastCharacter === ")" && countCharacter(url, ")") > countCharacter(url, "(")) {
|
|
152
|
-
url = url.slice(0, -1);
|
|
153
|
-
continue;
|
|
154
|
-
}
|
|
155
|
-
if (lastCharacter === "]" && countCharacter(url, "]") > countCharacter(url, "[")) {
|
|
156
|
-
url = url.slice(0, -1);
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
if (lastCharacter === "}" && countCharacter(url, "}") > countCharacter(url, "{")) {
|
|
160
|
-
url = url.slice(0, -1);
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
break;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (!/^https?:\/\//.test(url)) {
|
|
167
|
-
return null;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
try {
|
|
171
|
-
return new URL(url).toString();
|
|
172
|
-
} catch {
|
|
173
|
-
return null;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
function findMarkdownLinkUrlEnd(text: string, openParenIndex: number): number | null {
|
|
178
|
-
let depth = 0;
|
|
179
|
-
|
|
180
|
-
for (let index = openParenIndex; index < text.length; index += 1) {
|
|
181
|
-
const character = text[index];
|
|
182
|
-
if (!character || character === "\n") {
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
if (character === "(") {
|
|
186
|
-
depth += 1;
|
|
187
|
-
continue;
|
|
188
|
-
}
|
|
189
|
-
if (character !== ")") {
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
depth -= 1;
|
|
193
|
-
if (depth === 0) {
|
|
194
|
-
return index;
|
|
195
|
-
}
|
|
196
|
-
if (depth < 0) {
|
|
197
|
-
return null;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
return null;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Extracts citation sources from markdown links and bare URLs in the answer text.
|
|
206
|
-
* Used as a fallback when the OpenAI code backend response omits `url_citation` annotations.
|
|
207
|
-
*/
|
|
208
|
-
function extractTextSources(text: string): SearchSource[] {
|
|
209
|
-
const sources: SearchSource[] = [];
|
|
210
|
-
|
|
211
|
-
for (let index = 0; index < text.length; index += 1) {
|
|
212
|
-
if (text[index] !== "[") {
|
|
213
|
-
continue;
|
|
214
|
-
}
|
|
215
|
-
const titleEnd = text.indexOf("]", index + 1);
|
|
216
|
-
if (titleEnd === -1 || text[titleEnd + 1] !== "(") {
|
|
217
|
-
continue;
|
|
218
|
-
}
|
|
219
|
-
const urlEnd = findMarkdownLinkUrlEnd(text, titleEnd + 1);
|
|
220
|
-
if (urlEnd === null) {
|
|
221
|
-
continue;
|
|
222
|
-
}
|
|
223
|
-
const title = text.slice(index + 1, titleEnd).trim();
|
|
224
|
-
const url = normalizeExtractedUrl(text.slice(titleEnd + 2, urlEnd));
|
|
225
|
-
if (url) {
|
|
226
|
-
addSource(sources, { title: title || url, url });
|
|
227
|
-
}
|
|
228
|
-
index = urlEnd;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
for (const match of text.matchAll(/https?:\/\/\S+/g)) {
|
|
232
|
-
const url = normalizeExtractedUrl(match[0] ?? "");
|
|
233
|
-
if (!url) continue;
|
|
234
|
-
addSource(sources, { title: url, url });
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
return sources;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
122
|
/**
|
|
241
123
|
* Extracts account ID from a OpenAI code backend access token.
|
|
242
124
|
* @param accessToken - JWT access token
|
|
@@ -425,6 +425,98 @@ export async function searchGemini(params: GeminiSearchParams): Promise<SearchRe
|
|
|
425
425
|
};
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
+
/**
|
|
429
|
+
* Native Gemini web search over the public Generative Language REST API
|
|
430
|
+
* (`{baseUrl}/v1beta/models/{model}:generateContent`), reusing the ACTIVE
|
|
431
|
+
* model's own API key + baseUrl. This is the "native search over a proxy" path
|
|
432
|
+
* for `google-generative-ai` wire models whose canonical gemini-cli/antigravity
|
|
433
|
+
* OAuth is absent. Distinct from {@link searchGemini}, which speaks the Cloud
|
|
434
|
+
* Code Assist API with OAuth.
|
|
435
|
+
*/
|
|
436
|
+
async function searchGeminiViaGenerativeLanguage(params: SearchParams): Promise<SearchResponse> {
|
|
437
|
+
const ctx = params.activeModelContext;
|
|
438
|
+
if (!ctx) throw new SearchProviderError("gemini", "Gemini web search requires active model context", 400);
|
|
439
|
+
const apiKey = await params.authStorage.getApiKey(ctx.provider, params.sessionId, {
|
|
440
|
+
baseUrl: ctx.baseUrl,
|
|
441
|
+
modelId: ctx.modelId,
|
|
442
|
+
signal: params.signal,
|
|
443
|
+
});
|
|
444
|
+
if (!apiKey) throw new SearchProviderError("gemini", `No credentials for ${ctx.provider}`, 401);
|
|
445
|
+
|
|
446
|
+
const model = ctx.wireModelId ?? ctx.modelId;
|
|
447
|
+
const base = (ctx.baseUrl ?? "https://generativelanguage.googleapis.com").replace(/\/+$/, "");
|
|
448
|
+
// Respect an already-versioned active baseUrl (e.g. a proxy exposing `…/v1beta`)
|
|
449
|
+
// instead of double-appending the version segment.
|
|
450
|
+
const versionedBase = /\/v1(beta|alpha)?$/.test(base) ? base : `${base}/v1beta`;
|
|
451
|
+
const url = `${versionedBase}/models/${encodeURIComponent(model)}:generateContent`;
|
|
452
|
+
const systemPrompt = params.systemPrompt?.toWellFormed();
|
|
453
|
+
const body: Record<string, unknown> = {
|
|
454
|
+
contents: [{ role: "user", parts: [{ text: params.query }] }],
|
|
455
|
+
tools: buildGeminiRequestTools({ google_search: params.googleSearch }),
|
|
456
|
+
...(systemPrompt ? { systemInstruction: { parts: [{ text: systemPrompt }] } } : {}),
|
|
457
|
+
};
|
|
458
|
+
if (params.maxOutputTokens !== undefined || params.temperature !== undefined) {
|
|
459
|
+
const generationConfig: Record<string, number> = {};
|
|
460
|
+
if (params.maxOutputTokens !== undefined) generationConfig.maxOutputTokens = params.maxOutputTokens;
|
|
461
|
+
if (params.temperature !== undefined) generationConfig.temperature = params.temperature;
|
|
462
|
+
body.generationConfig = generationConfig;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const response = await fetch(url, {
|
|
466
|
+
method: "POST",
|
|
467
|
+
headers: { ...(ctx.headers ?? {}), "x-goog-api-key": apiKey, "Content-Type": "application/json" },
|
|
468
|
+
body: JSON.stringify(body),
|
|
469
|
+
signal: withHardTimeout(params.signal),
|
|
470
|
+
});
|
|
471
|
+
const text = await response.text();
|
|
472
|
+
if (!response.ok) {
|
|
473
|
+
const classified = classifyProviderHttpError("gemini", response.status, text);
|
|
474
|
+
if (classified) throw classified;
|
|
475
|
+
throw new SearchProviderError("gemini", `Gemini API error (${response.status}): ${text}`, response.status);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
const json = text ? JSON.parse(text) : {};
|
|
479
|
+
const candidate = json.candidates?.[0];
|
|
480
|
+
const grounding: GeminiGroundingMetadata | undefined = candidate?.groundingMetadata;
|
|
481
|
+
const answer = (candidate?.content?.parts ?? []).map((part: { text?: string }) => part.text ?? "").join("");
|
|
482
|
+
|
|
483
|
+
const sources: SearchSource[] = [];
|
|
484
|
+
const citations: SearchCitation[] = [];
|
|
485
|
+
const searchQueries: string[] = [];
|
|
486
|
+
const seenUrls = new Set<string>();
|
|
487
|
+
const chunks = grounding?.groundingChunks ?? [];
|
|
488
|
+
for (const grChunk of chunks) {
|
|
489
|
+
const uri = grChunk.web?.uri;
|
|
490
|
+
if (uri && !seenUrls.has(uri)) {
|
|
491
|
+
seenUrls.add(uri);
|
|
492
|
+
sources.push({ title: grChunk.web?.title ?? uri, url: uri });
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
for (const support of grounding?.groundingSupports ?? []) {
|
|
496
|
+
const citedText = support.segment?.text;
|
|
497
|
+
for (const idx of support.groundingChunkIndices ?? []) {
|
|
498
|
+
const uri = chunks[idx]?.web?.uri;
|
|
499
|
+
if (uri) citations.push({ url: uri, title: chunks[idx]?.web?.title ?? uri, citedText });
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
for (const q of grounding?.webSearchQueries ?? []) {
|
|
503
|
+
if (!searchQueries.includes(q)) searchQueries.push(q);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
if (sources.length === 0) {
|
|
507
|
+
throw new SearchProviderError("gemini", "Gemini native search returned no grounding sources", 424);
|
|
508
|
+
}
|
|
509
|
+
const limit = params.numSearchResults ?? params.limit;
|
|
510
|
+
return {
|
|
511
|
+
provider: "gemini",
|
|
512
|
+
answer: answer || undefined,
|
|
513
|
+
sources: limit && sources.length > limit ? sources.slice(0, limit) : sources,
|
|
514
|
+
citations: citations.length > 0 ? citations : undefined,
|
|
515
|
+
searchQueries: searchQueries.length > 0 ? searchQueries : undefined,
|
|
516
|
+
model: json.modelVersion ?? model,
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
|
|
428
520
|
/** Search provider for Google Gemini web search. */
|
|
429
521
|
export class GeminiProvider extends SearchProvider {
|
|
430
522
|
readonly id = "gemini";
|
|
@@ -438,6 +530,13 @@ export class GeminiProvider extends SearchProvider {
|
|
|
438
530
|
}
|
|
439
531
|
|
|
440
532
|
search(params: SearchParams): Promise<SearchResponse> {
|
|
533
|
+
// Native-over-proxy: when canonical gemini-cli/antigravity OAuth is
|
|
534
|
+
// absent but the active model speaks the Generative Language wire, reuse
|
|
535
|
+
// its own API key + baseUrl instead of failing closed.
|
|
536
|
+
const ctx = params.activeModelContext;
|
|
537
|
+
if (!hasGeminiOAuth(params.authStorage) && ctx?.api === "google-generative-ai") {
|
|
538
|
+
return searchGeminiViaGenerativeLanguage(params);
|
|
539
|
+
}
|
|
441
540
|
return searchGemini({
|
|
442
541
|
query: params.query,
|
|
443
542
|
system_prompt: params.systemPrompt,
|