@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.
- package/LICENSE +22 -0
- package/README.md +90 -84
- package/dist/api/anthropic-claude-code-bridge.d.ts.map +1 -1
- package/dist/api/anthropic-claude-code-bridge.js +50 -12
- package/dist/api/anthropic-claude-code-bridge.js.map +1 -1
- package/dist/api/anthropic-messages.d.ts.map +1 -1
- package/dist/api/anthropic-messages.js +3 -0
- package/dist/api/anthropic-messages.js.map +1 -1
- package/dist/api/azure-openai-responses.d.ts.map +1 -1
- package/dist/api/azure-openai-responses.js +1 -0
- package/dist/api/azure-openai-responses.js.map +1 -1
- package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
- package/dist/api/bedrock-converse-stream.js +8 -1
- package/dist/api/bedrock-converse-stream.js.map +1 -1
- package/dist/api/google-generative-ai.d.ts.map +1 -1
- package/dist/api/google-generative-ai.js +7 -2
- package/dist/api/google-generative-ai.js.map +1 -1
- package/dist/api/google-vertex.d.ts.map +1 -1
- package/dist/api/google-vertex.js +7 -2
- package/dist/api/google-vertex.js.map +1 -1
- package/dist/api/lazy.d.ts.map +1 -1
- package/dist/api/lazy.js +1 -0
- package/dist/api/lazy.js.map +1 -1
- package/dist/api/mistral-conversations.d.ts.map +1 -1
- package/dist/api/mistral-conversations.js +2 -0
- package/dist/api/mistral-conversations.js.map +1 -1
- package/dist/api/openai-codex-responses.d.ts.map +1 -1
- package/dist/api/openai-codex-responses.js +13 -3
- package/dist/api/openai-codex-responses.js.map +1 -1
- package/dist/api/openai-completions.d.ts.map +1 -1
- package/dist/api/openai-completions.js +9 -1
- package/dist/api/openai-completions.js.map +1 -1
- package/dist/api/openai-responses-shared.d.ts.map +1 -1
- package/dist/api/openai-responses-shared.js +7 -4
- package/dist/api/openai-responses-shared.js.map +1 -1
- package/dist/api/openai-responses.d.ts.map +1 -1
- package/dist/api/openai-responses.js +1 -0
- package/dist/api/openai-responses.js.map +1 -1
- package/dist/api/openrouter-images.d.ts.map +1 -1
- package/dist/api/openrouter-images.js +8 -2
- package/dist/api/openrouter-images.js.map +1 -1
- package/dist/api/pi-messages.d.ts.map +1 -1
- package/dist/api/pi-messages.js +19 -3
- package/dist/api/pi-messages.js.map +1 -1
- package/dist/auth/helpers.d.ts.map +1 -1
- package/dist/auth/helpers.js +2 -2
- package/dist/auth/helpers.js.map +1 -1
- package/dist/auth/oauth/anthropic.d.ts.map +1 -1
- package/dist/auth/oauth/anthropic.js +3 -4
- package/dist/auth/oauth/anthropic.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/models.d.ts +1 -1
- package/dist/models.d.ts.map +1 -1
- package/dist/models.generated.d.ts +42 -0
- package/dist/models.generated.d.ts.map +1 -1
- package/dist/models.js +5 -2
- package/dist/models.js.map +1 -1
- package/dist/providers/faux.d.ts.map +1 -1
- package/dist/providers/faux.js +5 -1
- package/dist/providers/faux.js.map +1 -1
- package/dist/providers/google-vertex.models.d.ts +21 -0
- package/dist/providers/google-vertex.models.d.ts.map +1 -1
- package/dist/providers/google-vertex.models.js +3 -0
- package/dist/providers/google-vertex.models.js.map +1 -1
- package/dist/providers/google.models.d.ts +21 -0
- package/dist/providers/google.models.d.ts.map +1 -1
- package/dist/providers/google.models.js +3 -0
- package/dist/providers/google.models.js.map +1 -1
- package/dist/types.d.ts +10 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/claude-code-assets.d.ts +8 -0
- package/dist/utils/claude-code-assets.d.ts.map +1 -0
- package/dist/utils/claude-code-assets.js +16 -0
- package/dist/utils/claude-code-assets.js.map +1 -0
- package/dist/utils/estimate.d.ts +3 -0
- package/dist/utils/estimate.d.ts.map +1 -1
- package/dist/utils/estimate.js +35 -30
- package/dist/utils/estimate.js.map +1 -1
- package/package.json +1 -1
- 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"]}
|
package/dist/api/pi-messages.js
CHANGED
|
@@ -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
|
-
|
|
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,
|
|
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"]}
|
package/dist/auth/helpers.js
CHANGED
|
@@ -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
|
},
|
package/dist/auth/helpers.js.map
CHANGED
|
@@ -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;
|
|
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
|
-
|
|
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",
|
|
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",
|
|
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";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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";
|