dsh-agy 0.2.4 → 0.2.5
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/README.md +3 -1
- package/lib/{accounts-DbTTxX_z.mjs → accounts-Blqno5Te.mjs} +4 -4
- package/lib/{accounts-DbTTxX_z.mjs.map → accounts-Blqno5Te.mjs.map} +1 -1
- package/lib/{catalog-iuikPZIb.mjs → catalog-DVHPJjfc.mjs} +32 -3
- package/lib/catalog-DVHPJjfc.mjs.map +1 -0
- package/lib/cli/index.mjs +4 -4
- package/lib/client.d.ts +8 -0
- package/lib/client.js +36 -0
- package/lib/{exchange-BvrLu2E4.mjs → exchange-C6y05v4v.mjs} +2 -2
- package/lib/{exchange-BvrLu2E4.mjs.map → exchange-C6y05v4v.mjs.map} +1 -1
- package/lib/{import-DSvpbB0T.mjs → import-Dmeiu2Xb.mjs} +3 -3
- package/lib/{import-DSvpbB0T.mjs.map → import-Dmeiu2Xb.mjs.map} +1 -1
- package/lib/index.mjs +2 -2
- package/lib/{models-DRWVi33p.mjs → models-3VFg0nRK.mjs} +5 -4
- package/lib/models-3VFg0nRK.mjs.map +1 -0
- package/lib/{plugin-common-D7lc-W6b.mjs → plugin-common-CP6Czgh9.mjs} +4 -4
- package/lib/{plugin-common-D7lc-W6b.mjs.map → plugin-common-CP6Czgh9.mjs.map} +1 -1
- package/lib/{translate-COjBTH4-.mjs → translate-Zf1mdBri.mjs} +3 -3
- package/lib/{translate-COjBTH4-.mjs.map → translate-Zf1mdBri.mjs.map} +1 -1
- package/lib/web/plugin.mjs +6 -6
- package/package.json +17 -1
- package/lib/catalog-iuikPZIb.mjs.map +0 -1
- package/lib/models-DRWVi33p.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate-COjBTH4-.mjs","names":[],"sources":["../src/runtime/signature-cache.ts","../src/adapter/translate.ts"],"sourcesContent":["/**\n * Gemini thought-signature cache for Antigravity tool calls.\n *\n * The Antigravity backend requires every outbound `functionCall` part to carry\n * a `thoughtSignature` (400 \"Function call is missing a thought_signature\"\n * otherwise). Signatures arrive on the *response* side — as a sibling field of\n * functionCall parts, and on thought parts — and must be replayed on the next\n * turn for the same tool call id. When nothing is cached, the translator\n * injects the `skip_thought_signature_validator` sentinel (the established\n * bypass both reference implementations use by default).\n *\n * Process-local with TTL; a cold process falls back to the sentinel, which the\n * upstream accepts, so cross-process persistence is not required for\n * correctness.\n */\n\nexport const THOUGHT_SIGNATURE_SENTINEL = 'skip_thought_signature_validator'\n\ninterface CacheEntry {\n signature: string\n expiresAt: number\n}\n\nconst DEFAULT_TTL_MS = 60 * 60 * 1000\nconst MAX_ENTRIES = 2000\n\nconst store = new Map<string, CacheEntry>()\n\nfunction pruneExpired(now = Date.now()): void {\n if (store.size < MAX_ENTRIES / 2) return\n for (const [key, entry] of store) {\n if (entry.expiresAt <= now) store.delete(key)\n }\n}\n\n/** Store the signature observed for one tool call id (response side). */\nexport function setThoughtSignature(toolCallId: string, signature: string, ttlMs = DEFAULT_TTL_MS): void {\n if (!toolCallId || !signature) return\n pruneExpired()\n if (store.size >= MAX_ENTRIES) {\n // Evict the oldest entry to keep the cache bounded.\n let oldestKey: string | null = null\n let oldestExpiry = Infinity\n for (const [key, entry] of store) {\n if (entry.expiresAt < oldestExpiry) {\n oldestExpiry = entry.expiresAt\n oldestKey = key\n }\n }\n if (oldestKey) store.delete(oldestKey)\n }\n store.set(toolCallId, { signature, expiresAt: Date.now() + ttlMs })\n}\n\n/** Resolve the signature for one tool call id, or null when unknown/expired. */\nexport function getThoughtSignature(toolCallId: string): string | null {\n if (!toolCallId) return null\n const entry = store.get(toolCallId)\n if (!entry) return null\n if (entry.expiresAt <= Date.now()) {\n store.delete(toolCallId)\n return null\n }\n return entry.signature\n}\n","/**\n * Translate a DSH GenerateOptions into the Antigravity wrapped request.\n *\n * Envelope shape follows the actively-maintained OmniRoute wire format\n * (the archived opencode reference predates it): top-level `project`,\n * `requestId`, `model`, `userAgent`, `requestType`, with the Gemini-style\n * body under `request` (contents/systemInstruction/tools/generationConfig/\n * sessionId). `toolConfig` VALIDATED is attached when tools are present, and\n * Claude-path requests strip trailing model turns (Vertex rejects \"assistant\n * message prefill\").\n *\n * Thinking blocks are carried as-is (Gemini `thought` parts); nothing is\n * stripped or re-signed — that signature dance was an artifact of the\n * reference plugin's interception architecture (see docs/ARCHITECTURE.md).\n */\n\nimport { createHash } from 'node:crypto'\nimport type { ContentBlock, GenerateOptions, Message, ToolSchema } from '@deepseek-ai/dsh-llm'\nimport { generateAntigravityRequestId } from '../runtime/identity.ts'\nimport { getThoughtSignature, THOUGHT_SIGNATURE_SENTINEL } from '../runtime/signature-cache.ts'\nimport { catalogModel, isLevelThinkingModel } from './catalog.ts'\n\nexport type AgyPart =\n | { text: string }\n | { thought: true; text: string }\n | { thoughtSignature: string; functionCall: { id: string; name: string; args: unknown } }\n | { functionResponse: { name: string; response: unknown } }\n | { inlineData: { mimeType: string; data: string } }\n\n/** Image bytes pre-resolved from the durable attachment store, keyed by attachment id. */\nexport interface AgyResolvedImage {\n mediaType: string\n /** Pure base64 (no data: prefix). */\n data: string\n}\n\nexport interface AgyContent {\n role: 'user' | 'model'\n parts: AgyPart[]\n}\n\nexport interface AgyRequestBody {\n project?: string\n requestId?: string\n model: string\n userAgent?: string\n requestType?: 'agent'\n request: {\n contents: AgyContent[]\n systemInstruction?: { parts: Array<{ text: string }> }\n tools?: Array<{ functionDeclarations: Array<{ name: string; description: string; parameters: unknown }> }>\n toolConfig?: { functionCallingConfig: { mode: 'VALIDATED' } }\n generationConfig?: {\n temperature?: number\n maxOutputTokens?: number\n stopSequences?: string[]\n thinkingConfig?: { thinkingLevel: string; includeThoughts: boolean }\n }\n sessionId?: string\n }\n}\n\n/** Whether a model id belongs to a Claude-branded model (Vertex-hosted). */\nexport function isClaudeModel(model: string): boolean {\n return model.startsWith('claude-') || model.includes('/claude')\n}\n\n/**\n * Vertex (the Antigravity Claude backend) rejects conversations ending on an\n * assistant/model turn (\"assistant message prefill\"); never strip to empty.\n */\nexport function stripTrailingModelTurn(contents: AgyContent[]): AgyContent[] {\n while (contents.length > 1 && contents[contents.length - 1]?.role === 'model') {\n contents.pop()\n }\n return contents\n}\n\n/**\n * The Antigravity backend parses tool `parameters` as a strict protobuf\n * schema and rejects ANY unknown keyword with 400 (verified empirically:\n * `$schema`, `propertyNames`, `pattern`, `minLength`, ... each fail in turn).\n * Denylisting is whack-a-mole, so keep only the keywords the upstream\n * accepts. Container shapes are handled distinctly: `properties` is a\n * name->schema map (keys preserved), `items`/`additionalProperties` are\n * nested schemas (additionalProperties also accepts a boolean — live-verified\n * against the Antigravity upstream), `required`/`enum` are plain arrays.\n *\n * Keyword VALUES are also constrained by the protobuf shape (verified\n * empirically): `type` must be a single enum string (union arrays like\n * `[\"string\",\"number\"]` are rejected) and every `enum` item must be a\n * string (booleans/numbers are rejected). Values are normalized to the\n * nearest valid form instead of being dropped wholesale.\n */\n// Exported for the contract invariant test (tests/adapter.test.ts); not part of\n// the package public API (translate.ts is an internal module).\nexport const AGY_SCHEMA_ALLOWLIST = new Set([\n 'type', 'format', 'title', 'description', 'nullable',\n 'items', 'enum', 'default', 'properties', 'required', 'additionalProperties',\n])\nconst AGY_SCHEMA_MAP_KEYS = new Set(['properties'])\nconst AGY_SCHEMA_NESTED_KEYS = new Set(['items', 'additionalProperties'])\nconst AGY_SCHEMA_LIST_KEYS = new Set(['required', 'enum'])\n\nfunction sanitizeToolSchema(schema: unknown): unknown {\n if (!schema || typeof schema !== 'object') return schema\n if (Array.isArray(schema)) return schema.map((entry) => sanitizeToolSchema(entry))\n\n // Normalize union types: upstream `type` is a single enum string. Pick the\n // first non-null string type (`\"null\"` maps to the `nullable` keyword);\n // fall back to `string` when no usable type remains.\n let normalized = schema as Record<string, unknown>\n if (Array.isArray(normalized.type)) {\n const types = normalized.type.filter((t): t is string => typeof t === 'string' && t !== 'null')\n normalized = { ...normalized, type: types[0] ?? 'string' }\n }\n\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(normalized)) {\n if (!AGY_SCHEMA_ALLOWLIST.has(key)) continue\n if (AGY_SCHEMA_MAP_KEYS.has(key)) {\n const map: Record<string, unknown> = {}\n for (const [name, child] of Object.entries(value as Record<string, unknown>)) {\n map[name] = sanitizeToolSchema(child)\n }\n result[key] = map\n continue\n }\n if (AGY_SCHEMA_NESTED_KEYS.has(key)) {\n result[key] = sanitizeToolSchema(value)\n continue\n }\n if (AGY_SCHEMA_LIST_KEYS.has(key)) {\n // Upstream `enum` items must be strings; filter the rest and omit an\n // empty enum entirely (an empty array would be rejected too).\n if (key === 'enum' && Array.isArray(value)) {\n const filtered = value.filter((v): v is string => typeof v === 'string')\n if (filtered.length > 0) result[key] = filtered\n } else {\n result[key] = value\n }\n continue\n }\n result[key] = value\n }\n return result\n}\n\n/** Collect tool-call names by id so tool-result blocks can name their function. */\nfunction buildToolNameIndex(messages: readonly Message[]): Map<string, string> {\n const index = new Map<string, string>()\n for (const message of messages) {\n for (const block of message.content) {\n if (block.type === 'tool-call') {\n index.set(block.id, block.name)\n }\n }\n }\n return index\n}\n\nfunction blockToParts(\n block: ContentBlock,\n toolNames: Map<string, string>,\n images: Map<string, AgyResolvedImage>,\n): AgyPart[] {\n switch (block.type) {\n case 'text':\n return [{ text: block.text }]\n case 'reasoning':\n return [{ thought: true, text: block.text }]\n case 'tool-call': {\n // Upstream parses functionCall.args as google.protobuf.Struct and\n // rejects a raw string with 400. Guarantee an object: parse the string\n // form, fall back to {} when it is truncated/malformed (the failure\n // mode for long multi-turn histories).\n let args: unknown = {}\n if (typeof block.arguments === 'object' && block.arguments !== null && !Array.isArray(block.arguments)) {\n args = block.arguments\n } else if (typeof block.arguments === 'string') {\n try {\n const parsed: unknown = JSON.parse(block.arguments)\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n args = parsed\n }\n } catch {\n // truncated/malformed JSON -> empty object\n }\n }\n // Antigravity rejects functionCall parts without a thoughtSignature\n // (400). Replay the signature captured for this tool call id on the\n // previous turn; the sentinel is the established bypass when nothing is\n // cached (both reference implementations default to it).\n const signature = getThoughtSignature(block.id) ?? THOUGHT_SIGNATURE_SENTINEL\n return [{\n thoughtSignature: signature,\n functionCall: { id: block.id, name: block.name, args },\n }]\n }\n case 'tool-result': {\n const name = toolNames.get(block.toolCallId) ?? block.toolCallId\n const text = block.content\n .filter((b): b is Extract<ContentBlock, { type: 'text' }> => b.type === 'text')\n .map((b) => b.text)\n .join('\\n')\n return [{\n functionResponse: {\n name,\n response: { result: text, is_error: block.isError === true },\n },\n }]\n }\n case 'image': {\n // Bytes are pre-resolved by the adapter before translation; a missing\n // entry breaks that invariant and must fail loudly, never silently drop.\n const resolved = images.get(block.attachment.attachmentId)\n if (!resolved) {\n throw new Error(`agy translate: unresolved image attachment \"${block.attachment.attachmentId}\"`)\n }\n return [{ inlineData: { mimeType: resolved.mediaType, data: resolved.data } }]\n }\n default:\n return [] // unknown block types (merge-extensible) are skipped\n }\n}\n\nfunction messageToContent(\n message: Message,\n toolNames: Map<string, string>,\n images: Map<string, AgyResolvedImage>,\n): AgyContent | null {\n const parts = message.content.flatMap((block) =>\n // Non-user images are out of scope by policy (docs ANTIGRAVITY-API §3.2):\n // skip them like any other untranslatable block instead of tripping the\n // unresolved-map guard, which protects only the user-image invariant.\n block.type === 'image' && message.role !== 'user'\n ? []\n : blockToParts(block, toolNames, images),\n )\n if (parts.length === 0) return null\n const role = message.role === 'assistant' ? 'model' : 'user'\n return { role, parts }\n}\n\n/**\n * Builtin Gemini tools must not shadow functionDeclarations names (upstream\n * treats them as native tools; verified by OmniRoute's GEMINI_BUILTIN_TOOL_NAMES).\n */\nconst AGY_BUILTIN_TOOL_NAMES = new Set(['google_search', 'web_search', 'search_web', 'googleSearch'])\n\n/** Level-thinking: single id + selectable low/medium/high via thinkingLevel (catalog thinking:'level'). */\nconst LEVEL_THINKING_LEVELS = new Set(['low', 'medium', 'high'])\n\n/** Upstream functionDeclarations names are `[a-zA-Z0-9_]` and ≤64 chars (OmniRoute-verified). */\nconst AGY_TOOL_NAME_MAX_LENGTH = 64\n\n/** Sanitize a tool name to the upstream charset/length; dedupe via a short hash. */\nfunction sanitizeToolName(name: string, seen: Set<string>): string {\n let candidate = name.replace(/[^a-zA-Z0-9_]/g, '_') || 'tool'\n if (candidate.length > AGY_TOOL_NAME_MAX_LENGTH || seen.has(candidate)) {\n const hash = createHash('sha256').update(candidate).digest('hex').slice(0, 8)\n const prefix = candidate.slice(0, AGY_TOOL_NAME_MAX_LENGTH - hash.length - 1)\n candidate = `${prefix}_${hash}`\n let i = 2\n while (seen.has(candidate)) candidate = `${prefix}_${i++}_${hash}`\n }\n seen.add(candidate)\n return candidate\n}\n\nfunction toolsToDeclarations(tools: ToolSchema[] | undefined): AgyRequestBody['request']['tools'] {\n if (!tools || tools.length === 0) return undefined\n const seenNames = new Set<string>()\n const declarations = []\n for (const tool of tools) {\n if (AGY_BUILTIN_TOOL_NAMES.has(tool.name)) continue\n declarations.push({\n name: sanitizeToolName(tool.name, seenNames),\n description: tool.description,\n parameters: sanitizeToolSchema(tool.parameters),\n })\n }\n if (declarations.length === 0) return undefined\n return [{ functionDeclarations: declarations }]\n}\n\n/** Build the wrapped Antigravity request body for one call. */\nexport function toAgyRequestBody(\n options: GenerateOptions,\n context: { projectId?: string; sessionId?: string; images?: Map<string, AgyResolvedImage> },\n): AgyRequestBody {\n const toolNames = buildToolNameIndex(options.messages)\n const images = context.images ?? new Map<string, AgyResolvedImage>()\n let contents = options.messages\n .map((message) => messageToContent(message, toolNames, images))\n .filter((c): c is AgyContent => c !== null)\n if (isClaudeModel(options.model)) {\n contents = stripTrailingModelTurn(contents)\n }\n\n const tools = toolsToDeclarations(options.tools)\n const generationConfig: NonNullable<AgyRequestBody['request']['generationConfig']> = {}\n if (options.temperature !== undefined) generationConfig.temperature = options.temperature\n if (options.maxTokens !== undefined) generationConfig.maxOutputTokens = options.maxTokens\n if (options.stop !== undefined && options.stop.length > 0) generationConfig.stopSequences = options.stop\n // Level-thinking: map the DSH reasoning effort to thinkingConfig.\n // Id-bound models (thinking !== 'level') never emit it — default is UI hint, not wire default.\n const effort = options.reasoningEffort?.toLowerCase()\n if (effort && isLevelThinkingModel(options.model) && LEVEL_THINKING_LEVELS.has(effort)) {\n generationConfig.thinkingConfig = { thinkingLevel: effort, includeThoughts: true }\n }\n\n return {\n project: context.projectId || undefined,\n requestId: generateAntigravityRequestId(),\n model: options.model,\n userAgent: 'antigravity',\n requestType: 'agent',\n request: {\n contents,\n ...(options.system ? { systemInstruction: { parts: [{ text: options.system }] } } : {}),\n ...(tools ? { tools } : {}),\n ...(tools ? { toolConfig: { functionCallingConfig: { mode: 'VALIDATED' } } } : {}),\n ...(Object.keys(generationConfig).length > 0 ? { generationConfig } : {}),\n ...(context.sessionId ? { sessionId: context.sessionId } : {}),\n },\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"translate-Zf1mdBri.mjs","names":[],"sources":["../src/runtime/signature-cache.ts","../src/adapter/translate.ts"],"sourcesContent":["/**\n * Gemini thought-signature cache for Antigravity tool calls.\n *\n * The Antigravity backend requires every outbound `functionCall` part to carry\n * a `thoughtSignature` (400 \"Function call is missing a thought_signature\"\n * otherwise). Signatures arrive on the *response* side — as a sibling field of\n * functionCall parts, and on thought parts — and must be replayed on the next\n * turn for the same tool call id. When nothing is cached, the translator\n * injects the `skip_thought_signature_validator` sentinel (the established\n * bypass both reference implementations use by default).\n *\n * Process-local with TTL; a cold process falls back to the sentinel, which the\n * upstream accepts, so cross-process persistence is not required for\n * correctness.\n */\n\nexport const THOUGHT_SIGNATURE_SENTINEL = 'skip_thought_signature_validator'\n\ninterface CacheEntry {\n signature: string\n expiresAt: number\n}\n\nconst DEFAULT_TTL_MS = 60 * 60 * 1000\nconst MAX_ENTRIES = 2000\n\nconst store = new Map<string, CacheEntry>()\n\nfunction pruneExpired(now = Date.now()): void {\n if (store.size < MAX_ENTRIES / 2) return\n for (const [key, entry] of store) {\n if (entry.expiresAt <= now) store.delete(key)\n }\n}\n\n/** Store the signature observed for one tool call id (response side). */\nexport function setThoughtSignature(toolCallId: string, signature: string, ttlMs = DEFAULT_TTL_MS): void {\n if (!toolCallId || !signature) return\n pruneExpired()\n if (store.size >= MAX_ENTRIES) {\n // Evict the oldest entry to keep the cache bounded.\n let oldestKey: string | null = null\n let oldestExpiry = Infinity\n for (const [key, entry] of store) {\n if (entry.expiresAt < oldestExpiry) {\n oldestExpiry = entry.expiresAt\n oldestKey = key\n }\n }\n if (oldestKey) store.delete(oldestKey)\n }\n store.set(toolCallId, { signature, expiresAt: Date.now() + ttlMs })\n}\n\n/** Resolve the signature for one tool call id, or null when unknown/expired. */\nexport function getThoughtSignature(toolCallId: string): string | null {\n if (!toolCallId) return null\n const entry = store.get(toolCallId)\n if (!entry) return null\n if (entry.expiresAt <= Date.now()) {\n store.delete(toolCallId)\n return null\n }\n return entry.signature\n}\n","/**\n * Translate a DSH GenerateOptions into the Antigravity wrapped request.\n *\n * Envelope shape follows the actively-maintained OmniRoute wire format\n * (the archived opencode reference predates it): top-level `project`,\n * `requestId`, `model`, `userAgent`, `requestType`, with the Gemini-style\n * body under `request` (contents/systemInstruction/tools/generationConfig/\n * sessionId). `toolConfig` VALIDATED is attached when tools are present, and\n * Claude-path requests strip trailing model turns (Vertex rejects \"assistant\n * message prefill\").\n *\n * Thinking blocks are carried as-is (Gemini `thought` parts); nothing is\n * stripped or re-signed — that signature dance was an artifact of the\n * reference plugin's interception architecture (see docs/ARCHITECTURE.md).\n */\n\nimport { createHash } from 'node:crypto'\nimport type { ContentBlock, GenerateOptions, Message, ToolSchema } from '@deepseek-ai/dsh-llm'\nimport { generateAntigravityRequestId } from '../runtime/identity.ts'\nimport { getThoughtSignature, THOUGHT_SIGNATURE_SENTINEL } from '../runtime/signature-cache.ts'\nimport { catalogModel, isLevelThinkingModel } from './catalog.ts'\n\nexport type AgyPart =\n | { text: string }\n | { thought: true; text: string }\n | { thoughtSignature: string; functionCall: { id: string; name: string; args: unknown } }\n | { functionResponse: { name: string; response: unknown } }\n | { inlineData: { mimeType: string; data: string } }\n\n/** Image bytes pre-resolved from the durable attachment store, keyed by attachment id. */\nexport interface AgyResolvedImage {\n mediaType: string\n /** Pure base64 (no data: prefix). */\n data: string\n}\n\nexport interface AgyContent {\n role: 'user' | 'model'\n parts: AgyPart[]\n}\n\nexport interface AgyRequestBody {\n project?: string\n requestId?: string\n model: string\n userAgent?: string\n requestType?: 'agent'\n request: {\n contents: AgyContent[]\n systemInstruction?: { parts: Array<{ text: string }> }\n tools?: Array<{ functionDeclarations: Array<{ name: string; description: string; parameters: unknown }> }>\n toolConfig?: { functionCallingConfig: { mode: 'VALIDATED' } }\n generationConfig?: {\n temperature?: number\n maxOutputTokens?: number\n stopSequences?: string[]\n thinkingConfig?: { thinkingLevel: string; includeThoughts: boolean }\n }\n sessionId?: string\n }\n}\n\n/** Whether a model id belongs to a Claude-branded model (Vertex-hosted). */\nexport function isClaudeModel(model: string): boolean {\n return model.startsWith('claude-') || model.includes('/claude')\n}\n\n/**\n * Vertex (the Antigravity Claude backend) rejects conversations ending on an\n * assistant/model turn (\"assistant message prefill\"); never strip to empty.\n */\nexport function stripTrailingModelTurn(contents: AgyContent[]): AgyContent[] {\n while (contents.length > 1 && contents[contents.length - 1]?.role === 'model') {\n contents.pop()\n }\n return contents\n}\n\n/**\n * The Antigravity backend parses tool `parameters` as a strict protobuf\n * schema and rejects ANY unknown keyword with 400 (verified empirically:\n * `$schema`, `propertyNames`, `pattern`, `minLength`, ... each fail in turn).\n * Denylisting is whack-a-mole, so keep only the keywords the upstream\n * accepts. Container shapes are handled distinctly: `properties` is a\n * name->schema map (keys preserved), `items`/`additionalProperties` are\n * nested schemas (additionalProperties also accepts a boolean — live-verified\n * against the Antigravity upstream), `required`/`enum` are plain arrays.\n *\n * Keyword VALUES are also constrained by the protobuf shape (verified\n * empirically): `type` must be a single enum string (union arrays like\n * `[\"string\",\"number\"]` are rejected) and every `enum` item must be a\n * string (booleans/numbers are rejected). Values are normalized to the\n * nearest valid form instead of being dropped wholesale.\n */\n// Exported for the contract invariant test (tests/adapter.test.ts); not part of\n// the package public API (translate.ts is an internal module).\nexport const AGY_SCHEMA_ALLOWLIST = new Set([\n 'type', 'format', 'title', 'description', 'nullable',\n 'items', 'enum', 'default', 'properties', 'required', 'additionalProperties',\n])\nconst AGY_SCHEMA_MAP_KEYS = new Set(['properties'])\nconst AGY_SCHEMA_NESTED_KEYS = new Set(['items', 'additionalProperties'])\nconst AGY_SCHEMA_LIST_KEYS = new Set(['required', 'enum'])\n\nfunction sanitizeToolSchema(schema: unknown): unknown {\n if (!schema || typeof schema !== 'object') return schema\n if (Array.isArray(schema)) return schema.map((entry) => sanitizeToolSchema(entry))\n\n // Normalize union types: upstream `type` is a single enum string. Pick the\n // first non-null string type (`\"null\"` maps to the `nullable` keyword);\n // fall back to `string` when no usable type remains.\n let normalized = schema as Record<string, unknown>\n if (Array.isArray(normalized.type)) {\n const types = normalized.type.filter((t): t is string => typeof t === 'string' && t !== 'null')\n normalized = { ...normalized, type: types[0] ?? 'string' }\n }\n\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(normalized)) {\n if (!AGY_SCHEMA_ALLOWLIST.has(key)) continue\n if (AGY_SCHEMA_MAP_KEYS.has(key)) {\n const map: Record<string, unknown> = {}\n for (const [name, child] of Object.entries(value as Record<string, unknown>)) {\n map[name] = sanitizeToolSchema(child)\n }\n result[key] = map\n continue\n }\n if (AGY_SCHEMA_NESTED_KEYS.has(key)) {\n result[key] = sanitizeToolSchema(value)\n continue\n }\n if (AGY_SCHEMA_LIST_KEYS.has(key)) {\n // Upstream `enum` items must be strings; filter the rest and omit an\n // empty enum entirely (an empty array would be rejected too).\n if (key === 'enum' && Array.isArray(value)) {\n const filtered = value.filter((v): v is string => typeof v === 'string')\n if (filtered.length > 0) result[key] = filtered\n } else {\n result[key] = value\n }\n continue\n }\n result[key] = value\n }\n return result\n}\n\n/** Collect tool-call names by id so tool-result blocks can name their function. */\nfunction buildToolNameIndex(messages: readonly Message[]): Map<string, string> {\n const index = new Map<string, string>()\n for (const message of messages) {\n for (const block of message.content) {\n if (block.type === 'tool-call') {\n index.set(block.id, block.name)\n }\n }\n }\n return index\n}\n\nfunction blockToParts(\n block: ContentBlock,\n toolNames: Map<string, string>,\n images: Map<string, AgyResolvedImage>,\n): AgyPart[] {\n switch (block.type) {\n case 'text':\n return [{ text: block.text }]\n case 'reasoning':\n return [{ thought: true, text: block.text }]\n case 'tool-call': {\n // Upstream parses functionCall.args as google.protobuf.Struct and\n // rejects a raw string with 400. Guarantee an object: parse the string\n // form, fall back to {} when it is truncated/malformed (the failure\n // mode for long multi-turn histories).\n let args: unknown = {}\n if (typeof block.arguments === 'object' && block.arguments !== null && !Array.isArray(block.arguments)) {\n args = block.arguments\n } else if (typeof block.arguments === 'string') {\n try {\n const parsed: unknown = JSON.parse(block.arguments)\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n args = parsed\n }\n } catch {\n // truncated/malformed JSON -> empty object\n }\n }\n // Antigravity rejects functionCall parts without a thoughtSignature\n // (400). Replay the signature captured for this tool call id on the\n // previous turn; the sentinel is the established bypass when nothing is\n // cached (both reference implementations default to it).\n const signature = getThoughtSignature(block.id) ?? THOUGHT_SIGNATURE_SENTINEL\n return [{\n thoughtSignature: signature,\n functionCall: { id: block.id, name: block.name, args },\n }]\n }\n case 'tool-result': {\n const name = toolNames.get(block.toolCallId) ?? block.toolCallId\n const text = block.content\n .filter((b): b is Extract<ContentBlock, { type: 'text' }> => b.type === 'text')\n .map((b) => b.text)\n .join('\\n')\n return [{\n functionResponse: {\n name,\n response: { result: text, is_error: block.isError === true },\n },\n }]\n }\n case 'image': {\n // Bytes are pre-resolved by the adapter before translation; a missing\n // entry breaks that invariant and must fail loudly, never silently drop.\n const resolved = images.get(block.attachment.attachmentId)\n if (!resolved) {\n throw new Error(`agy translate: unresolved image attachment \"${block.attachment.attachmentId}\"`)\n }\n return [{ inlineData: { mimeType: resolved.mediaType, data: resolved.data } }]\n }\n default:\n return [] // unknown block types (merge-extensible) are skipped\n }\n}\n\nfunction messageToContent(\n message: Message,\n toolNames: Map<string, string>,\n images: Map<string, AgyResolvedImage>,\n): AgyContent | null {\n const parts = message.content.flatMap((block) =>\n // Non-user images are out of scope by policy (docs ANTIGRAVITY-API §3.2):\n // skip them like any other untranslatable block instead of tripping the\n // unresolved-map guard, which protects only the user-image invariant.\n block.type === 'image' && message.role !== 'user'\n ? []\n : blockToParts(block, toolNames, images),\n )\n if (parts.length === 0) return null\n const role = message.role === 'assistant' ? 'model' : 'user'\n return { role, parts }\n}\n\n/**\n * Builtin Gemini tools must not shadow functionDeclarations names (upstream\n * treats them as native tools; verified by OmniRoute's GEMINI_BUILTIN_TOOL_NAMES).\n */\nconst AGY_BUILTIN_TOOL_NAMES = new Set(['google_search', 'web_search', 'search_web', 'googleSearch'])\n\n/** Level-thinking: single id + selectable low/medium/high via thinkingLevel (catalog thinking:'level'). */\nconst LEVEL_THINKING_LEVELS = new Set(['low', 'medium', 'high'])\n\n/** Upstream functionDeclarations names are `[a-zA-Z0-9_]` and ≤64 chars (OmniRoute-verified). */\nconst AGY_TOOL_NAME_MAX_LENGTH = 64\n\n/** Sanitize a tool name to the upstream charset/length; dedupe via a short hash. */\nfunction sanitizeToolName(name: string, seen: Set<string>): string {\n let candidate = name.replace(/[^a-zA-Z0-9_]/g, '_') || 'tool'\n if (candidate.length > AGY_TOOL_NAME_MAX_LENGTH || seen.has(candidate)) {\n const hash = createHash('sha256').update(candidate).digest('hex').slice(0, 8)\n const prefix = candidate.slice(0, AGY_TOOL_NAME_MAX_LENGTH - hash.length - 1)\n candidate = `${prefix}_${hash}`\n let i = 2\n while (seen.has(candidate)) candidate = `${prefix}_${i++}_${hash}`\n }\n seen.add(candidate)\n return candidate\n}\n\nfunction toolsToDeclarations(tools: ToolSchema[] | undefined): AgyRequestBody['request']['tools'] {\n if (!tools || tools.length === 0) return undefined\n const seenNames = new Set<string>()\n const declarations = []\n for (const tool of tools) {\n if (AGY_BUILTIN_TOOL_NAMES.has(tool.name)) continue\n declarations.push({\n name: sanitizeToolName(tool.name, seenNames),\n description: tool.description,\n parameters: sanitizeToolSchema(tool.parameters),\n })\n }\n if (declarations.length === 0) return undefined\n return [{ functionDeclarations: declarations }]\n}\n\n/** Build the wrapped Antigravity request body for one call. */\nexport function toAgyRequestBody(\n options: GenerateOptions,\n context: { projectId?: string; sessionId?: string; images?: Map<string, AgyResolvedImage> },\n): AgyRequestBody {\n const toolNames = buildToolNameIndex(options.messages)\n const images = context.images ?? new Map<string, AgyResolvedImage>()\n let contents = options.messages\n .map((message) => messageToContent(message, toolNames, images))\n .filter((c): c is AgyContent => c !== null)\n if (isClaudeModel(options.model)) {\n contents = stripTrailingModelTurn(contents)\n }\n\n const tools = toolsToDeclarations(options.tools)\n const generationConfig: NonNullable<AgyRequestBody['request']['generationConfig']> = {}\n if (options.temperature !== undefined) generationConfig.temperature = options.temperature\n if (options.maxTokens !== undefined) generationConfig.maxOutputTokens = options.maxTokens\n if (options.stop !== undefined && options.stop.length > 0) generationConfig.stopSequences = options.stop\n // Level-thinking: map the DSH reasoning effort to thinkingConfig.\n // Id-bound models (thinking !== 'level') never emit it — default is UI hint, not wire default.\n const effort = options.reasoningEffort?.toLowerCase()\n if (effort && isLevelThinkingModel(options.model) && LEVEL_THINKING_LEVELS.has(effort)) {\n generationConfig.thinkingConfig = { thinkingLevel: effort, includeThoughts: true }\n }\n\n return {\n project: context.projectId || undefined,\n requestId: generateAntigravityRequestId(),\n model: options.model,\n userAgent: 'antigravity',\n requestType: 'agent',\n request: {\n contents,\n ...(options.system ? { systemInstruction: { parts: [{ text: options.system }] } } : {}),\n ...(tools ? { tools } : {}),\n ...(tools ? { toolConfig: { functionCallingConfig: { mode: 'VALIDATED' } } } : {}),\n ...(Object.keys(generationConfig).length > 0 ? { generationConfig } : {}),\n ...(context.sessionId ? { sessionId: context.sessionId } : {}),\n },\n }\n}\n"],"mappings":"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"}
|
package/lib/web/plugin.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { d as isAgyDisabled, f as generateFingerprint, g as resolveAntigravityVersionBounded, n as maskProxyUrl, p as recordFingerprintVersion } from "../accounts-
|
|
1
|
+
import { d as isAgyDisabled, f as generateFingerprint, g as resolveAntigravityVersionBounded, n as maskProxyUrl, p as recordFingerprintVersion } from "../accounts-Blqno5Te.mjs";
|
|
2
2
|
import { a as proxyUrlForLogs, r as normalizeProxyUrl, t as isProxyReachable } from "../proxy-DQPIwUov.mjs";
|
|
3
|
-
import { t as createAgyRuntime } from "../plugin-common-
|
|
4
|
-
import { t as exchangeAntigravity } from "../exchange-
|
|
5
|
-
import { n as upsertImportedAccount, r as authorizeAntigravity, t as importManySources } from "../import-
|
|
3
|
+
import { t as createAgyRuntime } from "../plugin-common-CP6Czgh9.mjs";
|
|
4
|
+
import { t as exchangeAntigravity } from "../exchange-C6y05v4v.mjs";
|
|
5
|
+
import { n as upsertImportedAccount, r as authorizeAntigravity, t as importManySources } from "../import-Dmeiu2Xb.mjs";
|
|
6
6
|
//#region src/web/i18n.ts
|
|
7
7
|
const I18N_DICT = {
|
|
8
8
|
en: {
|
|
@@ -1382,7 +1382,7 @@ function createAgyWebRoutes(options) {
|
|
|
1382
1382
|
const session = await sessions.getSession().catch(() => void 0);
|
|
1383
1383
|
if (!session || session.index !== entry.index) continue;
|
|
1384
1384
|
try {
|
|
1385
|
-
const { fetchAvailableModels } = await import("../models-
|
|
1385
|
+
const { fetchAvailableModels } = await import("../models-3VFg0nRK.mjs").then((n) => n.r);
|
|
1386
1386
|
const discovered = await fetchAvailableModels(session.auth.access, session.account.projectId);
|
|
1387
1387
|
const models = Object.entries(discovered.models ?? {});
|
|
1388
1388
|
if (models.length > 0) {
|
|
@@ -1548,7 +1548,7 @@ function createAgyWebRoutes(options) {
|
|
|
1548
1548
|
return;
|
|
1549
1549
|
}
|
|
1550
1550
|
try {
|
|
1551
|
-
const { listAgyModels } = await import("../models-
|
|
1551
|
+
const { listAgyModels } = await import("../models-3VFg0nRK.mjs").then((n) => n.r);
|
|
1552
1552
|
const models = await listAgyModels(session.auth.access, session.account.projectId);
|
|
1553
1553
|
sendJson(res, 200, {
|
|
1554
1554
|
account: session.account.email ?? null,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-agy",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"packageManager": "pnpm@11.10.0",
|
|
5
5
|
"description": "Google Antigravity (agy) OAuth auth + model access plugin for DeepSeek Harness: multi-account pool, 429 rotation, device fingerprinting, CLI and web login.",
|
|
6
6
|
"type": "module",
|
|
@@ -25,6 +25,12 @@
|
|
|
25
25
|
"dsh": {
|
|
26
26
|
"bundle": {
|
|
27
27
|
"patch": "./cordis.patch.yml"
|
|
28
|
+
},
|
|
29
|
+
"client": {
|
|
30
|
+
"platform": "web",
|
|
31
|
+
"inject": [
|
|
32
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins"
|
|
33
|
+
]
|
|
28
34
|
}
|
|
29
35
|
},
|
|
30
36
|
"engines": {
|
|
@@ -64,8 +70,14 @@
|
|
|
64
70
|
"socks-proxy-agent": "^8.0.5"
|
|
65
71
|
},
|
|
66
72
|
"devDependencies": {
|
|
73
|
+
"@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
|
|
74
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.1-rc.2",
|
|
75
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.1-rc.2",
|
|
76
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.2",
|
|
67
77
|
"@types/node": "^24.0.0",
|
|
68
78
|
"@types/proper-lockfile": "^4.1.4",
|
|
79
|
+
"@types/react": "~18.3.1",
|
|
80
|
+
"react": "^18.2.0",
|
|
69
81
|
"tsdown": "^0.22.14",
|
|
70
82
|
"tsx": "^4.20.0",
|
|
71
83
|
"typescript": "^5.8.0",
|
|
@@ -80,6 +92,10 @@
|
|
|
80
92
|
"types": "./lib/web/plugin.d.mts",
|
|
81
93
|
"default": "./lib/web/plugin.mjs"
|
|
82
94
|
},
|
|
95
|
+
"./client": {
|
|
96
|
+
"types": "./lib/client.d.ts",
|
|
97
|
+
"default": "./lib/client.js"
|
|
98
|
+
},
|
|
83
99
|
"./package.json": "./package.json"
|
|
84
100
|
}
|
|
85
101
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"catalog-iuikPZIb.mjs","names":[],"sources":["../src/adapter/catalog.ts"],"sourcesContent":["/**\n * Pinned agy model catalog (metadata only — dynamic discovery is primary).\n *\n * Adapted from OmniRoute's `AGY_PUBLIC_MODELS` (MIT, see NOTICE.md), which was\n * pinned from the live `v1internal:fetchAvailableModels` endpoint. The dynamic\n * endpoint supplies ids + quotaInfo; this catalog supplies the capability\n * metadata the endpoint omits (context length, output cap, reasoning/vision/\n * tool-calling). Tab-completion models are intentionally excluded.\n */\n\nexport interface CatalogModel {\n id: string\n name: string\n contextLength: number\n maxOutputTokens: number\n supportsReasoning?: boolean\n supportsVision?: boolean\n toolCalling?: boolean\n /** Level-thinking: 'level' means single id + selectable low/medium/high via thinkingLevel. Omit = level bound to id. */\n thinking?: 'level'\n}\n\nexport const AGY_PUBLIC_MODELS: readonly CatalogModel[] = [\n { id: 'gemini-3.7-flash-tiered', name: 'Gemini 3.7 Flash', contextLength: 1048576, maxOutputTokens: 65536, supportsReasoning: true, supportsVision: true, toolCalling: true, thinking: 'level' },\n { id: 'gemini-3.6-flash-tiered', name: 'Gemini 3.6 Flash (Tiered)', contextLength: 1048576, maxOutputTokens: 65536, supportsReasoning: true, supportsVision: true, toolCalling: true, thinking: 'level' },\n { id: 'gemini-3.6-flash-high', name: 'Gemini 3.6 Flash (High)', contextLength: 1048576, maxOutputTokens: 65536, supportsReasoning: true, supportsVision: true, toolCalling: true },\n { id: 'gemini-3.6-flash-medium', name: 'Gemini 3.6 Flash (Medium)', contextLength: 1048576, maxOutputTokens: 65536, supportsReasoning: true, supportsVision: true, toolCalling: true },\n { id: 'gemini-3.6-flash-low', name: 'Gemini 3.6 Flash (Low)', contextLength: 1048576, maxOutputTokens: 65536, supportsReasoning: true, supportsVision: true, toolCalling: true },\n { id: 'claude-opus-4-6-thinking', name: 'Claude Opus 4.6 (Thinking)', contextLength: 1048576, maxOutputTokens: 65536, supportsReasoning: true, supportsVision: true, toolCalling: true },\n { id: 'claude-sonnet-4-6', name: 'Claude Sonnet 4.6 (Thinking)', contextLength: 1048576, maxOutputTokens: 65536, supportsReasoning: true, supportsVision: true, toolCalling: true },\n { id: 'gemini-pro-agent', name: 'Gemini 3.1 Pro (High)', contextLength: 1048576, maxOutputTokens: 65535, supportsReasoning: true, supportsVision: true, toolCalling: true },\n { id: 'gemini-3.1-pro-low', name: 'Gemini 3.1 Pro (Low)', contextLength: 1048576, maxOutputTokens: 65535, supportsReasoning: true, supportsVision: true, toolCalling: true },\n { id: 'gemini-3-flash-agent', name: 'Gemini 3.5 Flash (High)', contextLength: 1048576, maxOutputTokens: 65536, supportsReasoning: true, supportsVision: true, toolCalling: true },\n { id: 'gemini-3.5-flash-low', name: 'Gemini 3.5 Flash (Medium)', contextLength: 1048576, maxOutputTokens: 65536, supportsReasoning: true, supportsVision: true, toolCalling: true },\n { id: 'gemini-3.5-flash-extra-low', name: 'Gemini 3.5 Flash (Low)', contextLength: 1048576, maxOutputTokens: 65536, supportsReasoning: true, supportsVision: true, toolCalling: true },\n { id: 'gemini-3.1-flash-lite', name: 'Gemini 3.1 Flash Lite', contextLength: 1048576, maxOutputTokens: 65535, supportsVision: true, toolCalling: true },\n { id: 'gemini-2.5-flash-thinking', name: 'Gemini 2.5 Flash Thinking', contextLength: 1048576, maxOutputTokens: 65535, supportsReasoning: true, supportsVision: true, toolCalling: true },\n { id: 'gemini-2.5-flash', name: 'Gemini 2.5 Flash', contextLength: 1048576, maxOutputTokens: 65535, supportsVision: true, toolCalling: true },\n { id: 'gemini-2.5-flash-lite', name: 'Gemini 2.5 Flash Lite', contextLength: 1048576, maxOutputTokens: 65535, supportsVision: true, toolCalling: true },\n { id: 'gpt-oss-120b-medium', name: 'GPT-OSS 120B (Medium)', contextLength: 131072, maxOutputTokens: 32768, supportsReasoning: true, toolCalling: true },\n]\n\nconst CATALOG_BY_ID = new Map(AGY_PUBLIC_MODELS.map((m) => [m.id, m]))\n\n/** Tab-completion models are discoverable but not chat-callable. */\nexport function isChatCallableModelId(modelId: string): boolean {\n return !modelId.startsWith('tab_')\n}\n\nexport function catalogModel(modelId: string): CatalogModel | undefined {\n return CATALOG_BY_ID.get(modelId)\n}\n\n/** Level-thinking models: single id + selectable low/medium/high via thinkingLevel. */\nexport function isLevelThinkingModel(modelId: string): boolean {\n return catalogModel(modelId)?.thinking === 'level'\n}\n"],"mappings":";AAsBA,MAAa,oBAA6C;CACxD;EAAE,IAAI;EAA2B,MAAM;EAAoB,eAAe;EAAS,iBAAiB;EAAO,mBAAmB;EAAM,gBAAgB;EAAM,aAAa;EAAM,UAAU;CAAQ;CAC/L;EAAE,IAAI;EAA2B,MAAM;EAA6B,eAAe;EAAS,iBAAiB;EAAO,mBAAmB;EAAM,gBAAgB;EAAM,aAAa;EAAM,UAAU;CAAQ;CACxM;EAAE,IAAI;EAAyB,MAAM;EAA2B,eAAe;EAAS,iBAAiB;EAAO,mBAAmB;EAAM,gBAAgB;EAAM,aAAa;CAAK;CACjL;EAAE,IAAI;EAA2B,MAAM;EAA6B,eAAe;EAAS,iBAAiB;EAAO,mBAAmB;EAAM,gBAAgB;EAAM,aAAa;CAAK;CACrL;EAAE,IAAI;EAAwB,MAAM;EAA0B,eAAe;EAAS,iBAAiB;EAAO,mBAAmB;EAAM,gBAAgB;EAAM,aAAa;CAAK;CAC/K;EAAE,IAAI;EAA4B,MAAM;EAA8B,eAAe;EAAS,iBAAiB;EAAO,mBAAmB;EAAM,gBAAgB;EAAM,aAAa;CAAK;CACvL;EAAE,IAAI;EAAqB,MAAM;EAAgC,eAAe;EAAS,iBAAiB;EAAO,mBAAmB;EAAM,gBAAgB;EAAM,aAAa;CAAK;CAClL;EAAE,IAAI;EAAoB,MAAM;EAAyB,eAAe;EAAS,iBAAiB;EAAO,mBAAmB;EAAM,gBAAgB;EAAM,aAAa;CAAK;CAC1K;EAAE,IAAI;EAAsB,MAAM;EAAwB,eAAe;EAAS,iBAAiB;EAAO,mBAAmB;EAAM,gBAAgB;EAAM,aAAa;CAAK;CAC3K;EAAE,IAAI;EAAwB,MAAM;EAA2B,eAAe;EAAS,iBAAiB;EAAO,mBAAmB;EAAM,gBAAgB;EAAM,aAAa;CAAK;CAChL;EAAE,IAAI;EAAwB,MAAM;EAA6B,eAAe;EAAS,iBAAiB;EAAO,mBAAmB;EAAM,gBAAgB;EAAM,aAAa;CAAK;CAClL;EAAE,IAAI;EAA8B,MAAM;EAA0B,eAAe;EAAS,iBAAiB;EAAO,mBAAmB;EAAM,gBAAgB;EAAM,aAAa;CAAK;CACrL;EAAE,IAAI;EAAyB,MAAM;EAAyB,eAAe;EAAS,iBAAiB;EAAO,gBAAgB;EAAM,aAAa;CAAK;CACtJ;EAAE,IAAI;EAA6B,MAAM;EAA6B,eAAe;EAAS,iBAAiB;EAAO,mBAAmB;EAAM,gBAAgB;EAAM,aAAa;CAAK;CACvL;EAAE,IAAI;EAAoB,MAAM;EAAoB,eAAe;EAAS,iBAAiB;EAAO,gBAAgB;EAAM,aAAa;CAAK;CAC5I;EAAE,IAAI;EAAyB,MAAM;EAAyB,eAAe;EAAS,iBAAiB;EAAO,gBAAgB;EAAM,aAAa;CAAK;CACtJ;EAAE,IAAI;EAAuB,MAAM;EAAyB,eAAe;EAAQ,iBAAiB;EAAO,mBAAmB;EAAM,aAAa;CAAK;AACxJ;AAEA,MAAM,gBAAgB,IAAI,IAAI,kBAAkB,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;;AAGrE,SAAgB,sBAAsB,SAA0B;CAC9D,OAAO,CAAC,QAAQ,WAAW,MAAM;AACnC;AAEA,SAAgB,aAAa,SAA2C;CACtE,OAAO,cAAc,IAAI,OAAO;AAClC;;AAGA,SAAgB,qBAAqB,SAA0B;CAC7D,OAAO,aAAa,OAAO,CAAC,EAAE,aAAa;AAC7C"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"models-DRWVi33p.mjs","names":[],"sources":["../src/adapter/models.ts"],"sourcesContent":["/**\n * Model discovery: dynamic `v1internal:fetchAvailableModels` as the primary\n * source (fresh ids + per-model quotaInfo), the pinned catalog merged in for\n * capability metadata, and catalog fallback when the endpoint is unreachable.\n */\n\nimport { ReasoningEffortId, type LlmModelInfo, type LlmModelReasoningInfo, type LlmResolvedModelInfo, type ModelModality } from '@deepseek-ai/dsh-llm'\nimport { AGY_ENDPOINT_FALLBACKS, getAgyBootstrapUserAgent } from '../oauth/constants.ts'\nimport { proxiedFetch } from '../proxy.ts'\nimport { AGY_PUBLIC_MODELS, catalogModel, isChatCallableModelId, isLevelThinkingModel } from './catalog.ts'\n\nexport const AGY_PROVIDER = 'agy'\n\n/** Level-thinking: single id + selectable low/medium/high via thinkingLevel. Default is UI hint, not wire default. */\nconst LEVEL_REASONING: LlmModelReasoningInfo = Object.freeze({\n efforts: Object.freeze([\n { id: ReasoningEffortId('low'), name: 'Low' },\n { id: ReasoningEffortId('medium'), name: 'Medium' },\n { id: ReasoningEffortId('high'), name: 'High' },\n ] as const),\n defaultEffort: ReasoningEffortId('medium'),\n} as const)\n\n/**\n * Input modalities per model. Image support follows the catalog's own\n * `supportsVision` metadata for known models (gpt-oss-120b-medium is text-only\n * there); unknown dynamic ids default to vision-capable — the upstream schema\n * accepts inlineData across the board, and a wrong guess surfaces as a clear\n * upstream 400 instead of a silent drop.\n */\nconst AGY_INPUT_MODALITIES = ['text', 'image'] as const\nconst AGY_TEXT_ONLY_MODALITIES = ['text'] as const\n\nfunction inputModalitiesFor(meta: { supportsVision?: boolean } | undefined): ModelModality[] {\n return [...(meta ? meta.supportsVision === true : true) ? AGY_INPUT_MODALITIES : AGY_TEXT_ONLY_MODALITIES]\n}\n\nexport interface DiscoveredModelEntry {\n quotaInfo?: {\n remainingFraction?: number\n resetTime?: string\n }\n displayName?: string\n modelName?: string\n}\n\nexport interface DiscoveredModels {\n models?: Record<string, DiscoveredModelEntry>\n}\n\n/** Fetch the account's available models from the first reachable endpoint. */\nexport async function fetchAvailableModels(\n accessToken: string,\n projectId?: string,\n fetchImpl: typeof fetch = proxiedFetch,\n): Promise<DiscoveredModels> {\n let lastError: unknown = null\n const body = projectId ? { project: projectId } : {}\n for (const baseEndpoint of AGY_ENDPOINT_FALLBACKS) {\n try {\n const response = await fetchImpl(`${baseEndpoint}/v1internal:fetchAvailableModels`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n 'User-Agent': getAgyBootstrapUserAgent(),\n },\n body: JSON.stringify(body),\n })\n if (response.ok) {\n return (await response.json()) as DiscoveredModels\n }\n lastError = new Error(`fetchAvailableModels ${response.status} at ${baseEndpoint}`)\n } catch (error) {\n lastError = error\n }\n }\n throw lastError instanceof Error ? lastError : new Error('fetchAvailableModels: all endpoints failed')\n}\n\n/** Merge dynamic ids with catalog metadata; non-chat models and unknowns keep minimal info. */\nexport function mergeModelCatalog(dynamic: DiscoveredModels): LlmModelInfo[] {\n const entries: LlmModelInfo[] = []\n for (const [id, entry] of Object.entries(dynamic.models ?? {})) {\n if (!isChatCallableModelId(id)) continue\n const meta = catalogModel(id)\n entries.push({\n provider: AGY_PROVIDER,\n id,\n name: entry.displayName ?? meta?.name ?? entry.modelName ?? id,\n inputModalities: inputModalitiesFor(meta),\n ...(meta ? { context: { contextWindow: meta.contextLength } } : {}),\n })\n }\n return entries\n}\n\n/** Catalog-only model list used when the endpoint is unreachable. */\nexport function catalogModelList(): LlmModelInfo[] {\n return AGY_PUBLIC_MODELS.map((model) => ({\n provider: AGY_PROVIDER,\n id: model.id,\n name: model.name,\n inputModalities: inputModalitiesFor(model),\n context: { contextWindow: model.contextLength },\n }))\n}\n\n/** Adapter-facing listing: dynamic first, catalog fallback. */\nexport async function listAgyModels(\n accessToken: string | undefined,\n projectId: string | undefined,\n fetchImpl: typeof fetch = proxiedFetch,\n): Promise<readonly LlmModelInfo[]> {\n if (!accessToken) return catalogModelList()\n try {\n const dynamic = await fetchAvailableModels(accessToken, projectId, fetchImpl)\n const merged = mergeModelCatalog(dynamic)\n return merged.length > 0 ? merged : catalogModelList()\n } catch {\n return catalogModelList()\n }\n}\n\n/** Resolve one exact model's metadata (catalog-backed; dynamic ids pass through). */\nexport function resolveAgyModel(provider: string, model: string): LlmResolvedModelInfo {\n const meta = catalogModel(model)\n if (isLevelThinkingModel(model)) {\n return {\n provider,\n id: model,\n name: meta?.name ?? model,\n inputModalities: inputModalitiesFor(meta),\n context: { contextWindow: meta?.contextLength ?? 1048576 },\n defaultMaxTokens: meta?.maxOutputTokens ?? 65536,\n // Return a shallow copy so callers cannot mutate the frozen singleton.\n reasoning: { ...LEVEL_REASONING, efforts: [...LEVEL_REASONING.efforts] },\n }\n }\n return {\n provider,\n id: model,\n name: meta?.name ?? model,\n inputModalities: inputModalitiesFor(meta),\n ...(meta ? { context: { contextWindow: meta.contextLength }, defaultMaxTokens: meta.maxOutputTokens } : {}),\n }\n}\n"],"mappings":"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"}
|