@robota-sdk/agent-provider 3.0.0-beta.64

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 (220) hide show
  1. package/LICENSE +21 -0
  2. package/dist/browser/index.d.ts +1104 -0
  3. package/dist/browser/index.d.ts.map +1 -0
  4. package/dist/browser/index.js +7 -0
  5. package/dist/browser/index.js.map +1 -0
  6. package/dist/loggers/index.cjs +1 -0
  7. package/dist/loggers/index.d.ts +151 -0
  8. package/dist/loggers/index.d.ts.map +1 -0
  9. package/dist/loggers/index.js +2 -0
  10. package/dist/loggers/index.js.map +1 -0
  11. package/dist/node/anthropic/index.cjs +1 -0
  12. package/dist/node/anthropic/index.d.ts +158 -0
  13. package/dist/node/anthropic/index.d.ts.map +1 -0
  14. package/dist/node/anthropic/index.js +1 -0
  15. package/dist/node/anthropic--1vgLC-e.js +5 -0
  16. package/dist/node/anthropic--1vgLC-e.js.map +1 -0
  17. package/dist/node/anthropic-BFQ6DSCP.cjs +4 -0
  18. package/dist/node/bytedance/index.cjs +1 -0
  19. package/dist/node/bytedance/index.d.ts +74 -0
  20. package/dist/node/bytedance/index.d.ts.map +1 -0
  21. package/dist/node/bytedance/index.js +1 -0
  22. package/dist/node/bytedance-C_0sF_pJ.js +2 -0
  23. package/dist/node/bytedance-C_0sF_pJ.js.map +1 -0
  24. package/dist/node/bytedance-DVPxqEiC.cjs +1 -0
  25. package/dist/node/chunk-Bmb41Sf3.cjs +1 -0
  26. package/dist/node/deepseek/index.cjs +1 -0
  27. package/dist/node/deepseek/index.d.ts +2 -0
  28. package/dist/node/deepseek/index.js +1 -0
  29. package/dist/node/deepseek-_8Ixx7rA.js +2 -0
  30. package/dist/node/deepseek-_8Ixx7rA.js.map +1 -0
  31. package/dist/node/deepseek-oA2Y6bD0.cjs +1 -0
  32. package/dist/node/gemini/index.cjs +1 -0
  33. package/dist/node/gemini/index.d.ts +173 -0
  34. package/dist/node/gemini/index.d.ts.map +1 -0
  35. package/dist/node/gemini/index.js +1 -0
  36. package/dist/node/gemini-Bh2U87MY.js +4 -0
  37. package/dist/node/gemini-Bh2U87MY.js.map +1 -0
  38. package/dist/node/gemini-DSaNCxZj.cjs +3 -0
  39. package/dist/node/gemma/index.cjs +1 -0
  40. package/dist/node/gemma/index.d.ts +2 -0
  41. package/dist/node/gemma/index.js +1 -0
  42. package/dist/node/gemma-Dp_AfCUR.js +2 -0
  43. package/dist/node/gemma-Dp_AfCUR.js.map +1 -0
  44. package/dist/node/gemma-G-Pf_PnX.cjs +1 -0
  45. package/dist/node/google/index.cjs +1 -0
  46. package/dist/node/google/index.d.ts +14 -0
  47. package/dist/node/google/index.d.ts.map +1 -0
  48. package/dist/node/google/index.js +2 -0
  49. package/dist/node/google/index.js.map +1 -0
  50. package/dist/node/index-B6PnlDMd.d.ts +82 -0
  51. package/dist/node/index-B6PnlDMd.d.ts.map +1 -0
  52. package/dist/node/index-B7UvPJcI.d.ts +315 -0
  53. package/dist/node/index-B7UvPJcI.d.ts.map +1 -0
  54. package/dist/node/index-BLPOTNb5.d.ts +98 -0
  55. package/dist/node/index-BLPOTNb5.d.ts.map +1 -0
  56. package/dist/node/index-BqixM_XD.d.ts +231 -0
  57. package/dist/node/index-BqixM_XD.d.ts.map +1 -0
  58. package/dist/node/index-C3beaqKO.d.ts +231 -0
  59. package/dist/node/index-C3beaqKO.d.ts.map +1 -0
  60. package/dist/node/index-Cp2XRh9G.d.ts +82 -0
  61. package/dist/node/index-Cp2XRh9G.d.ts.map +1 -0
  62. package/dist/node/index-DSv5xruI.d.ts +98 -0
  63. package/dist/node/index-DSv5xruI.d.ts.map +1 -0
  64. package/dist/node/index-w0bV1uaP.d.ts +315 -0
  65. package/dist/node/index-w0bV1uaP.d.ts.map +1 -0
  66. package/dist/node/index.cjs +1 -0
  67. package/dist/node/index.d.ts +8 -0
  68. package/dist/node/index.js +1 -0
  69. package/dist/node/openai/index.cjs +1 -0
  70. package/dist/node/openai/index.d.ts +2 -0
  71. package/dist/node/openai/index.js +1 -0
  72. package/dist/node/openai-CRQjg4xF.js +2 -0
  73. package/dist/node/openai-CRQjg4xF.js.map +1 -0
  74. package/dist/node/openai-compatible-BYfyY5lb.cjs +1 -0
  75. package/dist/node/openai-compatible-Dm4Sof9e.js +2 -0
  76. package/dist/node/openai-compatible-Dm4Sof9e.js.map +1 -0
  77. package/dist/node/openai-xWC6pY7r.cjs +1 -0
  78. package/dist/node/qwen/index.cjs +1 -0
  79. package/dist/node/qwen/index.d.ts +2 -0
  80. package/dist/node/qwen/index.js +1 -0
  81. package/dist/node/qwen-ChUZobTL.js +2 -0
  82. package/dist/node/qwen-ChUZobTL.js.map +1 -0
  83. package/dist/node/qwen-CjT71vSM.cjs +1 -0
  84. package/package.json +157 -0
  85. package/src/anthropic/__tests__/abort-streaming.test.ts +199 -0
  86. package/src/anthropic/__tests__/model-catalog-refresh.test.ts +92 -0
  87. package/src/anthropic/__tests__/provider-definition.test.ts +55 -0
  88. package/src/anthropic/__tests__/provider.test.ts +1357 -0
  89. package/src/anthropic/__tests__/response-parser.test.ts +326 -0
  90. package/src/anthropic/index.ts +22 -0
  91. package/src/anthropic/message-converter.ts +181 -0
  92. package/src/anthropic/model-catalog-refresh.ts +128 -0
  93. package/src/anthropic/parsers/response-parser.ts +184 -0
  94. package/src/anthropic/provider-definition.ts +93 -0
  95. package/src/anthropic/provider.ts +290 -0
  96. package/src/anthropic/streaming-handler.ts +204 -0
  97. package/src/anthropic/types/api-types.ts +158 -0
  98. package/src/anthropic/types.ts +79 -0
  99. package/src/bytedance/http-client.test.ts +288 -0
  100. package/src/bytedance/http-client.ts +163 -0
  101. package/src/bytedance/index.ts +2 -0
  102. package/src/bytedance/provider.spec.ts +320 -0
  103. package/src/bytedance/provider.ts +171 -0
  104. package/src/bytedance/status-mapper.test.ts +299 -0
  105. package/src/bytedance/status-mapper.ts +141 -0
  106. package/src/bytedance/types.ts +68 -0
  107. package/src/deepseek/defaults.ts +4 -0
  108. package/src/deepseek/index.ts +22 -0
  109. package/src/deepseek/model-catalog-refresh.test.ts +57 -0
  110. package/src/deepseek/model-catalog-refresh.ts +105 -0
  111. package/src/deepseek/model-catalog.ts +55 -0
  112. package/src/deepseek/provider-definition.test.ts +109 -0
  113. package/src/deepseek/provider-definition.ts +132 -0
  114. package/src/deepseek/provider.test.ts +324 -0
  115. package/src/deepseek/provider.ts +298 -0
  116. package/src/deepseek/types.ts +37 -0
  117. package/src/gemini/execution-helpers.ts +233 -0
  118. package/src/gemini/genai-transport.test.ts +208 -0
  119. package/src/gemini/image-operations.test.ts +448 -0
  120. package/src/gemini/image-operations.ts +261 -0
  121. package/src/gemini/index.ts +11 -0
  122. package/src/gemini/message-converter.test.ts +616 -0
  123. package/src/gemini/message-converter.ts +140 -0
  124. package/src/gemini/model-catalog-refresh.test.ts +107 -0
  125. package/src/gemini/model-catalog-refresh.ts +92 -0
  126. package/src/gemini/provider-definition.test.ts +70 -0
  127. package/src/gemini/provider-definition.ts +78 -0
  128. package/src/gemini/provider-extended.test.ts +898 -0
  129. package/src/gemini/provider.spec.ts +216 -0
  130. package/src/gemini/provider.ts +279 -0
  131. package/src/gemini/request-converter.ts +226 -0
  132. package/src/gemini/tool-schema-converter.ts +78 -0
  133. package/src/gemini/types/api-types.ts +235 -0
  134. package/src/gemini/types.ts +121 -0
  135. package/src/gemma/index.ts +5 -0
  136. package/src/gemma/message-factory.ts +38 -0
  137. package/src/gemma/provider-definition.test.ts +43 -0
  138. package/src/gemma/provider-definition.ts +84 -0
  139. package/src/gemma/provider-projection.ts +49 -0
  140. package/src/gemma/provider.test.ts +628 -0
  141. package/src/gemma/provider.ts +308 -0
  142. package/src/gemma/pseudo-command-envelope.ts +58 -0
  143. package/src/gemma/pseudo-tool-call-projector.ts +243 -0
  144. package/src/gemma/pseudo-tool-call-tag-parser.ts +153 -0
  145. package/src/gemma/pseudo-tool-call-types.ts +31 -0
  146. package/src/gemma/reasoning-projector.test.ts +52 -0
  147. package/src/gemma/reasoning-projector.ts +144 -0
  148. package/src/gemma/streaming-projection.ts +79 -0
  149. package/src/gemma/tool-call-argument-parser.ts +126 -0
  150. package/src/gemma/tool-call-projector.test.ts +227 -0
  151. package/src/gemma/tool-call-projector.ts +264 -0
  152. package/src/gemma/types.ts +27 -0
  153. package/src/google/index.ts +11 -0
  154. package/src/google/provider-compat.test.ts +19 -0
  155. package/src/google/provider-definition.ts +6 -0
  156. package/src/google/provider.ts +10 -0
  157. package/src/google/types.ts +5 -0
  158. package/src/index.ts +9 -0
  159. package/src/openai/adapter.test.ts +494 -0
  160. package/src/openai/adapter.ts +145 -0
  161. package/src/openai/chat-completions-chat.ts +189 -0
  162. package/src/openai/executor-integration.test.ts +206 -0
  163. package/src/openai/index.ts +21 -0
  164. package/src/openai/interfaces/payload-logger.ts +48 -0
  165. package/src/openai/loggers/console-payload-logger.test.ts +173 -0
  166. package/src/openai/loggers/console-payload-logger.ts +94 -0
  167. package/src/openai/loggers/console.ts +9 -0
  168. package/src/openai/loggers/file-payload-logger.test.ts +238 -0
  169. package/src/openai/loggers/file-payload-logger.ts +112 -0
  170. package/src/openai/loggers/file.ts +9 -0
  171. package/src/openai/loggers/index.ts +12 -0
  172. package/src/openai/loggers/sanitize-openai-log-data.test.ts +89 -0
  173. package/src/openai/loggers/sanitize-openai-log-data.ts +14 -0
  174. package/src/openai/message-converter.ts +22 -0
  175. package/src/openai/model-catalog-refresh.test.ts +92 -0
  176. package/src/openai/model-catalog-refresh.ts +115 -0
  177. package/src/openai/openai-request-format.ts +92 -0
  178. package/src/openai/parsers/response-parser.test.ts +407 -0
  179. package/src/openai/parsers/response-parser.ts +47 -0
  180. package/src/openai/provider-definition.test.ts +75 -0
  181. package/src/openai/provider-definition.ts +132 -0
  182. package/src/openai/provider.test.ts +1402 -0
  183. package/src/openai/provider.ts +237 -0
  184. package/src/openai/responses-chat.ts +258 -0
  185. package/src/openai/responses-converter.ts +112 -0
  186. package/src/openai/responses-parser.ts +285 -0
  187. package/src/openai/responses-stream-utils.ts +45 -0
  188. package/src/openai/responses-types.ts +195 -0
  189. package/src/openai/streaming/stream-assembler.ts +3 -0
  190. package/src/openai/streaming/stream-handler.test.ts +367 -0
  191. package/src/openai/streaming/stream-handler.ts +119 -0
  192. package/src/openai/types/api-types.ts +112 -0
  193. package/src/openai/types.ts +194 -0
  194. package/src/qwen/defaults.ts +26 -0
  195. package/src/qwen/index.ts +5 -0
  196. package/src/qwen/model-catalog-refresh.test.ts +91 -0
  197. package/src/qwen/model-catalog-refresh.ts +97 -0
  198. package/src/qwen/provider-capabilities.ts +34 -0
  199. package/src/qwen/provider-definition.test.ts +139 -0
  200. package/src/qwen/provider-definition.ts +173 -0
  201. package/src/qwen/provider-streaming-assembly.ts +40 -0
  202. package/src/qwen/provider.test.ts +640 -0
  203. package/src/qwen/provider.ts +293 -0
  204. package/src/qwen/responses-chat.ts +194 -0
  205. package/src/qwen/responses-converter.ts +104 -0
  206. package/src/qwen/responses-parser.ts +299 -0
  207. package/src/qwen/responses-stream-utils.ts +38 -0
  208. package/src/qwen/types.ts +228 -0
  209. package/src/shared/openai-compatible/endpoint-probe.test.ts +52 -0
  210. package/src/shared/openai-compatible/endpoint-probe.ts +43 -0
  211. package/src/shared/openai-compatible/index.ts +6 -0
  212. package/src/shared/openai-compatible/message-converter.test.ts +111 -0
  213. package/src/shared/openai-compatible/message-converter.ts +84 -0
  214. package/src/shared/openai-compatible/native-payload-observer.test.ts +43 -0
  215. package/src/shared/openai-compatible/native-payload-observer.ts +26 -0
  216. package/src/shared/openai-compatible/response-parser.test.ts +172 -0
  217. package/src/shared/openai-compatible/response-parser.ts +180 -0
  218. package/src/shared/openai-compatible/stream-assembler.test.ts +266 -0
  219. package/src/shared/openai-compatible/stream-assembler.ts +248 -0
  220. package/src/shared/openai-compatible/types.ts +59 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bytedance-C_0sF_pJ.js","names":[],"sources":["../../src/bytedance/http-client.ts","../../src/bytedance/status-mapper.ts","../../src/bytedance/provider.ts"],"sourcesContent":["import type { TProviderMediaResult } from '@robota-sdk/agent-core';\nimport type { IBytedanceApiErrorResponse, IBytedanceProviderOptions } from './types';\n\nconst DEFAULT_TIMEOUT_MS = 60_000;\n\n/** HTTP status codes used by the Bytedance API error mapper. */\nconst HTTP_UNAUTHORIZED = 401;\nconst HTTP_FORBIDDEN = 403;\nconst HTTP_NOT_FOUND = 404;\nconst HTTP_CONFLICT = 409;\nconst HTTP_TOO_MANY_REQUESTS = 429;\nconst HTTP_BAD_REQUEST = 400;\nconst HTTP_INTERNAL_ERROR = 500;\n\n/** Sends an HTTP request to the Bytedance API and returns the parsed JSON response. */\nexport async function requestJson<TResponse>(\n options: IBytedanceProviderOptions,\n request: {\n path: string;\n method: 'GET' | 'POST' | 'DELETE';\n body?: string;\n },\n): Promise<TProviderMediaResult<TResponse>> {\n const controller = new AbortController();\n const timeoutHandle = setTimeout(\n () => controller.abort(),\n options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n );\n try {\n const response = await fetch(buildUrl(options.baseUrl, request.path), {\n method: request.method,\n headers: {\n Authorization: `Bearer ${options.apiKey}`,\n 'Content-Type': 'application/json',\n ...(options.defaultHeaders ?? {}),\n },\n body: request.body,\n signal: controller.signal,\n });\n const responseText = await response.text();\n if (!response.ok) {\n return mapHttpError(response.status, responseText);\n }\n\n const parsedResult = parseJsonRecord(responseText);\n if (!parsedResult.ok) {\n return parsedResult;\n }\n return {\n ok: true,\n value: parsedResult.value as TResponse,\n };\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n return {\n ok: false,\n error: { code: 'PROVIDER_TIMEOUT', message: 'Bytedance media request timed out.' },\n };\n }\n return {\n ok: false,\n error: {\n code: 'PROVIDER_UPSTREAM_ERROR',\n message: error instanceof Error ? error.message : 'Bytedance media request failed.',\n },\n };\n } finally {\n clearTimeout(timeoutHandle);\n }\n}\n\nfunction buildUrl(baseUrl: string, path: string): string {\n const sanitizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n const sanitizedPath = path.startsWith('/') ? path : `/${path}`;\n return `${sanitizedBaseUrl}${sanitizedPath}`;\n}\n\nfunction parseJsonRecord(\n responseText: string,\n): TProviderMediaResult<Record<string, string | number | boolean | undefined>> {\n try {\n const parsedValue = JSON.parse(responseText) as Record<\n string,\n string | number | boolean | undefined\n >;\n return { ok: true, value: parsedValue };\n } catch {\n return {\n ok: false,\n error: { code: 'PROVIDER_UPSTREAM_ERROR', message: 'Bytedance response is not valid JSON.' },\n };\n }\n}\n\nfunction parseErrorResponse(responseText: string): IBytedanceApiErrorResponse {\n try {\n return JSON.parse(responseText) as IBytedanceApiErrorResponse;\n } catch {\n return { message: responseText };\n }\n}\n\nfunction mapHttpError(statusCode: number, responseText: string): TProviderMediaResult<never> {\n const parsedError = parseErrorResponse(responseText);\n if (statusCode === HTTP_UNAUTHORIZED || statusCode === HTTP_FORBIDDEN) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_AUTH_ERROR',\n message: parsedError.message ?? 'Bytedance authentication failed.',\n details: parsedError.details,\n },\n };\n }\n if (statusCode === HTTP_NOT_FOUND) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_JOB_NOT_FOUND',\n message: parsedError.message ?? 'Bytedance video job was not found.',\n details: parsedError.details,\n },\n };\n }\n if (statusCode === HTTP_CONFLICT) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_JOB_NOT_CANCELLABLE',\n message: parsedError.message ?? 'Bytedance video job cannot be cancelled in current state.',\n details: parsedError.details,\n },\n };\n }\n if (statusCode === HTTP_TOO_MANY_REQUESTS) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_RATE_LIMITED',\n message: parsedError.message ?? 'Bytedance rate limit exceeded.',\n details: parsedError.details,\n },\n };\n }\n if (statusCode >= HTTP_BAD_REQUEST && statusCode < HTTP_INTERNAL_ERROR) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_INVALID_REQUEST',\n message: parsedError.message ?? 'Bytedance rejected request payload.',\n details: parsedError.details,\n },\n };\n }\n return {\n ok: false,\n error: {\n code: 'PROVIDER_UPSTREAM_ERROR',\n message: parsedError.message ?? 'Bytedance upstream request failed.',\n details: parsedError.details,\n },\n };\n}\n","import type { TProviderMediaResult, IVideoJobSnapshot } from '@robota-sdk/agent-core';\nimport type { IBytedanceVideoTaskResponse } from './types';\n\n/** Threshold (in milliseconds) above which a numeric timestamp is treated as milliseconds rather than seconds. */\nconst MILLISECOND_EPOCH_THRESHOLD = 1_000_000_000_000;\n\n/** Conversion factor from seconds to milliseconds. */\nconst MS_PER_SECOND = 1000;\n\n/** Maps a Bytedance video task response into a normalized job snapshot. */\nexport function mapVideoJobSnapshot(\n response: IBytedanceVideoTaskResponse,\n): TProviderMediaResult<IVideoJobSnapshot> {\n if (response.id.trim().length === 0) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_UPSTREAM_ERROR',\n message: 'Bytedance video job response is missing task id.',\n },\n };\n }\n const normalizedStatusResult = mapVideoStatus(response.status);\n if (!normalizedStatusResult.ok) {\n return normalizedStatusResult;\n }\n return {\n ok: true,\n value: {\n jobId: response.id,\n status: normalizedStatusResult.value,\n output: mapOutput(response),\n error:\n normalizedStatusResult.value === 'failed' && response.error_message\n ? { code: 'PROVIDER_UPSTREAM_ERROR', message: response.error_message }\n : undefined,\n updatedAt: toIsoTimestamp(response.updated_at ?? response.created_at),\n },\n };\n}\n\n/** Maps a Bytedance status string to a normalized video job status. */\nexport function mapVideoStatus(status: string): TProviderMediaResult<IVideoJobSnapshot['status']> {\n const normalized = status.trim().toLowerCase();\n if (normalized === 'queued' || normalized === 'pending' || normalized === 'submitted') {\n return { ok: true, value: 'queued' };\n }\n if (normalized === 'running' || normalized === 'processing' || normalized === 'in_progress') {\n return { ok: true, value: 'running' };\n }\n if (normalized === 'succeeded' || normalized === 'success' || normalized === 'completed') {\n return { ok: true, value: 'succeeded' };\n }\n if (normalized === 'failed' || normalized === 'error') {\n return { ok: true, value: 'failed' };\n }\n if (normalized === 'cancelled' || normalized === 'canceled') {\n return { ok: true, value: 'cancelled' };\n }\n return {\n ok: false,\n error: {\n code: 'PROVIDER_UPSTREAM_ERROR',\n message: `Unexpected video job status from Bytedance: ${status}`,\n },\n };\n}\n\n/** Maps the initial createVideo status to queued or running. */\nexport function mapInitialStatus(\n statusValue: string | undefined,\n): TProviderMediaResult<'queued' | 'running'> {\n if (typeof statusValue !== 'string' || statusValue.trim().length === 0) {\n return { ok: true, value: 'queued' };\n }\n const normalizedStatus = statusValue.trim().toLowerCase();\n if (\n normalizedStatus === 'queued' ||\n normalizedStatus === 'pending' ||\n normalizedStatus === 'submitted'\n ) {\n return { ok: true, value: 'queued' };\n }\n if (\n normalizedStatus === 'running' ||\n normalizedStatus === 'processing' ||\n normalizedStatus === 'in_progress'\n ) {\n return { ok: true, value: 'running' };\n }\n return {\n ok: false,\n error: {\n code: 'PROVIDER_UPSTREAM_ERROR',\n message: `Unexpected createVideo status from Bytedance: ${statusValue}`,\n },\n };\n}\n\n/** Converts a numeric or string timestamp to ISO 8601 format. */\nexport function toIsoTimestamp(value: string | number | undefined): string {\n if (typeof value === 'number' && Number.isFinite(value)) {\n const numericTimestamp = value > MILLISECOND_EPOCH_THRESHOLD ? value : value * MS_PER_SECOND;\n const date = new Date(numericTimestamp);\n if (!Number.isNaN(date.getTime())) {\n return date.toISOString();\n }\n }\n if (typeof value === 'string' && value.trim().length > 0) {\n const maybeNumeric = Number(value);\n if (Number.isFinite(maybeNumeric)) {\n return toIsoTimestamp(maybeNumeric);\n }\n const parsedDate = new Date(value);\n if (!Number.isNaN(parsedDate.getTime())) {\n return parsedDate.toISOString();\n }\n }\n return new Date().toISOString();\n}\n\nfunction mapOutput(response: IBytedanceVideoTaskResponse): IVideoJobSnapshot['output'] {\n const directVideoUrl =\n typeof response.video_url === 'string' && response.video_url.trim().length > 0\n ? response.video_url\n : undefined;\n const contentVideoUrl =\n typeof response.content?.video_url === 'string' && response.content.video_url.trim().length > 0\n ? response.content.video_url\n : undefined;\n const resolvedVideoUrl = directVideoUrl ?? contentVideoUrl;\n if (typeof resolvedVideoUrl !== 'string') {\n return undefined;\n }\n return {\n kind: 'uri',\n uri: resolvedVideoUrl,\n mimeType: response.mime_type,\n bytes: response.bytes,\n };\n}\n","import type {\n IInlineImageInputSource,\n IUriImageInputSource,\n TProviderMediaResult,\n IVideoGenerationProvider,\n IVideoGenerationRequest,\n IVideoJobAccepted,\n IVideoJobSnapshot,\n} from '@robota-sdk/agent-core';\nimport type {\n IBytedanceCreateVideoTaskRequest,\n IBytedanceCreateVideoTaskResponse,\n IBytedanceProviderOptions,\n IBytedanceVideoTaskResponse,\n TBytedanceTaskContent,\n} from './types';\nimport { requestJson } from './http-client';\nimport { mapVideoJobSnapshot, mapInitialStatus, toIsoTimestamp } from './status-mapper';\n\nconst DEFAULT_CREATE_VIDEO_PATH = '/contents/generations/tasks';\nconst DEFAULT_GET_VIDEO_TASK_PATH_TEMPLATE = '/contents/generations/tasks/{taskId}';\nconst DEFAULT_CANCEL_VIDEO_TASK_PATH_TEMPLATE = '/contents/generations/tasks/{taskId}';\n\nexport class BytedanceProvider implements IVideoGenerationProvider {\n private readonly options: IBytedanceProviderOptions;\n\n public constructor(options: IBytedanceProviderOptions) {\n this.options = options;\n }\n\n public async createVideo(\n request: IVideoGenerationRequest,\n ): Promise<TProviderMediaResult<IVideoJobAccepted>> {\n if (request.prompt.trim().length === 0) {\n return buildInvalidRequestError('Video generation requires non-empty prompt.');\n }\n if (request.model.trim().length === 0) {\n return buildInvalidRequestError('Video generation requires non-empty model.');\n }\n if (typeof request.seed === 'number') {\n return buildInvalidRequestError(\n 'ModelArk Seedance provider does not support seed field in current contract.',\n );\n }\n\n const contentResult = this.buildContentPayload(request.prompt, request.inputImages);\n if (!contentResult.ok) {\n return contentResult;\n }\n\n const payload: IBytedanceCreateVideoTaskRequest = {\n model: request.model.trim(),\n content: contentResult.value,\n duration: request.durationSeconds,\n ratio: request.aspectRatio,\n };\n\n const responseResult = await requestJson<IBytedanceCreateVideoTaskResponse>(this.options, {\n path: this.options.createVideoPath ?? DEFAULT_CREATE_VIDEO_PATH,\n method: 'POST',\n body: JSON.stringify(payload),\n });\n if (!responseResult.ok) {\n return responseResult;\n }\n\n if (responseResult.value.id.trim().length === 0) {\n return buildUpstreamError('Bytedance createVideo response is missing task id.');\n }\n const mappedStatus = mapInitialStatus(responseResult.value.status);\n if (!mappedStatus.ok) {\n return mappedStatus;\n }\n return {\n ok: true,\n value: {\n jobId: responseResult.value.id,\n status: mappedStatus.value,\n createdAt: toIsoTimestamp(responseResult.value.created_at),\n },\n };\n }\n\n public async getVideoJob(jobId: string): Promise<TProviderMediaResult<IVideoJobSnapshot>> {\n if (jobId.trim().length === 0) {\n return buildInvalidRequestError('Video job lookup requires non-empty jobId.');\n }\n\n const responseResult = await requestJson<IBytedanceVideoTaskResponse>(this.options, {\n path: buildPath(\n this.options.getVideoTaskPathTemplate ?? DEFAULT_GET_VIDEO_TASK_PATH_TEMPLATE,\n jobId,\n ),\n method: 'GET',\n });\n if (!responseResult.ok) {\n return responseResult;\n }\n return mapVideoJobSnapshot(responseResult.value);\n }\n\n public async cancelVideoJob(jobId: string): Promise<TProviderMediaResult<IVideoJobSnapshot>> {\n if (jobId.trim().length === 0) {\n return buildInvalidRequestError('Video job cancellation requires non-empty jobId.');\n }\n\n const cancelMethod = this.options.cancelVideoTaskMethod ?? 'DELETE';\n const responseResult = await requestJson<IBytedanceVideoTaskResponse>(this.options, {\n path: buildPath(\n this.options.cancelVideoTaskPathTemplate ?? DEFAULT_CANCEL_VIDEO_TASK_PATH_TEMPLATE,\n jobId,\n ),\n method: cancelMethod,\n });\n if (!responseResult.ok) {\n return responseResult;\n }\n return mapVideoJobSnapshot(responseResult.value);\n }\n\n private buildContentPayload(\n prompt: string,\n inputImages: IVideoGenerationRequest['inputImages'],\n ): TProviderMediaResult<TBytedanceTaskContent[]> {\n const normalizedPrompt = prompt.trim();\n if (normalizedPrompt.length === 0) {\n return buildInvalidRequestError('Video generation requires non-empty prompt.');\n }\n const content: TBytedanceTaskContent[] = [{ type: 'text', text: normalizedPrompt }];\n if (Array.isArray(inputImages)) {\n for (const image of inputImages) {\n const imageUrlResult = toContentImageUrl(image);\n if (!imageUrlResult.ok) {\n return imageUrlResult;\n }\n content.push({ type: 'image_url', image_url: { url: imageUrlResult.value } });\n }\n }\n return { ok: true, value: content };\n }\n}\n\nfunction buildPath(template: string, taskId: string): string {\n return template.replace('{taskId}', encodeURIComponent(taskId));\n}\n\nfunction buildInvalidRequestError(message: string): TProviderMediaResult<never> {\n return { ok: false, error: { code: 'PROVIDER_INVALID_REQUEST', message } };\n}\n\nfunction buildUpstreamError(message: string): TProviderMediaResult<never> {\n return { ok: false, error: { code: 'PROVIDER_UPSTREAM_ERROR', message } };\n}\n\nfunction toContentImageUrl(\n image: IInlineImageInputSource | IUriImageInputSource,\n): TProviderMediaResult<string> {\n if (image.kind === 'uri') {\n if (image.uri.trim().length === 0) {\n return buildInvalidRequestError('Image uri must be non-empty.');\n }\n return { ok: true, value: image.uri };\n }\n if (image.data.trim().length === 0) {\n return buildInvalidRequestError('Inline image data must be non-empty.');\n }\n if (image.mimeType.trim().length === 0) {\n return buildInvalidRequestError('Inline image mimeType must be non-empty.');\n }\n return { ok: true, value: `data:${image.mimeType};base64,${image.data}` };\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ async function e(e,r){let a=new AbortController,o=setTimeout(()=>a.abort(),e.timeoutMs??6e4);try{let o=await fetch(t(e.baseUrl,r.path),{method:r.method,headers:{Authorization:`Bearer ${e.apiKey}`,"Content-Type":`application/json`,...e.defaultHeaders??{}},body:r.body,signal:a.signal}),s=await o.text();if(!o.ok)return i(o.status,s);let c=n(s);return c.ok?{ok:!0,value:c.value}:c}catch(e){return e instanceof Error&&e.name===`AbortError`?{ok:!1,error:{code:`PROVIDER_TIMEOUT`,message:`Bytedance media request timed out.`}}:{ok:!1,error:{code:`PROVIDER_UPSTREAM_ERROR`,message:e instanceof Error?e.message:`Bytedance media request failed.`}}}finally{clearTimeout(o)}}function t(e,t){return`${e.endsWith(`/`)?e.slice(0,-1):e}${t.startsWith(`/`)?t:`/${t}`}`}function n(e){try{return{ok:!0,value:JSON.parse(e)}}catch{return{ok:!1,error:{code:`PROVIDER_UPSTREAM_ERROR`,message:`Bytedance response is not valid JSON.`}}}}function r(e){try{return JSON.parse(e)}catch{return{message:e}}}function i(e,t){let n=r(t);return e===401||e===403?{ok:!1,error:{code:`PROVIDER_AUTH_ERROR`,message:n.message??`Bytedance authentication failed.`,details:n.details}}:e===404?{ok:!1,error:{code:`PROVIDER_JOB_NOT_FOUND`,message:n.message??`Bytedance video job was not found.`,details:n.details}}:e===409?{ok:!1,error:{code:`PROVIDER_JOB_NOT_CANCELLABLE`,message:n.message??`Bytedance video job cannot be cancelled in current state.`,details:n.details}}:e===429?{ok:!1,error:{code:`PROVIDER_RATE_LIMITED`,message:n.message??`Bytedance rate limit exceeded.`,details:n.details}}:e>=400&&e<500?{ok:!1,error:{code:`PROVIDER_INVALID_REQUEST`,message:n.message??`Bytedance rejected request payload.`,details:n.details}}:{ok:!1,error:{code:`PROVIDER_UPSTREAM_ERROR`,message:n.message??`Bytedance upstream request failed.`,details:n.details}}}function a(e){if(e.id.trim().length===0)return{ok:!1,error:{code:`PROVIDER_UPSTREAM_ERROR`,message:`Bytedance video job response is missing task id.`}};let t=o(e.status);return t.ok?{ok:!0,value:{jobId:e.id,status:t.value,output:l(e),error:t.value===`failed`&&e.error_message?{code:`PROVIDER_UPSTREAM_ERROR`,message:e.error_message}:void 0,updatedAt:c(e.updated_at??e.created_at)}}:t}function o(e){let t=e.trim().toLowerCase();return t===`queued`||t===`pending`||t===`submitted`?{ok:!0,value:`queued`}:t===`running`||t===`processing`||t===`in_progress`?{ok:!0,value:`running`}:t===`succeeded`||t===`success`||t===`completed`?{ok:!0,value:`succeeded`}:t===`failed`||t===`error`?{ok:!0,value:`failed`}:t===`cancelled`||t===`canceled`?{ok:!0,value:`cancelled`}:{ok:!1,error:{code:`PROVIDER_UPSTREAM_ERROR`,message:`Unexpected video job status from Bytedance: ${e}`}}}function s(e){if(typeof e!=`string`||e.trim().length===0)return{ok:!0,value:`queued`};let t=e.trim().toLowerCase();return t===`queued`||t===`pending`||t===`submitted`?{ok:!0,value:`queued`}:t===`running`||t===`processing`||t===`in_progress`?{ok:!0,value:`running`}:{ok:!1,error:{code:`PROVIDER_UPSTREAM_ERROR`,message:`Unexpected createVideo status from Bytedance: ${e}`}}}function c(e){if(typeof e==`number`&&Number.isFinite(e)){let t=e>0xe8d4a51000?e:e*1e3,n=new Date(t);if(!Number.isNaN(n.getTime()))return n.toISOString()}if(typeof e==`string`&&e.trim().length>0){let t=Number(e);if(Number.isFinite(t))return c(t);let n=new Date(e);if(!Number.isNaN(n.getTime()))return n.toISOString()}return new Date().toISOString()}function l(e){let t=typeof e.video_url==`string`&&e.video_url.trim().length>0?e.video_url:void 0,n=typeof e.content?.video_url==`string`&&e.content.video_url.trim().length>0?e.content.video_url:void 0,r=t??n;if(typeof r==`string`)return{kind:`uri`,uri:r,mimeType:e.mime_type,bytes:e.bytes}}var u=class{options;constructor(e){this.options=e}async createVideo(t){if(t.prompt.trim().length===0)return f(`Video generation requires non-empty prompt.`);if(t.model.trim().length===0)return f(`Video generation requires non-empty model.`);if(typeof t.seed==`number`)return f(`ModelArk Seedance provider does not support seed field in current contract.`);let n=this.buildContentPayload(t.prompt,t.inputImages);if(!n.ok)return n;let r={model:t.model.trim(),content:n.value,duration:t.durationSeconds,ratio:t.aspectRatio},i=await e(this.options,{path:this.options.createVideoPath??`/contents/generations/tasks`,method:`POST`,body:JSON.stringify(r)});if(!i.ok)return i;if(i.value.id.trim().length===0)return p(`Bytedance createVideo response is missing task id.`);let a=s(i.value.status);return a.ok?{ok:!0,value:{jobId:i.value.id,status:a.value,createdAt:c(i.value.created_at)}}:a}async getVideoJob(t){if(t.trim().length===0)return f(`Video job lookup requires non-empty jobId.`);let n=await e(this.options,{path:d(this.options.getVideoTaskPathTemplate??`/contents/generations/tasks/{taskId}`,t),method:`GET`});return n.ok?a(n.value):n}async cancelVideoJob(t){if(t.trim().length===0)return f(`Video job cancellation requires non-empty jobId.`);let n=this.options.cancelVideoTaskMethod??`DELETE`,r=await e(this.options,{path:d(this.options.cancelVideoTaskPathTemplate??`/contents/generations/tasks/{taskId}`,t),method:n});return r.ok?a(r.value):r}buildContentPayload(e,t){let n=e.trim();if(n.length===0)return f(`Video generation requires non-empty prompt.`);let r=[{type:`text`,text:n}];if(Array.isArray(t))for(let e of t){let t=m(e);if(!t.ok)return t;r.push({type:`image_url`,image_url:{url:t.value}})}return{ok:!0,value:r}}};function d(e,t){return e.replace(`{taskId}`,encodeURIComponent(t))}function f(e){return{ok:!1,error:{code:`PROVIDER_INVALID_REQUEST`,message:e}}}function p(e){return{ok:!1,error:{code:`PROVIDER_UPSTREAM_ERROR`,message:e}}}function m(e){return e.kind===`uri`?e.uri.trim().length===0?f(`Image uri must be non-empty.`):{ok:!0,value:e.uri}:e.data.trim().length===0?f(`Inline image data must be non-empty.`):e.mimeType.trim().length===0?f(`Inline image mimeType must be non-empty.`):{ok:!0,value:`data:${e.mimeType};base64,${e.data}`}}Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return u}});
@@ -0,0 +1 @@
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return s}});
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../deepseek-oA2Y6bD0.cjs`);exports.DEEPSEEK_DEPRECATED_ALIAS_RETIREMENT_DATE=e.r,exports.DEEPSEEK_MODEL_CATALOG_SOURCE_URL=e.i,exports.DEEPSEEK_MODEL_LAST_VERIFIED_AT=e.a,exports.DEEPSEEK_MODEL_LIST_SOURCE_URL=e.o,exports.DEFAULT_DEEPSEEK_PROVIDER_API_KEY_ENV=e.c,exports.DEFAULT_DEEPSEEK_PROVIDER_API_KEY_REFERENCE=e.l,exports.DEFAULT_DEEPSEEK_PROVIDER_BASE_URL=e.u,exports.DEFAULT_DEEPSEEK_PROVIDER_MODEL=e.d,exports.DeepSeekProvider=e.s,exports.createDeepSeekProviderDefinition=e.t,exports.refreshDeepSeekModelCatalog=e.n;
@@ -0,0 +1,2 @@
1
+ import { a as refreshDeepSeekModelCatalog, c as DEFAULT_DEEPSEEK_PROVIDER_BASE_URL, d as DeepSeekProvider, f as IDeepSeekProviderOptions, g as TDeepSeekThinkingMode, h as TDeepSeekReasoningEffort, i as DEEPSEEK_MODEL_LIST_SOURCE_URL, l as DEFAULT_DEEPSEEK_PROVIDER_MODEL, m as TDeepSeekProviderOptionValue, n as DEEPSEEK_MODEL_CATALOG_SOURCE_URL, o as DEFAULT_DEEPSEEK_PROVIDER_API_KEY_ENV, p as IDeepSeekThinkingConfig, r as DEEPSEEK_MODEL_LAST_VERIFIED_AT, s as DEFAULT_DEEPSEEK_PROVIDER_API_KEY_REFERENCE, t as DEEPSEEK_DEPRECATED_ALIAS_RETIREMENT_DATE, u as createDeepSeekProviderDefinition } from "../index-Cp2XRh9G.js";
2
+ export { DEEPSEEK_DEPRECATED_ALIAS_RETIREMENT_DATE, DEEPSEEK_MODEL_CATALOG_SOURCE_URL, DEEPSEEK_MODEL_LAST_VERIFIED_AT, DEEPSEEK_MODEL_LIST_SOURCE_URL, DEFAULT_DEEPSEEK_PROVIDER_API_KEY_ENV, DEFAULT_DEEPSEEK_PROVIDER_API_KEY_REFERENCE, DEFAULT_DEEPSEEK_PROVIDER_BASE_URL, DEFAULT_DEEPSEEK_PROVIDER_MODEL, DeepSeekProvider, type IDeepSeekProviderOptions, type IDeepSeekThinkingConfig, type TDeepSeekProviderOptionValue, type TDeepSeekReasoningEffort, type TDeepSeekThinkingMode, createDeepSeekProviderDefinition, refreshDeepSeekModelCatalog };
@@ -0,0 +1 @@
1
+ import{a as e,c as t,d as n,i as r,l as i,n as a,o,r as s,s as c,t as l,u}from"../deepseek-_8Ixx7rA.js";export{s as DEEPSEEK_DEPRECATED_ALIAS_RETIREMENT_DATE,r as DEEPSEEK_MODEL_CATALOG_SOURCE_URL,e as DEEPSEEK_MODEL_LAST_VERIFIED_AT,o as DEEPSEEK_MODEL_LIST_SOURCE_URL,t as DEFAULT_DEEPSEEK_PROVIDER_API_KEY_ENV,i as DEFAULT_DEEPSEEK_PROVIDER_API_KEY_REFERENCE,u as DEFAULT_DEEPSEEK_PROVIDER_BASE_URL,n as DEFAULT_DEEPSEEK_PROVIDER_MODEL,c as DeepSeekProvider,l as createDeepSeekProviderDefinition,a as refreshDeepSeekModelCatalog};
@@ -0,0 +1,2 @@
1
+ import{a as e,i as t,n,o as r,r as i,t as a}from"./openai-compatible-Dm4Sof9e.js";import{AbstractAIProvider as o,SilentLogger as s}from"@robota-sdk/agent-core";import c from"openai";const l=`deepseek-v4-flash`,u=`DEEPSEEK_API_KEY`,d=`$ENV:${u}`,f=`https://api.deepseek.com`;var p=class extends o{name=`deepseek`;version=`1.0.0`;client;options;responseParser;onTextDelta;constructor(e){if(super(e.logger||s),this.options=e,e.executor&&(this.executor=e.executor),!this.executor)if(e.client)this.client=e.client;else if(e.apiKey)this.client=new c({apiKey:e.apiKey,baseURL:e.baseURL??`https://api.deepseek.com`,...e.timeout!==void 0&&{timeout:e.timeout}});else throw Error(`Either DeepSeek client, apiKey, or executor is required`);this.responseParser=new t({logger:this.logger})}async chat(e,t){if(this.validateMessages(e),this.validateNativeWebTools(t?.nativeWebTools),this.executor)try{return await this.executeViaExecutorOrDirect(e,t)}catch(e){throw this.logger.error(`DeepSeek Provider executor chat error:`,e instanceof Error?e.message:String(e)),e}let n=this.getClient();try{let r=this.buildRequestParams(e,t),i=t?.onTextDelta??this.onTextDelta;if(i)return await this.chatWithStreamingAssembly({...r,stream:!0},{...t,onTextDelta:i});t?.onProviderNativeRawPayload?.({provider:`deepseek`,apiSurface:`chat-completions`,payloadKind:`request`,payload:r});let a=await n.chat.completions.create(r);return t?.onProviderNativeRawPayload?.({provider:`deepseek`,apiSurface:`chat-completions`,payloadKind:`response`,payload:a}),this.responseParser.parseResponse(a)}catch(e){let t=e.message||`DeepSeek API request failed`;throw Error(`DeepSeek chat failed: ${t}`)}}async*chatStream(e,t){if(this.validateMessages(e),this.validateNativeWebTools(t?.nativeWebTools),this.executor)try{yield*this.executeStreamViaExecutorOrDirect(e,t);return}catch(e){throw this.logger.error(`DeepSeek Provider executor stream error:`,e instanceof Error?e.message:String(e)),e}let r=this.getClient();try{let i=this.buildStreamingRequestParams(e,t);t?.onProviderNativeRawPayload?.({provider:`deepseek`,apiSurface:`chat-completions`,payloadKind:`request`,payload:i});let a=n(await r.chat.completions.create(i),{provider:`deepseek`,apiSurface:`chat-completions`,onProviderNativeRawPayload:t?.onProviderNativeRawPayload});for await(let e of this.streamWithAbort(a,t?.signal)){let t=this.responseParser.parseStreamingChunk(e);t&&(yield t)}}catch(e){let t=e.message||`DeepSeek API request failed`;throw Error(`DeepSeek stream failed: ${t}`)}}supportsTools(){return!0}getCapabilities(){return{functionCalling:{supported:!0},nativeWebTools:{webSearch:{supported:!1,enabled:!1,source:`openai-compatible-chat-completions`,reason:`DeepSeek OpenAI-compatible Chat Completions supports declared function tools, not provider-native web search.`},webFetch:{supported:!1,enabled:!1,source:`openai-compatible-chat-completions`,reason:`DeepSeek OpenAI-compatible Chat Completions supports declared function tools, not provider-native web fetch.`}}}}validateConfig(){return!!this.client&&!!this.options}async dispose(){}buildRequestParams(t,n){this.validateTools(n?.tools);let i=n?.model??this.options.defaultModel;if(!i)throw Error(`Model is required in chat options. Please specify a model in defaultModel configuration.`);return{model:i,messages:e(t),...n?.temperature!==void 0&&{temperature:n.temperature},...n?.maxTokens!==void 0&&{max_tokens:n.maxTokens},...n?.tools&&{tools:r(n.tools),tool_choice:`auto`},...this.options.thinking!==void 0&&{thinking:{type:this.options.thinking}},...this.options.reasoningEffort!==void 0&&{reasoning_effort:this.options.reasoningEffort}}}buildStreamingRequestParams(e,t){return{...this.buildRequestParams(e,t),stream:!0}}getClient(){if(!this.client)throw Error(`DeepSeek client not available. Either provide a client/apiKey or use an executor.`);return this.client}async chatWithStreamingAssembly(e,t){let r=this.getClient();try{return t.onProviderNativeRawPayload?.({provider:`deepseek`,apiSurface:`chat-completions`,payloadKind:`request`,payload:e}),i({stream:n(await r.chat.completions.create(e,t.signal?{signal:t.signal}:void 0),{provider:`deepseek`,apiSurface:`chat-completions`,onProviderNativeRawPayload:t.onProviderNativeRawPayload}),onTextDelta:t.onTextDelta,signal:t.signal})}catch(e){let t=e.message||`DeepSeek streaming request failed`;throw Error(`DeepSeek stream failed: ${t}`)}}};const m=`https://api-docs.deepseek.com/quick_start/pricing`,h=`https://api-docs.deepseek.com/api/list-models`,g=`2026-05-07`,_=`2026-07-24`,v=[{id:l,displayName:`DeepSeek V4 Flash`,contextWindow:1e6,capabilities:[`tools`,`reasoning`,`json_schema`,`streaming`],lifecycle:`active`,sourceUrl:m,lastVerifiedAt:g},{id:`deepseek-v4-pro`,displayName:`DeepSeek V4 Pro`,contextWindow:1e6,capabilities:[`tools`,`reasoning`,`json_schema`,`streaming`],lifecycle:`active`,sourceUrl:m,lastVerifiedAt:g},{id:`deepseek-chat`,displayName:`DeepSeek Chat compatibility alias, deprecated ${_}`,aliases:[l],contextWindow:1e6,capabilities:[`tools`,`json_schema`,`streaming`],lifecycle:`deprecated`,sourceUrl:m,lastVerifiedAt:g},{id:`deepseek-reasoner`,displayName:`DeepSeek Reasoner compatibility alias, deprecated ${_}`,aliases:[l],contextWindow:1e6,capabilities:[`reasoning`,`json_schema`,`streaming`],lifecycle:`deprecated`,sourceUrl:m,lastVerifiedAt:g}];function y(e){return v.find(t=>t.id===e)}async function b(e,t=w){let n=await t(`${C(e.baseURL??`https://api.deepseek.com`)}/models`,x(e.apiKey));return n.ok?{status:`live`,sourceUrl:m,lastVerifiedAt:g,entries:((await n.json()).data??[]).map(e=>e.id).filter(e=>typeof e==`string`&&e.length>0).map(S)}:{status:`unavailable`,sourceUrl:m,message:`DeepSeek model refresh failed: HTTP ${n.status}`}}function x(e){if(e)return{headers:{Authorization:`Bearer ${e}`}}}function S(e){return y(e)??{id:e,displayName:e,lifecycle:`active`,sourceUrl:`https://api-docs.deepseek.com/quick_start/pricing`,lastVerifiedAt:`2026-05-07`}}function C(e){return e.replace(/\/$/,``)}async function w(e,t){let n=await fetch(e,{...t?.headers!==void 0&&{headers:t.headers}});return{ok:n.ok,status:n.status,json:()=>n.json()}}const T={status:`fallback`,sourceUrl:m,lastVerifiedAt:g,entries:v},E=[{kind:`api-key`,label:`DeepSeek API keys`,url:`https://platform.deepseek.com/api_keys`,sourceUrl:`https://api-docs.deepseek.com/`,lastVerifiedAt:`2026-05-08`}];function D(){return{type:`deepseek`,displayName:`DeepSeek`,description:`DeepSeek OpenAI-compatible endpoint`,defaults:{model:l,apiKey:d,baseURL:f},modelCatalog:T,setupHelpLinks:E,setupSteps:[{key:`baseURL`,title:`DeepSeek OpenAI-compatible base URL`,defaultValue:f},{key:`model`,title:`DeepSeek model`,defaultValue:l},{key:`apiKey`,title:`DeepSeek API key`,defaultValue:d,masked:!0}],requiresApiKey:!0,probeProfile:a,refreshModelCatalog:({profile:e})=>b(e),modelCatalogCacheTtlSeconds:86400,createProvider:e=>{let t=k(e.options);return new p({apiKey:O(e.apiKey),...e.baseURL!==void 0&&{baseURL:e.baseURL},...e.timeout!==void 0&&{timeout:e.timeout},...t.thinking!==void 0&&{thinking:t.thinking},...t.reasoningEffort!==void 0&&{reasoningEffort:t.reasoningEffort},defaultModel:e.model})}}}function O(e){if(!e)throw Error(`Provider deepseek requires apiKey`);return e}function k(e){let t=A(e?.thinking),n=j(e?.reasoningEffort);return{...t!==void 0&&{thinking:t},...n!==void 0&&{reasoningEffort:n}}}function A(e){if(e===!0)return`enabled`;if(e===!1)return`disabled`;if(e===`enabled`||e===`disabled`)return e;let t=M(e)?.type;return t===`enabled`||t===`disabled`?t:void 0}function j(e){if(e===`low`||e===`medium`||e===`high`||e===`xhigh`||e===`max`)return e}function M(e){if(!(e==null||e instanceof Date||Array.isArray(e)))return typeof e==`object`?e:void 0}export{g as a,u as c,l as d,m as i,d as l,b as n,h as o,_ as r,p as s,D as t,f as u};
2
+ //# sourceMappingURL=deepseek-_8Ixx7rA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deepseek-_8Ixx7rA.js","names":["deepSeekError"],"sources":["../../src/deepseek/defaults.ts","../../src/deepseek/provider.ts","../../src/deepseek/model-catalog.ts","../../src/deepseek/model-catalog-refresh.ts","../../src/deepseek/provider-definition.ts"],"sourcesContent":["export const DEFAULT_DEEPSEEK_PROVIDER_MODEL = 'deepseek-v4-flash';\nexport const DEFAULT_DEEPSEEK_PROVIDER_API_KEY_ENV = 'DEEPSEEK_API_KEY';\nexport const DEFAULT_DEEPSEEK_PROVIDER_API_KEY_REFERENCE = `$ENV:${DEFAULT_DEEPSEEK_PROVIDER_API_KEY_ENV}`;\nexport const DEFAULT_DEEPSEEK_PROVIDER_BASE_URL = 'https://api.deepseek.com';\n","import OpenAI from 'openai';\nimport { AbstractAIProvider, SilentLogger } from '@robota-sdk/agent-core';\nimport type {\n IChatOptions,\n IProviderCapabilities,\n TTextDeltaCallback,\n TUniversalMessage,\n} from '@robota-sdk/agent-core';\nimport {\n assembleOpenAICompatibleStream,\n convertToOpenAICompatibleMessages,\n convertToOpenAICompatibleTools,\n observeProviderNativeRawPayloadStream,\n OpenAICompatibleResponseParser,\n} from '../shared/openai-compatible/index.js';\nimport type { IOpenAICompatibleError } from '../shared/openai-compatible/index.js';\nimport { DEFAULT_DEEPSEEK_PROVIDER_BASE_URL } from './defaults';\nimport type {\n IDeepSeekProviderOptions,\n IDeepSeekThinkingConfig,\n TDeepSeekReasoningEffort,\n} from './types';\n\ntype TDeepSeekChatCompletionCreateParamsNonStreaming = Omit<\n OpenAI.Chat.ChatCompletionCreateParamsNonStreaming,\n 'reasoning_effort'\n> & {\n thinking?: IDeepSeekThinkingConfig;\n reasoning_effort?: TDeepSeekReasoningEffort;\n};\n\ntype TDeepSeekChatCompletionCreateParamsStreaming = Omit<\n OpenAI.Chat.ChatCompletionCreateParamsStreaming,\n 'reasoning_effort'\n> & {\n thinking?: IDeepSeekThinkingConfig;\n reasoning_effort?: TDeepSeekReasoningEffort;\n};\n\nexport class DeepSeekProvider extends AbstractAIProvider {\n override readonly name = 'deepseek';\n override readonly version = '1.0.0';\n\n private readonly client?: OpenAI;\n private readonly options: IDeepSeekProviderOptions;\n private readonly responseParser: OpenAICompatibleResponseParser;\n\n onTextDelta?: TTextDeltaCallback;\n\n constructor(options: IDeepSeekProviderOptions) {\n super(options.logger || SilentLogger);\n this.options = options;\n\n if (options.executor) {\n this.executor = options.executor;\n }\n\n if (!this.executor) {\n if (options.client) {\n this.client = options.client;\n } else if (options.apiKey) {\n this.client = new OpenAI({\n apiKey: options.apiKey,\n baseURL: options.baseURL ?? DEFAULT_DEEPSEEK_PROVIDER_BASE_URL,\n ...(options.timeout !== undefined && { timeout: options.timeout }),\n });\n } else {\n throw new Error('Either DeepSeek client, apiKey, or executor is required');\n }\n }\n\n this.responseParser = new OpenAICompatibleResponseParser({ logger: this.logger });\n }\n\n override async chat(\n messages: TUniversalMessage[],\n options?: IChatOptions,\n ): Promise<TUniversalMessage> {\n this.validateMessages(messages);\n this.validateNativeWebTools(options?.nativeWebTools);\n\n if (this.executor) {\n try {\n return await this.executeViaExecutorOrDirect(messages, options);\n } catch (error) {\n this.logger.error(\n 'DeepSeek Provider executor chat error:',\n error instanceof Error ? error.message : String(error),\n );\n throw error;\n }\n }\n\n const client = this.getClient();\n\n try {\n const requestParams = this.buildRequestParams(messages, options);\n const textDeltaCb = options?.onTextDelta ?? this.onTextDelta;\n if (textDeltaCb) {\n return await this.chatWithStreamingAssembly(\n { ...requestParams, stream: true },\n { ...options, onTextDelta: textDeltaCb },\n );\n }\n\n options?.onProviderNativeRawPayload?.({\n provider: 'deepseek',\n apiSurface: 'chat-completions',\n payloadKind: 'request',\n payload: requestParams,\n });\n const response = await client.chat.completions.create(\n requestParams as OpenAI.Chat.ChatCompletionCreateParamsNonStreaming,\n );\n options?.onProviderNativeRawPayload?.({\n provider: 'deepseek',\n apiSurface: 'chat-completions',\n payloadKind: 'response',\n payload: response,\n });\n return this.responseParser.parseResponse(response);\n } catch (error) {\n const deepSeekError = error as IOpenAICompatibleError;\n const errorMessage = deepSeekError.message || 'DeepSeek API request failed';\n throw new Error(`DeepSeek chat failed: ${errorMessage}`);\n }\n }\n\n override async *chatStream(\n messages: TUniversalMessage[],\n options?: IChatOptions,\n ): AsyncIterable<TUniversalMessage> {\n this.validateMessages(messages);\n this.validateNativeWebTools(options?.nativeWebTools);\n\n if (this.executor) {\n try {\n yield* this.executeStreamViaExecutorOrDirect(messages, options);\n return;\n } catch (error) {\n this.logger.error(\n 'DeepSeek Provider executor stream error:',\n error instanceof Error ? error.message : String(error),\n );\n throw error;\n }\n }\n\n const client = this.getClient();\n\n try {\n const requestParams = this.buildStreamingRequestParams(messages, options);\n options?.onProviderNativeRawPayload?.({\n provider: 'deepseek',\n apiSurface: 'chat-completions',\n payloadKind: 'request',\n payload: requestParams,\n });\n const stream = await client.chat.completions.create(\n requestParams as OpenAI.Chat.ChatCompletionCreateParamsStreaming,\n );\n const observedStream = observeProviderNativeRawPayloadStream(stream, {\n provider: 'deepseek',\n apiSurface: 'chat-completions',\n onProviderNativeRawPayload: options?.onProviderNativeRawPayload,\n });\n\n for await (const chunk of this.streamWithAbort(observedStream, options?.signal)) {\n const universalMessage = this.responseParser.parseStreamingChunk(chunk);\n if (universalMessage) {\n yield universalMessage;\n }\n }\n } catch (error) {\n const deepSeekError = error as IOpenAICompatibleError;\n const errorMessage = deepSeekError.message || 'DeepSeek API request failed';\n throw new Error(`DeepSeek stream failed: ${errorMessage}`);\n }\n }\n\n override supportsTools(): boolean {\n return true;\n }\n\n override getCapabilities(): IProviderCapabilities {\n return {\n functionCalling: { supported: true },\n nativeWebTools: {\n webSearch: {\n supported: false,\n enabled: false,\n source: 'openai-compatible-chat-completions',\n reason:\n 'DeepSeek OpenAI-compatible Chat Completions supports declared function tools, not provider-native web search.',\n },\n webFetch: {\n supported: false,\n enabled: false,\n source: 'openai-compatible-chat-completions',\n reason:\n 'DeepSeek OpenAI-compatible Chat Completions supports declared function tools, not provider-native web fetch.',\n },\n },\n };\n }\n\n override validateConfig(): boolean {\n return !!this.client && !!this.options;\n }\n\n override async dispose(): Promise<void> {\n // OpenAI-compatible DeepSeek clients do not need explicit cleanup.\n }\n\n private buildRequestParams(\n messages: TUniversalMessage[],\n options: IChatOptions | undefined,\n ): TDeepSeekChatCompletionCreateParamsNonStreaming {\n this.validateTools(options?.tools);\n const model = options?.model ?? this.options.defaultModel;\n if (!model) {\n throw new Error(\n 'Model is required in chat options. Please specify a model in defaultModel configuration.',\n );\n }\n\n return {\n model,\n messages: convertToOpenAICompatibleMessages(messages),\n ...(options?.temperature !== undefined && { temperature: options.temperature }),\n ...(options?.maxTokens !== undefined && { max_tokens: options.maxTokens }),\n ...(options?.tools && {\n tools: convertToOpenAICompatibleTools(options.tools),\n tool_choice: 'auto' as const,\n }),\n ...(this.options.thinking !== undefined && {\n thinking: { type: this.options.thinking },\n }),\n ...(this.options.reasoningEffort !== undefined && {\n reasoning_effort: this.options.reasoningEffort,\n }),\n };\n }\n\n private buildStreamingRequestParams(\n messages: TUniversalMessage[],\n options: IChatOptions | undefined,\n ): TDeepSeekChatCompletionCreateParamsStreaming {\n return {\n ...this.buildRequestParams(messages, options),\n stream: true,\n };\n }\n\n private getClient(): OpenAI {\n if (!this.client) {\n throw new Error(\n 'DeepSeek client not available. Either provide a client/apiKey or use an executor.',\n );\n }\n\n return this.client;\n }\n\n private async chatWithStreamingAssembly(\n requestParams: TDeepSeekChatCompletionCreateParamsStreaming,\n options: IChatOptions,\n ): Promise<TUniversalMessage> {\n const client = this.getClient();\n\n try {\n options.onProviderNativeRawPayload?.({\n provider: 'deepseek',\n apiSurface: 'chat-completions',\n payloadKind: 'request',\n payload: requestParams,\n });\n const stream = await client.chat.completions.create(\n requestParams as OpenAI.Chat.ChatCompletionCreateParamsStreaming,\n options.signal ? { signal: options.signal } : undefined,\n );\n\n return assembleOpenAICompatibleStream({\n stream: observeProviderNativeRawPayloadStream(stream, {\n provider: 'deepseek',\n apiSurface: 'chat-completions',\n onProviderNativeRawPayload: options.onProviderNativeRawPayload,\n }),\n onTextDelta: options.onTextDelta,\n signal: options.signal,\n });\n } catch (error) {\n const deepSeekError = error as IOpenAICompatibleError;\n const errorMessage = deepSeekError.message || 'DeepSeek streaming request failed';\n throw new Error(`DeepSeek stream failed: ${errorMessage}`);\n }\n }\n}\n","import type { IProviderModelCatalogEntry } from '@robota-sdk/agent-core';\nimport { DEFAULT_DEEPSEEK_PROVIDER_MODEL } from './defaults';\n\nexport const DEEPSEEK_MODEL_CATALOG_SOURCE_URL =\n 'https://api-docs.deepseek.com/quick_start/pricing';\nexport const DEEPSEEK_MODEL_LIST_SOURCE_URL = 'https://api-docs.deepseek.com/api/list-models';\nexport const DEEPSEEK_MODEL_LAST_VERIFIED_AT = '2026-05-07';\nexport const DEEPSEEK_DEPRECATED_ALIAS_RETIREMENT_DATE = '2026-07-24';\n\nexport const DEEPSEEK_MODEL_CATALOG_ENTRIES: readonly IProviderModelCatalogEntry[] = [\n {\n id: DEFAULT_DEEPSEEK_PROVIDER_MODEL,\n displayName: 'DeepSeek V4 Flash',\n contextWindow: 1_000_000,\n capabilities: ['tools', 'reasoning', 'json_schema', 'streaming'],\n lifecycle: 'active',\n sourceUrl: DEEPSEEK_MODEL_CATALOG_SOURCE_URL,\n lastVerifiedAt: DEEPSEEK_MODEL_LAST_VERIFIED_AT,\n },\n {\n id: 'deepseek-v4-pro',\n displayName: 'DeepSeek V4 Pro',\n contextWindow: 1_000_000,\n capabilities: ['tools', 'reasoning', 'json_schema', 'streaming'],\n lifecycle: 'active',\n sourceUrl: DEEPSEEK_MODEL_CATALOG_SOURCE_URL,\n lastVerifiedAt: DEEPSEEK_MODEL_LAST_VERIFIED_AT,\n },\n {\n id: 'deepseek-chat',\n displayName: `DeepSeek Chat compatibility alias, deprecated ${DEEPSEEK_DEPRECATED_ALIAS_RETIREMENT_DATE}`,\n aliases: [DEFAULT_DEEPSEEK_PROVIDER_MODEL],\n contextWindow: 1_000_000,\n capabilities: ['tools', 'json_schema', 'streaming'],\n lifecycle: 'deprecated',\n sourceUrl: DEEPSEEK_MODEL_CATALOG_SOURCE_URL,\n lastVerifiedAt: DEEPSEEK_MODEL_LAST_VERIFIED_AT,\n },\n {\n id: 'deepseek-reasoner',\n displayName: `DeepSeek Reasoner compatibility alias, deprecated ${DEEPSEEK_DEPRECATED_ALIAS_RETIREMENT_DATE}`,\n aliases: [DEFAULT_DEEPSEEK_PROVIDER_MODEL],\n contextWindow: 1_000_000,\n capabilities: ['reasoning', 'json_schema', 'streaming'],\n lifecycle: 'deprecated',\n sourceUrl: DEEPSEEK_MODEL_CATALOG_SOURCE_URL,\n lastVerifiedAt: DEEPSEEK_MODEL_LAST_VERIFIED_AT,\n },\n];\n\nexport function getDeepSeekFallbackModelCatalogEntry(\n id: string,\n): IProviderModelCatalogEntry | undefined {\n return DEEPSEEK_MODEL_CATALOG_ENTRIES.find((entry) => entry.id === id);\n}\n","import type {\n IProviderModelCatalog,\n IProviderModelCatalogEntry,\n IProviderProfileConfig,\n} from '@robota-sdk/agent-core';\nimport { DEFAULT_DEEPSEEK_PROVIDER_BASE_URL } from './defaults';\nimport {\n DEEPSEEK_MODEL_CATALOG_SOURCE_URL,\n DEEPSEEK_MODEL_LAST_VERIFIED_AT,\n getDeepSeekFallbackModelCatalogEntry,\n} from './model-catalog';\n\nexport interface IDeepSeekModelsResponse {\n data?: Array<{\n id?: string;\n object?: string;\n owned_by?: string;\n }>;\n}\n\nexport interface IDeepSeekFetchInit {\n headers?: Record<string, string>;\n}\n\nexport interface IDeepSeekFetchResponse {\n ok: boolean;\n status: number;\n json: () => Promise<IDeepSeekModelsResponse>;\n}\n\nexport type TDeepSeekFetch = (\n url: string,\n init?: IDeepSeekFetchInit,\n) => Promise<IDeepSeekFetchResponse>;\n\nexport async function refreshDeepSeekModelCatalog(\n profile: IProviderProfileConfig,\n fetcher: TDeepSeekFetch = defaultDeepSeekFetch,\n): Promise<IProviderModelCatalog> {\n const baseURL = trimTrailingSlash(profile.baseURL ?? DEFAULT_DEEPSEEK_PROVIDER_BASE_URL);\n const url = `${baseURL}/models`;\n const response = await fetcher(url, buildFetchInit(profile.apiKey));\n\n if (!response.ok) {\n return {\n status: 'unavailable',\n sourceUrl: DEEPSEEK_MODEL_CATALOG_SOURCE_URL,\n message: `DeepSeek model refresh failed: HTTP ${response.status}`,\n };\n }\n\n const body = await response.json();\n const entries = (body.data ?? [])\n .map((model) => model.id)\n .filter((id): id is string => typeof id === 'string' && id.length > 0)\n .map(toModelCatalogEntry);\n\n return {\n status: 'live',\n sourceUrl: DEEPSEEK_MODEL_CATALOG_SOURCE_URL,\n lastVerifiedAt: DEEPSEEK_MODEL_LAST_VERIFIED_AT,\n entries,\n };\n}\n\nfunction buildFetchInit(apiKey: string | undefined): IDeepSeekFetchInit | undefined {\n if (!apiKey) {\n return undefined;\n }\n return {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n },\n };\n}\n\nfunction toModelCatalogEntry(id: string): IProviderModelCatalogEntry {\n return (\n getDeepSeekFallbackModelCatalogEntry(id) ?? {\n id,\n displayName: id,\n lifecycle: 'active',\n sourceUrl: DEEPSEEK_MODEL_CATALOG_SOURCE_URL,\n lastVerifiedAt: DEEPSEEK_MODEL_LAST_VERIFIED_AT,\n }\n );\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/$/, '');\n}\n\nasync function defaultDeepSeekFetch(\n url: string,\n init?: IDeepSeekFetchInit,\n): Promise<IDeepSeekFetchResponse> {\n const response = await fetch(url, {\n ...(init?.headers !== undefined && { headers: init.headers }),\n });\n return {\n ok: response.ok,\n status: response.status,\n json: () => response.json() as Promise<IDeepSeekModelsResponse>,\n };\n}\n","import type { IProviderDefinition, TUniversalValue } from '@robota-sdk/agent-core';\nimport { probeOpenAICompatibleProfile } from '../shared/openai-compatible/index.js';\nimport {\n DEFAULT_DEEPSEEK_PROVIDER_API_KEY_REFERENCE,\n DEFAULT_DEEPSEEK_PROVIDER_BASE_URL,\n DEFAULT_DEEPSEEK_PROVIDER_MODEL,\n} from './defaults';\nimport {\n DEEPSEEK_MODEL_CATALOG_ENTRIES,\n DEEPSEEK_MODEL_CATALOG_SOURCE_URL,\n DEEPSEEK_MODEL_LAST_VERIFIED_AT,\n} from './model-catalog';\nimport { refreshDeepSeekModelCatalog } from './model-catalog-refresh';\nimport { DeepSeekProvider } from './provider';\nimport type { TDeepSeekReasoningEffort, TDeepSeekThinkingMode } from './types';\n\nconst DEEPSEEK_MODEL_CATALOG: NonNullable<IProviderDefinition['modelCatalog']> = {\n status: 'fallback',\n sourceUrl: DEEPSEEK_MODEL_CATALOG_SOURCE_URL,\n lastVerifiedAt: DEEPSEEK_MODEL_LAST_VERIFIED_AT,\n entries: DEEPSEEK_MODEL_CATALOG_ENTRIES,\n};\nconst DEEPSEEK_API_KEY_URL = 'https://platform.deepseek.com/api_keys';\nconst DEEPSEEK_SETUP_SOURCE_URL = 'https://api-docs.deepseek.com/';\nconst DEEPSEEK_SETUP_LAST_VERIFIED_AT = '2026-05-08';\nconst DEEPSEEK_SETUP_HELP_LINKS: NonNullable<IProviderDefinition['setupHelpLinks']> = [\n {\n kind: 'api-key',\n label: 'DeepSeek API keys',\n url: DEEPSEEK_API_KEY_URL,\n sourceUrl: DEEPSEEK_SETUP_SOURCE_URL,\n lastVerifiedAt: DEEPSEEK_SETUP_LAST_VERIFIED_AT,\n },\n];\n\nexport function createDeepSeekProviderDefinition(): IProviderDefinition {\n return {\n type: 'deepseek',\n displayName: 'DeepSeek',\n description: 'DeepSeek OpenAI-compatible endpoint',\n defaults: {\n model: DEFAULT_DEEPSEEK_PROVIDER_MODEL,\n apiKey: DEFAULT_DEEPSEEK_PROVIDER_API_KEY_REFERENCE,\n baseURL: DEFAULT_DEEPSEEK_PROVIDER_BASE_URL,\n },\n modelCatalog: DEEPSEEK_MODEL_CATALOG,\n setupHelpLinks: DEEPSEEK_SETUP_HELP_LINKS,\n setupSteps: [\n {\n key: 'baseURL',\n title: 'DeepSeek OpenAI-compatible base URL',\n defaultValue: DEFAULT_DEEPSEEK_PROVIDER_BASE_URL,\n },\n {\n key: 'model',\n title: 'DeepSeek model',\n defaultValue: DEFAULT_DEEPSEEK_PROVIDER_MODEL,\n },\n {\n key: 'apiKey',\n title: 'DeepSeek API key',\n defaultValue: DEFAULT_DEEPSEEK_PROVIDER_API_KEY_REFERENCE,\n masked: true,\n },\n ],\n requiresApiKey: true,\n probeProfile: probeOpenAICompatibleProfile,\n refreshModelCatalog: ({ profile }) => refreshDeepSeekModelCatalog(profile),\n modelCatalogCacheTtlSeconds: 86400,\n createProvider: (config) => {\n const options = parseDeepSeekProviderOptions(config.options);\n return new DeepSeekProvider({\n apiKey: requireApiKey(config.apiKey),\n ...(config.baseURL !== undefined && { baseURL: config.baseURL }),\n ...(config.timeout !== undefined && { timeout: config.timeout }),\n ...(options.thinking !== undefined && { thinking: options.thinking }),\n ...(options.reasoningEffort !== undefined && { reasoningEffort: options.reasoningEffort }),\n defaultModel: config.model,\n });\n },\n };\n}\n\nfunction requireApiKey(apiKey: string | undefined): string {\n if (!apiKey) {\n throw new Error('Provider deepseek requires apiKey');\n }\n return apiKey;\n}\n\nfunction parseDeepSeekProviderOptions(options: Record<string, TUniversalValue> | undefined): {\n thinking?: TDeepSeekThinkingMode;\n reasoningEffort?: TDeepSeekReasoningEffort;\n} {\n const thinking = parseThinkingMode(options?.['thinking']);\n const reasoningEffort = parseReasoningEffort(options?.['reasoningEffort']);\n return {\n ...(thinking !== undefined && { thinking }),\n ...(reasoningEffort !== undefined && { reasoningEffort }),\n };\n}\n\nfunction parseThinkingMode(value: TUniversalValue | undefined): TDeepSeekThinkingMode | undefined {\n if (value === true) return 'enabled';\n if (value === false) return 'disabled';\n if (value === 'enabled' || value === 'disabled') return value;\n const record = asRecord(value);\n const type = record?.['type'];\n return type === 'enabled' || type === 'disabled' ? type : undefined;\n}\n\nfunction parseReasoningEffort(\n value: TUniversalValue | undefined,\n): TDeepSeekReasoningEffort | undefined {\n if (\n value === 'low' ||\n value === 'medium' ||\n value === 'high' ||\n value === 'xhigh' ||\n value === 'max'\n ) {\n return value;\n }\n return undefined;\n}\n\nfunction asRecord(value: TUniversalValue | undefined): Record<string, TUniversalValue> | undefined {\n if (value === null || value === undefined || value instanceof Date || Array.isArray(value)) {\n return undefined;\n }\n return typeof value === 'object' ? value : undefined;\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ const e=require(`./chunk-Bmb41Sf3.cjs`),t=require(`./openai-compatible-BYfyY5lb.cjs`);let n=require(`@robota-sdk/agent-core`),r=require(`openai`);r=e.t(r,1);const i=`deepseek-v4-flash`,a=`DEEPSEEK_API_KEY`,o=`$ENV:${a}`,s=`https://api.deepseek.com`;var c=class extends n.AbstractAIProvider{name=`deepseek`;version=`1.0.0`;client;options;responseParser;onTextDelta;constructor(e){if(super(e.logger||n.SilentLogger),this.options=e,e.executor&&(this.executor=e.executor),!this.executor)if(e.client)this.client=e.client;else if(e.apiKey)this.client=new r.default({apiKey:e.apiKey,baseURL:e.baseURL??`https://api.deepseek.com`,...e.timeout!==void 0&&{timeout:e.timeout}});else throw Error(`Either DeepSeek client, apiKey, or executor is required`);this.responseParser=new t.i({logger:this.logger})}async chat(e,t){if(this.validateMessages(e),this.validateNativeWebTools(t?.nativeWebTools),this.executor)try{return await this.executeViaExecutorOrDirect(e,t)}catch(e){throw this.logger.error(`DeepSeek Provider executor chat error:`,e instanceof Error?e.message:String(e)),e}let n=this.getClient();try{let r=this.buildRequestParams(e,t),i=t?.onTextDelta??this.onTextDelta;if(i)return await this.chatWithStreamingAssembly({...r,stream:!0},{...t,onTextDelta:i});t?.onProviderNativeRawPayload?.({provider:`deepseek`,apiSurface:`chat-completions`,payloadKind:`request`,payload:r});let a=await n.chat.completions.create(r);return t?.onProviderNativeRawPayload?.({provider:`deepseek`,apiSurface:`chat-completions`,payloadKind:`response`,payload:a}),this.responseParser.parseResponse(a)}catch(e){let t=e.message||`DeepSeek API request failed`;throw Error(`DeepSeek chat failed: ${t}`)}}async*chatStream(e,n){if(this.validateMessages(e),this.validateNativeWebTools(n?.nativeWebTools),this.executor)try{yield*this.executeStreamViaExecutorOrDirect(e,n);return}catch(e){throw this.logger.error(`DeepSeek Provider executor stream error:`,e instanceof Error?e.message:String(e)),e}let r=this.getClient();try{let i=this.buildStreamingRequestParams(e,n);n?.onProviderNativeRawPayload?.({provider:`deepseek`,apiSurface:`chat-completions`,payloadKind:`request`,payload:i});let a=t.n(await r.chat.completions.create(i),{provider:`deepseek`,apiSurface:`chat-completions`,onProviderNativeRawPayload:n?.onProviderNativeRawPayload});for await(let e of this.streamWithAbort(a,n?.signal)){let t=this.responseParser.parseStreamingChunk(e);t&&(yield t)}}catch(e){let t=e.message||`DeepSeek API request failed`;throw Error(`DeepSeek stream failed: ${t}`)}}supportsTools(){return!0}getCapabilities(){return{functionCalling:{supported:!0},nativeWebTools:{webSearch:{supported:!1,enabled:!1,source:`openai-compatible-chat-completions`,reason:`DeepSeek OpenAI-compatible Chat Completions supports declared function tools, not provider-native web search.`},webFetch:{supported:!1,enabled:!1,source:`openai-compatible-chat-completions`,reason:`DeepSeek OpenAI-compatible Chat Completions supports declared function tools, not provider-native web fetch.`}}}}validateConfig(){return!!this.client&&!!this.options}async dispose(){}buildRequestParams(e,n){this.validateTools(n?.tools);let r=n?.model??this.options.defaultModel;if(!r)throw Error(`Model is required in chat options. Please specify a model in defaultModel configuration.`);return{model:r,messages:t.a(e),...n?.temperature!==void 0&&{temperature:n.temperature},...n?.maxTokens!==void 0&&{max_tokens:n.maxTokens},...n?.tools&&{tools:t.o(n.tools),tool_choice:`auto`},...this.options.thinking!==void 0&&{thinking:{type:this.options.thinking}},...this.options.reasoningEffort!==void 0&&{reasoning_effort:this.options.reasoningEffort}}}buildStreamingRequestParams(e,t){return{...this.buildRequestParams(e,t),stream:!0}}getClient(){if(!this.client)throw Error(`DeepSeek client not available. Either provide a client/apiKey or use an executor.`);return this.client}async chatWithStreamingAssembly(e,n){let r=this.getClient();try{return n.onProviderNativeRawPayload?.({provider:`deepseek`,apiSurface:`chat-completions`,payloadKind:`request`,payload:e}),t.r({stream:t.n(await r.chat.completions.create(e,n.signal?{signal:n.signal}:void 0),{provider:`deepseek`,apiSurface:`chat-completions`,onProviderNativeRawPayload:n.onProviderNativeRawPayload}),onTextDelta:n.onTextDelta,signal:n.signal})}catch(e){let t=e.message||`DeepSeek streaming request failed`;throw Error(`DeepSeek stream failed: ${t}`)}}};const l=`https://api-docs.deepseek.com/quick_start/pricing`,u=`2026-05-07`,d=`2026-07-24`,f=[{id:i,displayName:`DeepSeek V4 Flash`,contextWindow:1e6,capabilities:[`tools`,`reasoning`,`json_schema`,`streaming`],lifecycle:`active`,sourceUrl:l,lastVerifiedAt:u},{id:`deepseek-v4-pro`,displayName:`DeepSeek V4 Pro`,contextWindow:1e6,capabilities:[`tools`,`reasoning`,`json_schema`,`streaming`],lifecycle:`active`,sourceUrl:l,lastVerifiedAt:u},{id:`deepseek-chat`,displayName:`DeepSeek Chat compatibility alias, deprecated ${d}`,aliases:[i],contextWindow:1e6,capabilities:[`tools`,`json_schema`,`streaming`],lifecycle:`deprecated`,sourceUrl:l,lastVerifiedAt:u},{id:`deepseek-reasoner`,displayName:`DeepSeek Reasoner compatibility alias, deprecated ${d}`,aliases:[i],contextWindow:1e6,capabilities:[`reasoning`,`json_schema`,`streaming`],lifecycle:`deprecated`,sourceUrl:l,lastVerifiedAt:u}];function p(e){return f.find(t=>t.id===e)}async function m(e,t=v){let n=await t(`${_(e.baseURL??`https://api.deepseek.com`)}/models`,h(e.apiKey));return n.ok?{status:`live`,sourceUrl:l,lastVerifiedAt:u,entries:((await n.json()).data??[]).map(e=>e.id).filter(e=>typeof e==`string`&&e.length>0).map(g)}:{status:`unavailable`,sourceUrl:l,message:`DeepSeek model refresh failed: HTTP ${n.status}`}}function h(e){if(e)return{headers:{Authorization:`Bearer ${e}`}}}function g(e){return p(e)??{id:e,displayName:e,lifecycle:`active`,sourceUrl:`https://api-docs.deepseek.com/quick_start/pricing`,lastVerifiedAt:`2026-05-07`}}function _(e){return e.replace(/\/$/,``)}async function v(e,t){let n=await fetch(e,{...t?.headers!==void 0&&{headers:t.headers}});return{ok:n.ok,status:n.status,json:()=>n.json()}}const y={status:`fallback`,sourceUrl:l,lastVerifiedAt:u,entries:f},b=[{kind:`api-key`,label:`DeepSeek API keys`,url:`https://platform.deepseek.com/api_keys`,sourceUrl:`https://api-docs.deepseek.com/`,lastVerifiedAt:`2026-05-08`}];function x(){return{type:`deepseek`,displayName:`DeepSeek`,description:`DeepSeek OpenAI-compatible endpoint`,defaults:{model:i,apiKey:o,baseURL:s},modelCatalog:y,setupHelpLinks:b,setupSteps:[{key:`baseURL`,title:`DeepSeek OpenAI-compatible base URL`,defaultValue:s},{key:`model`,title:`DeepSeek model`,defaultValue:i},{key:`apiKey`,title:`DeepSeek API key`,defaultValue:o,masked:!0}],requiresApiKey:!0,probeProfile:t.t,refreshModelCatalog:({profile:e})=>m(e),modelCatalogCacheTtlSeconds:86400,createProvider:e=>{let t=C(e.options);return new c({apiKey:S(e.apiKey),...e.baseURL!==void 0&&{baseURL:e.baseURL},...e.timeout!==void 0&&{timeout:e.timeout},...t.thinking!==void 0&&{thinking:t.thinking},...t.reasoningEffort!==void 0&&{reasoningEffort:t.reasoningEffort},defaultModel:e.model})}}}function S(e){if(!e)throw Error(`Provider deepseek requires apiKey`);return e}function C(e){let t=w(e?.thinking),n=T(e?.reasoningEffort);return{...t!==void 0&&{thinking:t},...n!==void 0&&{reasoningEffort:n}}}function w(e){if(e===!0)return`enabled`;if(e===!1)return`disabled`;if(e===`enabled`||e===`disabled`)return e;let t=E(e)?.type;return t===`enabled`||t===`disabled`?t:void 0}function T(e){if(e===`low`||e===`medium`||e===`high`||e===`xhigh`||e===`max`)return e}function E(e){if(!(e==null||e instanceof Date||Array.isArray(e)))return typeof e==`object`?e:void 0}Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return`https://api-docs.deepseek.com/api/list-models`}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return s}});
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../gemini-DSaNCxZj.cjs`);exports.DEFAULT_GEMINI_PROVIDER_API_KEY_ENV=e.n,exports.DEFAULT_GEMINI_PROVIDER_API_KEY_REFERENCE=e.r,exports.DEFAULT_GEMINI_PROVIDER_MODEL=e.i,exports.GEMINI_MODEL_LAST_VERIFIED_AT=e.a,exports.GEMINI_MODEL_SOURCE_URL=e.o,exports.GeminiProvider=e.c,exports.createGeminiProviderDefinition=e.s,exports.refreshGeminiModelCatalog=e.t;
@@ -0,0 +1,173 @@
1
+ import { AbstractAIProvider, IChatOptions, IExecutor, IImageComposeRequest, IImageEditRequest, IImageGenerationProvider, IImageGenerationRequest, IImageGenerationResult, IProviderDefinition, IProviderModelCatalog, IProviderProfileConfig, TProviderMediaResult, TProviderOptionValueBase, TTextDeltaCallback, TUniversalMessage } from "@robota-sdk/agent-core";
2
+
3
+ //#region src/gemini/model-catalog-refresh.d.ts
4
+ interface IGeminiModelInfo {
5
+ name?: string;
6
+ displayName?: string;
7
+ description?: string;
8
+ inputTokenLimit?: number;
9
+ outputTokenLimit?: number;
10
+ supportedGenerationMethods?: string[];
11
+ }
12
+ interface IGeminiModelsResponse {
13
+ models?: IGeminiModelInfo[];
14
+ nextPageToken?: string;
15
+ }
16
+ interface IGeminiFetchInit {
17
+ headers?: Record<string, string>;
18
+ }
19
+ interface IGeminiFetchResponse {
20
+ ok: boolean;
21
+ status: number;
22
+ json: () => Promise<IGeminiModelsResponse>;
23
+ }
24
+ type TGeminiFetch = (url: string, init?: IGeminiFetchInit) => Promise<IGeminiFetchResponse>;
25
+ declare function refreshGeminiModelCatalog(profile: IProviderProfileConfig, fetcher?: TGeminiFetch): Promise<IProviderModelCatalog>;
26
+ //#endregion
27
+ //#region src/gemini/types.d.ts
28
+ /**
29
+ * Valid provider option value types
30
+ */
31
+ type TGeminiProviderOptionValue = string | number | boolean | undefined | null | IExecutor | TProviderOptionValueBase | TGeminiProviderOptionValue[] | {
32
+ [key: string]: TGeminiProviderOptionValue;
33
+ };
34
+ interface IGeminiSafetySetting {
35
+ [key: string]: TGeminiProviderOptionValue;
36
+ category: string;
37
+ threshold: string;
38
+ method?: string;
39
+ }
40
+ interface IGeminiThinkingConfig {
41
+ [key: string]: TGeminiProviderOptionValue;
42
+ includeThoughts?: boolean;
43
+ thinkingBudget?: number;
44
+ thinkingLevel?: string;
45
+ }
46
+ /**
47
+ * Gemini API provider options
48
+ */
49
+ interface IGeminiProviderOptions {
50
+ /**
51
+ * Additional provider-specific options
52
+ */
53
+ [key: string]: TGeminiProviderOptionValue;
54
+ /** Google AI API key */
55
+ apiKey: string;
56
+ /**
57
+ * Default model used when chat options do not provide a model.
58
+ */
59
+ defaultModel?: string;
60
+ /**
61
+ * Response MIME type
62
+ * - 'text/plain': Plain text response (default)
63
+ * - 'application/json': JSON response format
64
+ */
65
+ responseMimeType?: 'text/plain' | 'application/json';
66
+ /**
67
+ * Response schema for JSON output (only used when responseMimeType is 'application/json')
68
+ */
69
+ responseSchema?: Record<string, TGeminiProviderOptionValue>;
70
+ /**
71
+ * JSON Schema response format for current Gemini structured output support.
72
+ * Mutually exclusive with responseSchema.
73
+ */
74
+ responseJsonSchema?: Record<string, TGeminiProviderOptionValue>;
75
+ /**
76
+ * Default safety settings applied to every direct Gemini request.
77
+ * Per-request google.safetySettings overrides this value.
78
+ */
79
+ safetySettings?: IGeminiSafetySetting[];
80
+ /**
81
+ * Default thinking configuration for Gemini models that support thinking.
82
+ */
83
+ thinkingConfig?: IGeminiThinkingConfig;
84
+ /**
85
+ * Provider-level function calling config passed through to Gemini config.
86
+ */
87
+ toolConfig?: Record<string, TGeminiProviderOptionValue>;
88
+ /**
89
+ * Optional default response modalities for Gemini generation config.
90
+ * Example: ['TEXT', 'IMAGE']
91
+ */
92
+ defaultResponseModalities?: Array<'TEXT' | 'IMAGE'>;
93
+ /**
94
+ * Optional allowlist of models that support image generation/editing.
95
+ * If not provided, provider validates using model name heuristics.
96
+ */
97
+ imageCapableModels?: string[];
98
+ /**
99
+ * Optional executor for handling AI requests
100
+ *
101
+ * When provided, the provider will delegate all chat operations to this executor
102
+ * instead of making direct API calls. This enables remote execution capabilities.
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * import { LocalExecutor, RemoteExecutor } from '@robota-sdk/agent-core';
107
+ *
108
+ * // Local execution (registers this provider)
109
+ * const localExecutor = new LocalExecutor();
110
+ * localExecutor.registerProvider('gemini', new GeminiProvider({ apiKey: 'AIza...' }));
111
+ *
112
+ * // Remote execution
113
+ * const remoteExecutor = new RemoteExecutor({
114
+ * serverUrl: 'https://api.robota.io',
115
+ * userApiKey: 'user-token-123'
116
+ * });
117
+ *
118
+ * const provider = new GeminiProvider({
119
+ * apiKey: 'placeholder', // Required for type safety but not used
120
+ * executor: remoteExecutor
121
+ * });
122
+ * ```
123
+ */
124
+ executor?: IExecutor;
125
+ }
126
+ //#endregion
127
+ //#region src/gemini/provider.d.ts
128
+ /**
129
+ * Gemini provider implementation for Robota
130
+ *
131
+ * IMPORTANT PROVIDER-SPECIFIC RULES:
132
+ * 1. This provider MUST extend BaseAIProvider from @robota-sdk/agent-core
133
+ * 2. Content handling for Google Gemini API:
134
+ * - Function calls can have content (text) along with function calls
135
+ * - Content can be empty string or actual text, NOT null
136
+ * 3. Use override keyword for all methods inherited from BaseAIProvider
137
+ * 4. Provider-specific API behavior should be documented here
138
+ *
139
+ * @public
140
+ */
141
+ declare class GeminiProvider extends AbstractAIProvider implements IImageGenerationProvider {
142
+ readonly name: string;
143
+ readonly version = "1.0.0";
144
+ onTextDelta?: TTextDeltaCallback;
145
+ private readonly client?;
146
+ private readonly options;
147
+ constructor(options: IGeminiProviderOptions);
148
+ /** Generate response using TUniversalMessage */
149
+ chat(messages: TUniversalMessage[], options?: IChatOptions): Promise<TUniversalMessage>;
150
+ /** Generate streaming response using TUniversalMessage */
151
+ chatStream(messages: TUniversalMessage[], options?: IChatOptions): AsyncIterable<TUniversalMessage>;
152
+ /** Generate an image from a text prompt using the Gemini API. */
153
+ generateImage(request: IImageGenerationRequest): Promise<TProviderMediaResult<IImageGenerationResult>>;
154
+ /** Edit an existing image based on a text prompt using the Gemini API. */
155
+ editImage(request: IImageEditRequest): Promise<TProviderMediaResult<IImageGenerationResult>>;
156
+ /** Compose multiple images together based on a text prompt using the Gemini API. */
157
+ composeImage(request: IImageComposeRequest): Promise<TProviderMediaResult<IImageGenerationResult>>;
158
+ supportsTools(): boolean;
159
+ validateConfig(): boolean;
160
+ dispose(): Promise<void>;
161
+ private withProviderCallbacks;
162
+ }
163
+ //#endregion
164
+ //#region src/gemini/provider-definition.d.ts
165
+ declare const DEFAULT_GEMINI_PROVIDER_API_KEY_ENV = "GEMINI_API_KEY";
166
+ declare const DEFAULT_GEMINI_PROVIDER_API_KEY_REFERENCE = "$ENV:GEMINI_API_KEY";
167
+ declare const DEFAULT_GEMINI_PROVIDER_MODEL = "gemini-3-flash-preview";
168
+ declare const GEMINI_MODEL_SOURCE_URL = "https://ai.google.dev/api/models";
169
+ declare const GEMINI_MODEL_LAST_VERIFIED_AT = "2026-05-04";
170
+ declare function createGeminiProviderDefinition(): IProviderDefinition;
171
+ //#endregion
172
+ export { DEFAULT_GEMINI_PROVIDER_API_KEY_ENV, DEFAULT_GEMINI_PROVIDER_API_KEY_REFERENCE, DEFAULT_GEMINI_PROVIDER_MODEL, GEMINI_MODEL_LAST_VERIFIED_AT, GEMINI_MODEL_SOURCE_URL, GeminiProvider, IGeminiFetchInit, IGeminiFetchResponse, IGeminiModelInfo, IGeminiModelsResponse, IGeminiProviderOptions, IGeminiSafetySetting, IGeminiThinkingConfig, TGeminiFetch, TGeminiProviderOptionValue, createGeminiProviderDefinition, refreshGeminiModelCatalog };
173
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/gemini/model-catalog-refresh.ts","../../../src/gemini/types.ts","../../../src/gemini/provider.ts","../../../src/gemini/provider-definition.ts"],"mappings":";;;UASiB,gBAAA;EACf,IAAA;EACA,WAAA;EACA,WAAA;EACA,eAAA;EACA,gBAAA;EACA,0BAAA;AAAA;AAAA,UAGe,qBAAA;EACf,MAAA,GAAS,gBAAgB;EACzB,aAAA;AAAA;AAAA,UAGe,gBAAA;EACf,OAAA,GAAU,MAAM;AAAA;AAAA,UAGD,oBAAA;EACf,EAAA;EACA,MAAA;EACA,IAAA,QAAY,OAAO,CAAC,qBAAA;AAAA;AAAA,KAGV,YAAA,IAAgB,GAAA,UAAa,IAAA,GAAO,gBAAA,KAAqB,OAAA,CAAQ,oBAAA;AAAA,iBAEvD,yBAAA,CACpB,OAAA,EAAS,sBAAA,EACT,OAAA,GAAS,YAAA,GACR,OAAA,CAAQ,qBAAA;;;;;AA7BX;KCJY,0BAAA,kDAMR,SAAA,GACA,wBAAA,GACA,0BAAA;EAAA,CACG,GAAA,WAAc,0BAAA;AAAA;AAAA,UAEJ,oBAAA;EAAA,CACd,GAAA,WAAc,0BAA0B;EACzC,QAAA;EACA,SAAA;EACA,MAAA;AAAA;AAAA,UAGe,qBAAA;EAAA,CACd,GAAA,WAAc,0BAA0B;EACzC,eAAA;EACA,cAAA;EACA,aAAA;AAAA;;;;UAMe,sBAAA;EDbF;AAGf;;EAHe,CCiBZ,GAAA,WAAc,0BAAA;EDbf;ECgBA,MAAA;EDbe;;;ECkBf,YAAA;EDjBA;;;;;ECwBA,gBAAA;EDtByC;AAG3C;;ECwBE,cAAA,GAAiB,MAAA,SAAe,0BAAA;EDxBc;;;;EC8B9C,kBAAA,GAAqB,MAAA,SAAe,0BAAA;ED9BV;;;;ECoC1B,cAAA,GAAiB,oBAAA;EDpC8E;AAAA;AAEjG;ECuCE,cAAA,GAAiB,qBAAA;;;;EAKjB,UAAA,GAAa,MAAA,SAAe,0BAAA;EDzC3B;;;;EC+CD,yBAAA,GAA4B,KAAA;EDhDnB;;;;ECsDT,kBAAA;EDrD8B;;;;ACjChC;;;;;;;;;;;;;;;AAS+C;AAE/C;;;;;;EAuGE,QAAA,GAAW,SAAA;AAAA;;;AD9Gb;;;;;;;;;;;AAM4B;AAG5B;AATA,cEuBa,cAAA,SAAuB,kBAAA,YAA8B,wBAAA;EAAA,SAC9C,IAAA;EAAA,SACA,OAAA;EACX,WAAA,GAAc,kBAAA;EAAA,iBAEJ,MAAA;EAAA,iBACA,OAAA;cAEL,OAAA,EAAS,sBAAA;EFpBR;EEkCE,IAAA,CACb,QAAA,EAAU,iBAAA,IACV,OAAA,GAAU,YAAA,GACT,OAAA,CAAQ,iBAAA;EFlCoB;EEoEf,UAAA,CACd,QAAA,EAAU,iBAAA,IACV,OAAA,GAAU,YAAA,GACT,aAAA,CAAc,iBAAA;EFtEjB;EEwGa,aAAA,CACX,OAAA,EAAS,uBAAA,GACR,OAAA,CAAQ,oBAAA,CAAqB,sBAAA;EFvGjB;EEuIF,SAAA,CACX,OAAA,EAAS,iBAAA,GACR,OAAA,CAAQ,oBAAA,CAAqB,sBAAA;;EAqCnB,YAAA,CACX,OAAA,EAAS,oBAAA,GACR,OAAA,CAAQ,oBAAA,CAAqB,sBAAA;EAkDvB,aAAA,CAAA;EAIA,cAAA,CAAA;EAOM,OAAA,CAAA,GAAW,OAAA;EAAA,QAIlB,qBAAA;AAAA;;;cCxQG,mCAAA;AAAA,cACA,yCAAA;AAAA,cACA,6BAAA;AAAA,cACA,uBAAA;AAAA,cACA,6BAAA;AAAA,iBAcG,8BAAA,CAAA,GAAkC,mBAAmB"}
@@ -0,0 +1 @@
1
+ import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"../gemini-Bh2U87MY.js";export{r as DEFAULT_GEMINI_PROVIDER_API_KEY_ENV,a as DEFAULT_GEMINI_PROVIDER_API_KEY_REFERENCE,n as DEFAULT_GEMINI_PROVIDER_MODEL,e as GEMINI_MODEL_LAST_VERIFIED_AT,i as GEMINI_MODEL_SOURCE_URL,t as GeminiProvider,o as createGeminiProviderDefinition,s as refreshGeminiModelCatalog};
@@ -0,0 +1,4 @@
1
+ import{randomUUID as e}from"node:crypto";import{AbstractAIProvider as t}from"@robota-sdk/agent-core";import{GoogleGenAI as n,Type as r}from"@google/genai";function i(e){return e?e.some(e=>e.type===`image_inline`||e.type===`image_uri`):!1}function a(e){if(!e)return[];let t=[];for(let n of e)n.type===`image_inline`&&t.push({kind:`uri`,uri:`data:${n.mimeType};base64,${n.data}`,mimeType:n.mimeType});return t}function o(e){let t=e.indexOf(`,`);if(t<0)return;let n=e.slice(0,t),r=e.slice(t+1);if(!n.endsWith(`;base64`))return;let i=n.replace(`data:`,``).replace(`;base64`,``).trim();if(!(i.length===0||r.trim().length===0))return{mimeType:i,data:r}}function s(e){if(e.kind===`inline`)return e.mimeType.trim().length===0||e.data.trim().length===0?{ok:!1,error:{code:`PROVIDER_INVALID_REQUEST`,message:`Inline image source requires non-empty mimeType and data.`}}:{ok:!0,value:{type:`image_inline`,mimeType:e.mimeType,data:e.data}};if(!e.uri.startsWith(`data:`))return{ok:!1,error:{code:`PROVIDER_INVALID_REQUEST`,message:`Google image provider supports only inline or data URI input sources.`}};let t=o(e.uri);return t?{ok:!0,value:{type:`image_inline`,mimeType:t.mimeType,data:t.data}}:{ok:!1,error:{code:`PROVIDER_INVALID_REQUEST`,message:`Data URI source must use base64 payload.`}}}function c(e,t,n){return n&&n.length>0?n:e.some(e=>i(e.parts))?[`TEXT`,`IMAGE`]:t&&t.length>0?t:[`TEXT`]}function l(e,t){return!t||t.length===0?!0:t.includes(e)}function u(e,t,n){g(t);let r=c(e,t.defaultResponseModalities,n?.google?.responseModalities);d(n?.model,r,t);let i={responseModalities:r};return f(i,n),p(i,t,n),m(i,t),h(i,t),i}function d(e,t,n){if(!(!e||!t.includes(`IMAGE`))&&!l(e,n.imageCapableModels))throw Error(`Selected model "${e}" is not configured as image-capable for Google provider.`)}function f(e,t){typeof t?.temperature==`number`&&(e.temperature=t.temperature),typeof t?.maxTokens==`number`&&(e.maxOutputTokens=t.maxTokens),typeof t?.google?.topP==`number`&&(e.topP=t.google.topP),typeof t?.google?.topK==`number`&&(e.topK=t.google.topK),typeof t?.google?.candidateCount==`number`&&(e.candidateCount=t.google.candidateCount),t?.google?.stopSequences&&t.google.stopSequences.length>0&&(e.stopSequences=t.google.stopSequences),t?.signal&&(e.abortSignal=t.signal)}function p(e,t,n){let r=n?.google?.safetySettings??t.safetySettings;r&&r.length>0&&(e.safetySettings=r)}function m(e,t){t.responseMimeType&&(e.responseMimeType=t.responseMimeType),t.responseSchema&&(e.responseMimeType=t.responseMimeType??`application/json`,e.responseSchema=t.responseSchema),t.responseJsonSchema&&(e.responseMimeType=t.responseMimeType??`application/json`,e.responseJsonSchema=t.responseJsonSchema)}function h(e,t){t.thinkingConfig&&(e.thinkingConfig=t.thinkingConfig),t.toolConfig&&(e.toolConfig=t.toolConfig)}function g(e){if(e.responseSchema&&e.responseJsonSchema)throw Error(`Gemini structured output options responseSchema and responseJsonSchema are mutually exclusive.`)}function _(e){let t=[],n=e.parts??[];for(let e of n){if(e.type===`text`){t.push({text:e.text});continue}if(e.type===`image_inline`){t.push({inlineData:{mimeType:e.mimeType,data:e.data}});continue}throw Error(`Google provider does not support image URI parts directly: ${e.uri}`)}return t.length===0&&typeof e.content==`string`&&e.content.length>0&&t.push({text:e.content}),t}function v(e){let t=[],n=[];for(let r of e){if(r.role===`user`){t.push({role:`user`,parts:_(r)});continue}if(r.role===`assistant`){t.push(y(r));continue}if(r.role===`tool`){t.push(b(r));continue}let e=x(r);e.length>0&&n.push(e)}return{contents:t,...n.length>0&&{systemInstruction:n.join(`
2
+ `)}}}function y(e){let t=[],n=_(e);for(let e of n)t.push(e);return t.length===0&&e.content&&t.push({text:e.content}),e.toolCalls&&e.toolCalls.length>0&&e.toolCalls.forEach(e=>{t.push({functionCall:{id:e.id,name:e.function.name,args:C(e.function.arguments)}})}),{role:`model`,parts:t}}function b(e){return{role:`user`,parts:[{functionResponse:{id:e.toolCallId,name:S(e),response:w(e.content)}}]}}function x(e){let t=_(e);if(t.length===0)return e.content;let n=[];for(let e of t){if(typeof e.text==`string`){n.push(e.text);continue}throw Error(`Google provider system instructions support only text parts.`)}return n.join(`
3
+ `)}function S(e){let t=e.name?.trim();if(!t)throw Error(`Google provider tool message requires a function name.`);return t}function C(e){let t=JSON.parse(e);if(!T(t))throw Error(`Google provider tool call arguments must be a JSON object.`);return t}function w(e){let t=e.trim();if(t.length===0)return{output:null};try{let e=JSON.parse(t);return T(e)?e:{output:e}}catch{return{output:e}}}function T(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}const E={string:r.STRING,number:r.NUMBER,integer:r.INTEGER,boolean:r.BOOLEAN,array:r.ARRAY,object:r.OBJECT};function D(e){return e.map(e=>({name:e.name,description:e.description,parameters:{type:r.OBJECT,properties:O(e.parameters.properties),required:e.parameters.required}}))}function O(e){let t={};for(let[n,r]of Object.entries(e))t[n]=k(r);return t}function k(e){let t={},n=A(e.type);return n&&(t.type=n),e.description&&(t.description=e.description),e.enum&&(t.enum=e.enum.map(String)),e.items&&(t.items=k(e.items)),e.properties&&(t.properties=O(e.properties)),typeof e.minimum==`number`&&(t.minimum=e.minimum),typeof e.maximum==`number`&&(t.maximum=e.maximum),e.pattern&&(t.pattern=e.pattern),e.format&&(t.format=e.format),e.default!==void 0&&(t.default=e.default),t}function A(e){if(e!==`null`)return E[e]}function j(){return`call_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}function ee(t){let n=t.candidates?.[0];if(!n)throw Error(`No candidate in Gemini response`);let r=n.content;if(!r||!r.parts||r.parts.length===0)throw Error(`No content in Gemini response`);let i=te(r.parts),a={id:e(),state:`complete`,role:`assistant`,content:i.textValues.length>0?i.textValues.join(``):null,parts:i.messageParts,timestamp:new Date};if(i.functionCalls.length>0){let e=a;e.toolCalls=i.functionCalls.map(e=>({id:e.id??j(),type:`function`,function:{name:F(e),arguments:JSON.stringify(e.args??{})}}))}let o=P(t);return o&&(a.metadata=o),a}function te(e){let t=[],n=[],r=[];for(let i of e)M(i,t,n),N(i,n),i.functionCall&&r.push(i.functionCall);return{textValues:t,messageParts:n,functionCalls:r}}function M(e,t,n){typeof e.text==`string`&&(t.push(e.text),n.push({type:`text`,text:e.text}))}function N(e,t){!e.inlineData||typeof e.inlineData.data!=`string`||typeof e.inlineData.mimeType!=`string`||t.push({type:`image_inline`,data:e.inlineData.data,mimeType:e.inlineData.mimeType})}function P(e){if(!(!e.usageMetadata||typeof e.usageMetadata.promptTokenCount!=`number`||typeof e.usageMetadata.candidatesTokenCount!=`number`||typeof e.usageMetadata.totalTokenCount!=`number`))return{promptTokens:e.usageMetadata.promptTokenCount,completionTokens:e.usageMetadata.candidatesTokenCount,totalTokens:e.usageMetadata.totalTokenCount}}function F(e){if(!e.name||e.name.trim().length===0)throw Error(`Gemini function call is missing a function name.`);return e.name}async function I(e,t,n,r,a=`gemini`){let o=z(t,r),s=c(n,t.defaultResponseModalities,r?.google?.responseModalities);if(r?.onTextDelta&&!s.includes(`IMAGE`))return B(e,t,n,r,a);let l=v(n),d=u(n,t,{...r,model:o}),f=R(o,l.contents,d,r,l.systemInstruction);V(r,a,`request`,f);let p=await e.models.generateContent(f);V(r,a,`response`,p);let m=ee(p);if(s.includes(`IMAGE`)&&!i(m.parts))throw Error(`Gemini response did not include an image part while IMAGE modality was requested.`);return m}async function*L(t,n,r,i,a=`gemini`){let o=z(n,i);if(c(r,n.defaultResponseModalities,i?.google?.responseModalities).includes(`IMAGE`))throw Error(`Google provider does not support streaming image modality responses.`);let s=v(r),l=u(r,n,{...i,model:o}),d=R(o,s.contents,l,i,s.systemInstruction);V(i,a,`request`,d);let f=await t.models.generateContentStream(d),p=0;for await(let t of f){V(i,a,`stream_event`,t,p),p++;let n=H(t);n&&(i?.onTextDelta?.(n),yield{id:e(),role:`assistant`,content:n,state:`complete`,timestamp:new Date})}}function R(e,t,n,r,i){let a={...n};return r?.tools&&r.tools.length>0&&(a.tools=[{functionDeclarations:D(r.tools)}]),i&&(a.systemInstruction=i),{model:e,contents:t,config:a}}function z(e,t){let n=t?.model??e.defaultModel;if(!n)throw Error(`Model is required in chat options. Please specify a model in defaultModel configuration.`);return n}async function B(t,n,r,i,a=`gemini`){let o=[];for await(let e of L(t,n,r,i,a))typeof e.content==`string`&&o.push(e.content);let s=o.join(``);return{id:e(),role:`assistant`,content:s,parts:s.length>0?[{type:`text`,text:s}]:[],state:`complete`,timestamp:new Date}}function V(e,t,n,r,i){e?.onProviderNativeRawPayload?.({provider:t,apiSurface:`gemini-generate-content`,payloadKind:n,...i!==void 0&&{sequence:i},payload:r})}function H(e){let t=e.text;return typeof t==`function`?t():t}async function U(e,t,n){try{let r=a((await e(t,{model:n,google:{responseModalities:[`TEXT`,`IMAGE`]}})).parts);return r.length===0?{ok:!1,error:{code:`PROVIDER_UPSTREAM_ERROR`,message:`Google image response did not include image output parts.`}}:{ok:!0,value:{outputs:r,model:n}}}catch(e){return{ok:!1,error:{code:`PROVIDER_UPSTREAM_ERROR`,message:e instanceof Error?e.message:`Google image request failed.`}}}}var W=class extends t{name=`gemini`;version=`1.0.0`;onTextDelta;client;options;constructor(e){super(),this.options=e,e.executor&&(this.executor=e.executor),this.executor||(this.client=new n({apiKey:e.apiKey}))}async chat(e,t){if(this.validateMessages(e),this.executor)try{return await this.executeViaExecutorOrDirect(e,t)}catch(e){throw this.logger.error(`Gemini Provider executor chat error:`,e instanceof Error?e.message:String(e)),e}if(!this.client)throw Error(`Google client not available. Either provide apiKey or use an executor.`);try{return await I(this.client,this.options,e,this.withProviderCallbacks(t),this.name)}catch(e){let t=e instanceof Error?e.message:`Google API request failed`;throw Error(`Google chat failed: ${t}`)}}async*chatStream(e,t){if(this.validateMessages(e),this.executor)try{yield*this.executeStreamViaExecutorOrDirect(e,t);return}catch(e){throw this.logger.error(`Gemini Provider executor stream error:`,e instanceof Error?e.message:String(e)),e}if(!this.client)throw Error(`Google client not available. Either provide apiKey or use an executor.`);try{yield*L(this.client,this.options,e,this.withProviderCallbacks(t),this.name)}catch(e){let t=e instanceof Error?e.message:`Google API request failed`;throw Error(`Google stream failed: ${t}`)}}async generateImage(t){if(t.prompt.trim().length===0)return{ok:!1,error:{code:`PROVIDER_INVALID_REQUEST`,message:`Image generation requires a non-empty prompt.`}};if(t.model.trim().length===0)return{ok:!1,error:{code:`PROVIDER_INVALID_REQUEST`,message:`Image generation requires a non-empty model.`}};let n={id:e(),role:`user`,content:t.prompt,state:`complete`,parts:[{type:`text`,text:t.prompt}],timestamp:new Date};return U(this.chat.bind(this),[n],t.model)}async editImage(t){if(t.prompt.trim().length===0)return{ok:!1,error:{code:`PROVIDER_INVALID_REQUEST`,message:`Image edit requires a non-empty prompt.`}};if(t.model.trim().length===0)return{ok:!1,error:{code:`PROVIDER_INVALID_REQUEST`,message:`Image edit requires a non-empty model.`}};let n=s(t.image);if(!n.ok)return n;let r={id:e(),role:`user`,content:t.prompt,state:`complete`,parts:[n.value,{type:`text`,text:t.prompt}],timestamp:new Date};return U(this.chat.bind(this),[r],t.model)}async composeImage(t){if(t.prompt.trim().length===0)return{ok:!1,error:{code:`PROVIDER_INVALID_REQUEST`,message:`Image compose requires a non-empty prompt.`}};if(t.model.trim().length===0)return{ok:!1,error:{code:`PROVIDER_INVALID_REQUEST`,message:`Image compose requires a non-empty model.`}};if(t.images.length<2)return{ok:!1,error:{code:`PROVIDER_INVALID_REQUEST`,message:`Image compose requires at least two input images.`}};let n=[];for(let e of t.images){let t=s(e);if(!t.ok)return t;n.push(t.value)}n.push({type:`text`,text:t.prompt});let r={id:e(),role:`user`,content:t.prompt,state:`complete`,parts:n,timestamp:new Date};return U(this.chat.bind(this),[r],t.model)}supportsTools(){return!0}validateConfig(){return this.executor?this.executor.validateConfig():!!this.client&&!!this.options&&!!this.options.apiKey}async dispose(){}withProviderCallbacks(e){let t=e?.onTextDelta??this.onTextDelta;return t?{...e,onTextDelta:t}:e}};const G=`GEMINI_API_KEY`,K=`$ENV:${G}`,q=`gemini-3-flash-preview`,J=`https://ai.google.dev/api/models`,Y=`2026-05-04`,X=[{kind:`api-key`,label:`Google AI Studio API keys`,url:`https://aistudio.google.com/apikey`,sourceUrl:`https://ai.google.dev/gemini-api/docs/api-key`,lastVerifiedAt:`2026-05-08`}];function Z(){return{type:`gemini`,aliases:[`google`],displayName:`Gemini`,description:`Google Gemini API provider`,defaults:{model:q,apiKey:K},modelCatalog:{status:`fallback`,sourceUrl:J,lastVerifiedAt:Y,entries:[{id:q,displayName:`Gemini 3 Flash Preview`,capabilities:[`tools`,`vision`,`json_schema`,`reasoning`,`streaming`],lifecycle:`preview`,sourceUrl:J,lastVerifiedAt:Y}]},setupHelpLinks:X,setupSteps:[{key:`model`,title:`Gemini model`,defaultValue:q},{key:`apiKey`,title:`Gemini API key`,defaultValue:K,masked:!0}],requiresApiKey:!0,refreshModelCatalog:({profile:e})=>$(e),modelCatalogCacheTtlSeconds:86400,createProvider:e=>new W({apiKey:ne(e.apiKey),defaultModel:e.model})}}function ne(e){if(!e)throw Error(`Provider gemini requires apiKey`);return e}const Q=`https://generativelanguage.googleapis.com/v1beta/models`;async function $(e,t=ae){let n=await t(e.apiKey?`${Q}?key=${e.apiKey}`:Q);if(!n.ok)return{status:`unavailable`,sourceUrl:J,message:`Gemini model refresh failed: HTTP ${n.status}`};let r=((await n.json()).models??[]).filter(re).map(ie);return{status:`live`,sourceUrl:J,lastVerifiedAt:new Date().toISOString(),entries:r,message:`Fetched ${r.length} Gemini models`}}function re(e){return e.supportedGenerationMethods?.includes(`generateContent`)===!0}function ie(e){let t=e.name??``,n=t.startsWith(`models/`)?t.slice(7):t,r=t.includes(`preview`)?`preview`:`active`;return{id:n,displayName:e.displayName??n,lifecycle:r,sourceUrl:J,lastVerifiedAt:Y}}async function ae(e,t){let n=await fetch(e);return{ok:n.ok,status:n.status,json:()=>n.json()}}export{Y as a,W as c,q as i,G as n,J as o,K as r,Z as s,$ as t};
4
+ //# sourceMappingURL=gemini-Bh2U87MY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-Bh2U87MY.js","names":[],"sources":["../../src/gemini/image-operations.ts","../../src/gemini/request-converter.ts","../../src/gemini/tool-schema-converter.ts","../../src/gemini/message-converter.ts","../../src/gemini/execution-helpers.ts","../../src/gemini/provider.ts","../../src/gemini/provider-definition.ts","../../src/gemini/model-catalog-refresh.ts"],"sourcesContent":["import type {\n TUniversalMessage,\n TUniversalMessagePart,\n IMediaOutputRef,\n IImageEditRequest,\n IImageComposeRequest,\n TProviderMediaResult,\n IChatOptions,\n} from '@robota-sdk/agent-core';\nimport type { GenerateContentParameters } from '@google/genai';\nimport type { IGeminiProviderOptions } from './types';\n\n/** Checks whether the given parts contain an image part. */\nexport function hasImagePart(parts: TUniversalMessagePart[] | undefined): boolean {\n if (!parts) {\n return false;\n }\n return parts.some((part) => part.type === 'image_inline' || part.type === 'image_uri');\n}\n\n/** Extracts inline image parts from a message and converts them to media output references. */\nexport function mapInlineImagePartsToMediaOutputs(\n parts: TUniversalMessagePart[] | undefined,\n): IMediaOutputRef[] {\n if (!parts) {\n return [];\n }\n const outputs: IMediaOutputRef[] = [];\n for (const part of parts) {\n if (part.type !== 'image_inline') {\n continue;\n }\n outputs.push({\n kind: 'uri',\n uri: `data:${part.mimeType};base64,${part.data}`,\n mimeType: part.mimeType,\n });\n }\n return outputs;\n}\n\n/** Parses a data URI into its MIME type and base64 payload. */\nexport function parseDataUri(uri: string): { mimeType: string; data: string } | undefined {\n const commaIndex = uri.indexOf(',');\n if (commaIndex < 0) {\n return undefined;\n }\n const header = uri.slice(0, commaIndex);\n const payload = uri.slice(commaIndex + 1);\n if (!header.endsWith(';base64')) {\n return undefined;\n }\n const mimeType = header.replace('data:', '').replace(';base64', '').trim();\n if (mimeType.length === 0 || payload.trim().length === 0) {\n return undefined;\n }\n return {\n mimeType,\n data: payload,\n };\n}\n\n/** Maps an image input source (inline or URI) to a universal message part. */\nexport function mapImageInputSourceToPart(\n source: IImageEditRequest['image'] | IImageComposeRequest['images'][number],\n): TProviderMediaResult<TUniversalMessagePart> {\n if (source.kind === 'inline') {\n if (source.mimeType.trim().length === 0 || source.data.trim().length === 0) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_INVALID_REQUEST',\n message: 'Inline image source requires non-empty mimeType and data.',\n },\n };\n }\n return {\n ok: true,\n value: {\n type: 'image_inline',\n mimeType: source.mimeType,\n data: source.data,\n },\n };\n }\n if (!source.uri.startsWith('data:')) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_INVALID_REQUEST',\n message: 'Google image provider supports only inline or data URI input sources.',\n },\n };\n }\n const parsedResult = parseDataUri(source.uri);\n if (!parsedResult) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_INVALID_REQUEST',\n message: 'Data URI source must use base64 payload.',\n },\n };\n }\n return {\n ok: true,\n value: {\n type: 'image_inline',\n mimeType: parsedResult.mimeType,\n data: parsedResult.data,\n },\n };\n}\n\n/** Determines which response modalities to request from the Gemini API. */\nexport function buildResponseModalities(\n messages: TUniversalMessage[],\n defaultModalities: Array<'TEXT' | 'IMAGE'> | undefined,\n optionModalities: Array<'TEXT' | 'IMAGE'> | undefined,\n): Array<'TEXT' | 'IMAGE'> {\n if (optionModalities && optionModalities.length > 0) {\n return optionModalities;\n }\n const hasImageInput = messages.some((message) => hasImagePart(message.parts));\n if (hasImageInput) {\n return ['TEXT', 'IMAGE'];\n }\n if (defaultModalities && defaultModalities.length > 0) {\n return defaultModalities;\n }\n return ['TEXT'];\n}\n\n/** Checks whether the specified model is configured as image-capable. */\nexport function isImageCapableModel(\n model: string,\n configuredImageModels: string[] | undefined,\n): boolean {\n if (!configuredImageModels || configuredImageModels.length === 0) {\n return true;\n }\n return configuredImageModels.includes(model);\n}\n\n/** Builds the Gemini generation config including response modalities. */\nexport function buildGenerationConfig(\n messages: TUniversalMessage[],\n providerOptions: IGeminiProviderOptions,\n options?: IChatOptions,\n): NonNullable<GenerateContentParameters['config']> {\n assertCompatibleStructuredOutputOptions(providerOptions);\n const responseModalities = buildResponseModalities(\n messages,\n providerOptions.defaultResponseModalities,\n options?.google?.responseModalities,\n );\n validateImageCapableModel(options?.model, responseModalities, providerOptions);\n const config: NonNullable<GenerateContentParameters['config']> = { responseModalities };\n applyChatOptions(config, options);\n applySafetySettings(config, providerOptions, options);\n applyStructuredOutputOptions(config, providerOptions);\n applyProviderGenerationOptions(config, providerOptions);\n return config;\n}\n\nfunction validateImageCapableModel(\n model: string | undefined,\n responseModalities: Array<'TEXT' | 'IMAGE'>,\n providerOptions: IGeminiProviderOptions,\n): void {\n if (!model || !responseModalities.includes('IMAGE')) {\n return;\n }\n if (isImageCapableModel(model, providerOptions.imageCapableModels)) {\n return;\n }\n throw new Error(\n `Selected model \"${model}\" is not configured as image-capable for Google provider.`,\n );\n}\n\nfunction applyChatOptions(\n config: NonNullable<GenerateContentParameters['config']>,\n options?: IChatOptions,\n): void {\n if (typeof options?.temperature === 'number') {\n config.temperature = options.temperature;\n }\n if (typeof options?.maxTokens === 'number') {\n config.maxOutputTokens = options.maxTokens;\n }\n if (typeof options?.google?.topP === 'number') {\n config.topP = options.google.topP;\n }\n if (typeof options?.google?.topK === 'number') {\n config.topK = options.google.topK;\n }\n if (typeof options?.google?.candidateCount === 'number') {\n config.candidateCount = options.google.candidateCount;\n }\n if (options?.google?.stopSequences && options.google.stopSequences.length > 0) {\n config.stopSequences = options.google.stopSequences;\n }\n if (options?.signal) {\n config.abortSignal = options.signal;\n }\n}\n\nfunction applySafetySettings(\n config: NonNullable<GenerateContentParameters['config']>,\n providerOptions: IGeminiProviderOptions,\n options?: IChatOptions,\n): void {\n const safetySettings = options?.google?.safetySettings ?? providerOptions.safetySettings;\n if (safetySettings && safetySettings.length > 0) {\n config.safetySettings = safetySettings as NonNullable<\n GenerateContentParameters['config']\n >['safetySettings'];\n }\n}\n\nfunction applyStructuredOutputOptions(\n config: NonNullable<GenerateContentParameters['config']>,\n providerOptions: IGeminiProviderOptions,\n): void {\n if (providerOptions.responseMimeType) {\n config.responseMimeType = providerOptions.responseMimeType;\n }\n if (providerOptions.responseSchema) {\n config.responseMimeType = providerOptions.responseMimeType ?? 'application/json';\n config.responseSchema = providerOptions.responseSchema;\n }\n if (providerOptions.responseJsonSchema) {\n config.responseMimeType = providerOptions.responseMimeType ?? 'application/json';\n config.responseJsonSchema = providerOptions.responseJsonSchema;\n }\n}\n\nfunction applyProviderGenerationOptions(\n config: NonNullable<GenerateContentParameters['config']>,\n providerOptions: IGeminiProviderOptions,\n): void {\n if (providerOptions.thinkingConfig) {\n config.thinkingConfig = providerOptions.thinkingConfig as NonNullable<\n GenerateContentParameters['config']\n >['thinkingConfig'];\n }\n if (providerOptions.toolConfig) {\n config.toolConfig = providerOptions.toolConfig as NonNullable<\n GenerateContentParameters['config']\n >['toolConfig'];\n }\n}\n\nfunction assertCompatibleStructuredOutputOptions(providerOptions: IGeminiProviderOptions): void {\n if (providerOptions.responseSchema && providerOptions.responseJsonSchema) {\n throw new Error(\n 'Gemini structured output options responseSchema and responseJsonSchema are mutually exclusive.',\n );\n }\n}\n","import type { Content, Part } from '@google/genai';\nimport type {\n IAssistantMessage,\n ISystemMessage,\n IToolMessage,\n IUserMessage,\n TUniversalMessage,\n} from '@robota-sdk/agent-core';\n\ntype TGoogleJsonValue = string | number | boolean | null | TGoogleJsonValue[] | IGoogleJsonObject;\n\ninterface IGoogleJsonObject {\n readonly [key: string]: TGoogleJsonValue;\n}\n\nexport interface IGeminiMessageConversionResult {\n contents: Content[];\n systemInstruction?: string;\n}\n\n/**\n * Maps universal message parts to Gemini-compatible parts.\n * Supports text and inline image parts; throws on unsupported part types.\n */\nexport function mapMessagePartsToGeminiParts(\n message: IUserMessage | IAssistantMessage | ISystemMessage | IToolMessage,\n): Part[] {\n const parts: Part[] = [];\n const messageParts = message.parts ?? [];\n for (const part of messageParts) {\n if (part.type === 'text') {\n parts.push({ text: part.text });\n continue;\n }\n if (part.type === 'image_inline') {\n parts.push({\n inlineData: {\n mimeType: part.mimeType,\n data: part.data,\n },\n });\n continue;\n }\n throw new Error(`Google provider does not support image URI parts directly: ${part.uri}`);\n }\n if (parts.length === 0 && typeof message.content === 'string' && message.content.length > 0) {\n parts.push({ text: message.content });\n }\n return parts;\n}\n\n/**\n * Converts an array of universal messages to the Gemini Content format.\n *\n * IMPORTANT: Google Gemini allows content with function calls.\n * Content can be empty string or text, but NOT null.\n */\nexport function convertToGeminiFormat(messages: TUniversalMessage[]): Content[] {\n return convertToGeminiRequestFormat(messages).contents;\n}\n\n/**\n * Converts universal messages into Gemini request content plus request config\n * fields. Gemini system instructions are request-level config, not user turns.\n */\nexport function convertToGeminiRequestFormat(\n messages: TUniversalMessage[],\n): IGeminiMessageConversionResult {\n const contents: Content[] = [];\n const systemInstructionParts: string[] = [];\n\n for (const msg of messages) {\n if (msg.role === 'user') {\n contents.push({\n role: 'user',\n parts: mapMessagePartsToGeminiParts(msg as IUserMessage),\n });\n continue;\n }\n if (msg.role === 'assistant') {\n contents.push(convertAssistantMessage(msg as IAssistantMessage));\n continue;\n }\n if (msg.role === 'tool') {\n contents.push(convertToolMessage(msg as IToolMessage));\n continue;\n }\n\n const systemInstruction = extractSystemInstructionText(msg as ISystemMessage);\n if (systemInstruction.length > 0) {\n systemInstructionParts.push(systemInstruction);\n }\n }\n\n return {\n contents,\n ...(systemInstructionParts.length > 0 && {\n systemInstruction: systemInstructionParts.join('\\n'),\n }),\n };\n}\n\n/**\n * Converts all messages to Gemini contents, including system instructions as\n * user content. This exists only for compatibility with callers that still need\n * a contents-only value.\n */\nexport function convertToGeminiFormatWithInlineSystem(messages: TUniversalMessage[]): Content[] {\n return messages.map((msg) => {\n if (msg.role === 'user') {\n return {\n role: 'user',\n parts: mapMessagePartsToGeminiParts(msg as IUserMessage),\n };\n }\n if (msg.role === 'assistant') {\n return convertAssistantMessage(msg as IAssistantMessage);\n }\n if (msg.role === 'tool') {\n const toolMessage = msg as IToolMessage;\n return {\n role: 'user',\n parts: mapMessagePartsToGeminiParts(toolMessage),\n };\n }\n const systemMessage = msg as ISystemMessage;\n const systemParts = mapMessagePartsToGeminiParts(systemMessage);\n if (systemParts.length === 0) {\n systemParts.push({ text: `System: ${systemMessage.content || ''}` });\n }\n return {\n role: 'user',\n parts: systemParts,\n };\n });\n}\n\nfunction convertAssistantMessage(assistantMsg: IAssistantMessage): Content {\n const parts: Part[] = [];\n const mappedAssistantParts = mapMessagePartsToGeminiParts(assistantMsg);\n for (const mappedPart of mappedAssistantParts) {\n parts.push(mappedPart);\n }\n if (parts.length === 0 && assistantMsg.content) {\n parts.push({ text: assistantMsg.content });\n }\n if (assistantMsg.toolCalls && assistantMsg.toolCalls.length > 0) {\n assistantMsg.toolCalls.forEach((tc) => {\n parts.push({\n functionCall: {\n id: tc.id,\n name: tc.function.name,\n args: parseToolCallArguments(tc.function.arguments),\n },\n });\n });\n }\n return {\n role: 'model',\n parts,\n };\n}\n\nfunction convertToolMessage(toolMessage: IToolMessage): Content {\n const functionResponse = {\n id: toolMessage.toolCallId,\n name: requireToolMessageName(toolMessage),\n response: parseToolResponseContent(toolMessage.content),\n };\n return {\n role: 'user',\n parts: [{ functionResponse }],\n };\n}\n\nfunction extractSystemInstructionText(systemMessage: ISystemMessage): string {\n const parts = mapMessagePartsToGeminiParts(systemMessage);\n if (parts.length === 0) {\n return systemMessage.content;\n }\n const textParts: string[] = [];\n for (const part of parts) {\n if (typeof part.text === 'string') {\n textParts.push(part.text);\n continue;\n }\n throw new Error('Google provider system instructions support only text parts.');\n }\n return textParts.join('\\n');\n}\n\nfunction requireToolMessageName(toolMessage: IToolMessage): string {\n const toolName = toolMessage.name?.trim();\n if (!toolName) {\n throw new Error('Google provider tool message requires a function name.');\n }\n return toolName;\n}\n\nfunction parseToolCallArguments(serializedArguments: string): IGoogleJsonObject {\n const parsedArguments = JSON.parse(serializedArguments) as TGoogleJsonValue;\n if (!isJsonObject(parsedArguments)) {\n throw new Error('Google provider tool call arguments must be a JSON object.');\n }\n return parsedArguments;\n}\n\nfunction parseToolResponseContent(content: string): IGoogleJsonObject {\n const trimmedContent = content.trim();\n if (trimmedContent.length === 0) {\n return { output: null };\n }\n try {\n const parsedContent = JSON.parse(trimmedContent) as TGoogleJsonValue;\n if (isJsonObject(parsedContent)) {\n return parsedContent;\n }\n return { output: parsedContent };\n } catch {\n return { output: content };\n }\n}\n\nfunction isJsonObject(value: TGoogleJsonValue): value is IGoogleJsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { Type } from '@google/genai';\nimport type { FunctionDeclaration, Schema } from '@google/genai';\nimport type { IParameterSchema, IToolSchema, TJSONSchemaKind } from '@robota-sdk/agent-core';\n\nconst GOOGLE_SCHEMA_TYPE_BY_JSON_KIND: Record<Exclude<TJSONSchemaKind, 'null'>, Type> = {\n string: Type.STRING,\n number: Type.NUMBER,\n integer: Type.INTEGER,\n boolean: Type.BOOLEAN,\n array: Type.ARRAY,\n object: Type.OBJECT,\n};\n\n/** Converts Robota tool schemas to Gemini function declarations. */\nexport function convertToolsToGeminiFormat(tools: IToolSchema[]): FunctionDeclaration[] {\n return tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n parameters: {\n type: Type.OBJECT,\n properties: convertParameterProperties(tool.parameters.properties),\n required: tool.parameters.required,\n },\n }));\n}\n\nfunction convertParameterProperties(\n properties: Record<string, IParameterSchema>,\n): Record<string, Schema> {\n const convertedProperties: Record<string, Schema> = {};\n for (const [key, value] of Object.entries(properties)) {\n convertedProperties[key] = convertParameterSchema(value);\n }\n return convertedProperties;\n}\n\nfunction convertParameterSchema(schema: IParameterSchema): Schema {\n const convertedSchema: Schema = {};\n const schemaType = convertSchemaKind(schema.type);\n if (schemaType) {\n convertedSchema.type = schemaType;\n }\n if (schema.description) {\n convertedSchema.description = schema.description;\n }\n if (schema.enum) {\n convertedSchema.enum = schema.enum.map(String);\n }\n if (schema.items) {\n convertedSchema.items = convertParameterSchema(schema.items);\n }\n if (schema.properties) {\n convertedSchema.properties = convertParameterProperties(schema.properties);\n }\n if (typeof schema.minimum === 'number') {\n convertedSchema.minimum = schema.minimum;\n }\n if (typeof schema.maximum === 'number') {\n convertedSchema.maximum = schema.maximum;\n }\n if (schema.pattern) {\n convertedSchema.pattern = schema.pattern;\n }\n if (schema.format) {\n convertedSchema.format = schema.format;\n }\n if (schema.default !== undefined) {\n convertedSchema.default = schema.default;\n }\n return convertedSchema;\n}\n\nfunction convertSchemaKind(kind: TJSONSchemaKind): Type | undefined {\n if (kind === 'null') {\n return undefined;\n }\n return GOOGLE_SCHEMA_TYPE_BY_JSON_KIND[kind];\n}\n","import { randomUUID } from 'node:crypto';\nimport type { Part, FunctionCall, GenerateContentResponse } from '@google/genai';\nimport type {\n TUniversalMessage,\n IAssistantMessage,\n TUniversalMessagePart,\n} from '@robota-sdk/agent-core';\n\nconst RANDOM_ID_RADIX = 36;\nconst RANDOM_ID_LENGTH = 9;\n\ninterface ICollectedGeminiParts {\n textValues: string[];\n messageParts: TUniversalMessagePart[];\n functionCalls: FunctionCall[];\n}\n\nexport {\n convertToGeminiFormat,\n convertToGeminiFormatWithInlineSystem,\n convertToGeminiRequestFormat,\n mapMessagePartsToGeminiParts,\n} from './request-converter';\nexport type { IGeminiMessageConversionResult } from './request-converter';\n\n/** Generates a unique call identifier for function call responses. */\nexport function generateCallId(): string {\n return `call_${Date.now()}_${Math.random().toString(RANDOM_ID_RADIX).substr(2, RANDOM_ID_LENGTH)}`;\n}\n\n/** Converts a Gemini API response into a universal message. */\nexport function convertFromGeminiResponse(response: GenerateContentResponse): TUniversalMessage {\n const candidate = response.candidates?.[0];\n if (!candidate) {\n throw new Error('No candidate in Gemini response');\n }\n\n const content = candidate.content;\n if (!content || !content.parts || content.parts.length === 0) {\n throw new Error('No content in Gemini response');\n }\n\n const collectedParts = collectGeminiParts(content.parts);\n\n const result: TUniversalMessage = {\n id: randomUUID(),\n state: 'complete' as const,\n role: 'assistant',\n content: collectedParts.textValues.length > 0 ? collectedParts.textValues.join('') : null,\n parts: collectedParts.messageParts,\n timestamp: new Date(),\n };\n\n if (collectedParts.functionCalls.length > 0) {\n const assistantResult = result as IAssistantMessage;\n assistantResult.toolCalls = collectedParts.functionCalls.map((fc) => ({\n id: fc.id ?? generateCallId(),\n type: 'function' as const,\n function: {\n name: requireFunctionCallName(fc),\n arguments: JSON.stringify(fc.args ?? {}),\n },\n }));\n }\n\n const usageMetadata = mapUsageMetadata(response);\n if (usageMetadata) {\n result.metadata = usageMetadata;\n }\n\n return result;\n}\n\nfunction collectGeminiParts(parts: Part[]): ICollectedGeminiParts {\n const textValues: string[] = [];\n const messageParts: TUniversalMessagePart[] = [];\n const functionCalls: FunctionCall[] = [];\n\n for (const part of parts) {\n collectTextPart(part, textValues, messageParts);\n collectInlineImagePart(part, messageParts);\n if (part.functionCall) {\n functionCalls.push(part.functionCall);\n }\n }\n\n return { textValues, messageParts, functionCalls };\n}\n\nfunction collectTextPart(\n part: Part,\n textValues: string[],\n messageParts: TUniversalMessagePart[],\n): void {\n if (typeof part.text !== 'string') {\n return;\n }\n textValues.push(part.text);\n messageParts.push({ type: 'text', text: part.text });\n}\n\nfunction collectInlineImagePart(part: Part, messageParts: TUniversalMessagePart[]): void {\n if (\n !part.inlineData ||\n typeof part.inlineData.data !== 'string' ||\n typeof part.inlineData.mimeType !== 'string'\n ) {\n return;\n }\n messageParts.push({\n type: 'image_inline',\n data: part.inlineData.data,\n mimeType: part.inlineData.mimeType,\n });\n}\n\nfunction mapUsageMetadata(response: GenerateContentResponse): TUniversalMessage['metadata'] {\n if (\n !response.usageMetadata ||\n typeof response.usageMetadata.promptTokenCount !== 'number' ||\n typeof response.usageMetadata.candidatesTokenCount !== 'number' ||\n typeof response.usageMetadata.totalTokenCount !== 'number'\n ) {\n return undefined;\n }\n return {\n promptTokens: response.usageMetadata.promptTokenCount,\n completionTokens: response.usageMetadata.candidatesTokenCount,\n totalTokens: response.usageMetadata.totalTokenCount,\n };\n}\n\nexport { convertToolsToGeminiFormat } from './tool-schema-converter';\n\nfunction requireFunctionCallName(functionCall: FunctionCall): string {\n if (!functionCall.name || functionCall.name.trim().length === 0) {\n throw new Error('Gemini function call is missing a function name.');\n }\n return functionCall.name;\n}\n","import { randomUUID } from 'node:crypto';\nimport type { GoogleGenAI } from '@google/genai';\nimport type { Content, GenerateContentParameters, GenerateContentResponse } from '@google/genai';\nimport type { IGeminiProviderOptions } from './types';\nimport type {\n TUniversalMessage,\n IChatOptions,\n IImageGenerationResult,\n TProviderMediaResult,\n} from '@robota-sdk/agent-core';\nimport {\n convertToGeminiRequestFormat,\n convertFromGeminiResponse,\n convertToolsToGeminiFormat,\n} from './message-converter';\nimport {\n hasImagePart,\n mapInlineImagePartsToMediaOutputs,\n buildResponseModalities,\n buildGenerationConfig,\n} from './image-operations';\n\n/**\n * Execute a direct (non-streaming) chat request against the Gemini API.\n */\nexport async function executeDirect(\n client: GoogleGenAI,\n providerOptions: IGeminiProviderOptions,\n messages: TUniversalMessage[],\n options?: IChatOptions,\n providerName = 'gemini',\n): Promise<TUniversalMessage> {\n const model = resolveGeminiModel(providerOptions, options);\n const responseModalities = buildResponseModalities(\n messages,\n providerOptions.defaultResponseModalities,\n options?.google?.responseModalities,\n );\n\n if (options?.onTextDelta && !responseModalities.includes('IMAGE')) {\n return assembleStreamingChatResponse(client, providerOptions, messages, options, providerName);\n }\n\n const requestFormat = convertToGeminiRequestFormat(messages);\n const genConfig = buildGenerationConfig(messages, providerOptions, { ...options, model });\n const request = buildGenerateContentRequest(\n model,\n requestFormat.contents,\n genConfig,\n options,\n requestFormat.systemInstruction,\n );\n\n emitGeminiNativeRawPayload(options, providerName, 'request', request);\n const result = await client.models.generateContent(request);\n emitGeminiNativeRawPayload(options, providerName, 'response', result);\n\n const convertedResponse = convertFromGeminiResponse(result);\n if (responseModalities.includes('IMAGE') && !hasImagePart(convertedResponse.parts)) {\n throw new Error(\n 'Gemini response did not include an image part while IMAGE modality was requested.',\n );\n }\n return convertedResponse;\n}\n\n/**\n * Execute a streaming chat request against the Gemini API.\n */\nexport async function* executeDirectStream(\n client: GoogleGenAI,\n providerOptions: IGeminiProviderOptions,\n messages: TUniversalMessage[],\n options?: IChatOptions,\n providerName = 'gemini',\n): AsyncIterable<TUniversalMessage> {\n const model = resolveGeminiModel(providerOptions, options);\n const responseModalities = buildResponseModalities(\n messages,\n providerOptions.defaultResponseModalities,\n options?.google?.responseModalities,\n );\n if (responseModalities.includes('IMAGE')) {\n throw new Error('Google provider does not support streaming image modality responses.');\n }\n\n const requestFormat = convertToGeminiRequestFormat(messages);\n const genConfig = buildGenerationConfig(messages, providerOptions, { ...options, model });\n const request = buildGenerateContentRequest(\n model,\n requestFormat.contents,\n genConfig,\n options,\n requestFormat.systemInstruction,\n );\n\n emitGeminiNativeRawPayload(options, providerName, 'request', request);\n const stream = await client.models.generateContentStream(request);\n\n let sequence = 0;\n for await (const chunk of stream) {\n emitGeminiNativeRawPayload(options, providerName, 'stream_event', chunk, sequence);\n sequence++;\n const text = extractStreamText(chunk);\n if (text) {\n options?.onTextDelta?.(text);\n yield {\n id: randomUUID(),\n role: 'assistant',\n content: text,\n state: 'complete' as const,\n timestamp: new Date(),\n };\n }\n }\n}\n\nfunction buildGenerateContentRequest(\n model: string,\n contents: Content[],\n generationOptions: GenerateContentParameters['config'],\n options?: IChatOptions,\n systemInstruction?: string,\n): GenerateContentParameters {\n const config: GenerateContentParameters['config'] = { ...generationOptions };\n if (options?.tools && options.tools.length > 0) {\n config.tools = [{ functionDeclarations: convertToolsToGeminiFormat(options.tools) }];\n }\n if (systemInstruction) {\n config.systemInstruction = systemInstruction;\n }\n return {\n model,\n contents,\n config,\n };\n}\n\nfunction resolveGeminiModel(\n providerOptions: IGeminiProviderOptions,\n options?: IChatOptions,\n): string {\n const model = options?.model ?? providerOptions.defaultModel;\n if (!model) {\n throw new Error(\n 'Model is required in chat options. Please specify a model in defaultModel configuration.',\n );\n }\n return model;\n}\n\nasync function assembleStreamingChatResponse(\n client: GoogleGenAI,\n providerOptions: IGeminiProviderOptions,\n messages: TUniversalMessage[],\n options: IChatOptions,\n providerName = 'gemini',\n): Promise<TUniversalMessage> {\n const textParts: string[] = [];\n for await (const chunk of executeDirectStream(\n client,\n providerOptions,\n messages,\n options,\n providerName,\n )) {\n if (typeof chunk.content === 'string') {\n textParts.push(chunk.content);\n }\n }\n const content = textParts.join('');\n return {\n id: randomUUID(),\n role: 'assistant',\n content,\n parts: content.length > 0 ? [{ type: 'text', text: content }] : [],\n state: 'complete',\n timestamp: new Date(),\n };\n}\n\nfunction emitGeminiNativeRawPayload(\n options: IChatOptions | undefined,\n providerName: string,\n payloadKind: 'request' | 'response' | 'stream_event',\n payload: object,\n sequence?: number,\n): void {\n options?.onProviderNativeRawPayload?.({\n provider: providerName,\n apiSurface: 'gemini-generate-content',\n payloadKind,\n ...(sequence !== undefined && { sequence }),\n payload,\n });\n}\n\nfunction extractStreamText(\n chunk: GenerateContentResponse | { readonly text?: () => string },\n): string | undefined {\n const textValue = chunk.text;\n return typeof textValue === 'function' ? textValue() : textValue;\n}\n\n/**\n * Run an image generation request through the chat API.\n */\nexport async function runImageRequest(\n chatFn: (messages: TUniversalMessage[], options?: IChatOptions) => Promise<TUniversalMessage>,\n messages: TUniversalMessage[],\n model: string,\n): Promise<TProviderMediaResult<IImageGenerationResult>> {\n try {\n const response = await chatFn(messages, {\n model,\n google: { responseModalities: ['TEXT', 'IMAGE'] },\n });\n const outputs = mapInlineImagePartsToMediaOutputs(response.parts);\n if (outputs.length === 0) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_UPSTREAM_ERROR',\n message: 'Google image response did not include image output parts.',\n },\n };\n }\n return { ok: true, value: { outputs, model } };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Google image request failed.';\n return { ok: false, error: { code: 'PROVIDER_UPSTREAM_ERROR', message: errorMessage } };\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport { GoogleGenAI } from '@google/genai';\nimport type { IGeminiProviderOptions } from './types';\nimport { AbstractAIProvider } from '@robota-sdk/agent-core';\nimport type {\n TUniversalMessage,\n IChatOptions,\n TTextDeltaCallback,\n TUniversalMessagePart,\n IImageGenerationProvider,\n IImageGenerationRequest,\n IImageEditRequest,\n IImageComposeRequest,\n IImageGenerationResult,\n TProviderMediaResult,\n} from '@robota-sdk/agent-core';\nimport { mapImageInputSourceToPart } from './image-operations';\nimport { executeDirect, executeDirectStream, runImageRequest } from './execution-helpers';\n\n/**\n * Gemini provider implementation for Robota\n *\n * IMPORTANT PROVIDER-SPECIFIC RULES:\n * 1. This provider MUST extend BaseAIProvider from @robota-sdk/agent-core\n * 2. Content handling for Google Gemini API:\n * - Function calls can have content (text) along with function calls\n * - Content can be empty string or actual text, NOT null\n * 3. Use override keyword for all methods inherited from BaseAIProvider\n * 4. Provider-specific API behavior should be documented here\n *\n * @public\n */\nexport class GeminiProvider extends AbstractAIProvider implements IImageGenerationProvider {\n override readonly name: string = 'gemini';\n override readonly version = '1.0.0';\n public onTextDelta?: TTextDeltaCallback;\n\n private readonly client?: GoogleGenAI;\n private readonly options: IGeminiProviderOptions;\n\n constructor(options: IGeminiProviderOptions) {\n super();\n this.options = options;\n\n if (options.executor) {\n this.executor = options.executor;\n }\n\n if (!this.executor) {\n this.client = new GoogleGenAI({ apiKey: options.apiKey });\n }\n }\n\n /** Generate response using TUniversalMessage */\n override async chat(\n messages: TUniversalMessage[],\n options?: IChatOptions,\n ): Promise<TUniversalMessage> {\n this.validateMessages(messages);\n\n if (this.executor) {\n try {\n return await this.executeViaExecutorOrDirect(messages, options);\n } catch (error) {\n this.logger.error(\n 'Gemini Provider executor chat error:',\n error instanceof Error ? error.message : String(error),\n );\n throw error;\n }\n }\n\n if (!this.client) {\n throw new Error('Google client not available. Either provide apiKey or use an executor.');\n }\n\n try {\n return await executeDirect(\n this.client,\n this.options,\n messages,\n this.withProviderCallbacks(options),\n this.name,\n );\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Google API request failed';\n throw new Error(`Google chat failed: ${errorMessage}`);\n }\n }\n\n /** Generate streaming response using TUniversalMessage */\n override async *chatStream(\n messages: TUniversalMessage[],\n options?: IChatOptions,\n ): AsyncIterable<TUniversalMessage> {\n this.validateMessages(messages);\n if (this.executor) {\n try {\n yield* this.executeStreamViaExecutorOrDirect(messages, options);\n return;\n } catch (error) {\n this.logger.error(\n 'Gemini Provider executor stream error:',\n error instanceof Error ? error.message : String(error),\n );\n throw error;\n }\n }\n\n if (!this.client) {\n throw new Error('Google client not available. Either provide apiKey or use an executor.');\n }\n\n try {\n yield* executeDirectStream(\n this.client,\n this.options,\n messages,\n this.withProviderCallbacks(options),\n this.name,\n );\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Google API request failed';\n throw new Error(`Google stream failed: ${errorMessage}`);\n }\n }\n\n /** Generate an image from a text prompt using the Gemini API. */\n public async generateImage(\n request: IImageGenerationRequest,\n ): Promise<TProviderMediaResult<IImageGenerationResult>> {\n if (request.prompt.trim().length === 0) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_INVALID_REQUEST',\n message: 'Image generation requires a non-empty prompt.',\n },\n };\n }\n if (request.model.trim().length === 0) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_INVALID_REQUEST',\n message: 'Image generation requires a non-empty model.',\n },\n };\n }\n\n const message: TUniversalMessage = {\n id: randomUUID(),\n role: 'user',\n content: request.prompt,\n state: 'complete' as const,\n parts: [{ type: 'text', text: request.prompt }],\n timestamp: new Date(),\n };\n return runImageRequest(this.chat.bind(this), [message], request.model);\n }\n\n /** Edit an existing image based on a text prompt using the Gemini API. */\n public async editImage(\n request: IImageEditRequest,\n ): Promise<TProviderMediaResult<IImageGenerationResult>> {\n if (request.prompt.trim().length === 0) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_INVALID_REQUEST',\n message: 'Image edit requires a non-empty prompt.',\n },\n };\n }\n if (request.model.trim().length === 0) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_INVALID_REQUEST',\n message: 'Image edit requires a non-empty model.',\n },\n };\n }\n\n const inputPartResult = mapImageInputSourceToPart(request.image);\n if (!inputPartResult.ok) {\n return inputPartResult;\n }\n\n const message: TUniversalMessage = {\n id: randomUUID(),\n role: 'user',\n content: request.prompt,\n state: 'complete' as const,\n parts: [inputPartResult.value, { type: 'text', text: request.prompt }],\n timestamp: new Date(),\n };\n return runImageRequest(this.chat.bind(this), [message], request.model);\n }\n\n /** Compose multiple images together based on a text prompt using the Gemini API. */\n public async composeImage(\n request: IImageComposeRequest,\n ): Promise<TProviderMediaResult<IImageGenerationResult>> {\n if (request.prompt.trim().length === 0) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_INVALID_REQUEST',\n message: 'Image compose requires a non-empty prompt.',\n },\n };\n }\n if (request.model.trim().length === 0) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_INVALID_REQUEST',\n message: 'Image compose requires a non-empty model.',\n },\n };\n }\n if (request.images.length < 2) {\n return {\n ok: false,\n error: {\n code: 'PROVIDER_INVALID_REQUEST',\n message: 'Image compose requires at least two input images.',\n },\n };\n }\n\n const messageParts: TUniversalMessagePart[] = [];\n for (const imageSource of request.images) {\n const mappedPartResult = mapImageInputSourceToPart(imageSource);\n if (!mappedPartResult.ok) {\n return mappedPartResult;\n }\n messageParts.push(mappedPartResult.value);\n }\n messageParts.push({ type: 'text', text: request.prompt });\n\n const message: TUniversalMessage = {\n id: randomUUID(),\n role: 'user',\n content: request.prompt,\n state: 'complete' as const,\n parts: messageParts,\n timestamp: new Date(),\n };\n return runImageRequest(this.chat.bind(this), [message], request.model);\n }\n\n override supportsTools(): boolean {\n return true;\n }\n\n override validateConfig(): boolean {\n if (this.executor) {\n return this.executor.validateConfig();\n }\n return !!this.client && !!this.options && !!this.options.apiKey;\n }\n\n override async dispose(): Promise<void> {\n // Google client does not need explicit cleanup\n }\n\n private withProviderCallbacks(options?: IChatOptions): IChatOptions | undefined {\n const onTextDelta = options?.onTextDelta ?? this.onTextDelta;\n if (!onTextDelta) {\n return options;\n }\n return {\n ...options,\n onTextDelta,\n };\n }\n}\n","import type { IProviderDefinition } from '@robota-sdk/agent-core';\nimport { refreshGeminiModelCatalog } from './model-catalog-refresh';\nimport { GeminiProvider } from './provider';\n\nexport const DEFAULT_GEMINI_PROVIDER_API_KEY_ENV = 'GEMINI_API_KEY';\nexport const DEFAULT_GEMINI_PROVIDER_API_KEY_REFERENCE = `$ENV:${DEFAULT_GEMINI_PROVIDER_API_KEY_ENV}`;\nexport const DEFAULT_GEMINI_PROVIDER_MODEL = 'gemini-3-flash-preview';\nexport const GEMINI_MODEL_SOURCE_URL = 'https://ai.google.dev/api/models';\nexport const GEMINI_MODEL_LAST_VERIFIED_AT = '2026-05-04';\nconst GEMINI_API_KEY_URL = 'https://aistudio.google.com/apikey';\nconst GEMINI_SETUP_SOURCE_URL = 'https://ai.google.dev/gemini-api/docs/api-key';\nconst GEMINI_SETUP_LAST_VERIFIED_AT = '2026-05-08';\nconst GEMINI_SETUP_HELP_LINKS: NonNullable<IProviderDefinition['setupHelpLinks']> = [\n {\n kind: 'api-key',\n label: 'Google AI Studio API keys',\n url: GEMINI_API_KEY_URL,\n sourceUrl: GEMINI_SETUP_SOURCE_URL,\n lastVerifiedAt: GEMINI_SETUP_LAST_VERIFIED_AT,\n },\n];\n\nexport function createGeminiProviderDefinition(): IProviderDefinition {\n return {\n type: 'gemini',\n aliases: ['google'],\n displayName: 'Gemini',\n description: 'Google Gemini API provider',\n defaults: {\n model: DEFAULT_GEMINI_PROVIDER_MODEL,\n apiKey: DEFAULT_GEMINI_PROVIDER_API_KEY_REFERENCE,\n },\n modelCatalog: {\n status: 'fallback',\n sourceUrl: GEMINI_MODEL_SOURCE_URL,\n lastVerifiedAt: GEMINI_MODEL_LAST_VERIFIED_AT,\n entries: [\n {\n id: DEFAULT_GEMINI_PROVIDER_MODEL,\n displayName: 'Gemini 3 Flash Preview',\n capabilities: ['tools', 'vision', 'json_schema', 'reasoning', 'streaming'],\n lifecycle: 'preview',\n sourceUrl: GEMINI_MODEL_SOURCE_URL,\n lastVerifiedAt: GEMINI_MODEL_LAST_VERIFIED_AT,\n },\n ],\n },\n setupHelpLinks: GEMINI_SETUP_HELP_LINKS,\n setupSteps: [\n {\n key: 'model',\n title: 'Gemini model',\n defaultValue: DEFAULT_GEMINI_PROVIDER_MODEL,\n },\n {\n key: 'apiKey',\n title: 'Gemini API key',\n defaultValue: DEFAULT_GEMINI_PROVIDER_API_KEY_REFERENCE,\n masked: true,\n },\n ],\n requiresApiKey: true,\n refreshModelCatalog: ({ profile }) => refreshGeminiModelCatalog(profile),\n modelCatalogCacheTtlSeconds: 86400,\n createProvider: (config) =>\n new GeminiProvider({\n apiKey: requireApiKey(config.apiKey),\n defaultModel: config.model,\n }),\n };\n}\n\nfunction requireApiKey(apiKey: string | undefined): string {\n if (!apiKey) {\n throw new Error('Provider gemini requires apiKey');\n }\n return apiKey;\n}\n","import type {\n IProviderModelCatalog,\n IProviderModelCatalogEntry,\n IProviderProfileConfig,\n} from '@robota-sdk/agent-core';\nimport { GEMINI_MODEL_LAST_VERIFIED_AT, GEMINI_MODEL_SOURCE_URL } from './provider-definition';\n\nconst GEMINI_API_ENDPOINT = 'https://generativelanguage.googleapis.com/v1beta/models';\n\nexport interface IGeminiModelInfo {\n name?: string;\n displayName?: string;\n description?: string;\n inputTokenLimit?: number;\n outputTokenLimit?: number;\n supportedGenerationMethods?: string[];\n}\n\nexport interface IGeminiModelsResponse {\n models?: IGeminiModelInfo[];\n nextPageToken?: string;\n}\n\nexport interface IGeminiFetchInit {\n headers?: Record<string, string>;\n}\n\nexport interface IGeminiFetchResponse {\n ok: boolean;\n status: number;\n json: () => Promise<IGeminiModelsResponse>;\n}\n\nexport type TGeminiFetch = (url: string, init?: IGeminiFetchInit) => Promise<IGeminiFetchResponse>;\n\nexport async function refreshGeminiModelCatalog(\n profile: IProviderProfileConfig,\n fetcher: TGeminiFetch = defaultGeminiFetch,\n): Promise<IProviderModelCatalog> {\n const url = profile.apiKey ? `${GEMINI_API_ENDPOINT}?key=${profile.apiKey}` : GEMINI_API_ENDPOINT;\n\n const response = await fetcher(url);\n\n if (!response.ok) {\n return {\n status: 'unavailable',\n sourceUrl: GEMINI_MODEL_SOURCE_URL,\n message: `Gemini model refresh failed: HTTP ${response.status}`,\n };\n }\n\n const body = await response.json();\n const entries = (body.models ?? []).filter(supportsGenerateContent).map(toModelCatalogEntry);\n\n return {\n status: 'live',\n sourceUrl: GEMINI_MODEL_SOURCE_URL,\n lastVerifiedAt: new Date().toISOString(),\n entries,\n message: `Fetched ${entries.length} Gemini models`,\n };\n}\n\nfunction supportsGenerateContent(model: IGeminiModelInfo): boolean {\n return model.supportedGenerationMethods?.includes('generateContent') === true;\n}\n\nfunction toModelCatalogEntry(model: IGeminiModelInfo): IProviderModelCatalogEntry {\n const rawName = model.name ?? '';\n const id = rawName.startsWith('models/') ? rawName.slice('models/'.length) : rawName;\n const lifecycle = rawName.includes('preview') ? 'preview' : 'active';\n\n return {\n id,\n displayName: model.displayName ?? id,\n lifecycle,\n sourceUrl: GEMINI_MODEL_SOURCE_URL,\n lastVerifiedAt: GEMINI_MODEL_LAST_VERIFIED_AT,\n };\n}\n\nasync function defaultGeminiFetch(\n url: string,\n _init?: IGeminiFetchInit,\n): Promise<IGeminiFetchResponse> {\n const response = await fetch(url);\n return {\n ok: response.ok,\n status: response.status,\n json: () => response.json() as Promise<IGeminiModelsResponse>,\n };\n}\n"],"mappings":"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"}