@ashx-j/lunr-ai 0.2.26 → 0.2.28

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 (84) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +90 -84
  3. package/dist/api/anthropic-claude-code-bridge.d.ts.map +1 -1
  4. package/dist/api/anthropic-claude-code-bridge.js +50 -12
  5. package/dist/api/anthropic-claude-code-bridge.js.map +1 -1
  6. package/dist/api/anthropic-messages.d.ts.map +1 -1
  7. package/dist/api/anthropic-messages.js +3 -0
  8. package/dist/api/anthropic-messages.js.map +1 -1
  9. package/dist/api/azure-openai-responses.d.ts.map +1 -1
  10. package/dist/api/azure-openai-responses.js +1 -0
  11. package/dist/api/azure-openai-responses.js.map +1 -1
  12. package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
  13. package/dist/api/bedrock-converse-stream.js +8 -1
  14. package/dist/api/bedrock-converse-stream.js.map +1 -1
  15. package/dist/api/google-generative-ai.d.ts.map +1 -1
  16. package/dist/api/google-generative-ai.js +7 -2
  17. package/dist/api/google-generative-ai.js.map +1 -1
  18. package/dist/api/google-vertex.d.ts.map +1 -1
  19. package/dist/api/google-vertex.js +7 -2
  20. package/dist/api/google-vertex.js.map +1 -1
  21. package/dist/api/lazy.d.ts.map +1 -1
  22. package/dist/api/lazy.js +1 -0
  23. package/dist/api/lazy.js.map +1 -1
  24. package/dist/api/mistral-conversations.d.ts.map +1 -1
  25. package/dist/api/mistral-conversations.js +2 -0
  26. package/dist/api/mistral-conversations.js.map +1 -1
  27. package/dist/api/openai-codex-responses.d.ts.map +1 -1
  28. package/dist/api/openai-codex-responses.js +13 -3
  29. package/dist/api/openai-codex-responses.js.map +1 -1
  30. package/dist/api/openai-completions.d.ts.map +1 -1
  31. package/dist/api/openai-completions.js +9 -1
  32. package/dist/api/openai-completions.js.map +1 -1
  33. package/dist/api/openai-responses-shared.d.ts.map +1 -1
  34. package/dist/api/openai-responses-shared.js +7 -4
  35. package/dist/api/openai-responses-shared.js.map +1 -1
  36. package/dist/api/openai-responses.d.ts.map +1 -1
  37. package/dist/api/openai-responses.js +1 -0
  38. package/dist/api/openai-responses.js.map +1 -1
  39. package/dist/api/openrouter-images.d.ts.map +1 -1
  40. package/dist/api/openrouter-images.js +8 -2
  41. package/dist/api/openrouter-images.js.map +1 -1
  42. package/dist/api/pi-messages.d.ts.map +1 -1
  43. package/dist/api/pi-messages.js +19 -3
  44. package/dist/api/pi-messages.js.map +1 -1
  45. package/dist/auth/helpers.d.ts.map +1 -1
  46. package/dist/auth/helpers.js +2 -2
  47. package/dist/auth/helpers.js.map +1 -1
  48. package/dist/auth/oauth/anthropic.d.ts.map +1 -1
  49. package/dist/auth/oauth/anthropic.js +3 -4
  50. package/dist/auth/oauth/anthropic.js.map +1 -1
  51. package/dist/index.d.ts +1 -0
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +1 -0
  54. package/dist/index.js.map +1 -1
  55. package/dist/models.d.ts +1 -1
  56. package/dist/models.d.ts.map +1 -1
  57. package/dist/models.generated.d.ts +42 -0
  58. package/dist/models.generated.d.ts.map +1 -1
  59. package/dist/models.js +5 -2
  60. package/dist/models.js.map +1 -1
  61. package/dist/providers/faux.d.ts.map +1 -1
  62. package/dist/providers/faux.js +5 -1
  63. package/dist/providers/faux.js.map +1 -1
  64. package/dist/providers/google-vertex.models.d.ts +21 -0
  65. package/dist/providers/google-vertex.models.d.ts.map +1 -1
  66. package/dist/providers/google-vertex.models.js +3 -0
  67. package/dist/providers/google-vertex.models.js.map +1 -1
  68. package/dist/providers/google.models.d.ts +21 -0
  69. package/dist/providers/google.models.d.ts.map +1 -1
  70. package/dist/providers/google.models.js +3 -0
  71. package/dist/providers/google.models.js.map +1 -1
  72. package/dist/types.d.ts +10 -1
  73. package/dist/types.d.ts.map +1 -1
  74. package/dist/types.js.map +1 -1
  75. package/dist/utils/claude-code-assets.d.ts +8 -0
  76. package/dist/utils/claude-code-assets.d.ts.map +1 -0
  77. package/dist/utils/claude-code-assets.js +16 -0
  78. package/dist/utils/claude-code-assets.js.map +1 -0
  79. package/dist/utils/estimate.d.ts +3 -0
  80. package/dist/utils/estimate.d.ts.map +1 -1
  81. package/dist/utils/estimate.js +35 -30
  82. package/dist/utils/estimate.js.map +1 -1
  83. package/package.json +1 -1
  84. package/vendor/hermes-claude-subscription-directsdk/lunr_bridge.py +26 -2
@@ -1 +1 @@
1
- {"version":3,"file":"pi-messages.d.ts","sourceRoot":"","sources":["../../src/api/pi-messages.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * pi-messages API implementation.\n *\n * Streams pi's own message protocol directly to a backend: the request is a\n * single POST of `{ model, context, options }` to `<baseUrl>/messages`, the\n * response is an SSE stream of serialized assistant-message events plus a\n * terminal `done`/`error` event. This is the wire protocol spoken by the\n * Radius gateway, but any backend implementing it can be used, e.g. via a\n * models.json custom provider with `\"api\": \"pi-messages\"`.\n */\n\nimport type {\n\tAssistantMessage,\n\tAssistantMessageEvent,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tProviderEnv,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tThinkingLevel,\n\tToolCall,\n} from \"../types.ts\";\nimport { appendAssistantMessageDiagnostic, createAssistantMessageDiagnostic } from \"../utils/diagnostics.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord, providerHeadersToRecord } from \"../utils/headers.ts\";\nimport { parseStreamingJson } from \"../utils/json-parse.ts\";\nimport { getProviderEnvValue } from \"../utils/provider-env.ts\";\n\nexport interface PiMessagesOptions extends StreamOptions {\n\treasoning?: ThinkingLevel;\n\ttoolChoice?: \"auto\" | \"none\" | \"required\" | { type: \"function\"; function: { name: string } };\n\t/** Ask the backend for debug metadata (e.g. routing response headers). */\n\tdebug?: boolean;\n}\n\ntype PiMessagesUsage = AssistantMessage[\"usage\"];\ntype PiMessagesStopReason = AssistantMessage[\"stopReason\"];\n\n/** Impact summary of a server-side message rewrite (e.g. a gateway policy). */\nexport type PiMessagesRewriteImpact = {\n\tpolicyId: string;\n\tpolicyVersion: number;\n\tchanged: boolean;\n\ttokenCountChange: number;\n\tmessageCountChange: number;\n\tsystemPromptChanged: boolean;\n};\n\n/** Serialized assistant-message event as sent by a pi-messages backend. */\nexport type PiMessagesEvent =\n\t| { type: \"start\" }\n\t| { type: \"text_start\"; contentIndex: number }\n\t| { type: \"text_delta\"; contentIndex: number; delta: string }\n\t| { type: \"text_end\"; contentIndex: number; content: string; contentSignature?: string }\n\t| { type: \"thinking_start\"; contentIndex: number }\n\t| { type: \"thinking_delta\"; contentIndex: number; delta: string }\n\t| {\n\t\t\ttype: \"thinking_end\";\n\t\t\tcontentIndex: number;\n\t\t\tcontent: string;\n\t\t\tcontentSignature?: string;\n\t\t\tredacted?: boolean;\n\t }\n\t| { type: \"toolcall_start\"; contentIndex: number; id: string; toolName: string }\n\t| { type: \"toolcall_delta\"; contentIndex: number; delta: string }\n\t| { type: \"toolcall_end\"; contentIndex: number; toolCall: ToolCall }\n\t| {\n\t\t\ttype: \"done\";\n\t\t\treason: Extract<PiMessagesStopReason, \"stop\" | \"length\" | \"toolUse\">;\n\t\t\tusage: PiMessagesUsage;\n\t\t\tresponseId?: string;\n\t\t\trewrite?: PiMessagesRewriteImpact;\n\t }\n\t| {\n\t\t\ttype: \"error\";\n\t\t\treason: Extract<PiMessagesStopReason, \"aborted\" | \"error\">;\n\t\t\tusage: PiMessagesUsage;\n\t\t\terrorMessage?: string;\n\t\t\tresponseId?: string;\n\t\t\trewrite?: PiMessagesRewriteImpact;\n\t };\n\ntype PiMessagesErrorBody = {\n\terror?: {\n\t\tmessage?: unknown;\n\t\tcode?: unknown;\n\t\tdetails?: unknown;\n\t\t[key: string]: unknown;\n\t};\n};\n\nexport class PiMessagesResponseError extends Error {\n\tcode?: string;\n\treadonly diagnosticDetails: Record<string, unknown>;\n\n\tconstructor(message: string, code: string | undefined, diagnosticDetails: Record<string, unknown>) {\n\t\tsuper(message);\n\t\tthis.name = \"PiMessagesResponseError\";\n\t\tthis.code = code;\n\t\tthis.diagnosticDetails = diagnosticDetails;\n\t}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parsePiMessagesErrorBody(body: string): PiMessagesErrorBody | undefined {\n\ttry {\n\t\tconst parsed = JSON.parse(body) as unknown;\n\t\treturn isRecord(parsed) && isRecord(parsed.error) ? (parsed as PiMessagesErrorBody) : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction truncateDiagnosticString(value: string): string {\n\tconst maxLength = 8192;\n\treturn value.length > maxLength ? `${value.slice(0, maxLength)}…` : value;\n}\n\nfunction formatPiMessagesResponseError(\n\tresponse: Response,\n\tbody: string,\n\terrorBody: PiMessagesErrorBody | undefined,\n): string {\n\tconst message = typeof errorBody?.error?.message === \"string\" ? errorBody.error.message : undefined;\n\tconst code = typeof errorBody?.error?.code === \"string\" ? errorBody.error.code : undefined;\n\tconst suffix = message ?? body;\n\tconst codeSuffix = code ? ` (${code})` : \"\";\n\treturn `${response.status} ${response.statusText}: ${suffix}${codeSuffix}`;\n}\n\nfunction createPiMessagesResponseError(\n\tmodel: Model<\"pi-messages\">,\n\turl: URL,\n\tresponse: Response,\n\tbody: string,\n): PiMessagesResponseError {\n\tconst errorBody = parsePiMessagesErrorBody(body);\n\tconst code = typeof errorBody?.error?.code === \"string\" ? errorBody.error.code : undefined;\n\treturn new PiMessagesResponseError(formatPiMessagesResponseError(response, body, errorBody), code, {\n\t\tversion: 1,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\turl: url.toString(),\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\terror: errorBody?.error,\n\t\tbody: errorBody ? undefined : truncateDiagnosticString(body),\n\t\ttimestampMs: Date.now(),\n\t});\n}\n\nfunction createEmptyUsage(): PiMessagesUsage {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\ttotalTokens: 0,\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t};\n}\n\nfunction appendRewriteDiagnostic(message: AssistantMessage, rewrite: PiMessagesRewriteImpact | undefined): void {\n\tif (!rewrite) {\n\t\treturn;\n\t}\n\tappendAssistantMessageDiagnostic(message, {\n\t\ttype: \"pi_messages_rewrite\",\n\t\ttimestamp: Date.now(),\n\t\tdetails: { ...rewrite },\n\t});\n}\n\nfunction createEventConverter(model: Model<\"pi-messages\">) {\n\tconst partial: AssistantMessage = {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n\tconst toolJson = new Map<number, string>();\n\n\treturn (event: PiMessagesEvent): AssistantMessageEvent => {\n\t\tswitch (event.type) {\n\t\t\tcase \"done\":\n\t\t\t\tObject.assign(partial, {\n\t\t\t\t\tstopReason: event.reason,\n\t\t\t\t\tusage: event.usage,\n\t\t\t\t\tresponseId: event.responseId,\n\t\t\t\t});\n\t\t\t\tappendRewriteDiagnostic(partial, event.rewrite);\n\t\t\t\treturn { type: \"done\", reason: event.reason, message: partial };\n\t\t\tcase \"error\":\n\t\t\t\tObject.assign(partial, {\n\t\t\t\t\tstopReason: event.reason,\n\t\t\t\t\tusage: event.usage,\n\t\t\t\t\terrorMessage: event.errorMessage,\n\t\t\t\t\tresponseId: event.responseId,\n\t\t\t\t});\n\t\t\t\tappendRewriteDiagnostic(partial, event.rewrite);\n\t\t\t\treturn { type: \"error\", reason: event.reason, error: partial };\n\t\t\tcase \"start\":\n\t\t\t\tbreak;\n\t\t\tcase \"text_start\":\n\t\t\t\tpartial.content[event.contentIndex] = { type: \"text\", text: \"\" };\n\t\t\t\tbreak;\n\t\t\tcase \"text_delta\":\n\t\t\t\t(partial.content[event.contentIndex] as { text: string }).text += event.delta;\n\t\t\t\tbreak;\n\t\t\tcase \"text_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, {\n\t\t\t\t\ttext: event.content,\n\t\t\t\t\ttextSignature: event.contentSignature,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_start\":\n\t\t\t\tpartial.content[event.contentIndex] = { type: \"thinking\", thinking: \"\" };\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_delta\":\n\t\t\t\t(partial.content[event.contentIndex] as { thinking: string }).thinking += event.delta;\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, {\n\t\t\t\t\tthinking: event.content,\n\t\t\t\t\tthinkingSignature: event.contentSignature,\n\t\t\t\t\tredacted: event.redacted,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"toolcall_start\":\n\t\t\t\tpartial.content[event.contentIndex] = {\n\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\tid: event.id,\n\t\t\t\t\tname: event.toolName,\n\t\t\t\t\targuments: {},\n\t\t\t\t};\n\t\t\t\ttoolJson.set(event.contentIndex, \"\");\n\t\t\t\tbreak;\n\t\t\tcase \"toolcall_delta\": {\n\t\t\t\tconst json = `${toolJson.get(event.contentIndex) ?? \"\"}${event.delta}`;\n\t\t\t\ttoolJson.set(event.contentIndex, json);\n\t\t\t\t(partial.content[event.contentIndex] as ToolCall).arguments =\n\t\t\t\t\tparseStreamingJson<ToolCall[\"arguments\"]>(json);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"toolcall_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, event.toolCall);\n\t\t\t\ttoolJson.delete(event.contentIndex);\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"toolcall_end\",\n\t\t\t\t\tcontentIndex: event.contentIndex,\n\t\t\t\t\ttoolCall: partial.content[event.contentIndex] as ToolCall,\n\t\t\t\t\tpartial,\n\t\t\t\t};\n\t\t}\n\n\t\treturn { ...event, partial } as AssistantMessageEvent;\n\t};\n}\n\nasync function* readPiMessagesEvents(stream: ReadableStream<Uint8Array>): AsyncGenerator<PiMessagesEvent> {\n\tconst decoder = new TextDecoder();\n\tconst reader = stream.getReader();\n\tlet buffer = \"\";\n\n\ttry {\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tbuffer += done ? decoder.decode() : decoder.decode(value, { stream: true });\n\t\t\tbuffer = buffer.replace(/\\r\\n/g, \"\\n\");\n\n\t\t\tlet split = buffer.indexOf(\"\\n\\n\");\n\t\t\twhile (split !== -1) {\n\t\t\t\tconst event = parsePiMessagesEvent(buffer.slice(0, split));\n\t\t\t\tif (event) {\n\t\t\t\t\tyield event;\n\t\t\t\t}\n\t\t\t\tbuffer = buffer.slice(split + 2);\n\t\t\t\tsplit = buffer.indexOf(\"\\n\\n\");\n\t\t\t}\n\n\t\t\tif (done) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (buffer.trim()) {\n\t\t\tconst event = parsePiMessagesEvent(buffer);\n\t\t\tif (event) {\n\t\t\t\tyield event;\n\t\t\t}\n\t\t}\n\t} finally {\n\t\treader.releaseLock();\n\t}\n}\n\nfunction parsePiMessagesEvent(raw: string): PiMessagesEvent | undefined {\n\tconst data = raw\n\t\t.split(\"\\n\")\n\t\t.find((line) => line.startsWith(\"data:\"))\n\t\t?.slice(5)\n\t\t.trim();\n\n\treturn data && data !== \"[DONE]\" ? (JSON.parse(data) as PiMessagesEvent) : undefined;\n}\n\nfunction createErrorEvent(model: Model<\"pi-messages\">, error: unknown, aborted: boolean): AssistantMessageEvent {\n\tconst reason = aborted ? \"aborted\" : \"error\";\n\tconst assistantMessage: AssistantMessage = {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: reason,\n\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\ttimestamp: Date.now(),\n\t};\n\n\tif (!aborted && error instanceof PiMessagesResponseError) {\n\t\tappendAssistantMessageDiagnostic(\n\t\t\tassistantMessage,\n\t\t\tcreateAssistantMessageDiagnostic(\"pi_messages_response_failure\", error, error.diagnosticDetails),\n\t\t);\n\t}\n\n\treturn { type: \"error\", reason, error: assistantMessage };\n}\n\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention | undefined {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\t// Backend defaults apply when unset; only the legacy env opt-in is mapped.\n\treturn getProviderEnvValue(\"PI_CACHE_RETENTION\", env) === \"long\" ? \"long\" : undefined;\n}\n\nexport const stream: StreamFunction<\"pi-messages\", PiMessagesOptions> = (\n\tmodel: Model<\"pi-messages\">,\n\tcontext: Context,\n\toptions?: PiMessagesOptions,\n): AssistantMessageEventStream => {\n\tconst eventStream = new AssistantMessageEventStream();\n\tconst convertEvent = createEventConverter(model);\n\n\tvoid (async () => {\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey;\n\t\t\tif (!apiKey) {\n\t\t\t\tthrow new Error(`No API key provided for provider \"${model.provider}\"`);\n\t\t\t}\n\n\t\t\tconst url = new URL(`${model.baseUrl.replace(/\\/+$/u, \"\")}/messages`);\n\t\t\tif (options?.debug) {\n\t\t\t\turl.searchParams.set(\"debug\", \"1\");\n\t\t\t}\n\n\t\t\tlet payload: unknown = {\n\t\t\t\tmodel: model.id,\n\t\t\t\tcontext,\n\t\t\t\toptions: {\n\t\t\t\t\ttemperature: options?.temperature,\n\t\t\t\t\tmaxTokens: options?.maxTokens,\n\t\t\t\t\treasoning: options?.reasoning,\n\t\t\t\t\tcacheRetention: resolveCacheRetention(options?.cacheRetention, options?.env),\n\t\t\t\t\tsessionId: options?.sessionId,\n\t\t\t\t\ttoolChoice: options?.toolChoice,\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst nextPayload = await options?.onPayload?.(payload, model);\n\t\t\tif (nextPayload !== undefined) {\n\t\t\t\tpayload = nextPayload;\n\t\t\t}\n\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tauthorization: `Bearer ${apiKey}`,\n\t\t\t\t\taccept: \"text/event-stream\",\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\t...providerHeadersToRecord(options?.headers),\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\tsignal: options?.signal,\n\t\t\t});\n\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst body = await response.text();\n\t\t\t\tthrow createPiMessagesResponseError(model, url, response, body);\n\t\t\t}\n\t\t\tif (!response.body) {\n\t\t\t\tthrow new Error(`${model.provider} response has no body`);\n\t\t\t}\n\n\t\t\tfor await (const piEvent of readPiMessagesEvents(response.body)) {\n\t\t\t\tconst event = convertEvent(piEvent);\n\t\t\t\teventStream.push(event);\n\t\t\t\tif (event.type === \"done\" || event.type === \"error\") {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow new Error(`${model.provider} stream ended without a terminal event`);\n\t\t} catch (error) {\n\t\t\teventStream.push(createErrorEvent(model, error, options?.signal?.aborted ?? false));\n\t\t}\n\t})();\n\n\treturn eventStream;\n};\n\nexport const streamSimple: StreamFunction<\"pi-messages\", SimpleStreamOptions> = (\n\tmodel: Model<\"pi-messages\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tconst extra = options as PiMessagesOptions | undefined;\n\treturn stream(model, context, {\n\t\t...options,\n\t\treasoning: options?.reasoning,\n\t\ttoolChoice: extra?.toolChoice,\n\t\tdebug: extra?.debug,\n\t});\n};\n"]}
1
+ {"version":3,"file":"pi-messages.d.ts","sourceRoot":"","sources":["../../src/api/pi-messages.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * pi-messages API implementation.\n *\n * Streams pi's own message protocol directly to a backend: the request is a\n * single POST of `{ model, context, options }` to `<baseUrl>/messages`, the\n * response is an SSE stream of serialized assistant-message events plus a\n * terminal `done`/`error` event. This is the wire protocol spoken by the\n * Radius gateway, but any backend implementing it can be used, e.g. via a\n * models.json custom provider with `\"api\": \"pi-messages\"`.\n */\n\nimport type {\n\tAssistantMessage,\n\tAssistantMessageEvent,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tProviderEnv,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tThinkingLevel,\n\tToolCall,\n} from \"../types.ts\";\nimport { appendAssistantMessageDiagnostic, createAssistantMessageDiagnostic } from \"../utils/diagnostics.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord, providerHeadersToRecord } from \"../utils/headers.ts\";\nimport { parseStreamingJson } from \"../utils/json-parse.ts\";\nimport { getProviderEnvValue } from \"../utils/provider-env.ts\";\n\nexport interface PiMessagesOptions extends StreamOptions {\n\treasoning?: ThinkingLevel;\n\ttoolChoice?: \"auto\" | \"none\" | \"required\" | { type: \"function\"; function: { name: string } };\n\t/** Ask the backend for debug metadata (e.g. routing response headers). */\n\tdebug?: boolean;\n}\n\ntype PiMessagesUsage = AssistantMessage[\"usage\"];\ntype PiMessagesStopReason = AssistantMessage[\"stopReason\"];\n\n/** Impact summary of a server-side message rewrite (e.g. a gateway policy). */\nexport type PiMessagesRewriteImpact = {\n\tpolicyId: string;\n\tpolicyVersion: number;\n\tchanged: boolean;\n\ttokenCountChange: number;\n\tmessageCountChange: number;\n\tsystemPromptChanged: boolean;\n};\n\n/** Serialized assistant-message event as sent by a pi-messages backend. */\nexport type PiMessagesEvent =\n\t| { type: \"start\" }\n\t| { type: \"text_start\"; contentIndex: number }\n\t| { type: \"text_delta\"; contentIndex: number; delta: string }\n\t| { type: \"text_end\"; contentIndex: number; content: string; contentSignature?: string }\n\t| { type: \"thinking_start\"; contentIndex: number }\n\t| { type: \"thinking_delta\"; contentIndex: number; delta: string }\n\t| {\n\t\t\ttype: \"thinking_end\";\n\t\t\tcontentIndex: number;\n\t\t\tcontent: string;\n\t\t\tcontentSignature?: string;\n\t\t\tredacted?: boolean;\n\t }\n\t| { type: \"toolcall_start\"; contentIndex: number; id: string; toolName: string }\n\t| { type: \"toolcall_delta\"; contentIndex: number; delta: string }\n\t| { type: \"toolcall_end\"; contentIndex: number; toolCall: ToolCall }\n\t| {\n\t\t\ttype: \"done\";\n\t\t\treason: Extract<PiMessagesStopReason, \"stop\" | \"length\" | \"toolUse\">;\n\t\t\tusage: PiMessagesUsage;\n\t\t\tresponseId?: string;\n\t\t\trewrite?: PiMessagesRewriteImpact;\n\t }\n\t| {\n\t\t\ttype: \"error\";\n\t\t\treason: Extract<PiMessagesStopReason, \"aborted\" | \"error\">;\n\t\t\tusage: PiMessagesUsage;\n\t\t\terrorMessage?: string;\n\t\t\tresponseId?: string;\n\t\t\trewrite?: PiMessagesRewriteImpact;\n\t };\n\ntype PiMessagesErrorBody = {\n\terror?: {\n\t\tmessage?: unknown;\n\t\tcode?: unknown;\n\t\tdetails?: unknown;\n\t\t[key: string]: unknown;\n\t};\n};\n\nexport class PiMessagesResponseError extends Error {\n\tcode?: string;\n\treadonly diagnosticDetails: Record<string, unknown>;\n\n\tconstructor(message: string, code: string | undefined, diagnosticDetails: Record<string, unknown>) {\n\t\tsuper(message);\n\t\tthis.name = \"PiMessagesResponseError\";\n\t\tthis.code = code;\n\t\tthis.diagnosticDetails = diagnosticDetails;\n\t}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parsePiMessagesErrorBody(body: string): PiMessagesErrorBody | undefined {\n\ttry {\n\t\tconst parsed = JSON.parse(body) as unknown;\n\t\treturn isRecord(parsed) && isRecord(parsed.error) ? (parsed as PiMessagesErrorBody) : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction truncateDiagnosticString(value: string): string {\n\tconst maxLength = 8192;\n\treturn value.length > maxLength ? `${value.slice(0, maxLength)}…` : value;\n}\n\nfunction formatPiMessagesResponseError(\n\tresponse: Response,\n\tbody: string,\n\terrorBody: PiMessagesErrorBody | undefined,\n): string {\n\tconst message = typeof errorBody?.error?.message === \"string\" ? errorBody.error.message : undefined;\n\tconst code = typeof errorBody?.error?.code === \"string\" ? errorBody.error.code : undefined;\n\tconst suffix = message ?? body;\n\tconst codeSuffix = code ? ` (${code})` : \"\";\n\treturn `${response.status} ${response.statusText}: ${suffix}${codeSuffix}`;\n}\n\nfunction createPiMessagesResponseError(\n\tmodel: Model<\"pi-messages\">,\n\turl: URL,\n\tresponse: Response,\n\tbody: string,\n): PiMessagesResponseError {\n\tconst errorBody = parsePiMessagesErrorBody(body);\n\tconst code = typeof errorBody?.error?.code === \"string\" ? errorBody.error.code : undefined;\n\treturn new PiMessagesResponseError(formatPiMessagesResponseError(response, body, errorBody), code, {\n\t\tversion: 1,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\turl: url.toString(),\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\terror: errorBody?.error,\n\t\tbody: errorBody ? undefined : truncateDiagnosticString(body),\n\t\ttimestampMs: Date.now(),\n\t});\n}\n\nfunction createEmptyUsage(): PiMessagesUsage {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\ttotalTokens: 0,\n\t\tmeasurement: \"unknown\",\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t};\n}\n\nfunction appendRewriteDiagnostic(message: AssistantMessage, rewrite: PiMessagesRewriteImpact | undefined): void {\n\tif (!rewrite) {\n\t\treturn;\n\t}\n\tappendAssistantMessageDiagnostic(message, {\n\t\ttype: \"pi_messages_rewrite\",\n\t\ttimestamp: Date.now(),\n\t\tdetails: { ...rewrite },\n\t});\n}\n\nfunction createEventConverter(model: Model<\"pi-messages\">) {\n\tconst partial: AssistantMessage = {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n\tconst toolJson = new Map<number, string>();\n\n\treturn (event: PiMessagesEvent): AssistantMessageEvent => {\n\t\tswitch (event.type) {\n\t\t\tcase \"done\":\n\t\t\t\tObject.assign(partial, {\n\t\t\t\t\tstopReason: event.reason,\n\t\t\t\t\tusage: { ...event.usage, measurement: event.usage.measurement ?? \"reported\" },\n\t\t\t\t\tresponseId: event.responseId,\n\t\t\t\t});\n\t\t\t\tappendRewriteDiagnostic(partial, event.rewrite);\n\t\t\t\treturn { type: \"done\", reason: event.reason, message: partial };\n\t\t\tcase \"error\":\n\t\t\t\tObject.assign(partial, {\n\t\t\t\t\tstopReason: event.reason,\n\t\t\t\t\tusage: { ...event.usage, measurement: event.usage.measurement ?? \"reported\" },\n\t\t\t\t\terrorMessage: event.errorMessage,\n\t\t\t\t\tresponseId: event.responseId,\n\t\t\t\t});\n\t\t\t\tappendRewriteDiagnostic(partial, event.rewrite);\n\t\t\t\treturn { type: \"error\", reason: event.reason, error: partial };\n\t\t\tcase \"start\":\n\t\t\t\tbreak;\n\t\t\tcase \"text_start\":\n\t\t\t\tpartial.content[event.contentIndex] = { type: \"text\", text: \"\" };\n\t\t\t\tbreak;\n\t\t\tcase \"text_delta\":\n\t\t\t\t(partial.content[event.contentIndex] as { text: string }).text += event.delta;\n\t\t\t\tbreak;\n\t\t\tcase \"text_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, {\n\t\t\t\t\ttext: event.content,\n\t\t\t\t\ttextSignature: event.contentSignature,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_start\":\n\t\t\t\tpartial.content[event.contentIndex] = { type: \"thinking\", thinking: \"\" };\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_delta\":\n\t\t\t\t(partial.content[event.contentIndex] as { thinking: string }).thinking += event.delta;\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, {\n\t\t\t\t\tthinking: event.content,\n\t\t\t\t\tthinkingSignature: event.contentSignature,\n\t\t\t\t\tredacted: event.redacted,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"toolcall_start\":\n\t\t\t\tpartial.content[event.contentIndex] = {\n\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\tid: event.id,\n\t\t\t\t\tname: event.toolName,\n\t\t\t\t\targuments: {},\n\t\t\t\t};\n\t\t\t\ttoolJson.set(event.contentIndex, \"\");\n\t\t\t\tbreak;\n\t\t\tcase \"toolcall_delta\": {\n\t\t\t\tconst json = `${toolJson.get(event.contentIndex) ?? \"\"}${event.delta}`;\n\t\t\t\ttoolJson.set(event.contentIndex, json);\n\t\t\t\t(partial.content[event.contentIndex] as ToolCall).arguments =\n\t\t\t\t\tparseStreamingJson<ToolCall[\"arguments\"]>(json);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"toolcall_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, event.toolCall);\n\t\t\t\ttoolJson.delete(event.contentIndex);\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"toolcall_end\",\n\t\t\t\t\tcontentIndex: event.contentIndex,\n\t\t\t\t\ttoolCall: partial.content[event.contentIndex] as ToolCall,\n\t\t\t\t\tpartial,\n\t\t\t\t};\n\t\t}\n\n\t\treturn { ...event, partial } as AssistantMessageEvent;\n\t};\n}\n\nasync function* readPiMessagesEvents(stream: ReadableStream<Uint8Array>): AsyncGenerator<PiMessagesEvent> {\n\tconst decoder = new TextDecoder();\n\tconst reader = stream.getReader();\n\tlet buffer = \"\";\n\n\ttry {\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tbuffer += done ? decoder.decode() : decoder.decode(value, { stream: true });\n\t\t\tbuffer = buffer.replace(/\\r\\n/g, \"\\n\");\n\n\t\t\tlet split = buffer.indexOf(\"\\n\\n\");\n\t\t\twhile (split !== -1) {\n\t\t\t\tconst event = parsePiMessagesEvent(buffer.slice(0, split));\n\t\t\t\tif (event) {\n\t\t\t\t\tyield event;\n\t\t\t\t}\n\t\t\t\tbuffer = buffer.slice(split + 2);\n\t\t\t\tsplit = buffer.indexOf(\"\\n\\n\");\n\t\t\t}\n\n\t\t\tif (done) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (buffer.trim()) {\n\t\t\tconst event = parsePiMessagesEvent(buffer);\n\t\t\tif (event) {\n\t\t\t\tyield event;\n\t\t\t}\n\t\t}\n\t} finally {\n\t\treader.releaseLock();\n\t}\n}\n\nfunction parsePiMessagesEvent(raw: string): PiMessagesEvent | undefined {\n\tconst data = raw\n\t\t.split(\"\\n\")\n\t\t.find((line) => line.startsWith(\"data:\"))\n\t\t?.slice(5)\n\t\t.trim();\n\n\treturn data && data !== \"[DONE]\" ? (JSON.parse(data) as PiMessagesEvent) : undefined;\n}\n\nfunction createErrorEvent(model: Model<\"pi-messages\">, error: unknown, aborted: boolean): AssistantMessageEvent {\n\tconst reason = aborted ? \"aborted\" : \"error\";\n\tconst assistantMessage: AssistantMessage = {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: reason,\n\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\ttimestamp: Date.now(),\n\t};\n\n\tif (!aborted && error instanceof PiMessagesResponseError) {\n\t\tappendAssistantMessageDiagnostic(\n\t\t\tassistantMessage,\n\t\t\tcreateAssistantMessageDiagnostic(\"pi_messages_response_failure\", error, error.diagnosticDetails),\n\t\t);\n\t}\n\n\treturn { type: \"error\", reason, error: assistantMessage };\n}\n\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention | undefined {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\t// Backend defaults apply when unset; only the legacy env opt-in is mapped.\n\treturn getProviderEnvValue(\"PI_CACHE_RETENTION\", env) === \"long\" ? \"long\" : undefined;\n}\n\nexport const stream: StreamFunction<\"pi-messages\", PiMessagesOptions> = (\n\tmodel: Model<\"pi-messages\">,\n\tcontext: Context,\n\toptions?: PiMessagesOptions,\n): AssistantMessageEventStream => {\n\tconst eventStream = new AssistantMessageEventStream();\n\tconst convertEvent = createEventConverter(model);\n\tlet latestMessage: AssistantMessage | undefined;\n\n\tvoid (async () => {\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey;\n\t\t\tif (!apiKey) {\n\t\t\t\tthrow new Error(`No API key provided for provider \"${model.provider}\"`);\n\t\t\t}\n\n\t\t\tconst url = new URL(`${model.baseUrl.replace(/\\/+$/u, \"\")}/messages`);\n\t\t\tif (options?.debug) {\n\t\t\t\turl.searchParams.set(\"debug\", \"1\");\n\t\t\t}\n\n\t\t\tlet payload: unknown = {\n\t\t\t\tmodel: model.id,\n\t\t\t\tcontext,\n\t\t\t\toptions: {\n\t\t\t\t\ttemperature: options?.temperature,\n\t\t\t\t\tmaxTokens: options?.maxTokens,\n\t\t\t\t\treasoning: options?.reasoning,\n\t\t\t\t\tcacheRetention: resolveCacheRetention(options?.cacheRetention, options?.env),\n\t\t\t\t\tsessionId: options?.sessionId,\n\t\t\t\t\ttoolChoice: options?.toolChoice,\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst nextPayload = await options?.onPayload?.(payload, model);\n\t\t\tif (nextPayload !== undefined) {\n\t\t\t\tpayload = nextPayload;\n\t\t\t}\n\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tauthorization: `Bearer ${apiKey}`,\n\t\t\t\t\taccept: \"text/event-stream\",\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\t...providerHeadersToRecord(options?.headers),\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\tsignal: options?.signal,\n\t\t\t});\n\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst body = await response.text();\n\t\t\t\tthrow createPiMessagesResponseError(model, url, response, body);\n\t\t\t}\n\t\t\tif (!response.body) {\n\t\t\t\tthrow new Error(`${model.provider} response has no body`);\n\t\t\t}\n\n\t\t\tfor await (const piEvent of readPiMessagesEvents(response.body)) {\n\t\t\t\tconst event = convertEvent(piEvent);\n\t\t\t\tlatestMessage =\n\t\t\t\t\t\"partial\" in event\n\t\t\t\t\t\t? event.partial\n\t\t\t\t\t\t: event.type === \"done\"\n\t\t\t\t\t\t\t? event.message\n\t\t\t\t\t\t\t: event.type === \"error\"\n\t\t\t\t\t\t\t\t? event.error\n\t\t\t\t\t\t\t\t: latestMessage;\n\t\t\t\teventStream.push(event);\n\t\t\t\tif (event.type === \"done\" || event.type === \"error\") {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow new Error(`${model.provider} stream ended without a terminal event`);\n\t\t} catch (error) {\n\t\t\tconst event = createErrorEvent(model, error, options?.signal?.aborted ?? false);\n\t\t\tif (event.type === \"error\" && latestMessage) {\n\t\t\t\tevent.error.content = latestMessage.content;\n\t\t\t\tevent.error.usage = latestMessage.usage;\n\t\t\t\tevent.error.responseId = latestMessage.responseId;\n\t\t\t}\n\t\t\teventStream.push(event);\n\t\t}\n\t})();\n\n\treturn eventStream;\n};\n\nexport const streamSimple: StreamFunction<\"pi-messages\", SimpleStreamOptions> = (\n\tmodel: Model<\"pi-messages\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tconst extra = options as PiMessagesOptions | undefined;\n\treturn stream(model, context, {\n\t\t...options,\n\t\treasoning: options?.reasoning,\n\t\ttoolChoice: extra?.toolChoice,\n\t\tdebug: extra?.debug,\n\t});\n};\n"]}
@@ -68,6 +68,7 @@ function createEmptyUsage() {
68
68
  cacheRead: 0,
69
69
  cacheWrite: 0,
70
70
  totalTokens: 0,
71
+ measurement: "unknown",
71
72
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
72
73
  };
73
74
  }
@@ -98,7 +99,7 @@ function createEventConverter(model) {
98
99
  case "done":
99
100
  Object.assign(partial, {
100
101
  stopReason: event.reason,
101
- usage: event.usage,
102
+ usage: { ...event.usage, measurement: event.usage.measurement ?? "reported" },
102
103
  responseId: event.responseId,
103
104
  });
104
105
  appendRewriteDiagnostic(partial, event.rewrite);
@@ -106,7 +107,7 @@ function createEventConverter(model) {
106
107
  case "error":
107
108
  Object.assign(partial, {
108
109
  stopReason: event.reason,
109
- usage: event.usage,
110
+ usage: { ...event.usage, measurement: event.usage.measurement ?? "reported" },
110
111
  errorMessage: event.errorMessage,
111
112
  responseId: event.responseId,
112
113
  });
@@ -237,6 +238,7 @@ function resolveCacheRetention(cacheRetention, env) {
237
238
  export const stream = (model, context, options) => {
238
239
  const eventStream = new AssistantMessageEventStream();
239
240
  const convertEvent = createEventConverter(model);
241
+ let latestMessage;
240
242
  void (async () => {
241
243
  try {
242
244
  const apiKey = options?.apiKey;
@@ -284,6 +286,14 @@ export const stream = (model, context, options) => {
284
286
  }
285
287
  for await (const piEvent of readPiMessagesEvents(response.body)) {
286
288
  const event = convertEvent(piEvent);
289
+ latestMessage =
290
+ "partial" in event
291
+ ? event.partial
292
+ : event.type === "done"
293
+ ? event.message
294
+ : event.type === "error"
295
+ ? event.error
296
+ : latestMessage;
287
297
  eventStream.push(event);
288
298
  if (event.type === "done" || event.type === "error") {
289
299
  return;
@@ -292,7 +302,13 @@ export const stream = (model, context, options) => {
292
302
  throw new Error(`${model.provider} stream ended without a terminal event`);
293
303
  }
294
304
  catch (error) {
295
- eventStream.push(createErrorEvent(model, error, options?.signal?.aborted ?? false));
305
+ const event = createErrorEvent(model, error, options?.signal?.aborted ?? false);
306
+ if (event.type === "error" && latestMessage) {
307
+ event.error.content = latestMessage.content;
308
+ event.error.usage = latestMessage.usage;
309
+ event.error.responseId = latestMessage.responseId;
310
+ }
311
+ eventStream.push(event);
296
312
  }
297
313
  })();
298
314
  return eventStream;
@@ -1 +1 @@
1
- {"version":3,"file":"pi-messages.js","sourceRoot":"","sources":["../../src/api/pi-messages.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * pi-messages API implementation.\n *\n * Streams pi's own message protocol directly to a backend: the request is a\n * single POST of `{ model, context, options }` to `<baseUrl>/messages`, the\n * response is an SSE stream of serialized assistant-message events plus a\n * terminal `done`/`error` event. This is the wire protocol spoken by the\n * Radius gateway, but any backend implementing it can be used, e.g. via a\n * models.json custom provider with `\"api\": \"pi-messages\"`.\n */\n\nimport type {\n\tAssistantMessage,\n\tAssistantMessageEvent,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tProviderEnv,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tThinkingLevel,\n\tToolCall,\n} from \"../types.ts\";\nimport { appendAssistantMessageDiagnostic, createAssistantMessageDiagnostic } from \"../utils/diagnostics.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord, providerHeadersToRecord } from \"../utils/headers.ts\";\nimport { parseStreamingJson } from \"../utils/json-parse.ts\";\nimport { getProviderEnvValue } from \"../utils/provider-env.ts\";\n\nexport interface PiMessagesOptions extends StreamOptions {\n\treasoning?: ThinkingLevel;\n\ttoolChoice?: \"auto\" | \"none\" | \"required\" | { type: \"function\"; function: { name: string } };\n\t/** Ask the backend for debug metadata (e.g. routing response headers). */\n\tdebug?: boolean;\n}\n\ntype PiMessagesUsage = AssistantMessage[\"usage\"];\ntype PiMessagesStopReason = AssistantMessage[\"stopReason\"];\n\n/** Impact summary of a server-side message rewrite (e.g. a gateway policy). */\nexport type PiMessagesRewriteImpact = {\n\tpolicyId: string;\n\tpolicyVersion: number;\n\tchanged: boolean;\n\ttokenCountChange: number;\n\tmessageCountChange: number;\n\tsystemPromptChanged: boolean;\n};\n\n/** Serialized assistant-message event as sent by a pi-messages backend. */\nexport type PiMessagesEvent =\n\t| { type: \"start\" }\n\t| { type: \"text_start\"; contentIndex: number }\n\t| { type: \"text_delta\"; contentIndex: number; delta: string }\n\t| { type: \"text_end\"; contentIndex: number; content: string; contentSignature?: string }\n\t| { type: \"thinking_start\"; contentIndex: number }\n\t| { type: \"thinking_delta\"; contentIndex: number; delta: string }\n\t| {\n\t\t\ttype: \"thinking_end\";\n\t\t\tcontentIndex: number;\n\t\t\tcontent: string;\n\t\t\tcontentSignature?: string;\n\t\t\tredacted?: boolean;\n\t }\n\t| { type: \"toolcall_start\"; contentIndex: number; id: string; toolName: string }\n\t| { type: \"toolcall_delta\"; contentIndex: number; delta: string }\n\t| { type: \"toolcall_end\"; contentIndex: number; toolCall: ToolCall }\n\t| {\n\t\t\ttype: \"done\";\n\t\t\treason: Extract<PiMessagesStopReason, \"stop\" | \"length\" | \"toolUse\">;\n\t\t\tusage: PiMessagesUsage;\n\t\t\tresponseId?: string;\n\t\t\trewrite?: PiMessagesRewriteImpact;\n\t }\n\t| {\n\t\t\ttype: \"error\";\n\t\t\treason: Extract<PiMessagesStopReason, \"aborted\" | \"error\">;\n\t\t\tusage: PiMessagesUsage;\n\t\t\terrorMessage?: string;\n\t\t\tresponseId?: string;\n\t\t\trewrite?: PiMessagesRewriteImpact;\n\t };\n\ntype PiMessagesErrorBody = {\n\terror?: {\n\t\tmessage?: unknown;\n\t\tcode?: unknown;\n\t\tdetails?: unknown;\n\t\t[key: string]: unknown;\n\t};\n};\n\nexport class PiMessagesResponseError extends Error {\n\tcode?: string;\n\treadonly diagnosticDetails: Record<string, unknown>;\n\n\tconstructor(message: string, code: string | undefined, diagnosticDetails: Record<string, unknown>) {\n\t\tsuper(message);\n\t\tthis.name = \"PiMessagesResponseError\";\n\t\tthis.code = code;\n\t\tthis.diagnosticDetails = diagnosticDetails;\n\t}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parsePiMessagesErrorBody(body: string): PiMessagesErrorBody | undefined {\n\ttry {\n\t\tconst parsed = JSON.parse(body) as unknown;\n\t\treturn isRecord(parsed) && isRecord(parsed.error) ? (parsed as PiMessagesErrorBody) : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction truncateDiagnosticString(value: string): string {\n\tconst maxLength = 8192;\n\treturn value.length > maxLength ? `${value.slice(0, maxLength)}…` : value;\n}\n\nfunction formatPiMessagesResponseError(\n\tresponse: Response,\n\tbody: string,\n\terrorBody: PiMessagesErrorBody | undefined,\n): string {\n\tconst message = typeof errorBody?.error?.message === \"string\" ? errorBody.error.message : undefined;\n\tconst code = typeof errorBody?.error?.code === \"string\" ? errorBody.error.code : undefined;\n\tconst suffix = message ?? body;\n\tconst codeSuffix = code ? ` (${code})` : \"\";\n\treturn `${response.status} ${response.statusText}: ${suffix}${codeSuffix}`;\n}\n\nfunction createPiMessagesResponseError(\n\tmodel: Model<\"pi-messages\">,\n\turl: URL,\n\tresponse: Response,\n\tbody: string,\n): PiMessagesResponseError {\n\tconst errorBody = parsePiMessagesErrorBody(body);\n\tconst code = typeof errorBody?.error?.code === \"string\" ? errorBody.error.code : undefined;\n\treturn new PiMessagesResponseError(formatPiMessagesResponseError(response, body, errorBody), code, {\n\t\tversion: 1,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\turl: url.toString(),\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\terror: errorBody?.error,\n\t\tbody: errorBody ? undefined : truncateDiagnosticString(body),\n\t\ttimestampMs: Date.now(),\n\t});\n}\n\nfunction createEmptyUsage(): PiMessagesUsage {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\ttotalTokens: 0,\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t};\n}\n\nfunction appendRewriteDiagnostic(message: AssistantMessage, rewrite: PiMessagesRewriteImpact | undefined): void {\n\tif (!rewrite) {\n\t\treturn;\n\t}\n\tappendAssistantMessageDiagnostic(message, {\n\t\ttype: \"pi_messages_rewrite\",\n\t\ttimestamp: Date.now(),\n\t\tdetails: { ...rewrite },\n\t});\n}\n\nfunction createEventConverter(model: Model<\"pi-messages\">) {\n\tconst partial: AssistantMessage = {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n\tconst toolJson = new Map<number, string>();\n\n\treturn (event: PiMessagesEvent): AssistantMessageEvent => {\n\t\tswitch (event.type) {\n\t\t\tcase \"done\":\n\t\t\t\tObject.assign(partial, {\n\t\t\t\t\tstopReason: event.reason,\n\t\t\t\t\tusage: event.usage,\n\t\t\t\t\tresponseId: event.responseId,\n\t\t\t\t});\n\t\t\t\tappendRewriteDiagnostic(partial, event.rewrite);\n\t\t\t\treturn { type: \"done\", reason: event.reason, message: partial };\n\t\t\tcase \"error\":\n\t\t\t\tObject.assign(partial, {\n\t\t\t\t\tstopReason: event.reason,\n\t\t\t\t\tusage: event.usage,\n\t\t\t\t\terrorMessage: event.errorMessage,\n\t\t\t\t\tresponseId: event.responseId,\n\t\t\t\t});\n\t\t\t\tappendRewriteDiagnostic(partial, event.rewrite);\n\t\t\t\treturn { type: \"error\", reason: event.reason, error: partial };\n\t\t\tcase \"start\":\n\t\t\t\tbreak;\n\t\t\tcase \"text_start\":\n\t\t\t\tpartial.content[event.contentIndex] = { type: \"text\", text: \"\" };\n\t\t\t\tbreak;\n\t\t\tcase \"text_delta\":\n\t\t\t\t(partial.content[event.contentIndex] as { text: string }).text += event.delta;\n\t\t\t\tbreak;\n\t\t\tcase \"text_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, {\n\t\t\t\t\ttext: event.content,\n\t\t\t\t\ttextSignature: event.contentSignature,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_start\":\n\t\t\t\tpartial.content[event.contentIndex] = { type: \"thinking\", thinking: \"\" };\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_delta\":\n\t\t\t\t(partial.content[event.contentIndex] as { thinking: string }).thinking += event.delta;\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, {\n\t\t\t\t\tthinking: event.content,\n\t\t\t\t\tthinkingSignature: event.contentSignature,\n\t\t\t\t\tredacted: event.redacted,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"toolcall_start\":\n\t\t\t\tpartial.content[event.contentIndex] = {\n\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\tid: event.id,\n\t\t\t\t\tname: event.toolName,\n\t\t\t\t\targuments: {},\n\t\t\t\t};\n\t\t\t\ttoolJson.set(event.contentIndex, \"\");\n\t\t\t\tbreak;\n\t\t\tcase \"toolcall_delta\": {\n\t\t\t\tconst json = `${toolJson.get(event.contentIndex) ?? \"\"}${event.delta}`;\n\t\t\t\ttoolJson.set(event.contentIndex, json);\n\t\t\t\t(partial.content[event.contentIndex] as ToolCall).arguments =\n\t\t\t\t\tparseStreamingJson<ToolCall[\"arguments\"]>(json);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"toolcall_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, event.toolCall);\n\t\t\t\ttoolJson.delete(event.contentIndex);\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"toolcall_end\",\n\t\t\t\t\tcontentIndex: event.contentIndex,\n\t\t\t\t\ttoolCall: partial.content[event.contentIndex] as ToolCall,\n\t\t\t\t\tpartial,\n\t\t\t\t};\n\t\t}\n\n\t\treturn { ...event, partial } as AssistantMessageEvent;\n\t};\n}\n\nasync function* readPiMessagesEvents(stream: ReadableStream<Uint8Array>): AsyncGenerator<PiMessagesEvent> {\n\tconst decoder = new TextDecoder();\n\tconst reader = stream.getReader();\n\tlet buffer = \"\";\n\n\ttry {\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tbuffer += done ? decoder.decode() : decoder.decode(value, { stream: true });\n\t\t\tbuffer = buffer.replace(/\\r\\n/g, \"\\n\");\n\n\t\t\tlet split = buffer.indexOf(\"\\n\\n\");\n\t\t\twhile (split !== -1) {\n\t\t\t\tconst event = parsePiMessagesEvent(buffer.slice(0, split));\n\t\t\t\tif (event) {\n\t\t\t\t\tyield event;\n\t\t\t\t}\n\t\t\t\tbuffer = buffer.slice(split + 2);\n\t\t\t\tsplit = buffer.indexOf(\"\\n\\n\");\n\t\t\t}\n\n\t\t\tif (done) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (buffer.trim()) {\n\t\t\tconst event = parsePiMessagesEvent(buffer);\n\t\t\tif (event) {\n\t\t\t\tyield event;\n\t\t\t}\n\t\t}\n\t} finally {\n\t\treader.releaseLock();\n\t}\n}\n\nfunction parsePiMessagesEvent(raw: string): PiMessagesEvent | undefined {\n\tconst data = raw\n\t\t.split(\"\\n\")\n\t\t.find((line) => line.startsWith(\"data:\"))\n\t\t?.slice(5)\n\t\t.trim();\n\n\treturn data && data !== \"[DONE]\" ? (JSON.parse(data) as PiMessagesEvent) : undefined;\n}\n\nfunction createErrorEvent(model: Model<\"pi-messages\">, error: unknown, aborted: boolean): AssistantMessageEvent {\n\tconst reason = aborted ? \"aborted\" : \"error\";\n\tconst assistantMessage: AssistantMessage = {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: reason,\n\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\ttimestamp: Date.now(),\n\t};\n\n\tif (!aborted && error instanceof PiMessagesResponseError) {\n\t\tappendAssistantMessageDiagnostic(\n\t\t\tassistantMessage,\n\t\t\tcreateAssistantMessageDiagnostic(\"pi_messages_response_failure\", error, error.diagnosticDetails),\n\t\t);\n\t}\n\n\treturn { type: \"error\", reason, error: assistantMessage };\n}\n\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention | undefined {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\t// Backend defaults apply when unset; only the legacy env opt-in is mapped.\n\treturn getProviderEnvValue(\"PI_CACHE_RETENTION\", env) === \"long\" ? \"long\" : undefined;\n}\n\nexport const stream: StreamFunction<\"pi-messages\", PiMessagesOptions> = (\n\tmodel: Model<\"pi-messages\">,\n\tcontext: Context,\n\toptions?: PiMessagesOptions,\n): AssistantMessageEventStream => {\n\tconst eventStream = new AssistantMessageEventStream();\n\tconst convertEvent = createEventConverter(model);\n\n\tvoid (async () => {\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey;\n\t\t\tif (!apiKey) {\n\t\t\t\tthrow new Error(`No API key provided for provider \"${model.provider}\"`);\n\t\t\t}\n\n\t\t\tconst url = new URL(`${model.baseUrl.replace(/\\/+$/u, \"\")}/messages`);\n\t\t\tif (options?.debug) {\n\t\t\t\turl.searchParams.set(\"debug\", \"1\");\n\t\t\t}\n\n\t\t\tlet payload: unknown = {\n\t\t\t\tmodel: model.id,\n\t\t\t\tcontext,\n\t\t\t\toptions: {\n\t\t\t\t\ttemperature: options?.temperature,\n\t\t\t\t\tmaxTokens: options?.maxTokens,\n\t\t\t\t\treasoning: options?.reasoning,\n\t\t\t\t\tcacheRetention: resolveCacheRetention(options?.cacheRetention, options?.env),\n\t\t\t\t\tsessionId: options?.sessionId,\n\t\t\t\t\ttoolChoice: options?.toolChoice,\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst nextPayload = await options?.onPayload?.(payload, model);\n\t\t\tif (nextPayload !== undefined) {\n\t\t\t\tpayload = nextPayload;\n\t\t\t}\n\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tauthorization: `Bearer ${apiKey}`,\n\t\t\t\t\taccept: \"text/event-stream\",\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\t...providerHeadersToRecord(options?.headers),\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\tsignal: options?.signal,\n\t\t\t});\n\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst body = await response.text();\n\t\t\t\tthrow createPiMessagesResponseError(model, url, response, body);\n\t\t\t}\n\t\t\tif (!response.body) {\n\t\t\t\tthrow new Error(`${model.provider} response has no body`);\n\t\t\t}\n\n\t\t\tfor await (const piEvent of readPiMessagesEvents(response.body)) {\n\t\t\t\tconst event = convertEvent(piEvent);\n\t\t\t\teventStream.push(event);\n\t\t\t\tif (event.type === \"done\" || event.type === \"error\") {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow new Error(`${model.provider} stream ended without a terminal event`);\n\t\t} catch (error) {\n\t\t\teventStream.push(createErrorEvent(model, error, options?.signal?.aborted ?? false));\n\t\t}\n\t})();\n\n\treturn eventStream;\n};\n\nexport const streamSimple: StreamFunction<\"pi-messages\", SimpleStreamOptions> = (\n\tmodel: Model<\"pi-messages\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tconst extra = options as PiMessagesOptions | undefined;\n\treturn stream(model, context, {\n\t\t...options,\n\t\treasoning: options?.reasoning,\n\t\ttoolChoice: extra?.toolChoice,\n\t\tdebug: extra?.debug,\n\t});\n};\n"]}
1
+ {"version":3,"file":"pi-messages.js","sourceRoot":"","sources":["../../src/api/pi-messages.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * pi-messages API implementation.\n *\n * Streams pi's own message protocol directly to a backend: the request is a\n * single POST of `{ model, context, options }` to `<baseUrl>/messages`, the\n * response is an SSE stream of serialized assistant-message events plus a\n * terminal `done`/`error` event. This is the wire protocol spoken by the\n * Radius gateway, but any backend implementing it can be used, e.g. via a\n * models.json custom provider with `\"api\": \"pi-messages\"`.\n */\n\nimport type {\n\tAssistantMessage,\n\tAssistantMessageEvent,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tProviderEnv,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tThinkingLevel,\n\tToolCall,\n} from \"../types.ts\";\nimport { appendAssistantMessageDiagnostic, createAssistantMessageDiagnostic } from \"../utils/diagnostics.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord, providerHeadersToRecord } from \"../utils/headers.ts\";\nimport { parseStreamingJson } from \"../utils/json-parse.ts\";\nimport { getProviderEnvValue } from \"../utils/provider-env.ts\";\n\nexport interface PiMessagesOptions extends StreamOptions {\n\treasoning?: ThinkingLevel;\n\ttoolChoice?: \"auto\" | \"none\" | \"required\" | { type: \"function\"; function: { name: string } };\n\t/** Ask the backend for debug metadata (e.g. routing response headers). */\n\tdebug?: boolean;\n}\n\ntype PiMessagesUsage = AssistantMessage[\"usage\"];\ntype PiMessagesStopReason = AssistantMessage[\"stopReason\"];\n\n/** Impact summary of a server-side message rewrite (e.g. a gateway policy). */\nexport type PiMessagesRewriteImpact = {\n\tpolicyId: string;\n\tpolicyVersion: number;\n\tchanged: boolean;\n\ttokenCountChange: number;\n\tmessageCountChange: number;\n\tsystemPromptChanged: boolean;\n};\n\n/** Serialized assistant-message event as sent by a pi-messages backend. */\nexport type PiMessagesEvent =\n\t| { type: \"start\" }\n\t| { type: \"text_start\"; contentIndex: number }\n\t| { type: \"text_delta\"; contentIndex: number; delta: string }\n\t| { type: \"text_end\"; contentIndex: number; content: string; contentSignature?: string }\n\t| { type: \"thinking_start\"; contentIndex: number }\n\t| { type: \"thinking_delta\"; contentIndex: number; delta: string }\n\t| {\n\t\t\ttype: \"thinking_end\";\n\t\t\tcontentIndex: number;\n\t\t\tcontent: string;\n\t\t\tcontentSignature?: string;\n\t\t\tredacted?: boolean;\n\t }\n\t| { type: \"toolcall_start\"; contentIndex: number; id: string; toolName: string }\n\t| { type: \"toolcall_delta\"; contentIndex: number; delta: string }\n\t| { type: \"toolcall_end\"; contentIndex: number; toolCall: ToolCall }\n\t| {\n\t\t\ttype: \"done\";\n\t\t\treason: Extract<PiMessagesStopReason, \"stop\" | \"length\" | \"toolUse\">;\n\t\t\tusage: PiMessagesUsage;\n\t\t\tresponseId?: string;\n\t\t\trewrite?: PiMessagesRewriteImpact;\n\t }\n\t| {\n\t\t\ttype: \"error\";\n\t\t\treason: Extract<PiMessagesStopReason, \"aborted\" | \"error\">;\n\t\t\tusage: PiMessagesUsage;\n\t\t\terrorMessage?: string;\n\t\t\tresponseId?: string;\n\t\t\trewrite?: PiMessagesRewriteImpact;\n\t };\n\ntype PiMessagesErrorBody = {\n\terror?: {\n\t\tmessage?: unknown;\n\t\tcode?: unknown;\n\t\tdetails?: unknown;\n\t\t[key: string]: unknown;\n\t};\n};\n\nexport class PiMessagesResponseError extends Error {\n\tcode?: string;\n\treadonly diagnosticDetails: Record<string, unknown>;\n\n\tconstructor(message: string, code: string | undefined, diagnosticDetails: Record<string, unknown>) {\n\t\tsuper(message);\n\t\tthis.name = \"PiMessagesResponseError\";\n\t\tthis.code = code;\n\t\tthis.diagnosticDetails = diagnosticDetails;\n\t}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parsePiMessagesErrorBody(body: string): PiMessagesErrorBody | undefined {\n\ttry {\n\t\tconst parsed = JSON.parse(body) as unknown;\n\t\treturn isRecord(parsed) && isRecord(parsed.error) ? (parsed as PiMessagesErrorBody) : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction truncateDiagnosticString(value: string): string {\n\tconst maxLength = 8192;\n\treturn value.length > maxLength ? `${value.slice(0, maxLength)}…` : value;\n}\n\nfunction formatPiMessagesResponseError(\n\tresponse: Response,\n\tbody: string,\n\terrorBody: PiMessagesErrorBody | undefined,\n): string {\n\tconst message = typeof errorBody?.error?.message === \"string\" ? errorBody.error.message : undefined;\n\tconst code = typeof errorBody?.error?.code === \"string\" ? errorBody.error.code : undefined;\n\tconst suffix = message ?? body;\n\tconst codeSuffix = code ? ` (${code})` : \"\";\n\treturn `${response.status} ${response.statusText}: ${suffix}${codeSuffix}`;\n}\n\nfunction createPiMessagesResponseError(\n\tmodel: Model<\"pi-messages\">,\n\turl: URL,\n\tresponse: Response,\n\tbody: string,\n): PiMessagesResponseError {\n\tconst errorBody = parsePiMessagesErrorBody(body);\n\tconst code = typeof errorBody?.error?.code === \"string\" ? errorBody.error.code : undefined;\n\treturn new PiMessagesResponseError(formatPiMessagesResponseError(response, body, errorBody), code, {\n\t\tversion: 1,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\turl: url.toString(),\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\terror: errorBody?.error,\n\t\tbody: errorBody ? undefined : truncateDiagnosticString(body),\n\t\ttimestampMs: Date.now(),\n\t});\n}\n\nfunction createEmptyUsage(): PiMessagesUsage {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\ttotalTokens: 0,\n\t\tmeasurement: \"unknown\",\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t};\n}\n\nfunction appendRewriteDiagnostic(message: AssistantMessage, rewrite: PiMessagesRewriteImpact | undefined): void {\n\tif (!rewrite) {\n\t\treturn;\n\t}\n\tappendAssistantMessageDiagnostic(message, {\n\t\ttype: \"pi_messages_rewrite\",\n\t\ttimestamp: Date.now(),\n\t\tdetails: { ...rewrite },\n\t});\n}\n\nfunction createEventConverter(model: Model<\"pi-messages\">) {\n\tconst partial: AssistantMessage = {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n\tconst toolJson = new Map<number, string>();\n\n\treturn (event: PiMessagesEvent): AssistantMessageEvent => {\n\t\tswitch (event.type) {\n\t\t\tcase \"done\":\n\t\t\t\tObject.assign(partial, {\n\t\t\t\t\tstopReason: event.reason,\n\t\t\t\t\tusage: { ...event.usage, measurement: event.usage.measurement ?? \"reported\" },\n\t\t\t\t\tresponseId: event.responseId,\n\t\t\t\t});\n\t\t\t\tappendRewriteDiagnostic(partial, event.rewrite);\n\t\t\t\treturn { type: \"done\", reason: event.reason, message: partial };\n\t\t\tcase \"error\":\n\t\t\t\tObject.assign(partial, {\n\t\t\t\t\tstopReason: event.reason,\n\t\t\t\t\tusage: { ...event.usage, measurement: event.usage.measurement ?? \"reported\" },\n\t\t\t\t\terrorMessage: event.errorMessage,\n\t\t\t\t\tresponseId: event.responseId,\n\t\t\t\t});\n\t\t\t\tappendRewriteDiagnostic(partial, event.rewrite);\n\t\t\t\treturn { type: \"error\", reason: event.reason, error: partial };\n\t\t\tcase \"start\":\n\t\t\t\tbreak;\n\t\t\tcase \"text_start\":\n\t\t\t\tpartial.content[event.contentIndex] = { type: \"text\", text: \"\" };\n\t\t\t\tbreak;\n\t\t\tcase \"text_delta\":\n\t\t\t\t(partial.content[event.contentIndex] as { text: string }).text += event.delta;\n\t\t\t\tbreak;\n\t\t\tcase \"text_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, {\n\t\t\t\t\ttext: event.content,\n\t\t\t\t\ttextSignature: event.contentSignature,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_start\":\n\t\t\t\tpartial.content[event.contentIndex] = { type: \"thinking\", thinking: \"\" };\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_delta\":\n\t\t\t\t(partial.content[event.contentIndex] as { thinking: string }).thinking += event.delta;\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, {\n\t\t\t\t\tthinking: event.content,\n\t\t\t\t\tthinkingSignature: event.contentSignature,\n\t\t\t\t\tredacted: event.redacted,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"toolcall_start\":\n\t\t\t\tpartial.content[event.contentIndex] = {\n\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\tid: event.id,\n\t\t\t\t\tname: event.toolName,\n\t\t\t\t\targuments: {},\n\t\t\t\t};\n\t\t\t\ttoolJson.set(event.contentIndex, \"\");\n\t\t\t\tbreak;\n\t\t\tcase \"toolcall_delta\": {\n\t\t\t\tconst json = `${toolJson.get(event.contentIndex) ?? \"\"}${event.delta}`;\n\t\t\t\ttoolJson.set(event.contentIndex, json);\n\t\t\t\t(partial.content[event.contentIndex] as ToolCall).arguments =\n\t\t\t\t\tparseStreamingJson<ToolCall[\"arguments\"]>(json);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"toolcall_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, event.toolCall);\n\t\t\t\ttoolJson.delete(event.contentIndex);\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"toolcall_end\",\n\t\t\t\t\tcontentIndex: event.contentIndex,\n\t\t\t\t\ttoolCall: partial.content[event.contentIndex] as ToolCall,\n\t\t\t\t\tpartial,\n\t\t\t\t};\n\t\t}\n\n\t\treturn { ...event, partial } as AssistantMessageEvent;\n\t};\n}\n\nasync function* readPiMessagesEvents(stream: ReadableStream<Uint8Array>): AsyncGenerator<PiMessagesEvent> {\n\tconst decoder = new TextDecoder();\n\tconst reader = stream.getReader();\n\tlet buffer = \"\";\n\n\ttry {\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tbuffer += done ? decoder.decode() : decoder.decode(value, { stream: true });\n\t\t\tbuffer = buffer.replace(/\\r\\n/g, \"\\n\");\n\n\t\t\tlet split = buffer.indexOf(\"\\n\\n\");\n\t\t\twhile (split !== -1) {\n\t\t\t\tconst event = parsePiMessagesEvent(buffer.slice(0, split));\n\t\t\t\tif (event) {\n\t\t\t\t\tyield event;\n\t\t\t\t}\n\t\t\t\tbuffer = buffer.slice(split + 2);\n\t\t\t\tsplit = buffer.indexOf(\"\\n\\n\");\n\t\t\t}\n\n\t\t\tif (done) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (buffer.trim()) {\n\t\t\tconst event = parsePiMessagesEvent(buffer);\n\t\t\tif (event) {\n\t\t\t\tyield event;\n\t\t\t}\n\t\t}\n\t} finally {\n\t\treader.releaseLock();\n\t}\n}\n\nfunction parsePiMessagesEvent(raw: string): PiMessagesEvent | undefined {\n\tconst data = raw\n\t\t.split(\"\\n\")\n\t\t.find((line) => line.startsWith(\"data:\"))\n\t\t?.slice(5)\n\t\t.trim();\n\n\treturn data && data !== \"[DONE]\" ? (JSON.parse(data) as PiMessagesEvent) : undefined;\n}\n\nfunction createErrorEvent(model: Model<\"pi-messages\">, error: unknown, aborted: boolean): AssistantMessageEvent {\n\tconst reason = aborted ? \"aborted\" : \"error\";\n\tconst assistantMessage: AssistantMessage = {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: reason,\n\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\ttimestamp: Date.now(),\n\t};\n\n\tif (!aborted && error instanceof PiMessagesResponseError) {\n\t\tappendAssistantMessageDiagnostic(\n\t\t\tassistantMessage,\n\t\t\tcreateAssistantMessageDiagnostic(\"pi_messages_response_failure\", error, error.diagnosticDetails),\n\t\t);\n\t}\n\n\treturn { type: \"error\", reason, error: assistantMessage };\n}\n\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention | undefined {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\t// Backend defaults apply when unset; only the legacy env opt-in is mapped.\n\treturn getProviderEnvValue(\"PI_CACHE_RETENTION\", env) === \"long\" ? \"long\" : undefined;\n}\n\nexport const stream: StreamFunction<\"pi-messages\", PiMessagesOptions> = (\n\tmodel: Model<\"pi-messages\">,\n\tcontext: Context,\n\toptions?: PiMessagesOptions,\n): AssistantMessageEventStream => {\n\tconst eventStream = new AssistantMessageEventStream();\n\tconst convertEvent = createEventConverter(model);\n\tlet latestMessage: AssistantMessage | undefined;\n\n\tvoid (async () => {\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey;\n\t\t\tif (!apiKey) {\n\t\t\t\tthrow new Error(`No API key provided for provider \"${model.provider}\"`);\n\t\t\t}\n\n\t\t\tconst url = new URL(`${model.baseUrl.replace(/\\/+$/u, \"\")}/messages`);\n\t\t\tif (options?.debug) {\n\t\t\t\turl.searchParams.set(\"debug\", \"1\");\n\t\t\t}\n\n\t\t\tlet payload: unknown = {\n\t\t\t\tmodel: model.id,\n\t\t\t\tcontext,\n\t\t\t\toptions: {\n\t\t\t\t\ttemperature: options?.temperature,\n\t\t\t\t\tmaxTokens: options?.maxTokens,\n\t\t\t\t\treasoning: options?.reasoning,\n\t\t\t\t\tcacheRetention: resolveCacheRetention(options?.cacheRetention, options?.env),\n\t\t\t\t\tsessionId: options?.sessionId,\n\t\t\t\t\ttoolChoice: options?.toolChoice,\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst nextPayload = await options?.onPayload?.(payload, model);\n\t\t\tif (nextPayload !== undefined) {\n\t\t\t\tpayload = nextPayload;\n\t\t\t}\n\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tauthorization: `Bearer ${apiKey}`,\n\t\t\t\t\taccept: \"text/event-stream\",\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\t...providerHeadersToRecord(options?.headers),\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\tsignal: options?.signal,\n\t\t\t});\n\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst body = await response.text();\n\t\t\t\tthrow createPiMessagesResponseError(model, url, response, body);\n\t\t\t}\n\t\t\tif (!response.body) {\n\t\t\t\tthrow new Error(`${model.provider} response has no body`);\n\t\t\t}\n\n\t\t\tfor await (const piEvent of readPiMessagesEvents(response.body)) {\n\t\t\t\tconst event = convertEvent(piEvent);\n\t\t\t\tlatestMessage =\n\t\t\t\t\t\"partial\" in event\n\t\t\t\t\t\t? event.partial\n\t\t\t\t\t\t: event.type === \"done\"\n\t\t\t\t\t\t\t? event.message\n\t\t\t\t\t\t\t: event.type === \"error\"\n\t\t\t\t\t\t\t\t? event.error\n\t\t\t\t\t\t\t\t: latestMessage;\n\t\t\t\teventStream.push(event);\n\t\t\t\tif (event.type === \"done\" || event.type === \"error\") {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow new Error(`${model.provider} stream ended without a terminal event`);\n\t\t} catch (error) {\n\t\t\tconst event = createErrorEvent(model, error, options?.signal?.aborted ?? false);\n\t\t\tif (event.type === \"error\" && latestMessage) {\n\t\t\t\tevent.error.content = latestMessage.content;\n\t\t\t\tevent.error.usage = latestMessage.usage;\n\t\t\t\tevent.error.responseId = latestMessage.responseId;\n\t\t\t}\n\t\t\teventStream.push(event);\n\t\t}\n\t})();\n\n\treturn eventStream;\n};\n\nexport const streamSimple: StreamFunction<\"pi-messages\", SimpleStreamOptions> = (\n\tmodel: Model<\"pi-messages\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tconst extra = options as PiMessagesOptions | undefined;\n\treturn stream(model, context, {\n\t\t...options,\n\t\treasoning: options?.reasoning,\n\t\ttoolChoice: extra?.toolChoice,\n\t\tdebug: extra?.debug,\n\t});\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/auth/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAExD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAgBlF;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,CAAA;CAAE,GAAG,SAAS,CAajH","sourcesContent":["import type { ApiKeyAuth, OAuthAuth } from \"./types.ts\";\n\n/**\n * Standard api-key auth: a stored credential key wins, otherwise the first\n * set env var resolves. Includes a `login` that prompts for the key.\n * Providers with non-standard resolution (provider env, ambient files, IAM)\n * write their own `ApiKeyAuth`.\n */\nexport function envApiKeyAuth(name: string, envVars: readonly string[]): ApiKeyAuth {\n\treturn {\n\t\tname,\n\t\tlogin: async (interaction) => {\n\t\t\tconst key = await interaction.prompt({ type: \"secret\", message: `Enter ${name}` });\n\t\t\treturn { type: \"api_key\", key };\n\t\t},\n\t\tresolve: async ({ ctx, credential }) => {\n\t\t\tif (credential?.key) return { auth: { apiKey: credential.key }, source: \"stored credential\" };\n\t\t\tfor (const envVar of envVars) {\n\t\t\t\tconst value = await ctx.env(envVar);\n\t\t\t\tif (value) return { auth: { apiKey: value }, source: envVar };\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\t};\n}\n\n/**\n * Wraps a dynamically imported `OAuthAuth` so provider definitions can\n * advertise OAuth without importing the implementation. The flow loads on\n * first `login`/`refresh`/`toAuth` call; callers keep Node-only flow code out\n * of bundles by loading through a bundler-opaque dynamic import (variable\n * specifier, see the bedrock lazy wrapper).\n */\nexport function lazyOAuth(input: { name: string; loginLabel?: string; load: () => Promise<OAuthAuth> }): OAuthAuth {\n\tlet promise: Promise<OAuthAuth> | undefined;\n\tconst loaded = () => {\n\t\tpromise ??= input.load();\n\t\treturn promise;\n\t};\n\treturn {\n\t\tname: input.name,\n\t\tloginLabel: input.loginLabel,\n\t\tlogin: async (interaction) => (await loaded()).login(interaction),\n\t\trefresh: async (credential, signal) => (await loaded()).refresh(credential, signal),\n\t\ttoAuth: async (credential) => (await loaded()).toAuth(credential),\n\t};\n}\n"]}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/auth/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAExD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAiBlF;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,CAAA;CAAE,GAAG,SAAS,CAajH","sourcesContent":["import type { ApiKeyAuth, OAuthAuth } from \"./types.ts\";\n\n/**\n * Standard api-key auth: a stored credential key wins, otherwise the first\n * set env var resolves. Includes a `login` that prompts for the key.\n * Providers with non-standard resolution (provider env, ambient files, IAM)\n * write their own `ApiKeyAuth`.\n */\nexport function envApiKeyAuth(name: string, envVars: readonly string[]): ApiKeyAuth {\n\treturn {\n\t\tname,\n\t\tlogin: async (interaction) => {\n\t\t\tconst key = await interaction.prompt({ type: \"secret\", message: `Enter ${name}` });\n\t\t\treturn { type: \"api_key\", key };\n\t\t},\n\t\tresolve: async ({ ctx, credential }) => {\n\t\t\tif (credential?.key)\n\t\t\t\treturn { auth: { apiKey: credential.key }, env: credential.env, source: \"stored credential\" };\n\t\t\tfor (const envVar of envVars) {\n\t\t\t\tconst value = await ctx.env(envVar);\n\t\t\t\tif (value) return { auth: { apiKey: value }, env: credential?.env, source: envVar };\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\t};\n}\n\n/**\n * Wraps a dynamically imported `OAuthAuth` so provider definitions can\n * advertise OAuth without importing the implementation. The flow loads on\n * first `login`/`refresh`/`toAuth` call; callers keep Node-only flow code out\n * of bundles by loading through a bundler-opaque dynamic import (variable\n * specifier, see the bedrock lazy wrapper).\n */\nexport function lazyOAuth(input: { name: string; loginLabel?: string; load: () => Promise<OAuthAuth> }): OAuthAuth {\n\tlet promise: Promise<OAuthAuth> | undefined;\n\tconst loaded = () => {\n\t\tpromise ??= input.load();\n\t\treturn promise;\n\t};\n\treturn {\n\t\tname: input.name,\n\t\tloginLabel: input.loginLabel,\n\t\tlogin: async (interaction) => (await loaded()).login(interaction),\n\t\trefresh: async (credential, signal) => (await loaded()).refresh(credential, signal),\n\t\ttoAuth: async (credential) => (await loaded()).toAuth(credential),\n\t};\n}\n"]}
@@ -13,11 +13,11 @@ export function envApiKeyAuth(name, envVars) {
13
13
  },
14
14
  resolve: async ({ ctx, credential }) => {
15
15
  if (credential?.key)
16
- return { auth: { apiKey: credential.key }, source: "stored credential" };
16
+ return { auth: { apiKey: credential.key }, env: credential.env, source: "stored credential" };
17
17
  for (const envVar of envVars) {
18
18
  const value = await ctx.env(envVar);
19
19
  if (value)
20
- return { auth: { apiKey: value }, source: envVar };
20
+ return { auth: { apiKey: value }, env: credential?.env, source: envVar };
21
21
  }
22
22
  return undefined;
23
23
  },
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/auth/helpers.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,OAA0B,EAAc;IACnF,OAAO;QACN,IAAI;QACJ,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,IAAI,EAAE,EAAE,CAAC,CAAC;YACnF,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;QAAA,CAChC;QACD,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;YACvC,IAAI,UAAU,EAAE,GAAG;gBAAE,OAAO,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;YAC9F,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC9B,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACpC,IAAI,KAAK;oBAAE,OAAO,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;YAC/D,CAAC;YACD,OAAO,SAAS,CAAC;QAAA,CACjB;KACD,CAAC;AAAA,CACF;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,KAA4E,EAAa;IAClH,IAAI,OAAuC,CAAC;IAC5C,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC;QACpB,OAAO,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC;IAAA,CACf,CAAC;IACF,OAAO;QACN,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC;QACjE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC;QACnF,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;KACjE,CAAC;AAAA,CACF","sourcesContent":["import type { ApiKeyAuth, OAuthAuth } from \"./types.ts\";\n\n/**\n * Standard api-key auth: a stored credential key wins, otherwise the first\n * set env var resolves. Includes a `login` that prompts for the key.\n * Providers with non-standard resolution (provider env, ambient files, IAM)\n * write their own `ApiKeyAuth`.\n */\nexport function envApiKeyAuth(name: string, envVars: readonly string[]): ApiKeyAuth {\n\treturn {\n\t\tname,\n\t\tlogin: async (interaction) => {\n\t\t\tconst key = await interaction.prompt({ type: \"secret\", message: `Enter ${name}` });\n\t\t\treturn { type: \"api_key\", key };\n\t\t},\n\t\tresolve: async ({ ctx, credential }) => {\n\t\t\tif (credential?.key) return { auth: { apiKey: credential.key }, source: \"stored credential\" };\n\t\t\tfor (const envVar of envVars) {\n\t\t\t\tconst value = await ctx.env(envVar);\n\t\t\t\tif (value) return { auth: { apiKey: value }, source: envVar };\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\t};\n}\n\n/**\n * Wraps a dynamically imported `OAuthAuth` so provider definitions can\n * advertise OAuth without importing the implementation. The flow loads on\n * first `login`/`refresh`/`toAuth` call; callers keep Node-only flow code out\n * of bundles by loading through a bundler-opaque dynamic import (variable\n * specifier, see the bedrock lazy wrapper).\n */\nexport function lazyOAuth(input: { name: string; loginLabel?: string; load: () => Promise<OAuthAuth> }): OAuthAuth {\n\tlet promise: Promise<OAuthAuth> | undefined;\n\tconst loaded = () => {\n\t\tpromise ??= input.load();\n\t\treturn promise;\n\t};\n\treturn {\n\t\tname: input.name,\n\t\tloginLabel: input.loginLabel,\n\t\tlogin: async (interaction) => (await loaded()).login(interaction),\n\t\trefresh: async (credential, signal) => (await loaded()).refresh(credential, signal),\n\t\ttoAuth: async (credential) => (await loaded()).toAuth(credential),\n\t};\n}\n"]}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/auth/helpers.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,OAA0B,EAAc;IACnF,OAAO;QACN,IAAI;QACJ,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,IAAI,EAAE,EAAE,CAAC,CAAC;YACnF,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;QAAA,CAChC;QACD,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;YACvC,IAAI,UAAU,EAAE,GAAG;gBAClB,OAAO,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;YAC/F,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC9B,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACpC,IAAI,KAAK;oBAAE,OAAO,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;YACrF,CAAC;YACD,OAAO,SAAS,CAAC;QAAA,CACjB;KACD,CAAC;AAAA,CACF;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,KAA4E,EAAa;IAClH,IAAI,OAAuC,CAAC;IAC5C,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC;QACpB,OAAO,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC;IAAA,CACf,CAAC;IACF,OAAO;QACN,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC;QACjE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC;QACnF,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;KACjE,CAAC;AAAA,CACF","sourcesContent":["import type { ApiKeyAuth, OAuthAuth } from \"./types.ts\";\n\n/**\n * Standard api-key auth: a stored credential key wins, otherwise the first\n * set env var resolves. Includes a `login` that prompts for the key.\n * Providers with non-standard resolution (provider env, ambient files, IAM)\n * write their own `ApiKeyAuth`.\n */\nexport function envApiKeyAuth(name: string, envVars: readonly string[]): ApiKeyAuth {\n\treturn {\n\t\tname,\n\t\tlogin: async (interaction) => {\n\t\t\tconst key = await interaction.prompt({ type: \"secret\", message: `Enter ${name}` });\n\t\t\treturn { type: \"api_key\", key };\n\t\t},\n\t\tresolve: async ({ ctx, credential }) => {\n\t\t\tif (credential?.key)\n\t\t\t\treturn { auth: { apiKey: credential.key }, env: credential.env, source: \"stored credential\" };\n\t\t\tfor (const envVar of envVars) {\n\t\t\t\tconst value = await ctx.env(envVar);\n\t\t\t\tif (value) return { auth: { apiKey: value }, env: credential?.env, source: envVar };\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\t};\n}\n\n/**\n * Wraps a dynamically imported `OAuthAuth` so provider definitions can\n * advertise OAuth without importing the implementation. The flow loads on\n * first `login`/`refresh`/`toAuth` call; callers keep Node-only flow code out\n * of bundles by loading through a bundler-opaque dynamic import (variable\n * specifier, see the bedrock lazy wrapper).\n */\nexport function lazyOAuth(input: { name: string; loginLabel?: string; load: () => Promise<OAuthAuth> }): OAuthAuth {\n\tlet promise: Promise<OAuthAuth> | undefined;\n\tconst loaded = () => {\n\t\tpromise ??= input.load();\n\t\treturn promise;\n\t};\n\treturn {\n\t\tname: input.name,\n\t\tloginLabel: input.loginLabel,\n\t\tlogin: async (interaction) => (await loaded()).login(interaction),\n\t\trefresh: async (credential, signal) => (await loaded()).refresh(credential, signal),\n\t\ttoAuth: async (credential) => (await loaded()).toAuth(credential),\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/auth/oauth/anthropic.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAiD,SAAS,EAAE,MAAM,aAAa,CAAC;AAO5F,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnE;AA2OD,eAAO,MAAM,cAAc,EAAE,SAU5B,CAAC","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { access, constants } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { delimiter, isAbsolute, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { claudeCodeEnvironment, stopNative } from \"../../api/anthropic-claude-code-bridge.ts\";\nimport type { AuthInteraction, ExternalClaudeCodeCredential, OAuthAuth } from \"../types.ts\";\n\nconst SETUP_WORKER = fileURLToPath(\n\tnew URL(\"../../../vendor/hermes-claude-subscription-directsdk/lunr_setup_bridge.py\", import.meta.url),\n);\nconst VERSION = \"2.1.263\";\n\nexport function isQualifiedClaudeCodeVersion(value: string): boolean {\n\treturn new RegExp(`^${VERSION.replaceAll(\".\", \"\\\\.\")}(?:\\\\s|$)`).test(value);\n}\n\nasync function run(command: string, args: string[], input?: string, timeout = 25_000): Promise<string> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst child = spawn(command, args, {\n\t\t\tstdio: [\"pipe\", \"pipe\", \"ignore\"],\n\t\t\twindowsHide: true,\n\t\t\tdetached: process.platform !== \"win32\",\n\t\t\tenv: claudeCodeEnvironment(undefined, false),\n\t\t});\n\t\tlet output = \"\";\n\t\tlet timedOut = false;\n\t\tconst timer = setTimeout(() => {\n\t\t\ttimedOut = true;\n\t\t\tvoid stopNative(child.pid ?? 0).finally(() => {\n\t\t\t\tchild.kill();\n\t\t\t\tchild.stdout.destroy();\n\t\t\t\tchild.stdin.destroy();\n\t\t\t\treject(new Error(\"Dependency check timed out\"));\n\t\t\t});\n\t\t}, timeout);\n\t\tchild.stdout.on(\"data\", (chunk: Buffer) => {\n\t\t\toutput += chunk.toString(\"utf8\");\n\t\t\tif (output.length > 64 * 1024) child.kill();\n\t\t});\n\t\tchild.stdin.on(\"error\", () => {});\n\t\tchild.on(\"error\", reject);\n\t\tchild.on(\"close\", (code) => {\n\t\t\tclearTimeout(timer);\n\t\t\tif (timedOut) return;\n\t\t\tif (code !== 0) reject(new Error(\"Dependency check failed\"));\n\t\t\telse resolve(output.trim());\n\t\t});\n\t\tchild.stdin.end(input);\n\t});\n}\n\nasync function executable(name: string): Promise<string | undefined> {\n\tconst suffixes = process.platform === \"win32\" ? [\"\", \".exe\", \".cmd\", \".bat\"] : [\"\"];\n\tconst directories = isAbsolute(name)\n\t\t? [\"\"]\n\t\t: [...(process.env.PATH ?? \"\").split(delimiter), join(homedir(), \".local\", \"bin\")];\n\tfor (const directory of directories) {\n\t\tfor (const suffix of suffixes) {\n\t\t\tconst candidate = directory ? join(directory, `${name}${suffix}`) : `${name}${suffix}`;\n\t\t\ttry {\n\t\t\t\tawait access(candidate, constants.X_OK);\n\t\t\t\treturn candidate;\n\t\t\t} catch {\n\t\t\t\t/* Next location. */\n\t\t\t}\n\t\t}\n\t}\n\treturn undefined;\n}\n\nasync function pythonInterpreter(): Promise<string | undefined> {\n\tfor (const name of [\"python3\", \"python\"]) {\n\t\tconst path = await executable(name);\n\t\tif (!path) continue;\n\t\ttry {\n\t\t\tconst version = await run(path, [\"--version\"]);\n\t\t\tconst match = /^Python (\\d+)\\.(\\d+)/.exec(version);\n\t\t\tif (match && (Number(match[1]) > 3 || (Number(match[1]) === 3 && Number(match[2]) >= 10))) return path;\n\t\t} catch {\n\t\t\t/* Try another interpreter. */\n\t\t}\n\t}\n\treturn undefined;\n}\n\nasync function install(command: string, args: string[], interaction: AuthInteraction): Promise<void> {\n\tconst confirm = await interaction.prompt({\n\t\ttype: \"select\",\n\t\tmessage: `Run ${command} ${args.join(\" \")}? This downloads software and changes your user-level system installation.`,\n\t\toptions: [\n\t\t\t{ id: \"yes\", label: \"Install\" },\n\t\t\t{ id: \"no\", label: \"Cancel\" },\n\t\t],\n\t});\n\tif (confirm !== \"yes\") throw new Error(\"Anthropic subscription setup cancelled\");\n\tinteraction.notify({ type: \"progress\", message: \"Running the confirmed installer...\" });\n\tawait run(command, args, undefined, 300_000);\n}\n\nasync function setupProbe(python: string, command: string, type: \"status\" | \"discover\" | \"version\"): Promise<unknown> {\n\tconst requestId = randomUUID();\n\tconst line = await run(\n\t\tpython,\n\t\t[\"-s\", \"-B\", \"-u\", SETUP_WORKER],\n\t\t`${JSON.stringify({ v: 1, requestId, type, command, env: claudeCodeEnvironment(undefined, false) })}\\n`,\n\t\t55_000,\n\t);\n\tconst record: unknown = JSON.parse(line);\n\tif (\n\t\t!record ||\n\t\ttypeof record !== \"object\" ||\n\t\t!(\"v\" in record) ||\n\t\trecord.v !== 1 ||\n\t\t!(\"requestId\" in record) ||\n\t\trecord.requestId !== requestId ||\n\t\t!(\"type\" in record) ||\n\t\trecord.type !== \"result\" ||\n\t\t!(\"result\" in record)\n\t) {\n\t\tthrow new Error(\"Invalid Claude Code setup response\");\n\t}\n\treturn record.result;\n}\n\nasync function login(interaction: AuthInteraction): Promise<ExternalClaudeCodeCredential> {\n\tinteraction.notify({\n\t\ttype: \"info\",\n\t\tmessage:\n\t\t\t\"Claude Code handles subscription authentication and one generation per lunR request. lunR still owns tools, permissions, history, compaction, and subagents. Python 3.10+ and Claude Code are required. No credentials are copied into lunR.\",\n\t});\n\tlet python = await pythonInterpreter();\n\tif (!python) {\n\t\tinteraction.notify({\n\t\t\ttype: \"info\",\n\t\t\tmessage:\n\t\t\t\t\"Install Python 3.10+ from https://www.python.org/downloads/ . This is a separate operating-system installation, not part of lunR.\",\n\t\t});\n\t\tconst packageManager =\n\t\t\tprocess.platform === \"darwin\"\n\t\t\t\t? await executable(\"brew\")\n\t\t\t\t: process.platform === \"linux\"\n\t\t\t\t\t? ((await executable(\"apt-get\")) ?? (await executable(\"dnf\")))\n\t\t\t\t\t: undefined;\n\t\tconst installer =\n\t\t\tprocess.platform === \"win32\"\n\t\t\t\t? { command: \"winget\", args: [\"install\", \"--id\", \"Python.Python.3.13\", \"-e\"] }\n\t\t\t\t: packageManager?.endsWith(\"apt-get\")\n\t\t\t\t\t? { command: \"sudo\", args: [packageManager, \"install\", \"-y\", \"python3\"] }\n\t\t\t\t\t: packageManager?.endsWith(\"dnf\")\n\t\t\t\t\t\t? { command: \"sudo\", args: [packageManager, \"install\", \"-y\", \"python3\"] }\n\t\t\t\t\t\t: packageManager\n\t\t\t\t\t\t\t? { command: packageManager, args: [\"install\", \"python@3.13\"] }\n\t\t\t\t\t\t\t: undefined;\n\t\tconst choice = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage:\n\t\t\t\t\"Python 3.10+ is missing. A system installer may request administrator access and change your machine.\",\n\t\t\toptions: [\n\t\t\t\t...(installer\n\t\t\t\t\t? [{ id: \"install\", label: `Install through ${installer.command} ${installer.args.join(\" \")}` }]\n\t\t\t\t\t: []),\n\t\t\t\t{ id: \"cancel\", label: \"Cancel and install Python yourself\" },\n\t\t\t],\n\t\t});\n\t\tif (choice === \"install\" && installer) await install(installer.command, installer.args, interaction);\n\t\telse throw new Error(\"Install Python 3.10+ and retry /login anthropic\");\n\t\tpython = await pythonInterpreter();\n\t\tif (!python)\n\t\t\tthrow new Error(\"Python installation finished but the interpreter is not on PATH. Restart lunR and retry.\");\n\t}\n\tlet command = await executable(\"claude\");\n\tif (!command) {\n\t\tconst choice = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage: \"Claude Code is missing. Installation changes your user-level system and may require a new PATH.\",\n\t\t\toptions: [\n\t\t\t\t{ id: \"install\", label: \"Install Claude Code\" },\n\t\t\t\t{ id: \"existing\", label: \"Use existing executable\" },\n\t\t\t\t{ id: \"cancel\", label: \"Cancel\" },\n\t\t\t],\n\t\t});\n\t\tif (choice === \"install\") {\n\t\t\tif (process.platform === \"win32\")\n\t\t\t\tawait install(\n\t\t\t\t\t\"powershell\",\n\t\t\t\t\t[\"-NoProfile\", \"-Command\", \"irm https://claude.ai/install.ps1 | iex\"],\n\t\t\t\t\tinteraction,\n\t\t\t\t);\n\t\t\telse await install(\"sh\", [\"-c\", \"curl -fsSL https://claude.ai/install.sh | bash\"], interaction);\n\t\t\tcommand = await executable(\"claude\");\n\t\t} else if (choice === \"existing\") {\n\t\t\tconst path = await interaction.prompt({ type: \"text\", message: \"Absolute path to Claude Code executable:\" });\n\t\t\tif (!isAbsolute(path)) throw new Error(\"Claude Code path must be absolute\");\n\t\t\tcommand = await executable(path);\n\t\t} else throw new Error(\"Anthropic subscription setup cancelled\");\n\t}\n\tif (!command) throw new Error(\"Claude Code executable not found. Restart lunR after installation and retry.\");\n\tconst version = (await setupProbe(python, command, \"version\")) as string;\n\tif (!isQualifiedClaudeCodeVersion(version))\n\t\tthrow new Error(\n\t\t\t`Claude Code ${VERSION} is the only qualified version. Found ${version.slice(0, 40)}. Subscription requests are disabled until this version is qualified.`,\n\t\t);\n\tlet status = (await setupProbe(python, command, \"status\")) as {\n\t\tlogged_in?: boolean;\n\t\tplan?: string;\n\t\taccountFingerprint?: string;\n\t};\n\tif (!status.logged_in || !/Claude (Pro|Max|Team|Enterprise)/i.test(status.plan ?? \"\")) {\n\t\tif (!interaction.handoff)\n\t\t\tthrow new Error(\n\t\t\t\t`Run \"${command}\" auth login in a terminal, select a Claude subscription, then retry /login anthropic`,\n\t\t\t);\n\t\tconst choice = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage: \"Claude Code needs a subscription login. Hand the terminal to Claude Code now?\",\n\t\t\toptions: [\n\t\t\t\t{ id: \"login\", label: \"Run Claude Code login\" },\n\t\t\t\t{ id: \"cancel\", label: \"Cancel\" },\n\t\t\t],\n\t\t});\n\t\tif (choice !== \"login\") throw new Error(\"Anthropic subscription setup cancelled\");\n\t\tawait interaction.handoff(\n\t\t\tpython,\n\t\t\t[\"-s\", \"-B\", \"-u\", SETUP_WORKER, \"auth-login\", command],\n\t\t\tclaudeCodeEnvironment(undefined, false),\n\t\t);\n\t\tstatus = (await setupProbe(python, command, \"status\")) as typeof status;\n\t\tif (!status.logged_in || !/Claude (Pro|Max|Team|Enterprise)/i.test(status.plan ?? \"\"))\n\t\t\tthrow new Error(\"Claude Code is not signed into a Claude subscription\");\n\t}\n\tconst discovered = await setupProbe(python, command, \"discover\");\n\tif (\n\t\t!Array.isArray(discovered) ||\n\t\t!discovered.length ||\n\t\tdiscovered.some((row) => !row || typeof row.id !== \"string\" || row.upstream_requests !== 0)\n\t) {\n\t\tthrow new Error(\"Claude Code model discovery did not verify zero Messages requests. Setup not saved.\");\n\t}\n\treturn {\n\t\ttype: \"external_claude_code\",\n\t\tversion: 1,\n\t\tmanager: \"claude-code\",\n\t\tcommand,\n\t\tpython,\n\t\taccountFingerprint: status.accountFingerprint ?? randomUUID(),\n\t\troutes: discovered.map((row) => row.id),\n\t};\n}\n\nexport const anthropicOAuth: OAuthAuth = {\n\tname: \"Anthropic subscription through Claude Code\",\n\tloginLabel: \"Connect Claude Pro/Max through Claude Code\",\n\tlogin,\n\trefresh: async () => {\n\t\tthrow new Error(\"Legacy Anthropic OAuth tokens are unsupported. Run /login anthropic.\");\n\t},\n\ttoAuth: async () => {\n\t\tthrow new Error(\"Legacy Anthropic OAuth tokens are unsupported. Run /login anthropic.\");\n\t},\n};\n"]}
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/auth/oauth/anthropic.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAiD,SAAS,EAAE,MAAM,aAAa,CAAC;AAI5F,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnE;AA2OD,eAAO,MAAM,cAAc,EAAE,SAU5B,CAAC","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { access, constants } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { delimiter, isAbsolute, join } from \"node:path\";\nimport { claudeCodeEnvironment, stopNative } from \"../../api/anthropic-claude-code-bridge.ts\";\nimport { getClaudeCodeWorkerPath } from \"../../utils/claude-code-assets.ts\";\nimport type { AuthInteraction, ExternalClaudeCodeCredential, OAuthAuth } from \"../types.ts\";\n\nconst VERSION = \"2.1.263\";\n\nexport function isQualifiedClaudeCodeVersion(value: string): boolean {\n\treturn new RegExp(`^${VERSION.replaceAll(\".\", \"\\\\.\")}(?:\\\\s|$)`).test(value);\n}\n\nasync function run(command: string, args: string[], input?: string, timeout = 25_000): Promise<string> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst child = spawn(command, args, {\n\t\t\tstdio: [\"pipe\", \"pipe\", \"ignore\"],\n\t\t\twindowsHide: true,\n\t\t\tdetached: process.platform !== \"win32\",\n\t\t\tenv: claudeCodeEnvironment(undefined, false),\n\t\t});\n\t\tlet output = \"\";\n\t\tlet timedOut = false;\n\t\tconst timer = setTimeout(() => {\n\t\t\ttimedOut = true;\n\t\t\tvoid stopNative(child.pid ?? 0).finally(() => {\n\t\t\t\tchild.kill();\n\t\t\t\tchild.stdout.destroy();\n\t\t\t\tchild.stdin.destroy();\n\t\t\t\treject(new Error(\"Dependency check timed out\"));\n\t\t\t});\n\t\t}, timeout);\n\t\tchild.stdout.on(\"data\", (chunk: Buffer) => {\n\t\t\toutput += chunk.toString(\"utf8\");\n\t\t\tif (output.length > 64 * 1024) child.kill();\n\t\t});\n\t\tchild.stdin.on(\"error\", () => {});\n\t\tchild.on(\"error\", reject);\n\t\tchild.on(\"close\", (code) => {\n\t\t\tclearTimeout(timer);\n\t\t\tif (timedOut) return;\n\t\t\tif (code !== 0) reject(new Error(\"Dependency check failed\"));\n\t\t\telse resolve(output.trim());\n\t\t});\n\t\tchild.stdin.end(input);\n\t});\n}\n\nasync function executable(name: string): Promise<string | undefined> {\n\tconst suffixes = process.platform === \"win32\" ? [\"\", \".exe\", \".cmd\", \".bat\"] : [\"\"];\n\tconst directories = isAbsolute(name)\n\t\t? [\"\"]\n\t\t: [...(process.env.PATH ?? \"\").split(delimiter), join(homedir(), \".local\", \"bin\")];\n\tfor (const directory of directories) {\n\t\tfor (const suffix of suffixes) {\n\t\t\tconst candidate = directory ? join(directory, `${name}${suffix}`) : `${name}${suffix}`;\n\t\t\ttry {\n\t\t\t\tawait access(candidate, constants.X_OK);\n\t\t\t\treturn candidate;\n\t\t\t} catch {\n\t\t\t\t/* Next location. */\n\t\t\t}\n\t\t}\n\t}\n\treturn undefined;\n}\n\nasync function pythonInterpreter(): Promise<string | undefined> {\n\tfor (const name of [\"python3\", \"python\"]) {\n\t\tconst path = await executable(name);\n\t\tif (!path) continue;\n\t\ttry {\n\t\t\tconst version = await run(path, [\"--version\"]);\n\t\t\tconst match = /^Python (\\d+)\\.(\\d+)/.exec(version);\n\t\t\tif (match && (Number(match[1]) > 3 || (Number(match[1]) === 3 && Number(match[2]) >= 10))) return path;\n\t\t} catch {\n\t\t\t/* Try another interpreter. */\n\t\t}\n\t}\n\treturn undefined;\n}\n\nasync function install(command: string, args: string[], interaction: AuthInteraction): Promise<void> {\n\tconst confirm = await interaction.prompt({\n\t\ttype: \"select\",\n\t\tmessage: `Run ${command} ${args.join(\" \")}? This downloads software and changes your user-level system installation.`,\n\t\toptions: [\n\t\t\t{ id: \"yes\", label: \"Install\" },\n\t\t\t{ id: \"no\", label: \"Cancel\" },\n\t\t],\n\t});\n\tif (confirm !== \"yes\") throw new Error(\"Anthropic subscription setup cancelled\");\n\tinteraction.notify({ type: \"progress\", message: \"Running the confirmed installer...\" });\n\tawait run(command, args, undefined, 300_000);\n}\n\nasync function setupProbe(python: string, command: string, type: \"status\" | \"discover\" | \"version\"): Promise<unknown> {\n\tconst requestId = randomUUID();\n\tconst line = await run(\n\t\tpython,\n\t\t[\"-s\", \"-B\", \"-u\", getClaudeCodeWorkerPath(\"lunr_setup_bridge.py\")],\n\t\t`${JSON.stringify({ v: 1, requestId, type, command, env: claudeCodeEnvironment(undefined, false) })}\\n`,\n\t\t55_000,\n\t);\n\tconst record: unknown = JSON.parse(line);\n\tif (\n\t\t!record ||\n\t\ttypeof record !== \"object\" ||\n\t\t!(\"v\" in record) ||\n\t\trecord.v !== 1 ||\n\t\t!(\"requestId\" in record) ||\n\t\trecord.requestId !== requestId ||\n\t\t!(\"type\" in record) ||\n\t\trecord.type !== \"result\" ||\n\t\t!(\"result\" in record)\n\t) {\n\t\tthrow new Error(\"Invalid Claude Code setup response\");\n\t}\n\treturn record.result;\n}\n\nasync function login(interaction: AuthInteraction): Promise<ExternalClaudeCodeCredential> {\n\tinteraction.notify({\n\t\ttype: \"info\",\n\t\tmessage:\n\t\t\t\"Claude Code handles subscription authentication and one generation per lunR request. lunR still owns tools, permissions, history, compaction, and subagents. Python 3.10+ and Claude Code are required. No credentials are copied into lunR.\",\n\t});\n\tlet python = await pythonInterpreter();\n\tif (!python) {\n\t\tinteraction.notify({\n\t\t\ttype: \"info\",\n\t\t\tmessage:\n\t\t\t\t\"Install Python 3.10+ from https://www.python.org/downloads/ . This is a separate operating-system installation, not part of lunR.\",\n\t\t});\n\t\tconst packageManager =\n\t\t\tprocess.platform === \"darwin\"\n\t\t\t\t? await executable(\"brew\")\n\t\t\t\t: process.platform === \"linux\"\n\t\t\t\t\t? ((await executable(\"apt-get\")) ?? (await executable(\"dnf\")))\n\t\t\t\t\t: undefined;\n\t\tconst installer =\n\t\t\tprocess.platform === \"win32\"\n\t\t\t\t? { command: \"winget\", args: [\"install\", \"--id\", \"Python.Python.3.13\", \"-e\"] }\n\t\t\t\t: packageManager?.endsWith(\"apt-get\")\n\t\t\t\t\t? { command: \"sudo\", args: [packageManager, \"install\", \"-y\", \"python3\"] }\n\t\t\t\t\t: packageManager?.endsWith(\"dnf\")\n\t\t\t\t\t\t? { command: \"sudo\", args: [packageManager, \"install\", \"-y\", \"python3\"] }\n\t\t\t\t\t\t: packageManager\n\t\t\t\t\t\t\t? { command: packageManager, args: [\"install\", \"python@3.13\"] }\n\t\t\t\t\t\t\t: undefined;\n\t\tconst choice = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage:\n\t\t\t\t\"Python 3.10+ is missing. A system installer may request administrator access and change your machine.\",\n\t\t\toptions: [\n\t\t\t\t...(installer\n\t\t\t\t\t? [{ id: \"install\", label: `Install through ${installer.command} ${installer.args.join(\" \")}` }]\n\t\t\t\t\t: []),\n\t\t\t\t{ id: \"cancel\", label: \"Cancel and install Python yourself\" },\n\t\t\t],\n\t\t});\n\t\tif (choice === \"install\" && installer) await install(installer.command, installer.args, interaction);\n\t\telse throw new Error(\"Install Python 3.10+ and retry /login anthropic\");\n\t\tpython = await pythonInterpreter();\n\t\tif (!python)\n\t\t\tthrow new Error(\"Python installation finished but the interpreter is not on PATH. Restart lunR and retry.\");\n\t}\n\tlet command = await executable(\"claude\");\n\tif (!command) {\n\t\tconst choice = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage: \"Claude Code is missing. Installation changes your user-level system and may require a new PATH.\",\n\t\t\toptions: [\n\t\t\t\t{ id: \"install\", label: \"Install Claude Code\" },\n\t\t\t\t{ id: \"existing\", label: \"Use existing executable\" },\n\t\t\t\t{ id: \"cancel\", label: \"Cancel\" },\n\t\t\t],\n\t\t});\n\t\tif (choice === \"install\") {\n\t\t\tif (process.platform === \"win32\")\n\t\t\t\tawait install(\n\t\t\t\t\t\"powershell\",\n\t\t\t\t\t[\"-NoProfile\", \"-Command\", \"irm https://claude.ai/install.ps1 | iex\"],\n\t\t\t\t\tinteraction,\n\t\t\t\t);\n\t\t\telse await install(\"sh\", [\"-c\", \"curl -fsSL https://claude.ai/install.sh | bash\"], interaction);\n\t\t\tcommand = await executable(\"claude\");\n\t\t} else if (choice === \"existing\") {\n\t\t\tconst path = await interaction.prompt({ type: \"text\", message: \"Absolute path to Claude Code executable:\" });\n\t\t\tif (!isAbsolute(path)) throw new Error(\"Claude Code path must be absolute\");\n\t\t\tcommand = await executable(path);\n\t\t} else throw new Error(\"Anthropic subscription setup cancelled\");\n\t}\n\tif (!command) throw new Error(\"Claude Code executable not found. Restart lunR after installation and retry.\");\n\tconst version = (await setupProbe(python, command, \"version\")) as string;\n\tif (!isQualifiedClaudeCodeVersion(version))\n\t\tthrow new Error(\n\t\t\t`Claude Code ${VERSION} is the only qualified version. Found ${version.slice(0, 40)}. Subscription requests are disabled until this version is qualified.`,\n\t\t);\n\tlet status = (await setupProbe(python, command, \"status\")) as {\n\t\tlogged_in?: boolean;\n\t\tplan?: string;\n\t\taccountFingerprint?: string;\n\t};\n\tif (!status.logged_in || !/Claude (Pro|Max|Team|Enterprise)/i.test(status.plan ?? \"\")) {\n\t\tif (!interaction.handoff)\n\t\t\tthrow new Error(\n\t\t\t\t`Run \"${command}\" auth login in a terminal, select a Claude subscription, then retry /login anthropic`,\n\t\t\t);\n\t\tconst choice = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage: \"Claude Code needs a subscription login. Hand the terminal to Claude Code now?\",\n\t\t\toptions: [\n\t\t\t\t{ id: \"login\", label: \"Run Claude Code login\" },\n\t\t\t\t{ id: \"cancel\", label: \"Cancel\" },\n\t\t\t],\n\t\t});\n\t\tif (choice !== \"login\") throw new Error(\"Anthropic subscription setup cancelled\");\n\t\tawait interaction.handoff(\n\t\t\tpython,\n\t\t\t[\"-s\", \"-B\", \"-u\", getClaudeCodeWorkerPath(\"lunr_setup_bridge.py\"), \"auth-login\", command],\n\t\t\tclaudeCodeEnvironment(undefined, false),\n\t\t);\n\t\tstatus = (await setupProbe(python, command, \"status\")) as typeof status;\n\t\tif (!status.logged_in || !/Claude (Pro|Max|Team|Enterprise)/i.test(status.plan ?? \"\"))\n\t\t\tthrow new Error(\"Claude Code is not signed into a Claude subscription\");\n\t}\n\tconst discovered = await setupProbe(python, command, \"discover\");\n\tif (\n\t\t!Array.isArray(discovered) ||\n\t\t!discovered.length ||\n\t\tdiscovered.some((row) => !row || typeof row.id !== \"string\" || row.upstream_requests !== 0)\n\t) {\n\t\tthrow new Error(\"Claude Code model discovery did not verify zero Messages requests. Setup not saved.\");\n\t}\n\treturn {\n\t\ttype: \"external_claude_code\",\n\t\tversion: 1,\n\t\tmanager: \"claude-code\",\n\t\tcommand,\n\t\tpython,\n\t\taccountFingerprint: status.accountFingerprint ?? randomUUID(),\n\t\troutes: discovered.map((row) => row.id),\n\t};\n}\n\nexport const anthropicOAuth: OAuthAuth = {\n\tname: \"Anthropic subscription through Claude Code\",\n\tloginLabel: \"Connect Claude Pro/Max through Claude Code\",\n\tlogin,\n\trefresh: async () => {\n\t\tthrow new Error(\"Legacy Anthropic OAuth tokens are unsupported. Run /login anthropic.\");\n\t},\n\ttoAuth: async () => {\n\t\tthrow new Error(\"Legacy Anthropic OAuth tokens are unsupported. Run /login anthropic.\");\n\t},\n};\n"]}
@@ -3,9 +3,8 @@ import { randomUUID } from "node:crypto";
3
3
  import { access, constants } from "node:fs/promises";
4
4
  import { homedir } from "node:os";
5
5
  import { delimiter, isAbsolute, join } from "node:path";
6
- import { fileURLToPath } from "node:url";
7
6
  import { claudeCodeEnvironment, stopNative } from "../../api/anthropic-claude-code-bridge.js";
8
- const SETUP_WORKER = fileURLToPath(new URL("../../../vendor/hermes-claude-subscription-directsdk/lunr_setup_bridge.py", import.meta.url));
7
+ import { getClaudeCodeWorkerPath } from "../../utils/claude-code-assets.js";
9
8
  const VERSION = "2.1.263";
10
9
  export function isQualifiedClaudeCodeVersion(value) {
11
10
  return new RegExp(`^${VERSION.replaceAll(".", "\\.")}(?:\\s|$)`).test(value);
@@ -100,7 +99,7 @@ async function install(command, args, interaction) {
100
99
  }
101
100
  async function setupProbe(python, command, type) {
102
101
  const requestId = randomUUID();
103
- const line = await run(python, ["-s", "-B", "-u", SETUP_WORKER], `${JSON.stringify({ v: 1, requestId, type, command, env: claudeCodeEnvironment(undefined, false) })}\n`, 55_000);
102
+ const line = await run(python, ["-s", "-B", "-u", getClaudeCodeWorkerPath("lunr_setup_bridge.py")], `${JSON.stringify({ v: 1, requestId, type, command, env: claudeCodeEnvironment(undefined, false) })}\n`, 55_000);
104
103
  const record = JSON.parse(line);
105
104
  if (!record ||
106
105
  typeof record !== "object" ||
@@ -204,7 +203,7 @@ async function login(interaction) {
204
203
  });
205
204
  if (choice !== "login")
206
205
  throw new Error("Anthropic subscription setup cancelled");
207
- await interaction.handoff(python, ["-s", "-B", "-u", SETUP_WORKER, "auth-login", command], claudeCodeEnvironment(undefined, false));
206
+ await interaction.handoff(python, ["-s", "-B", "-u", getClaudeCodeWorkerPath("lunr_setup_bridge.py"), "auth-login", command], claudeCodeEnvironment(undefined, false));
208
207
  status = (await setupProbe(python, command, "status"));
209
208
  if (!status.logged_in || !/Claude (Pro|Max|Team|Enterprise)/i.test(status.plan ?? ""))
210
209
  throw new Error("Claude Code is not signed into a Claude subscription");
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/auth/oauth/anthropic.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { access, constants } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { delimiter, isAbsolute, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { claudeCodeEnvironment, stopNative } from \"../../api/anthropic-claude-code-bridge.ts\";\nimport type { AuthInteraction, ExternalClaudeCodeCredential, OAuthAuth } from \"../types.ts\";\n\nconst SETUP_WORKER = fileURLToPath(\n\tnew URL(\"../../../vendor/hermes-claude-subscription-directsdk/lunr_setup_bridge.py\", import.meta.url),\n);\nconst VERSION = \"2.1.263\";\n\nexport function isQualifiedClaudeCodeVersion(value: string): boolean {\n\treturn new RegExp(`^${VERSION.replaceAll(\".\", \"\\\\.\")}(?:\\\\s|$)`).test(value);\n}\n\nasync function run(command: string, args: string[], input?: string, timeout = 25_000): Promise<string> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst child = spawn(command, args, {\n\t\t\tstdio: [\"pipe\", \"pipe\", \"ignore\"],\n\t\t\twindowsHide: true,\n\t\t\tdetached: process.platform !== \"win32\",\n\t\t\tenv: claudeCodeEnvironment(undefined, false),\n\t\t});\n\t\tlet output = \"\";\n\t\tlet timedOut = false;\n\t\tconst timer = setTimeout(() => {\n\t\t\ttimedOut = true;\n\t\t\tvoid stopNative(child.pid ?? 0).finally(() => {\n\t\t\t\tchild.kill();\n\t\t\t\tchild.stdout.destroy();\n\t\t\t\tchild.stdin.destroy();\n\t\t\t\treject(new Error(\"Dependency check timed out\"));\n\t\t\t});\n\t\t}, timeout);\n\t\tchild.stdout.on(\"data\", (chunk: Buffer) => {\n\t\t\toutput += chunk.toString(\"utf8\");\n\t\t\tif (output.length > 64 * 1024) child.kill();\n\t\t});\n\t\tchild.stdin.on(\"error\", () => {});\n\t\tchild.on(\"error\", reject);\n\t\tchild.on(\"close\", (code) => {\n\t\t\tclearTimeout(timer);\n\t\t\tif (timedOut) return;\n\t\t\tif (code !== 0) reject(new Error(\"Dependency check failed\"));\n\t\t\telse resolve(output.trim());\n\t\t});\n\t\tchild.stdin.end(input);\n\t});\n}\n\nasync function executable(name: string): Promise<string | undefined> {\n\tconst suffixes = process.platform === \"win32\" ? [\"\", \".exe\", \".cmd\", \".bat\"] : [\"\"];\n\tconst directories = isAbsolute(name)\n\t\t? [\"\"]\n\t\t: [...(process.env.PATH ?? \"\").split(delimiter), join(homedir(), \".local\", \"bin\")];\n\tfor (const directory of directories) {\n\t\tfor (const suffix of suffixes) {\n\t\t\tconst candidate = directory ? join(directory, `${name}${suffix}`) : `${name}${suffix}`;\n\t\t\ttry {\n\t\t\t\tawait access(candidate, constants.X_OK);\n\t\t\t\treturn candidate;\n\t\t\t} catch {\n\t\t\t\t/* Next location. */\n\t\t\t}\n\t\t}\n\t}\n\treturn undefined;\n}\n\nasync function pythonInterpreter(): Promise<string | undefined> {\n\tfor (const name of [\"python3\", \"python\"]) {\n\t\tconst path = await executable(name);\n\t\tif (!path) continue;\n\t\ttry {\n\t\t\tconst version = await run(path, [\"--version\"]);\n\t\t\tconst match = /^Python (\\d+)\\.(\\d+)/.exec(version);\n\t\t\tif (match && (Number(match[1]) > 3 || (Number(match[1]) === 3 && Number(match[2]) >= 10))) return path;\n\t\t} catch {\n\t\t\t/* Try another interpreter. */\n\t\t}\n\t}\n\treturn undefined;\n}\n\nasync function install(command: string, args: string[], interaction: AuthInteraction): Promise<void> {\n\tconst confirm = await interaction.prompt({\n\t\ttype: \"select\",\n\t\tmessage: `Run ${command} ${args.join(\" \")}? This downloads software and changes your user-level system installation.`,\n\t\toptions: [\n\t\t\t{ id: \"yes\", label: \"Install\" },\n\t\t\t{ id: \"no\", label: \"Cancel\" },\n\t\t],\n\t});\n\tif (confirm !== \"yes\") throw new Error(\"Anthropic subscription setup cancelled\");\n\tinteraction.notify({ type: \"progress\", message: \"Running the confirmed installer...\" });\n\tawait run(command, args, undefined, 300_000);\n}\n\nasync function setupProbe(python: string, command: string, type: \"status\" | \"discover\" | \"version\"): Promise<unknown> {\n\tconst requestId = randomUUID();\n\tconst line = await run(\n\t\tpython,\n\t\t[\"-s\", \"-B\", \"-u\", SETUP_WORKER],\n\t\t`${JSON.stringify({ v: 1, requestId, type, command, env: claudeCodeEnvironment(undefined, false) })}\\n`,\n\t\t55_000,\n\t);\n\tconst record: unknown = JSON.parse(line);\n\tif (\n\t\t!record ||\n\t\ttypeof record !== \"object\" ||\n\t\t!(\"v\" in record) ||\n\t\trecord.v !== 1 ||\n\t\t!(\"requestId\" in record) ||\n\t\trecord.requestId !== requestId ||\n\t\t!(\"type\" in record) ||\n\t\trecord.type !== \"result\" ||\n\t\t!(\"result\" in record)\n\t) {\n\t\tthrow new Error(\"Invalid Claude Code setup response\");\n\t}\n\treturn record.result;\n}\n\nasync function login(interaction: AuthInteraction): Promise<ExternalClaudeCodeCredential> {\n\tinteraction.notify({\n\t\ttype: \"info\",\n\t\tmessage:\n\t\t\t\"Claude Code handles subscription authentication and one generation per lunR request. lunR still owns tools, permissions, history, compaction, and subagents. Python 3.10+ and Claude Code are required. No credentials are copied into lunR.\",\n\t});\n\tlet python = await pythonInterpreter();\n\tif (!python) {\n\t\tinteraction.notify({\n\t\t\ttype: \"info\",\n\t\t\tmessage:\n\t\t\t\t\"Install Python 3.10+ from https://www.python.org/downloads/ . This is a separate operating-system installation, not part of lunR.\",\n\t\t});\n\t\tconst packageManager =\n\t\t\tprocess.platform === \"darwin\"\n\t\t\t\t? await executable(\"brew\")\n\t\t\t\t: process.platform === \"linux\"\n\t\t\t\t\t? ((await executable(\"apt-get\")) ?? (await executable(\"dnf\")))\n\t\t\t\t\t: undefined;\n\t\tconst installer =\n\t\t\tprocess.platform === \"win32\"\n\t\t\t\t? { command: \"winget\", args: [\"install\", \"--id\", \"Python.Python.3.13\", \"-e\"] }\n\t\t\t\t: packageManager?.endsWith(\"apt-get\")\n\t\t\t\t\t? { command: \"sudo\", args: [packageManager, \"install\", \"-y\", \"python3\"] }\n\t\t\t\t\t: packageManager?.endsWith(\"dnf\")\n\t\t\t\t\t\t? { command: \"sudo\", args: [packageManager, \"install\", \"-y\", \"python3\"] }\n\t\t\t\t\t\t: packageManager\n\t\t\t\t\t\t\t? { command: packageManager, args: [\"install\", \"python@3.13\"] }\n\t\t\t\t\t\t\t: undefined;\n\t\tconst choice = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage:\n\t\t\t\t\"Python 3.10+ is missing. A system installer may request administrator access and change your machine.\",\n\t\t\toptions: [\n\t\t\t\t...(installer\n\t\t\t\t\t? [{ id: \"install\", label: `Install through ${installer.command} ${installer.args.join(\" \")}` }]\n\t\t\t\t\t: []),\n\t\t\t\t{ id: \"cancel\", label: \"Cancel and install Python yourself\" },\n\t\t\t],\n\t\t});\n\t\tif (choice === \"install\" && installer) await install(installer.command, installer.args, interaction);\n\t\telse throw new Error(\"Install Python 3.10+ and retry /login anthropic\");\n\t\tpython = await pythonInterpreter();\n\t\tif (!python)\n\t\t\tthrow new Error(\"Python installation finished but the interpreter is not on PATH. Restart lunR and retry.\");\n\t}\n\tlet command = await executable(\"claude\");\n\tif (!command) {\n\t\tconst choice = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage: \"Claude Code is missing. Installation changes your user-level system and may require a new PATH.\",\n\t\t\toptions: [\n\t\t\t\t{ id: \"install\", label: \"Install Claude Code\" },\n\t\t\t\t{ id: \"existing\", label: \"Use existing executable\" },\n\t\t\t\t{ id: \"cancel\", label: \"Cancel\" },\n\t\t\t],\n\t\t});\n\t\tif (choice === \"install\") {\n\t\t\tif (process.platform === \"win32\")\n\t\t\t\tawait install(\n\t\t\t\t\t\"powershell\",\n\t\t\t\t\t[\"-NoProfile\", \"-Command\", \"irm https://claude.ai/install.ps1 | iex\"],\n\t\t\t\t\tinteraction,\n\t\t\t\t);\n\t\t\telse await install(\"sh\", [\"-c\", \"curl -fsSL https://claude.ai/install.sh | bash\"], interaction);\n\t\t\tcommand = await executable(\"claude\");\n\t\t} else if (choice === \"existing\") {\n\t\t\tconst path = await interaction.prompt({ type: \"text\", message: \"Absolute path to Claude Code executable:\" });\n\t\t\tif (!isAbsolute(path)) throw new Error(\"Claude Code path must be absolute\");\n\t\t\tcommand = await executable(path);\n\t\t} else throw new Error(\"Anthropic subscription setup cancelled\");\n\t}\n\tif (!command) throw new Error(\"Claude Code executable not found. Restart lunR after installation and retry.\");\n\tconst version = (await setupProbe(python, command, \"version\")) as string;\n\tif (!isQualifiedClaudeCodeVersion(version))\n\t\tthrow new Error(\n\t\t\t`Claude Code ${VERSION} is the only qualified version. Found ${version.slice(0, 40)}. Subscription requests are disabled until this version is qualified.`,\n\t\t);\n\tlet status = (await setupProbe(python, command, \"status\")) as {\n\t\tlogged_in?: boolean;\n\t\tplan?: string;\n\t\taccountFingerprint?: string;\n\t};\n\tif (!status.logged_in || !/Claude (Pro|Max|Team|Enterprise)/i.test(status.plan ?? \"\")) {\n\t\tif (!interaction.handoff)\n\t\t\tthrow new Error(\n\t\t\t\t`Run \"${command}\" auth login in a terminal, select a Claude subscription, then retry /login anthropic`,\n\t\t\t);\n\t\tconst choice = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage: \"Claude Code needs a subscription login. Hand the terminal to Claude Code now?\",\n\t\t\toptions: [\n\t\t\t\t{ id: \"login\", label: \"Run Claude Code login\" },\n\t\t\t\t{ id: \"cancel\", label: \"Cancel\" },\n\t\t\t],\n\t\t});\n\t\tif (choice !== \"login\") throw new Error(\"Anthropic subscription setup cancelled\");\n\t\tawait interaction.handoff(\n\t\t\tpython,\n\t\t\t[\"-s\", \"-B\", \"-u\", SETUP_WORKER, \"auth-login\", command],\n\t\t\tclaudeCodeEnvironment(undefined, false),\n\t\t);\n\t\tstatus = (await setupProbe(python, command, \"status\")) as typeof status;\n\t\tif (!status.logged_in || !/Claude (Pro|Max|Team|Enterprise)/i.test(status.plan ?? \"\"))\n\t\t\tthrow new Error(\"Claude Code is not signed into a Claude subscription\");\n\t}\n\tconst discovered = await setupProbe(python, command, \"discover\");\n\tif (\n\t\t!Array.isArray(discovered) ||\n\t\t!discovered.length ||\n\t\tdiscovered.some((row) => !row || typeof row.id !== \"string\" || row.upstream_requests !== 0)\n\t) {\n\t\tthrow new Error(\"Claude Code model discovery did not verify zero Messages requests. Setup not saved.\");\n\t}\n\treturn {\n\t\ttype: \"external_claude_code\",\n\t\tversion: 1,\n\t\tmanager: \"claude-code\",\n\t\tcommand,\n\t\tpython,\n\t\taccountFingerprint: status.accountFingerprint ?? randomUUID(),\n\t\troutes: discovered.map((row) => row.id),\n\t};\n}\n\nexport const anthropicOAuth: OAuthAuth = {\n\tname: \"Anthropic subscription through Claude Code\",\n\tloginLabel: \"Connect Claude Pro/Max through Claude Code\",\n\tlogin,\n\trefresh: async () => {\n\t\tthrow new Error(\"Legacy Anthropic OAuth tokens are unsupported. Run /login anthropic.\");\n\t},\n\ttoAuth: async () => {\n\t\tthrow new Error(\"Legacy Anthropic OAuth tokens are unsupported. Run /login anthropic.\");\n\t},\n};\n"]}
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/auth/oauth/anthropic.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { access, constants } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { delimiter, isAbsolute, join } from \"node:path\";\nimport { claudeCodeEnvironment, stopNative } from \"../../api/anthropic-claude-code-bridge.ts\";\nimport { getClaudeCodeWorkerPath } from \"../../utils/claude-code-assets.ts\";\nimport type { AuthInteraction, ExternalClaudeCodeCredential, OAuthAuth } from \"../types.ts\";\n\nconst VERSION = \"2.1.263\";\n\nexport function isQualifiedClaudeCodeVersion(value: string): boolean {\n\treturn new RegExp(`^${VERSION.replaceAll(\".\", \"\\\\.\")}(?:\\\\s|$)`).test(value);\n}\n\nasync function run(command: string, args: string[], input?: string, timeout = 25_000): Promise<string> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst child = spawn(command, args, {\n\t\t\tstdio: [\"pipe\", \"pipe\", \"ignore\"],\n\t\t\twindowsHide: true,\n\t\t\tdetached: process.platform !== \"win32\",\n\t\t\tenv: claudeCodeEnvironment(undefined, false),\n\t\t});\n\t\tlet output = \"\";\n\t\tlet timedOut = false;\n\t\tconst timer = setTimeout(() => {\n\t\t\ttimedOut = true;\n\t\t\tvoid stopNative(child.pid ?? 0).finally(() => {\n\t\t\t\tchild.kill();\n\t\t\t\tchild.stdout.destroy();\n\t\t\t\tchild.stdin.destroy();\n\t\t\t\treject(new Error(\"Dependency check timed out\"));\n\t\t\t});\n\t\t}, timeout);\n\t\tchild.stdout.on(\"data\", (chunk: Buffer) => {\n\t\t\toutput += chunk.toString(\"utf8\");\n\t\t\tif (output.length > 64 * 1024) child.kill();\n\t\t});\n\t\tchild.stdin.on(\"error\", () => {});\n\t\tchild.on(\"error\", reject);\n\t\tchild.on(\"close\", (code) => {\n\t\t\tclearTimeout(timer);\n\t\t\tif (timedOut) return;\n\t\t\tif (code !== 0) reject(new Error(\"Dependency check failed\"));\n\t\t\telse resolve(output.trim());\n\t\t});\n\t\tchild.stdin.end(input);\n\t});\n}\n\nasync function executable(name: string): Promise<string | undefined> {\n\tconst suffixes = process.platform === \"win32\" ? [\"\", \".exe\", \".cmd\", \".bat\"] : [\"\"];\n\tconst directories = isAbsolute(name)\n\t\t? [\"\"]\n\t\t: [...(process.env.PATH ?? \"\").split(delimiter), join(homedir(), \".local\", \"bin\")];\n\tfor (const directory of directories) {\n\t\tfor (const suffix of suffixes) {\n\t\t\tconst candidate = directory ? join(directory, `${name}${suffix}`) : `${name}${suffix}`;\n\t\t\ttry {\n\t\t\t\tawait access(candidate, constants.X_OK);\n\t\t\t\treturn candidate;\n\t\t\t} catch {\n\t\t\t\t/* Next location. */\n\t\t\t}\n\t\t}\n\t}\n\treturn undefined;\n}\n\nasync function pythonInterpreter(): Promise<string | undefined> {\n\tfor (const name of [\"python3\", \"python\"]) {\n\t\tconst path = await executable(name);\n\t\tif (!path) continue;\n\t\ttry {\n\t\t\tconst version = await run(path, [\"--version\"]);\n\t\t\tconst match = /^Python (\\d+)\\.(\\d+)/.exec(version);\n\t\t\tif (match && (Number(match[1]) > 3 || (Number(match[1]) === 3 && Number(match[2]) >= 10))) return path;\n\t\t} catch {\n\t\t\t/* Try another interpreter. */\n\t\t}\n\t}\n\treturn undefined;\n}\n\nasync function install(command: string, args: string[], interaction: AuthInteraction): Promise<void> {\n\tconst confirm = await interaction.prompt({\n\t\ttype: \"select\",\n\t\tmessage: `Run ${command} ${args.join(\" \")}? This downloads software and changes your user-level system installation.`,\n\t\toptions: [\n\t\t\t{ id: \"yes\", label: \"Install\" },\n\t\t\t{ id: \"no\", label: \"Cancel\" },\n\t\t],\n\t});\n\tif (confirm !== \"yes\") throw new Error(\"Anthropic subscription setup cancelled\");\n\tinteraction.notify({ type: \"progress\", message: \"Running the confirmed installer...\" });\n\tawait run(command, args, undefined, 300_000);\n}\n\nasync function setupProbe(python: string, command: string, type: \"status\" | \"discover\" | \"version\"): Promise<unknown> {\n\tconst requestId = randomUUID();\n\tconst line = await run(\n\t\tpython,\n\t\t[\"-s\", \"-B\", \"-u\", getClaudeCodeWorkerPath(\"lunr_setup_bridge.py\")],\n\t\t`${JSON.stringify({ v: 1, requestId, type, command, env: claudeCodeEnvironment(undefined, false) })}\\n`,\n\t\t55_000,\n\t);\n\tconst record: unknown = JSON.parse(line);\n\tif (\n\t\t!record ||\n\t\ttypeof record !== \"object\" ||\n\t\t!(\"v\" in record) ||\n\t\trecord.v !== 1 ||\n\t\t!(\"requestId\" in record) ||\n\t\trecord.requestId !== requestId ||\n\t\t!(\"type\" in record) ||\n\t\trecord.type !== \"result\" ||\n\t\t!(\"result\" in record)\n\t) {\n\t\tthrow new Error(\"Invalid Claude Code setup response\");\n\t}\n\treturn record.result;\n}\n\nasync function login(interaction: AuthInteraction): Promise<ExternalClaudeCodeCredential> {\n\tinteraction.notify({\n\t\ttype: \"info\",\n\t\tmessage:\n\t\t\t\"Claude Code handles subscription authentication and one generation per lunR request. lunR still owns tools, permissions, history, compaction, and subagents. Python 3.10+ and Claude Code are required. No credentials are copied into lunR.\",\n\t});\n\tlet python = await pythonInterpreter();\n\tif (!python) {\n\t\tinteraction.notify({\n\t\t\ttype: \"info\",\n\t\t\tmessage:\n\t\t\t\t\"Install Python 3.10+ from https://www.python.org/downloads/ . This is a separate operating-system installation, not part of lunR.\",\n\t\t});\n\t\tconst packageManager =\n\t\t\tprocess.platform === \"darwin\"\n\t\t\t\t? await executable(\"brew\")\n\t\t\t\t: process.platform === \"linux\"\n\t\t\t\t\t? ((await executable(\"apt-get\")) ?? (await executable(\"dnf\")))\n\t\t\t\t\t: undefined;\n\t\tconst installer =\n\t\t\tprocess.platform === \"win32\"\n\t\t\t\t? { command: \"winget\", args: [\"install\", \"--id\", \"Python.Python.3.13\", \"-e\"] }\n\t\t\t\t: packageManager?.endsWith(\"apt-get\")\n\t\t\t\t\t? { command: \"sudo\", args: [packageManager, \"install\", \"-y\", \"python3\"] }\n\t\t\t\t\t: packageManager?.endsWith(\"dnf\")\n\t\t\t\t\t\t? { command: \"sudo\", args: [packageManager, \"install\", \"-y\", \"python3\"] }\n\t\t\t\t\t\t: packageManager\n\t\t\t\t\t\t\t? { command: packageManager, args: [\"install\", \"python@3.13\"] }\n\t\t\t\t\t\t\t: undefined;\n\t\tconst choice = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage:\n\t\t\t\t\"Python 3.10+ is missing. A system installer may request administrator access and change your machine.\",\n\t\t\toptions: [\n\t\t\t\t...(installer\n\t\t\t\t\t? [{ id: \"install\", label: `Install through ${installer.command} ${installer.args.join(\" \")}` }]\n\t\t\t\t\t: []),\n\t\t\t\t{ id: \"cancel\", label: \"Cancel and install Python yourself\" },\n\t\t\t],\n\t\t});\n\t\tif (choice === \"install\" && installer) await install(installer.command, installer.args, interaction);\n\t\telse throw new Error(\"Install Python 3.10+ and retry /login anthropic\");\n\t\tpython = await pythonInterpreter();\n\t\tif (!python)\n\t\t\tthrow new Error(\"Python installation finished but the interpreter is not on PATH. Restart lunR and retry.\");\n\t}\n\tlet command = await executable(\"claude\");\n\tif (!command) {\n\t\tconst choice = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage: \"Claude Code is missing. Installation changes your user-level system and may require a new PATH.\",\n\t\t\toptions: [\n\t\t\t\t{ id: \"install\", label: \"Install Claude Code\" },\n\t\t\t\t{ id: \"existing\", label: \"Use existing executable\" },\n\t\t\t\t{ id: \"cancel\", label: \"Cancel\" },\n\t\t\t],\n\t\t});\n\t\tif (choice === \"install\") {\n\t\t\tif (process.platform === \"win32\")\n\t\t\t\tawait install(\n\t\t\t\t\t\"powershell\",\n\t\t\t\t\t[\"-NoProfile\", \"-Command\", \"irm https://claude.ai/install.ps1 | iex\"],\n\t\t\t\t\tinteraction,\n\t\t\t\t);\n\t\t\telse await install(\"sh\", [\"-c\", \"curl -fsSL https://claude.ai/install.sh | bash\"], interaction);\n\t\t\tcommand = await executable(\"claude\");\n\t\t} else if (choice === \"existing\") {\n\t\t\tconst path = await interaction.prompt({ type: \"text\", message: \"Absolute path to Claude Code executable:\" });\n\t\t\tif (!isAbsolute(path)) throw new Error(\"Claude Code path must be absolute\");\n\t\t\tcommand = await executable(path);\n\t\t} else throw new Error(\"Anthropic subscription setup cancelled\");\n\t}\n\tif (!command) throw new Error(\"Claude Code executable not found. Restart lunR after installation and retry.\");\n\tconst version = (await setupProbe(python, command, \"version\")) as string;\n\tif (!isQualifiedClaudeCodeVersion(version))\n\t\tthrow new Error(\n\t\t\t`Claude Code ${VERSION} is the only qualified version. Found ${version.slice(0, 40)}. Subscription requests are disabled until this version is qualified.`,\n\t\t);\n\tlet status = (await setupProbe(python, command, \"status\")) as {\n\t\tlogged_in?: boolean;\n\t\tplan?: string;\n\t\taccountFingerprint?: string;\n\t};\n\tif (!status.logged_in || !/Claude (Pro|Max|Team|Enterprise)/i.test(status.plan ?? \"\")) {\n\t\tif (!interaction.handoff)\n\t\t\tthrow new Error(\n\t\t\t\t`Run \"${command}\" auth login in a terminal, select a Claude subscription, then retry /login anthropic`,\n\t\t\t);\n\t\tconst choice = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage: \"Claude Code needs a subscription login. Hand the terminal to Claude Code now?\",\n\t\t\toptions: [\n\t\t\t\t{ id: \"login\", label: \"Run Claude Code login\" },\n\t\t\t\t{ id: \"cancel\", label: \"Cancel\" },\n\t\t\t],\n\t\t});\n\t\tif (choice !== \"login\") throw new Error(\"Anthropic subscription setup cancelled\");\n\t\tawait interaction.handoff(\n\t\t\tpython,\n\t\t\t[\"-s\", \"-B\", \"-u\", getClaudeCodeWorkerPath(\"lunr_setup_bridge.py\"), \"auth-login\", command],\n\t\t\tclaudeCodeEnvironment(undefined, false),\n\t\t);\n\t\tstatus = (await setupProbe(python, command, \"status\")) as typeof status;\n\t\tif (!status.logged_in || !/Claude (Pro|Max|Team|Enterprise)/i.test(status.plan ?? \"\"))\n\t\t\tthrow new Error(\"Claude Code is not signed into a Claude subscription\");\n\t}\n\tconst discovered = await setupProbe(python, command, \"discover\");\n\tif (\n\t\t!Array.isArray(discovered) ||\n\t\t!discovered.length ||\n\t\tdiscovered.some((row) => !row || typeof row.id !== \"string\" || row.upstream_requests !== 0)\n\t) {\n\t\tthrow new Error(\"Claude Code model discovery did not verify zero Messages requests. Setup not saved.\");\n\t}\n\treturn {\n\t\ttype: \"external_claude_code\",\n\t\tversion: 1,\n\t\tmanager: \"claude-code\",\n\t\tcommand,\n\t\tpython,\n\t\taccountFingerprint: status.accountFingerprint ?? randomUUID(),\n\t\troutes: discovered.map((row) => row.id),\n\t};\n}\n\nexport const anthropicOAuth: OAuthAuth = {\n\tname: \"Anthropic subscription through Claude Code\",\n\tloginLabel: \"Connect Claude Pro/Max through Claude Code\",\n\tlogin,\n\trefresh: async () => {\n\t\tthrow new Error(\"Legacy Anthropic OAuth tokens are unsupported. Run /login anthropic.\");\n\t},\n\ttoAuth: async () => {\n\t\tthrow new Error(\"Legacy Anthropic OAuth tokens are unsupported. Run /login anthropic.\");\n\t},\n};\n"]}
package/dist/index.d.ts CHANGED
@@ -26,6 +26,7 @@ export * from "./providers/faux.ts";
26
26
  export * from "./session-resources.ts";
27
27
  export * from "./types.ts";
28
28
  export * from "./utils/diagnostics.ts";
29
+ export * from "./utils/estimate.ts";
29
30
  export * from "./utils/event-stream.ts";
30
31
  export * from "./utils/json-parse.ts";
31
32
  export * from "./utils/overflow.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAO/B,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC/G,YAAY,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AACnF,YAAY,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/F,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,cAAc,eAAe,CAAC;AAC9B,YAAY,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,YAAY,EAAE,2BAA2B,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AACnH,YAAY,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,YAAY,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACxE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACxG,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,YAAY,EACX,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,iBAAiB,GACjB,MAAM,mCAAmC,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACN,sBAAsB,EACtB,iBAAiB,EACjB,8BAA8B,EAC9B,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,wBAAwB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,OAAO,EACN,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,6BAA6B,EAC7B,6BAA6B,EAC7B,oBAAoB,EACpB,gCAAgC,EAChC,uBAAuB,GACvB,MAAM,iBAAiB,CAAC","sourcesContent":["export type { Static, TSchema } from \"typebox\";\nexport { Type } from \"typebox\";\n\n// Core only, side-effect free: no generated catalogs, no provider factories,\n// no api-registry, no OAuth implementations, no compat. Provider factories\n// live under \"@ashx-j/lunr-ai/providers/*\", API implementations under\n// \"@ashx-j/lunr-ai/api/*\", the old global API under\n// \"@ashx-j/lunr-ai/compat\".\nexport type { AnthropicEffort, AnthropicOptions, AnthropicThinkingDisplay } from \"./api/anthropic-messages.ts\";\nexport type { AzureOpenAIResponsesOptions } from \"./api/azure-openai-responses.ts\";\nexport type { BedrockOptions, BedrockThinkingDisplay } from \"./api/bedrock-converse-stream.ts\";\nexport type { GoogleOptions } from \"./api/google-generative-ai.ts\";\nexport type { GoogleThinkingLevel } from \"./api/google-shared.ts\";\nexport type { GoogleVertexOptions } from \"./api/google-vertex.ts\";\nexport * from \"./api/lazy.ts\";\nexport type { MistralOptions } from \"./api/mistral-conversations.ts\";\nexport type { OpenAICodexResponsesOptions, OpenAICodexWebSocketDebugStats } from \"./api/openai-codex-responses.ts\";\nexport type { OpenAICompletionsOptions } from \"./api/openai-completions.ts\";\nexport type { OpenAIResponsesOptions } from \"./api/openai-responses.ts\";\nexport type { PiMessagesEvent, PiMessagesOptions, PiMessagesRewriteImpact } from \"./api/pi-messages.ts\";\nexport * from \"./auth/anthropic-route.ts\";\nexport * from \"./auth/context.ts\";\nexport * from \"./auth/credential-store.ts\";\nexport * from \"./auth/helpers.ts\";\nexport * from \"./auth/types.ts\";\nexport type {\n\tOAuthAuthInfo,\n\tOAuthDeviceCodeInfo,\n\tOAuthLoginCallbacks,\n\tOAuthPrompt,\n\tOAuthSelectOption,\n\tOAuthSelectPrompt,\n} from \"./compat/extension-oauth-types.ts\";\nexport * from \"./images-models.ts\";\nexport * from \"./models.ts\";\nexport * from \"./models-store.ts\";\nexport {\n\tcanonicalOpenAiModelId,\n\tisOpenAiChatModel,\n\tOPENAI_GPT6_THINKING_LEVEL_MAP,\n\tparseOpenAiGptVersion,\n\tsupportsOpenAiMax,\n\tsupportsOpenAiXhigh,\n\twithOpenAiEffortMetadata,\n} from \"./openai-effort.ts\";\nexport * from \"./providers/faux.ts\";\nexport * from \"./session-resources.ts\";\nexport * from \"./types.ts\";\nexport * from \"./utils/diagnostics.ts\";\nexport * from \"./utils/event-stream.ts\";\nexport * from \"./utils/json-parse.ts\";\nexport * from \"./utils/overflow.ts\";\nexport * from \"./utils/retry.ts\";\nexport * from \"./utils/typebox-helpers.ts\";\nexport * from \"./utils/validation.ts\";\nexport {\n\tparseXaiGrok4Minor,\n\tshouldUseXaiResponsesApi,\n\twithXaiEffortMetadata,\n\tXAI_GROK45_THINKING_LEVEL_MAP,\n\tXAI_GROK46_THINKING_LEVEL_MAP,\n\tXAI_RESPONSES_COMPAT,\n\tXAI_RESPONSES_EXCLUDED_MODEL_IDS,\n\tXAI_RESPONSES_MIN_MINOR,\n} from \"./xai-effort.ts\";\n"]}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAO/B,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC/G,YAAY,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AACnF,YAAY,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/F,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,cAAc,eAAe,CAAC;AAC9B,YAAY,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,YAAY,EAAE,2BAA2B,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AACnH,YAAY,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,YAAY,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACxE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACxG,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,YAAY,EACX,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,iBAAiB,GACjB,MAAM,mCAAmC,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACN,sBAAsB,EACtB,iBAAiB,EACjB,8BAA8B,EAC9B,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,wBAAwB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,OAAO,EACN,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,6BAA6B,EAC7B,6BAA6B,EAC7B,oBAAoB,EACpB,gCAAgC,EAChC,uBAAuB,GACvB,MAAM,iBAAiB,CAAC","sourcesContent":["export type { Static, TSchema } from \"typebox\";\nexport { Type } from \"typebox\";\n\n// Core only, side-effect free: no generated catalogs, no provider factories,\n// no api-registry, no OAuth implementations, no compat. Provider factories\n// live under \"@ashx-j/lunr-ai/providers/*\", API implementations under\n// \"@ashx-j/lunr-ai/api/*\", the old global API under\n// \"@ashx-j/lunr-ai/compat\".\nexport type { AnthropicEffort, AnthropicOptions, AnthropicThinkingDisplay } from \"./api/anthropic-messages.ts\";\nexport type { AzureOpenAIResponsesOptions } from \"./api/azure-openai-responses.ts\";\nexport type { BedrockOptions, BedrockThinkingDisplay } from \"./api/bedrock-converse-stream.ts\";\nexport type { GoogleOptions } from \"./api/google-generative-ai.ts\";\nexport type { GoogleThinkingLevel } from \"./api/google-shared.ts\";\nexport type { GoogleVertexOptions } from \"./api/google-vertex.ts\";\nexport * from \"./api/lazy.ts\";\nexport type { MistralOptions } from \"./api/mistral-conversations.ts\";\nexport type { OpenAICodexResponsesOptions, OpenAICodexWebSocketDebugStats } from \"./api/openai-codex-responses.ts\";\nexport type { OpenAICompletionsOptions } from \"./api/openai-completions.ts\";\nexport type { OpenAIResponsesOptions } from \"./api/openai-responses.ts\";\nexport type { PiMessagesEvent, PiMessagesOptions, PiMessagesRewriteImpact } from \"./api/pi-messages.ts\";\nexport * from \"./auth/anthropic-route.ts\";\nexport * from \"./auth/context.ts\";\nexport * from \"./auth/credential-store.ts\";\nexport * from \"./auth/helpers.ts\";\nexport * from \"./auth/types.ts\";\nexport type {\n\tOAuthAuthInfo,\n\tOAuthDeviceCodeInfo,\n\tOAuthLoginCallbacks,\n\tOAuthPrompt,\n\tOAuthSelectOption,\n\tOAuthSelectPrompt,\n} from \"./compat/extension-oauth-types.ts\";\nexport * from \"./images-models.ts\";\nexport * from \"./models.ts\";\nexport * from \"./models-store.ts\";\nexport {\n\tcanonicalOpenAiModelId,\n\tisOpenAiChatModel,\n\tOPENAI_GPT6_THINKING_LEVEL_MAP,\n\tparseOpenAiGptVersion,\n\tsupportsOpenAiMax,\n\tsupportsOpenAiXhigh,\n\twithOpenAiEffortMetadata,\n} from \"./openai-effort.ts\";\nexport * from \"./providers/faux.ts\";\nexport * from \"./session-resources.ts\";\nexport * from \"./types.ts\";\nexport * from \"./utils/diagnostics.ts\";\nexport * from \"./utils/estimate.ts\";\nexport * from \"./utils/event-stream.ts\";\nexport * from \"./utils/json-parse.ts\";\nexport * from \"./utils/overflow.ts\";\nexport * from \"./utils/retry.ts\";\nexport * from \"./utils/typebox-helpers.ts\";\nexport * from \"./utils/validation.ts\";\nexport {\n\tparseXaiGrok4Minor,\n\tshouldUseXaiResponsesApi,\n\twithXaiEffortMetadata,\n\tXAI_GROK45_THINKING_LEVEL_MAP,\n\tXAI_GROK46_THINKING_LEVEL_MAP,\n\tXAI_RESPONSES_COMPAT,\n\tXAI_RESPONSES_EXCLUDED_MODEL_IDS,\n\tXAI_RESPONSES_MIN_MINOR,\n} from \"./xai-effort.ts\";\n"]}
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ export * from "./providers/faux.js";
13
13
  export * from "./session-resources.js";
14
14
  export * from "./types.js";
15
15
  export * from "./utils/diagnostics.js";
16
+ export * from "./utils/estimate.js";
16
17
  export * from "./utils/event-stream.js";
17
18
  export * from "./utils/json-parse.js";
18
19
  export * from "./utils/overflow.js";