@earendil-works/pi-ai 0.83.0 → 0.84.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/README.md +16 -7
  2. package/dist/api/anthropic-messages.d.ts.map +1 -1
  3. package/dist/api/anthropic-messages.js +3 -3
  4. package/dist/api/anthropic-messages.js.map +1 -1
  5. package/dist/api/azure-openai-responses.d.ts.map +1 -1
  6. package/dist/api/azure-openai-responses.js +5 -1
  7. package/dist/api/azure-openai-responses.js.map +1 -1
  8. package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
  9. package/dist/api/bedrock-converse-stream.js +48 -0
  10. package/dist/api/bedrock-converse-stream.js.map +1 -1
  11. package/dist/api/google-generative-ai.d.ts.map +1 -1
  12. package/dist/api/google-generative-ai.js +2 -2
  13. package/dist/api/google-generative-ai.js.map +1 -1
  14. package/dist/api/google-shared.d.ts +11 -1
  15. package/dist/api/google-shared.d.ts.map +1 -1
  16. package/dist/api/google-shared.js +44 -7
  17. package/dist/api/google-shared.js.map +1 -1
  18. package/dist/api/google-vertex.d.ts.map +1 -1
  19. package/dist/api/google-vertex.js +2 -2
  20. package/dist/api/google-vertex.js.map +1 -1
  21. package/dist/api/lazy.d.ts +5 -1
  22. package/dist/api/lazy.d.ts.map +1 -1
  23. package/dist/api/lazy.js +19 -7
  24. package/dist/api/lazy.js.map +1 -1
  25. package/dist/api/openai-codex-responses.d.ts.map +1 -1
  26. package/dist/api/openai-codex-responses.js +39 -19
  27. package/dist/api/openai-codex-responses.js.map +1 -1
  28. package/dist/api/openai-completions.d.ts +5 -2
  29. package/dist/api/openai-completions.d.ts.map +1 -1
  30. package/dist/api/openai-completions.js +57 -8
  31. package/dist/api/openai-completions.js.map +1 -1
  32. package/dist/api/openai-responses-shared.d.ts.map +1 -1
  33. package/dist/api/openai-responses-shared.js +22 -9
  34. package/dist/api/openai-responses-shared.js.map +1 -1
  35. package/dist/api/openai-responses.d.ts.map +1 -1
  36. package/dist/api/openai-responses.js +5 -1
  37. package/dist/api/openai-responses.js.map +1 -1
  38. package/dist/api/simple-options.d.ts +2 -0
  39. package/dist/api/simple-options.d.ts.map +1 -1
  40. package/dist/api/simple-options.js +8 -2
  41. package/dist/api/simple-options.js.map +1 -1
  42. package/dist/auth/credential-store.d.ts +6 -6
  43. package/dist/auth/credential-store.d.ts.map +1 -1
  44. package/dist/auth/credential-store.js +22 -11
  45. package/dist/auth/credential-store.js.map +1 -1
  46. package/dist/auth/helpers.d.ts +1 -0
  47. package/dist/auth/helpers.d.ts.map +1 -1
  48. package/dist/auth/helpers.js +7 -2
  49. package/dist/auth/helpers.js.map +1 -1
  50. package/dist/auth/oauth/anthropic.d.ts.map +1 -1
  51. package/dist/auth/oauth/anthropic.js +14 -8
  52. package/dist/auth/oauth/anthropic.js.map +1 -1
  53. package/dist/auth/oauth/device-code.d.ts +1 -1
  54. package/dist/auth/oauth/device-code.d.ts.map +1 -1
  55. package/dist/auth/oauth/device-code.js +4 -4
  56. package/dist/auth/oauth/device-code.js.map +1 -1
  57. package/dist/auth/oauth/github-copilot.d.ts.map +1 -1
  58. package/dist/auth/oauth/github-copilot.js +43 -30
  59. package/dist/auth/oauth/github-copilot.js.map +1 -1
  60. package/dist/auth/oauth/kimi-coding.d.ts.map +1 -1
  61. package/dist/auth/oauth/kimi-coding.js +17 -5
  62. package/dist/auth/oauth/kimi-coding.js.map +1 -1
  63. package/dist/auth/oauth/openai-codex.d.ts.map +1 -1
  64. package/dist/auth/oauth/openai-codex.js +12 -5
  65. package/dist/auth/oauth/openai-codex.js.map +1 -1
  66. package/dist/auth/oauth/openrouter.d.ts.map +1 -1
  67. package/dist/auth/oauth/openrouter.js +10 -10
  68. package/dist/auth/oauth/openrouter.js.map +1 -1
  69. package/dist/auth/oauth/radius.d.ts.map +1 -1
  70. package/dist/auth/oauth/radius.js +8 -7
  71. package/dist/auth/oauth/radius.js.map +1 -1
  72. package/dist/auth/oauth/xai.d.ts.map +1 -1
  73. package/dist/auth/oauth/xai.js +3 -2
  74. package/dist/auth/oauth/xai.js.map +1 -1
  75. package/dist/auth/resolve.d.ts +1 -0
  76. package/dist/auth/resolve.d.ts.map +1 -1
  77. package/dist/auth/resolve.js +24 -13
  78. package/dist/auth/resolve.js.map +1 -1
  79. package/dist/auth/types.d.ts +20 -8
  80. package/dist/auth/types.d.ts.map +1 -1
  81. package/dist/auth/types.js.map +1 -1
  82. package/dist/cli.d.ts.map +1 -1
  83. package/dist/cli.js +1 -0
  84. package/dist/cli.js.map +1 -1
  85. package/dist/env-api-keys.d.ts.map +1 -1
  86. package/dist/env-api-keys.js +1 -0
  87. package/dist/env-api-keys.js.map +1 -1
  88. package/dist/image-models.generated.d.ts +30 -0
  89. package/dist/image-models.generated.d.ts.map +1 -1
  90. package/dist/image-models.generated.js +32 -2
  91. package/dist/image-models.generated.js.map +1 -1
  92. package/dist/images-models.d.ts.map +1 -1
  93. package/dist/images-models.js +1 -0
  94. package/dist/images-models.js.map +1 -1
  95. package/dist/models-store.d.ts +9 -12
  96. package/dist/models-store.d.ts.map +1 -1
  97. package/dist/models-store.js +6 -3
  98. package/dist/models-store.js.map +1 -1
  99. package/dist/models.d.ts +40 -18
  100. package/dist/models.d.ts.map +1 -1
  101. package/dist/models.generated.d.ts +2 -0
  102. package/dist/models.generated.d.ts.map +1 -1
  103. package/dist/models.generated.js +2 -0
  104. package/dist/models.generated.js.map +1 -1
  105. package/dist/models.js +245 -89
  106. package/dist/models.js.map +1 -1
  107. package/dist/providers/all.d.ts.map +1 -1
  108. package/dist/providers/all.js +2 -0
  109. package/dist/providers/all.js.map +1 -1
  110. package/dist/providers/amazon-bedrock.d.ts.map +1 -1
  111. package/dist/providers/amazon-bedrock.js +15 -7
  112. package/dist/providers/amazon-bedrock.js.map +1 -1
  113. package/dist/providers/anthropic.d.ts.map +1 -1
  114. package/dist/providers/anthropic.js +15 -6
  115. package/dist/providers/anthropic.js.map +1 -1
  116. package/dist/providers/baseten.d.ts +3 -0
  117. package/dist/providers/baseten.d.ts.map +1 -0
  118. package/dist/providers/baseten.js +15 -0
  119. package/dist/providers/baseten.js.map +1 -0
  120. package/dist/providers/baseten.models.d.ts +4 -0
  121. package/dist/providers/baseten.models.d.ts.map +1 -0
  122. package/dist/providers/baseten.models.js +6 -0
  123. package/dist/providers/baseten.models.js.map +1 -0
  124. package/dist/providers/cloudflare-auth.d.ts.map +1 -1
  125. package/dist/providers/cloudflare-auth.js +15 -10
  126. package/dist/providers/cloudflare-auth.js.map +1 -1
  127. package/dist/providers/data/.manifest.json +1 -1
  128. package/dist/providers/data/amazon-bedrock.json +1 -1
  129. package/dist/providers/data/anthropic.json +1 -1
  130. package/dist/providers/data/azure-openai-responses.json +1 -1
  131. package/dist/providers/data/baseten.json +1 -0
  132. package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  133. package/dist/providers/data/fireworks.json +1 -1
  134. package/dist/providers/data/github-copilot.json +1 -1
  135. package/dist/providers/data/groq.json +1 -1
  136. package/dist/providers/data/huggingface.json +1 -1
  137. package/dist/providers/data/mistral.json +1 -1
  138. package/dist/providers/data/openai-codex.json +1 -1
  139. package/dist/providers/data/openai.json +1 -1
  140. package/dist/providers/data/opencode-go.json +1 -1
  141. package/dist/providers/data/opencode.json +1 -1
  142. package/dist/providers/data/openrouter.json +1 -1
  143. package/dist/providers/data/qwen-token-plan-cn.json +1 -1
  144. package/dist/providers/data/qwen-token-plan.json +1 -1
  145. package/dist/providers/data/together.json +1 -1
  146. package/dist/providers/data/vercel-ai-gateway.json +1 -1
  147. package/dist/providers/data/zai-coding-cn.json +1 -1
  148. package/dist/providers/data/zai.json +1 -1
  149. package/dist/providers/faux.d.ts +18 -13
  150. package/dist/providers/faux.d.ts.map +1 -1
  151. package/dist/providers/faux.js +95 -5
  152. package/dist/providers/faux.js.map +1 -1
  153. package/dist/providers/github-copilot.d.ts.map +1 -1
  154. package/dist/providers/github-copilot.js +1 -1
  155. package/dist/providers/github-copilot.js.map +1 -1
  156. package/dist/providers/google-vertex.d.ts.map +1 -1
  157. package/dist/providers/google-vertex.js +15 -7
  158. package/dist/providers/google-vertex.js.map +1 -1
  159. package/dist/providers/kimi-coding.d.ts.map +1 -1
  160. package/dist/providers/kimi-coding.js +1 -0
  161. package/dist/providers/kimi-coding.js.map +1 -1
  162. package/dist/providers/openai-codex.d.ts.map +1 -1
  163. package/dist/providers/openai-codex.js +5 -1
  164. package/dist/providers/openai-codex.js.map +1 -1
  165. package/dist/providers/opencode-go.d.ts.map +1 -1
  166. package/dist/providers/opencode-go.js +1 -1
  167. package/dist/providers/opencode-go.js.map +1 -1
  168. package/dist/providers/radius.d.ts.map +1 -1
  169. package/dist/providers/radius.js +36 -26
  170. package/dist/providers/radius.js.map +1 -1
  171. package/dist/providers/xai.d.ts.map +1 -1
  172. package/dist/providers/xai.js +1 -0
  173. package/dist/providers/xai.js.map +1 -1
  174. package/dist/types.d.ts +96 -80
  175. package/dist/types.d.ts.map +1 -1
  176. package/dist/types.js.map +1 -1
  177. package/dist/utils/abort.d.ts +8 -0
  178. package/dist/utils/abort.d.ts.map +1 -0
  179. package/dist/utils/abort.js +49 -0
  180. package/dist/utils/abort.js.map +1 -0
  181. package/dist/utils/error-body.d.ts.map +1 -1
  182. package/dist/utils/error-body.js +23 -4
  183. package/dist/utils/error-body.js.map +1 -1
  184. package/dist/utils/overflow.d.ts +10 -1
  185. package/dist/utils/overflow.d.ts.map +1 -1
  186. package/dist/utils/overflow.js +12 -1
  187. package/dist/utils/overflow.js.map +1 -1
  188. package/dist/utils/validation.d.ts.map +1 -1
  189. package/dist/utils/validation.js +6 -0
  190. package/dist/utils/validation.js.map +1 -1
  191. package/package.json +2 -1
@@ -1,5 +1,5 @@
1
1
  import { type Provider } from "../models.ts";
2
- import type { AssistantMessage, Context, Model, SimpleStreamOptions, StreamFunction, StreamOptions, TextContent, ThinkingContent, ToolCall } from "../types.ts";
2
+ import type { AssistantMessage, AssistantMessageEventStream, Context, DeferredCancelOptions, DeferredFetchOptions, DeferredHandle, Model, SimpleStreamOptions, StreamFunction, TextContent, ThinkingContent, ToolCall } from "../types.ts";
3
3
  export interface FauxModelDefinition {
4
4
  id: string;
5
5
  name?: string;
@@ -22,18 +22,27 @@ export declare function fauxToolCall(name: string, arguments_: ToolCall["argumen
22
22
  }): ToolCall;
23
23
  export declare function fauxAssistantMessage(content: string | FauxContentBlock | FauxContentBlock[], options?: {
24
24
  stopReason?: AssistantMessage["stopReason"];
25
+ deferred?: DeferredHandle;
25
26
  errorMessage?: string;
26
27
  responseId?: string;
27
28
  timestamp?: number;
28
29
  }): AssistantMessage;
29
- export type FauxResponseFactory = (context: Context, options: StreamOptions | undefined, state: {
30
+ export interface FauxProviderState {
30
31
  callCount: number;
31
- }, model: Model<string>) => AssistantMessage | Promise<AssistantMessage>;
32
+ deferredFetchCount: number;
33
+ cancelledDeferred: DeferredHandle[];
34
+ }
35
+ export type FauxResponseFactory = (context: Context, options: SimpleStreamOptions | undefined, state: FauxProviderState, model: Model<string>) => AssistantMessage | Promise<AssistantMessage>;
32
36
  export type FauxResponseStep = AssistantMessage | FauxResponseFactory;
33
37
  export interface RegisterFauxProviderOptions {
34
38
  api?: string;
35
39
  provider?: string;
36
40
  models?: FauxModelDefinition[];
41
+ deferred?: {
42
+ /** Number of fetches that return the original handle before the scripted response becomes ready. */
43
+ pendingFetches?: number;
44
+ pollAfterMs?: number;
45
+ };
37
46
  tokensPerSecond?: number;
38
47
  tokenSize?: {
39
48
  min?: number;
@@ -45,9 +54,7 @@ export interface FauxProviderRegistration {
45
54
  models: [Model<string>, ...Model<string>[]];
46
55
  getModel(): Model<string>;
47
56
  getModel(modelId: string): Model<string> | undefined;
48
- state: {
49
- callCount: number;
50
- };
57
+ state: FauxProviderState;
51
58
  setResponses: (responses: FauxResponseStep[]) => void;
52
59
  appendResponses: (responses: FauxResponseStep[]) => void;
53
60
  getPendingResponseCount: () => number;
@@ -59,9 +66,7 @@ export interface FauxProviderHandle {
59
66
  models: [Model<string>, ...Model<string>[]];
60
67
  getModel(): Model<string>;
61
68
  getModel(modelId: string): Model<string> | undefined;
62
- state: {
63
- callCount: number;
64
- };
69
+ state: FauxProviderState;
65
70
  setResponses: (responses: FauxResponseStep[]) => void;
66
71
  appendResponses: (responses: FauxResponseStep[]) => void;
67
72
  getPendingResponseCount: () => number;
@@ -70,15 +75,15 @@ export declare function createFauxCore(options: RegisterFauxProviderOptions): {
70
75
  api: string;
71
76
  provider: string;
72
77
  models: [Model<string>, ...Model<string>[]];
73
- stream: StreamFunction<string, StreamOptions>;
78
+ stream: StreamFunction<string, SimpleStreamOptions>;
74
79
  streamSimple: StreamFunction<string, SimpleStreamOptions>;
80
+ fetchDeferred: (requestModel: Model<string>, handle: DeferredHandle, fetchOptions?: DeferredFetchOptions | undefined) => AssistantMessageEventStream;
81
+ cancelDeferred: (requestModel: Model<string>, handle: DeferredHandle, cancelOptions?: DeferredCancelOptions | undefined) => Promise<void>;
75
82
  getModel: {
76
83
  (): Model<string>;
77
84
  (requestedModelId: string): Model<string> | undefined;
78
85
  };
79
- state: {
80
- callCount: number;
81
- };
86
+ state: FauxProviderState;
82
87
  setResponses(responses: FauxResponseStep[]): void;
83
88
  appendResponses(responses: FauxResponseStep[]): void;
84
89
  getPendingResponseCount(): number;
@@ -1 +1 @@
1
- {"version":3,"file":"faux.d.ts","sourceRoot":"","sources":["../../src/providers/faux.ts"],"names":[],"mappings":"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","sourcesContent":["import { createProvider, type Provider } from \"../models.ts\";\nimport type {\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tContext,\n\tImageContent,\n\tMessage,\n\tModel,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n\tToolCall,\n\tToolResultMessage,\n\tUsage,\n} from \"../types.ts\";\nimport { createAssistantMessageEventStream } from \"../utils/event-stream.ts\";\n\nconst DEFAULT_API = \"faux\";\nconst DEFAULT_PROVIDER = \"faux\";\nconst DEFAULT_MODEL_ID = \"faux-1\";\nconst DEFAULT_MODEL_NAME = \"Faux Model\";\nconst DEFAULT_BASE_URL = \"http://localhost:0\";\nconst DEFAULT_MIN_TOKEN_SIZE = 3;\nconst DEFAULT_MAX_TOKEN_SIZE = 5;\n\nconst DEFAULT_USAGE: Usage = {\n\tinput: 0,\n\toutput: 0,\n\tcacheRead: 0,\n\tcacheWrite: 0,\n\ttotalTokens: 0,\n\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n};\n\nexport interface FauxModelDefinition {\n\tid: string;\n\tname?: string;\n\treasoning?: boolean;\n\tinput?: (\"text\" | \"image\")[];\n\tcost?: { input: number; output: number; cacheRead: number; cacheWrite: number };\n\tcontextWindow?: number;\n\tmaxTokens?: number;\n}\n\nexport type FauxContentBlock = TextContent | ThinkingContent | ToolCall;\n\nexport function fauxText(text: string): TextContent {\n\treturn { type: \"text\", text };\n}\n\nexport function fauxThinking(thinking: string): ThinkingContent {\n\treturn { type: \"thinking\", thinking };\n}\n\nexport function fauxToolCall(name: string, arguments_: ToolCall[\"arguments\"], options: { id?: string } = {}): ToolCall {\n\treturn {\n\t\ttype: \"toolCall\",\n\t\tid: options.id ?? randomId(\"tool\"),\n\t\tname,\n\t\targuments: arguments_,\n\t};\n}\n\nfunction normalizeFauxAssistantContent(content: string | FauxContentBlock | FauxContentBlock[]): FauxContentBlock[] {\n\tif (typeof content === \"string\") {\n\t\treturn [fauxText(content)];\n\t}\n\treturn Array.isArray(content) ? content : [content];\n}\n\nexport function fauxAssistantMessage(\n\tcontent: string | FauxContentBlock | FauxContentBlock[],\n\toptions: {\n\t\tstopReason?: AssistantMessage[\"stopReason\"];\n\t\terrorMessage?: string;\n\t\tresponseId?: string;\n\t\ttimestamp?: number;\n\t} = {},\n): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: normalizeFauxAssistantContent(content),\n\t\tapi: DEFAULT_API,\n\t\tprovider: DEFAULT_PROVIDER,\n\t\tmodel: DEFAULT_MODEL_ID,\n\t\tusage: DEFAULT_USAGE,\n\t\tstopReason: options.stopReason ?? \"stop\",\n\t\terrorMessage: options.errorMessage,\n\t\tresponseId: options.responseId,\n\t\ttimestamp: options.timestamp ?? Date.now(),\n\t};\n}\n\nexport type FauxResponseFactory = (\n\tcontext: Context,\n\toptions: StreamOptions | undefined,\n\tstate: { callCount: number },\n\tmodel: Model<string>,\n) => AssistantMessage | Promise<AssistantMessage>;\n\nexport type FauxResponseStep = AssistantMessage | FauxResponseFactory;\n\nexport interface RegisterFauxProviderOptions {\n\tapi?: string;\n\tprovider?: string;\n\tmodels?: FauxModelDefinition[];\n\ttokensPerSecond?: number;\n\ttokenSize?: {\n\t\tmin?: number;\n\t\tmax?: number;\n\t};\n}\n\nexport interface FauxProviderRegistration {\n\tapi: string;\n\tmodels: [Model<string>, ...Model<string>[]];\n\tgetModel(): Model<string>;\n\tgetModel(modelId: string): Model<string> | undefined;\n\tstate: { callCount: number };\n\tsetResponses: (responses: FauxResponseStep[]) => void;\n\tappendResponses: (responses: FauxResponseStep[]) => void;\n\tgetPendingResponseCount: () => number;\n\tunregister: () => void;\n}\n\nexport interface FauxProviderHandle {\n\tprovider: Provider;\n\tapi: string;\n\tmodels: [Model<string>, ...Model<string>[]];\n\tgetModel(): Model<string>;\n\tgetModel(modelId: string): Model<string> | undefined;\n\tstate: { callCount: number };\n\tsetResponses: (responses: FauxResponseStep[]) => void;\n\tappendResponses: (responses: FauxResponseStep[]) => void;\n\tgetPendingResponseCount: () => number;\n}\n\nfunction estimateTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\nfunction randomId(prefix: string): string {\n\treturn `${prefix}:${Date.now()}:${Math.random().toString(36).slice(2)}`;\n}\n\nfunction contentToText(content: string | Array<TextContent | ImageContent>): string {\n\tif (typeof content === \"string\") {\n\t\treturn content;\n\t}\n\treturn content\n\t\t.map((block) => {\n\t\t\tif (block.type === \"text\") {\n\t\t\t\treturn block.text;\n\t\t\t}\n\t\t\treturn `[image:${block.mimeType}:${block.data.length}]`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n\nfunction assistantContentToText(content: Array<TextContent | ThinkingContent | ToolCall>): string {\n\treturn content\n\t\t.map((block) => {\n\t\t\tif (block.type === \"text\") {\n\t\t\t\treturn block.text;\n\t\t\t}\n\t\t\tif (block.type === \"thinking\") {\n\t\t\t\treturn block.thinking;\n\t\t\t}\n\t\t\treturn `${block.name}:${JSON.stringify(block.arguments)}`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n\nfunction toolResultToText(message: ToolResultMessage): string {\n\treturn [message.toolName, ...message.content.map((block) => contentToText([block]))].join(\"\\n\");\n}\n\nfunction messageToText(message: Message): string {\n\tif (message.role === \"user\") {\n\t\treturn contentToText(message.content);\n\t}\n\tif (message.role === \"assistant\") {\n\t\treturn assistantContentToText(message.content);\n\t}\n\treturn toolResultToText(message);\n}\n\nfunction serializeContext(context: Context): string {\n\tconst parts: string[] = [];\n\tif (context.systemPrompt) {\n\t\tparts.push(`system:${context.systemPrompt}`);\n\t}\n\tfor (const message of context.messages) {\n\t\tparts.push(`${message.role}:${messageToText(message)}`);\n\t}\n\tif (context.tools?.length) {\n\t\tparts.push(`tools:${JSON.stringify(context.tools)}`);\n\t}\n\treturn parts.join(\"\\n\\n\");\n}\n\nfunction commonPrefixLength(a: string, b: string): number {\n\tconst length = Math.min(a.length, b.length);\n\tlet index = 0;\n\twhile (index < length && a[index] === b[index]) {\n\t\tindex++;\n\t}\n\treturn index;\n}\n\nfunction withUsageEstimate(\n\tmessage: AssistantMessage,\n\tcontext: Context,\n\toptions: StreamOptions | undefined,\n\tpromptCache: Map<string, string>,\n): AssistantMessage {\n\tconst promptText = serializeContext(context);\n\tconst promptTokens = estimateTokens(promptText);\n\tconst outputTokens = estimateTokens(assistantContentToText(message.content));\n\tlet input = promptTokens;\n\tlet cacheRead = 0;\n\tlet cacheWrite = 0;\n\tconst sessionId = options?.sessionId;\n\n\tif (sessionId && options?.cacheRetention !== \"none\") {\n\t\tconst previousPrompt = promptCache.get(sessionId);\n\t\tif (previousPrompt) {\n\t\t\tconst cachedChars = commonPrefixLength(previousPrompt, promptText);\n\t\t\tcacheRead = estimateTokens(previousPrompt.slice(0, cachedChars));\n\t\t\tcacheWrite = estimateTokens(promptText.slice(cachedChars));\n\t\t\tinput = Math.max(0, promptTokens - cacheRead);\n\t\t} else {\n\t\t\tcacheWrite = promptTokens;\n\t\t}\n\t\tpromptCache.set(sessionId, promptText);\n\t}\n\n\treturn {\n\t\t...message,\n\t\tusage: {\n\t\t\tinput,\n\t\t\toutput: outputTokens,\n\t\t\tcacheRead,\n\t\t\tcacheWrite,\n\t\t\ttotalTokens: input + outputTokens + cacheRead + cacheWrite,\n\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t},\n\t};\n}\n\nfunction splitStringByTokenSize(text: string, minTokenSize: number, maxTokenSize: number): string[] {\n\tconst chunks: string[] = [];\n\tlet index = 0;\n\twhile (index < text.length) {\n\t\tconst tokenSize = minTokenSize + Math.floor(Math.random() * (maxTokenSize - minTokenSize + 1));\n\t\tconst charSize = Math.max(1, tokenSize * 4);\n\t\tchunks.push(text.slice(index, index + charSize));\n\t\tindex += charSize;\n\t}\n\treturn chunks.length > 0 ? chunks : [\"\"];\n}\n\nfunction cloneMessage(message: AssistantMessage, api: string, provider: string, modelId: string): AssistantMessage {\n\tconst cloned = structuredClone(message);\n\treturn {\n\t\t...cloned,\n\t\tapi,\n\t\tprovider,\n\t\tmodel: modelId,\n\t\ttimestamp: cloned.timestamp ?? Date.now(),\n\t\tusage: cloned.usage ?? DEFAULT_USAGE,\n\t};\n}\n\nfunction createErrorMessage(error: unknown, api: string, provider: string, modelId: string): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi,\n\t\tprovider,\n\t\tmodel: modelId,\n\t\tusage: DEFAULT_USAGE,\n\t\tstopReason: \"error\",\n\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction createAbortedMessage(partial: AssistantMessage): AssistantMessage {\n\treturn {\n\t\t...partial,\n\t\tstopReason: \"aborted\",\n\t\terrorMessage: \"Request was aborted\",\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction scheduleChunk(chunk: string, tokensPerSecond: number | undefined): Promise<void> {\n\tif (!tokensPerSecond || tokensPerSecond <= 0) {\n\t\treturn new Promise((resolve) => queueMicrotask(resolve));\n\t}\n\tconst delayMs = (estimateTokens(chunk) / tokensPerSecond) * 1000;\n\treturn new Promise((resolve) => setTimeout(resolve, delayMs));\n}\n\nasync function streamWithDeltas(\n\tstream: AssistantMessageEventStream,\n\tmessage: AssistantMessage,\n\tminTokenSize: number,\n\tmaxTokenSize: number,\n\ttokensPerSecond: number | undefined,\n\tsignal: AbortSignal | undefined,\n): Promise<void> {\n\tconst partial: AssistantMessage = { ...message, content: [], stopReason: \"pending\" };\n\tif (signal?.aborted) {\n\t\tconst aborted = createAbortedMessage(partial);\n\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\tstream.end(aborted);\n\t\treturn;\n\t}\n\n\tstream.push({ type: \"start\", partial: { ...partial } });\n\n\tfor (let index = 0; index < message.content.length; index++) {\n\t\tif (signal?.aborted) {\n\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\tstream.end(aborted);\n\t\t\treturn;\n\t\t}\n\n\t\tconst block = message.content[index];\n\n\t\tif (block.type === \"thinking\") {\n\t\t\tpartial.content = [...partial.content, { type: \"thinking\", thinking: \"\" }];\n\t\t\tstream.push({ type: \"thinking_start\", contentIndex: index, partial: { ...partial } });\n\t\t\tfor (const chunk of splitStringByTokenSize(block.thinking, minTokenSize, maxTokenSize)) {\n\t\t\t\tawait scheduleChunk(chunk, tokensPerSecond);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\t\t\tstream.end(aborted);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t(partial.content[index] as ThinkingContent).thinking += chunk;\n\t\t\t\tstream.push({ type: \"thinking_delta\", contentIndex: index, delta: chunk, partial: { ...partial } });\n\t\t\t}\n\t\t\tstream.push({\n\t\t\t\ttype: \"thinking_end\",\n\t\t\t\tcontentIndex: index,\n\t\t\t\tcontent: block.thinking,\n\t\t\t\tpartial: { ...partial },\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (block.type === \"text\") {\n\t\t\tpartial.content = [...partial.content, { type: \"text\", text: \"\" }];\n\t\t\tstream.push({ type: \"text_start\", contentIndex: index, partial: { ...partial } });\n\t\t\tfor (const chunk of splitStringByTokenSize(block.text, minTokenSize, maxTokenSize)) {\n\t\t\t\tawait scheduleChunk(chunk, tokensPerSecond);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\t\t\tstream.end(aborted);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t(partial.content[index] as TextContent).text += chunk;\n\t\t\t\tstream.push({ type: \"text_delta\", contentIndex: index, delta: chunk, partial: { ...partial } });\n\t\t\t}\n\t\t\tstream.push({ type: \"text_end\", contentIndex: index, content: block.text, partial: { ...partial } });\n\t\t\tcontinue;\n\t\t}\n\n\t\tpartial.content = [...partial.content, { type: \"toolCall\", id: block.id, name: block.name, arguments: {} }];\n\t\tstream.push({ type: \"toolcall_start\", contentIndex: index, partial: { ...partial } });\n\t\tfor (const chunk of splitStringByTokenSize(JSON.stringify(block.arguments), minTokenSize, maxTokenSize)) {\n\t\t\tawait scheduleChunk(chunk, tokensPerSecond);\n\t\t\tif (signal?.aborted) {\n\t\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\t\tstream.end(aborted);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstream.push({ type: \"toolcall_delta\", contentIndex: index, delta: chunk, partial: { ...partial } });\n\t\t}\n\t\t(partial.content[index] as ToolCall).arguments = block.arguments;\n\t\tstream.push({ type: \"toolcall_end\", contentIndex: index, toolCall: block, partial: { ...partial } });\n\t}\n\n\tif (message.stopReason === \"pending\") {\n\t\tthrow new Error(\"Faux response ended without a stop reason\");\n\t}\n\tif (message.stopReason === \"error\" || message.stopReason === \"aborted\") {\n\t\tstream.push({ type: \"error\", reason: message.stopReason, error: message });\n\t\tstream.end(message);\n\t\treturn;\n\t}\n\n\tstream.push({ type: \"done\", reason: message.stopReason, message });\n\tstream.end(message);\n}\n\nexport function createFauxCore(options: RegisterFauxProviderOptions) {\n\tconst api = options.api ?? randomId(DEFAULT_API);\n\tconst provider = options.provider ?? DEFAULT_PROVIDER;\n\tconst minTokenSize = Math.max(\n\t\t1,\n\t\tMath.min(options.tokenSize?.min ?? DEFAULT_MIN_TOKEN_SIZE, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE),\n\t);\n\tconst maxTokenSize = Math.max(minTokenSize, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE);\n\tlet pendingResponses: FauxResponseStep[] = [];\n\tconst tokensPerSecond = options.tokensPerSecond;\n\tconst state = { callCount: 0 };\n\tconst promptCache = new Map<string, string>();\n\n\tconst modelDefinitions = options.models?.length\n\t\t? options.models\n\t\t: [\n\t\t\t\t{\n\t\t\t\t\tid: DEFAULT_MODEL_ID,\n\t\t\t\t\tname: DEFAULT_MODEL_NAME,\n\t\t\t\t\treasoning: false,\n\t\t\t\t\tinput: [\"text\", \"image\"] as (\"text\" | \"image\")[],\n\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\t\t\t\tcontextWindow: 128000,\n\t\t\t\t\tmaxTokens: 16384,\n\t\t\t\t},\n\t\t\t];\n\tconst models = modelDefinitions.map((definition) => ({\n\t\tid: definition.id,\n\t\tname: definition.name ?? definition.id,\n\t\tapi,\n\t\tprovider,\n\t\tbaseUrl: DEFAULT_BASE_URL,\n\t\treasoning: definition.reasoning ?? false,\n\t\tinput: definition.input ?? [\"text\", \"image\"],\n\t\tcost: definition.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: definition.contextWindow ?? 128000,\n\t\tmaxTokens: definition.maxTokens ?? 16384,\n\t})) as [Model<string>, ...Model<string>[]];\n\n\tconst stream: StreamFunction<string, StreamOptions> = (requestModel, context, streamOptions) => {\n\t\tconst outer = createAssistantMessageEventStream();\n\t\tconst step = pendingResponses.shift();\n\t\tstate.callCount++;\n\n\t\tqueueMicrotask(async () => {\n\t\t\ttry {\n\t\t\t\tawait streamOptions?.onResponse?.({ status: 200, headers: {} }, requestModel);\n\t\t\t\tif (!step) {\n\t\t\t\t\tlet message = createErrorMessage(\n\t\t\t\t\t\tnew Error(\"No more faux responses queued\"),\n\t\t\t\t\t\tapi,\n\t\t\t\t\t\tprovider,\n\t\t\t\t\t\trequestModel.id,\n\t\t\t\t\t);\n\t\t\t\t\tmessage = withUsageEstimate(message, context, streamOptions, promptCache);\n\t\t\t\t\touter.push({ type: \"error\", reason: \"error\", error: message });\n\t\t\t\t\touter.end(message);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst resolved =\n\t\t\t\t\ttypeof step === \"function\" ? await step(context, streamOptions, state, requestModel) : step;\n\t\t\t\tlet message = cloneMessage(resolved, api, provider, requestModel.id);\n\t\t\t\tmessage = withUsageEstimate(message, context, streamOptions, promptCache);\n\t\t\t\tawait streamWithDeltas(outer, message, minTokenSize, maxTokenSize, tokensPerSecond, streamOptions?.signal);\n\t\t\t} catch (error) {\n\t\t\t\tconst message = createErrorMessage(error, api, provider, requestModel.id);\n\t\t\t\touter.push({ type: \"error\", reason: \"error\", error: message });\n\t\t\t\touter.end(message);\n\t\t\t}\n\t\t});\n\n\t\treturn outer;\n\t};\n\n\tconst streamSimple: StreamFunction<string, SimpleStreamOptions> = (streamModel, context, streamOptions) =>\n\t\tstream(streamModel, context, streamOptions);\n\n\tfunction getModel(): Model<string>;\n\tfunction getModel(requestedModelId: string): Model<string> | undefined;\n\tfunction getModel(requestedModelId?: string): Model<string> | undefined {\n\t\tif (!requestedModelId) {\n\t\t\treturn models[0];\n\t\t}\n\t\treturn models.find((candidate) => candidate.id === requestedModelId);\n\t}\n\n\treturn {\n\t\tapi,\n\t\tprovider,\n\t\tmodels,\n\t\tstream,\n\t\tstreamSimple,\n\t\tgetModel,\n\t\tstate,\n\t\tsetResponses(responses: FauxResponseStep[]) {\n\t\t\tpendingResponses = [...responses];\n\t\t},\n\t\tappendResponses(responses: FauxResponseStep[]) {\n\t\t\tpendingResponses.push(...responses);\n\t\t},\n\t\tgetPendingResponseCount() {\n\t\t\treturn pendingResponses.length;\n\t\t},\n\t};\n}\n\n/**\n * Faux provider for tests built on explicit `Models` collections:\n *\n * ```ts\n * const faux = fauxProvider();\n * const models = createModels();\n * models.setProvider(faux.provider);\n * faux.setResponses([fauxAssistantMessage(\"hi\")]);\n * ```\n */\nexport function fauxProvider(options: RegisterFauxProviderOptions = {}): FauxProviderHandle {\n\tconst core = createFauxCore(options);\n\tconst provider = createProvider({\n\t\tid: core.provider,\n\t\tauth: { apiKey: { name: \"Faux\", resolve: async () => ({ auth: {} }) } },\n\t\tmodels: core.models,\n\t\tapi: { stream: core.stream, streamSimple: core.streamSimple },\n\t});\n\treturn {\n\t\tprovider,\n\t\tapi: core.api,\n\t\tmodels: core.models,\n\t\tgetModel: core.getModel,\n\t\tstate: core.state,\n\t\tsetResponses: core.setResponses,\n\t\tappendResponses: core.appendResponses,\n\t\tgetPendingResponseCount: core.getPendingResponseCount,\n\t};\n}\n"]}
1
+ {"version":3,"file":"faux.d.ts","sourceRoot":"","sources":["../../src/providers/faux.ts"],"names":[],"mappings":"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","sourcesContent":["import { createProvider, type Provider } from \"../models.ts\";\nimport type {\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tContext,\n\tDeferredCancelOptions,\n\tDeferredFetchOptions,\n\tDeferredHandle,\n\tImageContent,\n\tMessage,\n\tModel,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n\tToolCall,\n\tToolResultMessage,\n\tUsage,\n} from \"../types.ts\";\nimport { createAssistantMessageEventStream } from \"../utils/event-stream.ts\";\n\nconst DEFAULT_API = \"faux\";\nconst DEFAULT_PROVIDER = \"faux\";\nconst DEFAULT_MODEL_ID = \"faux-1\";\nconst DEFAULT_MODEL_NAME = \"Faux Model\";\nconst DEFAULT_BASE_URL = \"http://localhost:0\";\nconst DEFAULT_MIN_TOKEN_SIZE = 3;\nconst DEFAULT_MAX_TOKEN_SIZE = 5;\n\nconst DEFAULT_USAGE: Usage = {\n\tinput: 0,\n\toutput: 0,\n\tcacheRead: 0,\n\tcacheWrite: 0,\n\ttotalTokens: 0,\n\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n};\n\nexport interface FauxModelDefinition {\n\tid: string;\n\tname?: string;\n\treasoning?: boolean;\n\tinput?: (\"text\" | \"image\")[];\n\tcost?: { input: number; output: number; cacheRead: number; cacheWrite: number };\n\tcontextWindow?: number;\n\tmaxTokens?: number;\n}\n\nexport type FauxContentBlock = TextContent | ThinkingContent | ToolCall;\n\nexport function fauxText(text: string): TextContent {\n\treturn { type: \"text\", text };\n}\n\nexport function fauxThinking(thinking: string): ThinkingContent {\n\treturn { type: \"thinking\", thinking };\n}\n\nexport function fauxToolCall(name: string, arguments_: ToolCall[\"arguments\"], options: { id?: string } = {}): ToolCall {\n\treturn {\n\t\ttype: \"toolCall\",\n\t\tid: options.id ?? randomId(\"tool\"),\n\t\tname,\n\t\targuments: arguments_,\n\t};\n}\n\nfunction normalizeFauxAssistantContent(content: string | FauxContentBlock | FauxContentBlock[]): FauxContentBlock[] {\n\tif (typeof content === \"string\") {\n\t\treturn [fauxText(content)];\n\t}\n\treturn Array.isArray(content) ? content : [content];\n}\n\nexport function fauxAssistantMessage(\n\tcontent: string | FauxContentBlock | FauxContentBlock[],\n\toptions: {\n\t\tstopReason?: AssistantMessage[\"stopReason\"];\n\t\tdeferred?: DeferredHandle;\n\t\terrorMessage?: string;\n\t\tresponseId?: string;\n\t\ttimestamp?: number;\n\t} = {},\n): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: normalizeFauxAssistantContent(content),\n\t\tapi: DEFAULT_API,\n\t\tprovider: DEFAULT_PROVIDER,\n\t\tmodel: DEFAULT_MODEL_ID,\n\t\tusage: DEFAULT_USAGE,\n\t\tstopReason: options.stopReason ?? \"stop\",\n\t\tdeferred: options.deferred,\n\t\terrorMessage: options.errorMessage,\n\t\tresponseId: options.responseId,\n\t\ttimestamp: options.timestamp ?? Date.now(),\n\t};\n}\n\nexport interface FauxProviderState {\n\tcallCount: number;\n\tdeferredFetchCount: number;\n\tcancelledDeferred: DeferredHandle[];\n}\n\nexport type FauxResponseFactory = (\n\tcontext: Context,\n\toptions: SimpleStreamOptions | undefined,\n\tstate: FauxProviderState,\n\tmodel: Model<string>,\n) => AssistantMessage | Promise<AssistantMessage>;\n\nexport type FauxResponseStep = AssistantMessage | FauxResponseFactory;\n\nexport interface RegisterFauxProviderOptions {\n\tapi?: string;\n\tprovider?: string;\n\tmodels?: FauxModelDefinition[];\n\tdeferred?: {\n\t\t/** Number of fetches that return the original handle before the scripted response becomes ready. */\n\t\tpendingFetches?: number;\n\t\tpollAfterMs?: number;\n\t};\n\ttokensPerSecond?: number;\n\ttokenSize?: {\n\t\tmin?: number;\n\t\tmax?: number;\n\t};\n}\n\nexport interface FauxProviderRegistration {\n\tapi: string;\n\tmodels: [Model<string>, ...Model<string>[]];\n\tgetModel(): Model<string>;\n\tgetModel(modelId: string): Model<string> | undefined;\n\tstate: FauxProviderState;\n\tsetResponses: (responses: FauxResponseStep[]) => void;\n\tappendResponses: (responses: FauxResponseStep[]) => void;\n\tgetPendingResponseCount: () => number;\n\tunregister: () => void;\n}\n\nexport interface FauxProviderHandle {\n\tprovider: Provider;\n\tapi: string;\n\tmodels: [Model<string>, ...Model<string>[]];\n\tgetModel(): Model<string>;\n\tgetModel(modelId: string): Model<string> | undefined;\n\tstate: FauxProviderState;\n\tsetResponses: (responses: FauxResponseStep[]) => void;\n\tappendResponses: (responses: FauxResponseStep[]) => void;\n\tgetPendingResponseCount: () => number;\n}\n\nfunction estimateTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\nfunction randomId(prefix: string): string {\n\treturn `${prefix}:${Date.now()}:${Math.random().toString(36).slice(2)}`;\n}\n\nfunction contentToText(content: string | Array<TextContent | ImageContent>): string {\n\tif (typeof content === \"string\") {\n\t\treturn content;\n\t}\n\treturn content\n\t\t.map((block) => {\n\t\t\tif (block.type === \"text\") {\n\t\t\t\treturn block.text;\n\t\t\t}\n\t\t\treturn `[image:${block.mimeType}:${block.data.length}]`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n\nfunction assistantContentToText(content: Array<TextContent | ThinkingContent | ToolCall>): string {\n\treturn content\n\t\t.map((block) => {\n\t\t\tif (block.type === \"text\") {\n\t\t\t\treturn block.text;\n\t\t\t}\n\t\t\tif (block.type === \"thinking\") {\n\t\t\t\treturn block.thinking;\n\t\t\t}\n\t\t\treturn `${block.name}:${JSON.stringify(block.arguments)}`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n\nfunction toolResultToText(message: ToolResultMessage): string {\n\treturn [message.toolName, ...message.content.map((block) => contentToText([block]))].join(\"\\n\");\n}\n\nfunction messageToText(message: Message): string {\n\tif (message.role === \"user\") {\n\t\treturn contentToText(message.content);\n\t}\n\tif (message.role === \"assistant\") {\n\t\treturn assistantContentToText(message.content);\n\t}\n\treturn toolResultToText(message);\n}\n\nfunction serializeContext(context: Context): string {\n\tconst parts: string[] = [];\n\tif (context.systemPrompt) {\n\t\tparts.push(`system:${context.systemPrompt}`);\n\t}\n\tfor (const message of context.messages) {\n\t\tparts.push(`${message.role}:${messageToText(message)}`);\n\t}\n\tif (context.tools?.length) {\n\t\tparts.push(`tools:${JSON.stringify(context.tools)}`);\n\t}\n\treturn parts.join(\"\\n\\n\");\n}\n\nfunction commonPrefixLength(a: string, b: string): number {\n\tconst length = Math.min(a.length, b.length);\n\tlet index = 0;\n\twhile (index < length && a[index] === b[index]) {\n\t\tindex++;\n\t}\n\treturn index;\n}\n\nfunction withUsageEstimate(\n\tmessage: AssistantMessage,\n\tcontext: Context,\n\toptions: StreamOptions | undefined,\n\tpromptCache: Map<string, string>,\n): AssistantMessage {\n\tconst promptText = serializeContext(context);\n\tconst promptTokens = estimateTokens(promptText);\n\tconst outputTokens = estimateTokens(assistantContentToText(message.content));\n\tlet input = promptTokens;\n\tlet cacheRead = 0;\n\tlet cacheWrite = 0;\n\tconst sessionId = options?.sessionId;\n\n\tif (sessionId && options?.cacheRetention !== \"none\") {\n\t\tconst previousPrompt = promptCache.get(sessionId);\n\t\tif (previousPrompt) {\n\t\t\tconst cachedChars = commonPrefixLength(previousPrompt, promptText);\n\t\t\tcacheRead = estimateTokens(previousPrompt.slice(0, cachedChars));\n\t\t\tcacheWrite = estimateTokens(promptText.slice(cachedChars));\n\t\t\tinput = Math.max(0, promptTokens - cacheRead);\n\t\t} else {\n\t\t\tcacheWrite = promptTokens;\n\t\t}\n\t\tpromptCache.set(sessionId, promptText);\n\t}\n\n\treturn {\n\t\t...message,\n\t\tusage: {\n\t\t\tinput,\n\t\t\toutput: outputTokens,\n\t\t\tcacheRead,\n\t\t\tcacheWrite,\n\t\t\ttotalTokens: input + outputTokens + cacheRead + cacheWrite,\n\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t},\n\t};\n}\n\nfunction splitStringByTokenSize(text: string, minTokenSize: number, maxTokenSize: number): string[] {\n\tconst chunks: string[] = [];\n\tlet index = 0;\n\twhile (index < text.length) {\n\t\tconst tokenSize = minTokenSize + Math.floor(Math.random() * (maxTokenSize - minTokenSize + 1));\n\t\tconst charSize = Math.max(1, tokenSize * 4);\n\t\tchunks.push(text.slice(index, index + charSize));\n\t\tindex += charSize;\n\t}\n\treturn chunks.length > 0 ? chunks : [\"\"];\n}\n\nfunction cloneMessage(message: AssistantMessage, api: string, provider: string, modelId: string): AssistantMessage {\n\tconst cloned = structuredClone(message);\n\treturn {\n\t\t...cloned,\n\t\tapi,\n\t\tprovider,\n\t\tmodel: modelId,\n\t\ttimestamp: cloned.timestamp ?? Date.now(),\n\t\tusage: cloned.usage ?? DEFAULT_USAGE,\n\t};\n}\n\nfunction createDeferredMessage(model: Model<string>, handle: DeferredHandle): AssistantMessage {\n\treturn {\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: DEFAULT_USAGE,\n\t\tstopReason: \"deferred\",\n\t\tdeferred: handle,\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction createErrorMessage(error: unknown, api: string, provider: string, modelId: string): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi,\n\t\tprovider,\n\t\tmodel: modelId,\n\t\tusage: DEFAULT_USAGE,\n\t\tstopReason: \"error\",\n\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction createAbortedMessage(partial: AssistantMessage): AssistantMessage {\n\treturn {\n\t\t...partial,\n\t\tstopReason: \"aborted\",\n\t\terrorMessage: \"Request was aborted\",\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction scheduleChunk(chunk: string, tokensPerSecond: number | undefined): Promise<void> {\n\tif (!tokensPerSecond || tokensPerSecond <= 0) {\n\t\treturn new Promise((resolve) => queueMicrotask(resolve));\n\t}\n\tconst delayMs = (estimateTokens(chunk) / tokensPerSecond) * 1000;\n\treturn new Promise((resolve) => setTimeout(resolve, delayMs));\n}\n\nasync function streamWithDeltas(\n\tstream: AssistantMessageEventStream,\n\tmessage: AssistantMessage,\n\tminTokenSize: number,\n\tmaxTokenSize: number,\n\ttokensPerSecond: number | undefined,\n\tsignal: AbortSignal | undefined,\n): Promise<void> {\n\tconst partial: AssistantMessage = { ...message, content: [], stopReason: \"pending\" };\n\tif (signal?.aborted) {\n\t\tconst aborted = createAbortedMessage(partial);\n\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\tstream.end(aborted);\n\t\treturn;\n\t}\n\n\tstream.push({ type: \"start\", partial: { ...partial } });\n\n\tfor (let index = 0; index < message.content.length; index++) {\n\t\tif (signal?.aborted) {\n\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\tstream.end(aborted);\n\t\t\treturn;\n\t\t}\n\n\t\tconst block = message.content[index];\n\n\t\tif (block.type === \"thinking\") {\n\t\t\tpartial.content = [...partial.content, { type: \"thinking\", thinking: \"\" }];\n\t\t\tstream.push({ type: \"thinking_start\", contentIndex: index, partial: { ...partial } });\n\t\t\tfor (const chunk of splitStringByTokenSize(block.thinking, minTokenSize, maxTokenSize)) {\n\t\t\t\tawait scheduleChunk(chunk, tokensPerSecond);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\t\t\tstream.end(aborted);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t(partial.content[index] as ThinkingContent).thinking += chunk;\n\t\t\t\tstream.push({ type: \"thinking_delta\", contentIndex: index, delta: chunk, partial: { ...partial } });\n\t\t\t}\n\t\t\tstream.push({\n\t\t\t\ttype: \"thinking_end\",\n\t\t\t\tcontentIndex: index,\n\t\t\t\tcontent: block.thinking,\n\t\t\t\tpartial: { ...partial },\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (block.type === \"text\") {\n\t\t\tpartial.content = [...partial.content, { type: \"text\", text: \"\" }];\n\t\t\tstream.push({ type: \"text_start\", contentIndex: index, partial: { ...partial } });\n\t\t\tfor (const chunk of splitStringByTokenSize(block.text, minTokenSize, maxTokenSize)) {\n\t\t\t\tawait scheduleChunk(chunk, tokensPerSecond);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\t\t\tstream.end(aborted);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t(partial.content[index] as TextContent).text += chunk;\n\t\t\t\tstream.push({ type: \"text_delta\", contentIndex: index, delta: chunk, partial: { ...partial } });\n\t\t\t}\n\t\t\tstream.push({ type: \"text_end\", contentIndex: index, content: block.text, partial: { ...partial } });\n\t\t\tcontinue;\n\t\t}\n\n\t\tpartial.content = [...partial.content, { type: \"toolCall\", id: block.id, name: block.name, arguments: {} }];\n\t\tstream.push({ type: \"toolcall_start\", contentIndex: index, partial: { ...partial } });\n\t\tfor (const chunk of splitStringByTokenSize(JSON.stringify(block.arguments), minTokenSize, maxTokenSize)) {\n\t\t\tawait scheduleChunk(chunk, tokensPerSecond);\n\t\t\tif (signal?.aborted) {\n\t\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\t\tstream.end(aborted);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstream.push({ type: \"toolcall_delta\", contentIndex: index, delta: chunk, partial: { ...partial } });\n\t\t}\n\t\t(partial.content[index] as ToolCall).arguments = block.arguments;\n\t\tstream.push({ type: \"toolcall_end\", contentIndex: index, toolCall: block, partial: { ...partial } });\n\t}\n\n\tif (message.stopReason === \"pending\") {\n\t\tthrow new Error(\"Faux response ended without a stop reason\");\n\t}\n\tif (message.stopReason === \"error\" || message.stopReason === \"aborted\") {\n\t\tstream.push({ type: \"error\", reason: message.stopReason, error: message });\n\t\tstream.end(message);\n\t\treturn;\n\t}\n\n\tstream.push({ type: \"done\", reason: message.stopReason, message });\n\tstream.end(message);\n}\n\nexport function createFauxCore(options: RegisterFauxProviderOptions) {\n\tconst api = options.api ?? randomId(DEFAULT_API);\n\tconst provider = options.provider ?? DEFAULT_PROVIDER;\n\tconst minTokenSize = Math.max(\n\t\t1,\n\t\tMath.min(options.tokenSize?.min ?? DEFAULT_MIN_TOKEN_SIZE, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE),\n\t);\n\tconst maxTokenSize = Math.max(minTokenSize, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE);\n\tlet pendingResponses: FauxResponseStep[] = [];\n\tconst tokensPerSecond = options.tokensPerSecond;\n\tconst state: FauxProviderState = { callCount: 0, deferredFetchCount: 0, cancelledDeferred: [] };\n\tconst promptCache = new Map<string, string>();\n\tconst deferredResponses = new Map<\n\t\tstring,\n\t\t{\n\t\t\thandle: DeferredHandle;\n\t\t\tstep: FauxResponseStep;\n\t\t\tcontext: Context;\n\t\t\toptions: SimpleStreamOptions | undefined;\n\t\t\tmodel: Model<string>;\n\t\t\tpendingFetches: number;\n\t\t\tcancelled: boolean;\n\t\t\tfinal?: AssistantMessage;\n\t\t}\n\t>();\n\n\tconst modelDefinitions = options.models?.length\n\t\t? options.models\n\t\t: [\n\t\t\t\t{\n\t\t\t\t\tid: DEFAULT_MODEL_ID,\n\t\t\t\t\tname: DEFAULT_MODEL_NAME,\n\t\t\t\t\treasoning: false,\n\t\t\t\t\tinput: [\"text\", \"image\"] as (\"text\" | \"image\")[],\n\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\t\t\t\tcontextWindow: 128000,\n\t\t\t\t\tmaxTokens: 16384,\n\t\t\t\t},\n\t\t\t];\n\tconst models = modelDefinitions.map((definition) => ({\n\t\tid: definition.id,\n\t\tname: definition.name ?? definition.id,\n\t\tapi,\n\t\tprovider,\n\t\tbaseUrl: DEFAULT_BASE_URL,\n\t\treasoning: definition.reasoning ?? false,\n\t\tinput: definition.input ?? [\"text\", \"image\"],\n\t\tcost: definition.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: definition.contextWindow ?? 128000,\n\t\tmaxTokens: definition.maxTokens ?? 16384,\n\t})) as [Model<string>, ...Model<string>[]];\n\n\tconst resolveResponse = async (\n\t\tstep: FauxResponseStep,\n\t\tcontext: Context,\n\t\tstreamOptions: SimpleStreamOptions | undefined,\n\t\trequestModel: Model<string>,\n\t): Promise<AssistantMessage> => {\n\t\tconst resolved = typeof step === \"function\" ? await step(context, streamOptions, state, requestModel) : step;\n\t\treturn withUsageEstimate(\n\t\t\tcloneMessage(resolved, api, provider, requestModel.id),\n\t\t\tcontext,\n\t\t\tstreamOptions,\n\t\t\tpromptCache,\n\t\t);\n\t};\n\n\tconst stream: StreamFunction<string, SimpleStreamOptions> = (requestModel, context, streamOptions) => {\n\t\tconst outer = createAssistantMessageEventStream();\n\t\tconst step = pendingResponses.shift();\n\t\tstate.callCount++;\n\n\t\tqueueMicrotask(async () => {\n\t\t\ttry {\n\t\t\t\tawait streamOptions?.onResponse?.({ status: 200, headers: {} }, requestModel);\n\t\t\t\tif (!step) {\n\t\t\t\t\tlet message = createErrorMessage(\n\t\t\t\t\t\tnew Error(\"No more faux responses queued\"),\n\t\t\t\t\t\tapi,\n\t\t\t\t\t\tprovider,\n\t\t\t\t\t\trequestModel.id,\n\t\t\t\t\t);\n\t\t\t\t\tmessage = withUsageEstimate(message, context, streamOptions, promptCache);\n\t\t\t\t\touter.push({ type: \"error\", reason: \"error\", error: message });\n\t\t\t\t\touter.end(message);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (streamOptions?.deferred) {\n\t\t\t\t\tconst handle: DeferredHandle = {\n\t\t\t\t\t\tprovider: requestModel.provider,\n\t\t\t\t\t\tmodelId: requestModel.id,\n\t\t\t\t\t\tapi: requestModel.api,\n\t\t\t\t\t\tid: randomId(\"deferred\"),\n\t\t\t\t\t\t...(options.deferred?.pollAfterMs !== undefined ? { pollAfterMs: options.deferred.pollAfterMs } : {}),\n\t\t\t\t\t};\n\t\t\t\t\tdeferredResponses.set(handle.id, {\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\tstep,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\toptions: streamOptions,\n\t\t\t\t\t\tmodel: requestModel,\n\t\t\t\t\t\tpendingFetches: Math.max(0, Math.floor(options.deferred?.pendingFetches ?? 0)),\n\t\t\t\t\t\tcancelled: false,\n\t\t\t\t\t});\n\t\t\t\t\tawait streamWithDeltas(\n\t\t\t\t\t\touter,\n\t\t\t\t\t\tcreateDeferredMessage(requestModel, handle),\n\t\t\t\t\t\tminTokenSize,\n\t\t\t\t\t\tmaxTokenSize,\n\t\t\t\t\t\ttokensPerSecond,\n\t\t\t\t\t\tstreamOptions.signal,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst message = await resolveResponse(step, context, streamOptions, requestModel);\n\t\t\t\tawait streamWithDeltas(outer, message, minTokenSize, maxTokenSize, tokensPerSecond, streamOptions?.signal);\n\t\t\t} catch (error) {\n\t\t\t\tconst message = createErrorMessage(error, api, provider, requestModel.id);\n\t\t\t\touter.push({ type: \"error\", reason: \"error\", error: message });\n\t\t\t\touter.end(message);\n\t\t\t}\n\t\t});\n\n\t\treturn outer;\n\t};\n\n\tconst streamSimple: StreamFunction<string, SimpleStreamOptions> = (streamModel, context, streamOptions) =>\n\t\tstream(streamModel, context, streamOptions);\n\n\tconst fetchDeferred = (\n\t\trequestModel: Model<string>,\n\t\thandle: DeferredHandle,\n\t\tfetchOptions?: DeferredFetchOptions,\n\t): AssistantMessageEventStream => {\n\t\tconst outer = createAssistantMessageEventStream();\n\t\tstate.deferredFetchCount++;\n\n\t\tqueueMicrotask(async () => {\n\t\t\ttry {\n\t\t\t\tawait fetchOptions?.onResponse?.({ status: 200, headers: {} }, requestModel);\n\t\t\t\tconst entry = deferredResponses.get(handle.id);\n\t\t\t\tif (\n\t\t\t\t\t!entry ||\n\t\t\t\t\tentry.handle.provider !== handle.provider ||\n\t\t\t\t\tentry.handle.modelId !== handle.modelId ||\n\t\t\t\t\tentry.handle.api !== handle.api\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(`Unknown faux deferred response: ${handle.id}`);\n\t\t\t\t}\n\t\t\t\tif (entry.cancelled) throw new Error(`Faux deferred response was cancelled: ${handle.id}`);\n\n\t\t\t\tif (entry.pendingFetches > 0) {\n\t\t\t\t\tentry.pendingFetches--;\n\t\t\t\t\tawait streamWithDeltas(\n\t\t\t\t\t\touter,\n\t\t\t\t\t\tcreateDeferredMessage(requestModel, entry.handle),\n\t\t\t\t\t\tminTokenSize,\n\t\t\t\t\t\tmaxTokenSize,\n\t\t\t\t\t\ttokensPerSecond,\n\t\t\t\t\t\tfetchOptions?.signal,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!entry.final) {\n\t\t\t\t\tconst {\n\t\t\t\t\t\tdeferred: _deferred,\n\t\t\t\t\t\tsignal: _submissionSignal,\n\t\t\t\t\t\tonResponse: _submissionOnResponse,\n\t\t\t\t\t\t...submissionOptions\n\t\t\t\t\t} = entry.options ?? {};\n\t\t\t\t\ttry {\n\t\t\t\t\t\tentry.final = await resolveResponse(entry.step, entry.context, submissionOptions, entry.model);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tentry.final = createErrorMessage(error, api, provider, entry.model.id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tawait streamWithDeltas(\n\t\t\t\t\touter,\n\t\t\t\t\tentry.final,\n\t\t\t\t\tminTokenSize,\n\t\t\t\t\tmaxTokenSize,\n\t\t\t\t\ttokensPerSecond,\n\t\t\t\t\tfetchOptions?.signal,\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tconst message = createErrorMessage(error, api, provider, requestModel.id);\n\t\t\t\touter.push({ type: \"error\", reason: \"error\", error: message });\n\t\t\t\touter.end(message);\n\t\t\t}\n\t\t});\n\n\t\treturn outer;\n\t};\n\n\tconst cancelDeferred = async (\n\t\trequestModel: Model<string>,\n\t\thandle: DeferredHandle,\n\t\tcancelOptions?: DeferredCancelOptions,\n\t): Promise<void> => {\n\t\tstate.cancelledDeferred.push(structuredClone(handle));\n\t\tconst entry = deferredResponses.get(handle.id);\n\t\tif (entry) entry.cancelled = true;\n\t\tawait cancelOptions?.onResponse?.({ status: 200, headers: {} }, requestModel);\n\t};\n\n\tfunction getModel(): Model<string>;\n\tfunction getModel(requestedModelId: string): Model<string> | undefined;\n\tfunction getModel(requestedModelId?: string): Model<string> | undefined {\n\t\tif (!requestedModelId) {\n\t\t\treturn models[0];\n\t\t}\n\t\treturn models.find((candidate) => candidate.id === requestedModelId);\n\t}\n\n\treturn {\n\t\tapi,\n\t\tprovider,\n\t\tmodels,\n\t\tstream,\n\t\tstreamSimple,\n\t\tfetchDeferred,\n\t\tcancelDeferred,\n\t\tgetModel,\n\t\tstate,\n\t\tsetResponses(responses: FauxResponseStep[]) {\n\t\t\tpendingResponses = [...responses];\n\t\t},\n\t\tappendResponses(responses: FauxResponseStep[]) {\n\t\t\tpendingResponses.push(...responses);\n\t\t},\n\t\tgetPendingResponseCount() {\n\t\t\treturn pendingResponses.length;\n\t\t},\n\t};\n}\n\n/**\n * Faux provider for tests built on explicit `Models` collections:\n *\n * ```ts\n * const faux = fauxProvider();\n * const models = createModels();\n * models.setProvider(faux.provider);\n * faux.setResponses([fauxAssistantMessage(\"hi\")]);\n * ```\n */\nexport function fauxProvider(options: RegisterFauxProviderOptions = {}): FauxProviderHandle {\n\tconst core = createFauxCore(options);\n\tconst provider = createProvider({\n\t\tid: core.provider,\n\t\tauth: { apiKey: { name: \"Faux\", resolve: async () => ({ auth: {} }) } },\n\t\tmodels: core.models,\n\t\tapi: {\n\t\t\tstream: core.stream,\n\t\t\tstreamSimple: core.streamSimple,\n\t\t\tfetchDeferred: core.fetchDeferred,\n\t\t\tcancelDeferred: core.cancelDeferred,\n\t\t},\n\t});\n\treturn {\n\t\tprovider,\n\t\tapi: core.api,\n\t\tmodels: core.models,\n\t\tgetModel: core.getModel,\n\t\tstate: core.state,\n\t\tsetResponses: core.setResponses,\n\t\tappendResponses: core.appendResponses,\n\t\tgetPendingResponseCount: core.getPendingResponseCount,\n\t};\n}\n"]}
@@ -44,6 +44,7 @@ export function fauxAssistantMessage(content, options = {}) {
44
44
  model: DEFAULT_MODEL_ID,
45
45
  usage: DEFAULT_USAGE,
46
46
  stopReason: options.stopReason ?? "stop",
47
+ deferred: options.deferred,
47
48
  errorMessage: options.errorMessage,
48
49
  responseId: options.responseId,
49
50
  timestamp: options.timestamp ?? Date.now(),
@@ -169,6 +170,19 @@ function cloneMessage(message, api, provider, modelId) {
169
170
  usage: cloned.usage ?? DEFAULT_USAGE,
170
171
  };
171
172
  }
173
+ function createDeferredMessage(model, handle) {
174
+ return {
175
+ role: "assistant",
176
+ content: [],
177
+ api: model.api,
178
+ provider: model.provider,
179
+ model: model.id,
180
+ usage: DEFAULT_USAGE,
181
+ stopReason: "deferred",
182
+ deferred: handle,
183
+ timestamp: Date.now(),
184
+ };
185
+ }
172
186
  function createErrorMessage(error, api, provider, modelId) {
173
187
  return {
174
188
  role: "assistant",
@@ -286,8 +300,9 @@ export function createFauxCore(options) {
286
300
  const maxTokenSize = Math.max(minTokenSize, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE);
287
301
  let pendingResponses = [];
288
302
  const tokensPerSecond = options.tokensPerSecond;
289
- const state = { callCount: 0 };
303
+ const state = { callCount: 0, deferredFetchCount: 0, cancelledDeferred: [] };
290
304
  const promptCache = new Map();
305
+ const deferredResponses = new Map();
291
306
  const modelDefinitions = options.models?.length
292
307
  ? options.models
293
308
  : [
@@ -313,6 +328,10 @@ export function createFauxCore(options) {
313
328
  contextWindow: definition.contextWindow ?? 128000,
314
329
  maxTokens: definition.maxTokens ?? 16384,
315
330
  }));
331
+ const resolveResponse = async (step, context, streamOptions, requestModel) => {
332
+ const resolved = typeof step === "function" ? await step(context, streamOptions, state, requestModel) : step;
333
+ return withUsageEstimate(cloneMessage(resolved, api, provider, requestModel.id), context, streamOptions, promptCache);
334
+ };
316
335
  const stream = (requestModel, context, streamOptions) => {
317
336
  const outer = createAssistantMessageEventStream();
318
337
  const step = pendingResponses.shift();
@@ -327,9 +346,27 @@ export function createFauxCore(options) {
327
346
  outer.end(message);
328
347
  return;
329
348
  }
330
- const resolved = typeof step === "function" ? await step(context, streamOptions, state, requestModel) : step;
331
- let message = cloneMessage(resolved, api, provider, requestModel.id);
332
- message = withUsageEstimate(message, context, streamOptions, promptCache);
349
+ if (streamOptions?.deferred) {
350
+ const handle = {
351
+ provider: requestModel.provider,
352
+ modelId: requestModel.id,
353
+ api: requestModel.api,
354
+ id: randomId("deferred"),
355
+ ...(options.deferred?.pollAfterMs !== undefined ? { pollAfterMs: options.deferred.pollAfterMs } : {}),
356
+ };
357
+ deferredResponses.set(handle.id, {
358
+ handle,
359
+ step,
360
+ context,
361
+ options: streamOptions,
362
+ model: requestModel,
363
+ pendingFetches: Math.max(0, Math.floor(options.deferred?.pendingFetches ?? 0)),
364
+ cancelled: false,
365
+ });
366
+ await streamWithDeltas(outer, createDeferredMessage(requestModel, handle), minTokenSize, maxTokenSize, tokensPerSecond, streamOptions.signal);
367
+ return;
368
+ }
369
+ const message = await resolveResponse(step, context, streamOptions, requestModel);
333
370
  await streamWithDeltas(outer, message, minTokenSize, maxTokenSize, tokensPerSecond, streamOptions?.signal);
334
371
  }
335
372
  catch (error) {
@@ -341,6 +378,52 @@ export function createFauxCore(options) {
341
378
  return outer;
342
379
  };
343
380
  const streamSimple = (streamModel, context, streamOptions) => stream(streamModel, context, streamOptions);
381
+ const fetchDeferred = (requestModel, handle, fetchOptions) => {
382
+ const outer = createAssistantMessageEventStream();
383
+ state.deferredFetchCount++;
384
+ queueMicrotask(async () => {
385
+ try {
386
+ await fetchOptions?.onResponse?.({ status: 200, headers: {} }, requestModel);
387
+ const entry = deferredResponses.get(handle.id);
388
+ if (!entry ||
389
+ entry.handle.provider !== handle.provider ||
390
+ entry.handle.modelId !== handle.modelId ||
391
+ entry.handle.api !== handle.api) {
392
+ throw new Error(`Unknown faux deferred response: ${handle.id}`);
393
+ }
394
+ if (entry.cancelled)
395
+ throw new Error(`Faux deferred response was cancelled: ${handle.id}`);
396
+ if (entry.pendingFetches > 0) {
397
+ entry.pendingFetches--;
398
+ await streamWithDeltas(outer, createDeferredMessage(requestModel, entry.handle), minTokenSize, maxTokenSize, tokensPerSecond, fetchOptions?.signal);
399
+ return;
400
+ }
401
+ if (!entry.final) {
402
+ const { deferred: _deferred, signal: _submissionSignal, onResponse: _submissionOnResponse, ...submissionOptions } = entry.options ?? {};
403
+ try {
404
+ entry.final = await resolveResponse(entry.step, entry.context, submissionOptions, entry.model);
405
+ }
406
+ catch (error) {
407
+ entry.final = createErrorMessage(error, api, provider, entry.model.id);
408
+ }
409
+ }
410
+ await streamWithDeltas(outer, entry.final, minTokenSize, maxTokenSize, tokensPerSecond, fetchOptions?.signal);
411
+ }
412
+ catch (error) {
413
+ const message = createErrorMessage(error, api, provider, requestModel.id);
414
+ outer.push({ type: "error", reason: "error", error: message });
415
+ outer.end(message);
416
+ }
417
+ });
418
+ return outer;
419
+ };
420
+ const cancelDeferred = async (requestModel, handle, cancelOptions) => {
421
+ state.cancelledDeferred.push(structuredClone(handle));
422
+ const entry = deferredResponses.get(handle.id);
423
+ if (entry)
424
+ entry.cancelled = true;
425
+ await cancelOptions?.onResponse?.({ status: 200, headers: {} }, requestModel);
426
+ };
344
427
  function getModel(requestedModelId) {
345
428
  if (!requestedModelId) {
346
429
  return models[0];
@@ -353,6 +436,8 @@ export function createFauxCore(options) {
353
436
  models,
354
437
  stream,
355
438
  streamSimple,
439
+ fetchDeferred,
440
+ cancelDeferred,
356
441
  getModel,
357
442
  state,
358
443
  setResponses(responses) {
@@ -382,7 +467,12 @@ export function fauxProvider(options = {}) {
382
467
  id: core.provider,
383
468
  auth: { apiKey: { name: "Faux", resolve: async () => ({ auth: {} }) } },
384
469
  models: core.models,
385
- api: { stream: core.stream, streamSimple: core.streamSimple },
470
+ api: {
471
+ stream: core.stream,
472
+ streamSimple: core.streamSimple,
473
+ fetchDeferred: core.fetchDeferred,
474
+ cancelDeferred: core.cancelDeferred,
475
+ },
386
476
  });
387
477
  return {
388
478
  provider,
@@ -1 +1 @@
1
- {"version":3,"file":"faux.js","sourceRoot":"","sources":["../../src/providers/faux.ts"],"names":[],"mappings":"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","sourcesContent":["import { createProvider, type Provider } from \"../models.ts\";\nimport type {\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tContext,\n\tImageContent,\n\tMessage,\n\tModel,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n\tToolCall,\n\tToolResultMessage,\n\tUsage,\n} from \"../types.ts\";\nimport { createAssistantMessageEventStream } from \"../utils/event-stream.ts\";\n\nconst DEFAULT_API = \"faux\";\nconst DEFAULT_PROVIDER = \"faux\";\nconst DEFAULT_MODEL_ID = \"faux-1\";\nconst DEFAULT_MODEL_NAME = \"Faux Model\";\nconst DEFAULT_BASE_URL = \"http://localhost:0\";\nconst DEFAULT_MIN_TOKEN_SIZE = 3;\nconst DEFAULT_MAX_TOKEN_SIZE = 5;\n\nconst DEFAULT_USAGE: Usage = {\n\tinput: 0,\n\toutput: 0,\n\tcacheRead: 0,\n\tcacheWrite: 0,\n\ttotalTokens: 0,\n\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n};\n\nexport interface FauxModelDefinition {\n\tid: string;\n\tname?: string;\n\treasoning?: boolean;\n\tinput?: (\"text\" | \"image\")[];\n\tcost?: { input: number; output: number; cacheRead: number; cacheWrite: number };\n\tcontextWindow?: number;\n\tmaxTokens?: number;\n}\n\nexport type FauxContentBlock = TextContent | ThinkingContent | ToolCall;\n\nexport function fauxText(text: string): TextContent {\n\treturn { type: \"text\", text };\n}\n\nexport function fauxThinking(thinking: string): ThinkingContent {\n\treturn { type: \"thinking\", thinking };\n}\n\nexport function fauxToolCall(name: string, arguments_: ToolCall[\"arguments\"], options: { id?: string } = {}): ToolCall {\n\treturn {\n\t\ttype: \"toolCall\",\n\t\tid: options.id ?? randomId(\"tool\"),\n\t\tname,\n\t\targuments: arguments_,\n\t};\n}\n\nfunction normalizeFauxAssistantContent(content: string | FauxContentBlock | FauxContentBlock[]): FauxContentBlock[] {\n\tif (typeof content === \"string\") {\n\t\treturn [fauxText(content)];\n\t}\n\treturn Array.isArray(content) ? content : [content];\n}\n\nexport function fauxAssistantMessage(\n\tcontent: string | FauxContentBlock | FauxContentBlock[],\n\toptions: {\n\t\tstopReason?: AssistantMessage[\"stopReason\"];\n\t\terrorMessage?: string;\n\t\tresponseId?: string;\n\t\ttimestamp?: number;\n\t} = {},\n): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: normalizeFauxAssistantContent(content),\n\t\tapi: DEFAULT_API,\n\t\tprovider: DEFAULT_PROVIDER,\n\t\tmodel: DEFAULT_MODEL_ID,\n\t\tusage: DEFAULT_USAGE,\n\t\tstopReason: options.stopReason ?? \"stop\",\n\t\terrorMessage: options.errorMessage,\n\t\tresponseId: options.responseId,\n\t\ttimestamp: options.timestamp ?? Date.now(),\n\t};\n}\n\nexport type FauxResponseFactory = (\n\tcontext: Context,\n\toptions: StreamOptions | undefined,\n\tstate: { callCount: number },\n\tmodel: Model<string>,\n) => AssistantMessage | Promise<AssistantMessage>;\n\nexport type FauxResponseStep = AssistantMessage | FauxResponseFactory;\n\nexport interface RegisterFauxProviderOptions {\n\tapi?: string;\n\tprovider?: string;\n\tmodels?: FauxModelDefinition[];\n\ttokensPerSecond?: number;\n\ttokenSize?: {\n\t\tmin?: number;\n\t\tmax?: number;\n\t};\n}\n\nexport interface FauxProviderRegistration {\n\tapi: string;\n\tmodels: [Model<string>, ...Model<string>[]];\n\tgetModel(): Model<string>;\n\tgetModel(modelId: string): Model<string> | undefined;\n\tstate: { callCount: number };\n\tsetResponses: (responses: FauxResponseStep[]) => void;\n\tappendResponses: (responses: FauxResponseStep[]) => void;\n\tgetPendingResponseCount: () => number;\n\tunregister: () => void;\n}\n\nexport interface FauxProviderHandle {\n\tprovider: Provider;\n\tapi: string;\n\tmodels: [Model<string>, ...Model<string>[]];\n\tgetModel(): Model<string>;\n\tgetModel(modelId: string): Model<string> | undefined;\n\tstate: { callCount: number };\n\tsetResponses: (responses: FauxResponseStep[]) => void;\n\tappendResponses: (responses: FauxResponseStep[]) => void;\n\tgetPendingResponseCount: () => number;\n}\n\nfunction estimateTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\nfunction randomId(prefix: string): string {\n\treturn `${prefix}:${Date.now()}:${Math.random().toString(36).slice(2)}`;\n}\n\nfunction contentToText(content: string | Array<TextContent | ImageContent>): string {\n\tif (typeof content === \"string\") {\n\t\treturn content;\n\t}\n\treturn content\n\t\t.map((block) => {\n\t\t\tif (block.type === \"text\") {\n\t\t\t\treturn block.text;\n\t\t\t}\n\t\t\treturn `[image:${block.mimeType}:${block.data.length}]`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n\nfunction assistantContentToText(content: Array<TextContent | ThinkingContent | ToolCall>): string {\n\treturn content\n\t\t.map((block) => {\n\t\t\tif (block.type === \"text\") {\n\t\t\t\treturn block.text;\n\t\t\t}\n\t\t\tif (block.type === \"thinking\") {\n\t\t\t\treturn block.thinking;\n\t\t\t}\n\t\t\treturn `${block.name}:${JSON.stringify(block.arguments)}`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n\nfunction toolResultToText(message: ToolResultMessage): string {\n\treturn [message.toolName, ...message.content.map((block) => contentToText([block]))].join(\"\\n\");\n}\n\nfunction messageToText(message: Message): string {\n\tif (message.role === \"user\") {\n\t\treturn contentToText(message.content);\n\t}\n\tif (message.role === \"assistant\") {\n\t\treturn assistantContentToText(message.content);\n\t}\n\treturn toolResultToText(message);\n}\n\nfunction serializeContext(context: Context): string {\n\tconst parts: string[] = [];\n\tif (context.systemPrompt) {\n\t\tparts.push(`system:${context.systemPrompt}`);\n\t}\n\tfor (const message of context.messages) {\n\t\tparts.push(`${message.role}:${messageToText(message)}`);\n\t}\n\tif (context.tools?.length) {\n\t\tparts.push(`tools:${JSON.stringify(context.tools)}`);\n\t}\n\treturn parts.join(\"\\n\\n\");\n}\n\nfunction commonPrefixLength(a: string, b: string): number {\n\tconst length = Math.min(a.length, b.length);\n\tlet index = 0;\n\twhile (index < length && a[index] === b[index]) {\n\t\tindex++;\n\t}\n\treturn index;\n}\n\nfunction withUsageEstimate(\n\tmessage: AssistantMessage,\n\tcontext: Context,\n\toptions: StreamOptions | undefined,\n\tpromptCache: Map<string, string>,\n): AssistantMessage {\n\tconst promptText = serializeContext(context);\n\tconst promptTokens = estimateTokens(promptText);\n\tconst outputTokens = estimateTokens(assistantContentToText(message.content));\n\tlet input = promptTokens;\n\tlet cacheRead = 0;\n\tlet cacheWrite = 0;\n\tconst sessionId = options?.sessionId;\n\n\tif (sessionId && options?.cacheRetention !== \"none\") {\n\t\tconst previousPrompt = promptCache.get(sessionId);\n\t\tif (previousPrompt) {\n\t\t\tconst cachedChars = commonPrefixLength(previousPrompt, promptText);\n\t\t\tcacheRead = estimateTokens(previousPrompt.slice(0, cachedChars));\n\t\t\tcacheWrite = estimateTokens(promptText.slice(cachedChars));\n\t\t\tinput = Math.max(0, promptTokens - cacheRead);\n\t\t} else {\n\t\t\tcacheWrite = promptTokens;\n\t\t}\n\t\tpromptCache.set(sessionId, promptText);\n\t}\n\n\treturn {\n\t\t...message,\n\t\tusage: {\n\t\t\tinput,\n\t\t\toutput: outputTokens,\n\t\t\tcacheRead,\n\t\t\tcacheWrite,\n\t\t\ttotalTokens: input + outputTokens + cacheRead + cacheWrite,\n\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t},\n\t};\n}\n\nfunction splitStringByTokenSize(text: string, minTokenSize: number, maxTokenSize: number): string[] {\n\tconst chunks: string[] = [];\n\tlet index = 0;\n\twhile (index < text.length) {\n\t\tconst tokenSize = minTokenSize + Math.floor(Math.random() * (maxTokenSize - minTokenSize + 1));\n\t\tconst charSize = Math.max(1, tokenSize * 4);\n\t\tchunks.push(text.slice(index, index + charSize));\n\t\tindex += charSize;\n\t}\n\treturn chunks.length > 0 ? chunks : [\"\"];\n}\n\nfunction cloneMessage(message: AssistantMessage, api: string, provider: string, modelId: string): AssistantMessage {\n\tconst cloned = structuredClone(message);\n\treturn {\n\t\t...cloned,\n\t\tapi,\n\t\tprovider,\n\t\tmodel: modelId,\n\t\ttimestamp: cloned.timestamp ?? Date.now(),\n\t\tusage: cloned.usage ?? DEFAULT_USAGE,\n\t};\n}\n\nfunction createErrorMessage(error: unknown, api: string, provider: string, modelId: string): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi,\n\t\tprovider,\n\t\tmodel: modelId,\n\t\tusage: DEFAULT_USAGE,\n\t\tstopReason: \"error\",\n\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction createAbortedMessage(partial: AssistantMessage): AssistantMessage {\n\treturn {\n\t\t...partial,\n\t\tstopReason: \"aborted\",\n\t\terrorMessage: \"Request was aborted\",\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction scheduleChunk(chunk: string, tokensPerSecond: number | undefined): Promise<void> {\n\tif (!tokensPerSecond || tokensPerSecond <= 0) {\n\t\treturn new Promise((resolve) => queueMicrotask(resolve));\n\t}\n\tconst delayMs = (estimateTokens(chunk) / tokensPerSecond) * 1000;\n\treturn new Promise((resolve) => setTimeout(resolve, delayMs));\n}\n\nasync function streamWithDeltas(\n\tstream: AssistantMessageEventStream,\n\tmessage: AssistantMessage,\n\tminTokenSize: number,\n\tmaxTokenSize: number,\n\ttokensPerSecond: number | undefined,\n\tsignal: AbortSignal | undefined,\n): Promise<void> {\n\tconst partial: AssistantMessage = { ...message, content: [], stopReason: \"pending\" };\n\tif (signal?.aborted) {\n\t\tconst aborted = createAbortedMessage(partial);\n\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\tstream.end(aborted);\n\t\treturn;\n\t}\n\n\tstream.push({ type: \"start\", partial: { ...partial } });\n\n\tfor (let index = 0; index < message.content.length; index++) {\n\t\tif (signal?.aborted) {\n\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\tstream.end(aborted);\n\t\t\treturn;\n\t\t}\n\n\t\tconst block = message.content[index];\n\n\t\tif (block.type === \"thinking\") {\n\t\t\tpartial.content = [...partial.content, { type: \"thinking\", thinking: \"\" }];\n\t\t\tstream.push({ type: \"thinking_start\", contentIndex: index, partial: { ...partial } });\n\t\t\tfor (const chunk of splitStringByTokenSize(block.thinking, minTokenSize, maxTokenSize)) {\n\t\t\t\tawait scheduleChunk(chunk, tokensPerSecond);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\t\t\tstream.end(aborted);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t(partial.content[index] as ThinkingContent).thinking += chunk;\n\t\t\t\tstream.push({ type: \"thinking_delta\", contentIndex: index, delta: chunk, partial: { ...partial } });\n\t\t\t}\n\t\t\tstream.push({\n\t\t\t\ttype: \"thinking_end\",\n\t\t\t\tcontentIndex: index,\n\t\t\t\tcontent: block.thinking,\n\t\t\t\tpartial: { ...partial },\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (block.type === \"text\") {\n\t\t\tpartial.content = [...partial.content, { type: \"text\", text: \"\" }];\n\t\t\tstream.push({ type: \"text_start\", contentIndex: index, partial: { ...partial } });\n\t\t\tfor (const chunk of splitStringByTokenSize(block.text, minTokenSize, maxTokenSize)) {\n\t\t\t\tawait scheduleChunk(chunk, tokensPerSecond);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\t\t\tstream.end(aborted);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t(partial.content[index] as TextContent).text += chunk;\n\t\t\t\tstream.push({ type: \"text_delta\", contentIndex: index, delta: chunk, partial: { ...partial } });\n\t\t\t}\n\t\t\tstream.push({ type: \"text_end\", contentIndex: index, content: block.text, partial: { ...partial } });\n\t\t\tcontinue;\n\t\t}\n\n\t\tpartial.content = [...partial.content, { type: \"toolCall\", id: block.id, name: block.name, arguments: {} }];\n\t\tstream.push({ type: \"toolcall_start\", contentIndex: index, partial: { ...partial } });\n\t\tfor (const chunk of splitStringByTokenSize(JSON.stringify(block.arguments), minTokenSize, maxTokenSize)) {\n\t\t\tawait scheduleChunk(chunk, tokensPerSecond);\n\t\t\tif (signal?.aborted) {\n\t\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\t\tstream.end(aborted);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstream.push({ type: \"toolcall_delta\", contentIndex: index, delta: chunk, partial: { ...partial } });\n\t\t}\n\t\t(partial.content[index] as ToolCall).arguments = block.arguments;\n\t\tstream.push({ type: \"toolcall_end\", contentIndex: index, toolCall: block, partial: { ...partial } });\n\t}\n\n\tif (message.stopReason === \"pending\") {\n\t\tthrow new Error(\"Faux response ended without a stop reason\");\n\t}\n\tif (message.stopReason === \"error\" || message.stopReason === \"aborted\") {\n\t\tstream.push({ type: \"error\", reason: message.stopReason, error: message });\n\t\tstream.end(message);\n\t\treturn;\n\t}\n\n\tstream.push({ type: \"done\", reason: message.stopReason, message });\n\tstream.end(message);\n}\n\nexport function createFauxCore(options: RegisterFauxProviderOptions) {\n\tconst api = options.api ?? randomId(DEFAULT_API);\n\tconst provider = options.provider ?? DEFAULT_PROVIDER;\n\tconst minTokenSize = Math.max(\n\t\t1,\n\t\tMath.min(options.tokenSize?.min ?? DEFAULT_MIN_TOKEN_SIZE, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE),\n\t);\n\tconst maxTokenSize = Math.max(minTokenSize, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE);\n\tlet pendingResponses: FauxResponseStep[] = [];\n\tconst tokensPerSecond = options.tokensPerSecond;\n\tconst state = { callCount: 0 };\n\tconst promptCache = new Map<string, string>();\n\n\tconst modelDefinitions = options.models?.length\n\t\t? options.models\n\t\t: [\n\t\t\t\t{\n\t\t\t\t\tid: DEFAULT_MODEL_ID,\n\t\t\t\t\tname: DEFAULT_MODEL_NAME,\n\t\t\t\t\treasoning: false,\n\t\t\t\t\tinput: [\"text\", \"image\"] as (\"text\" | \"image\")[],\n\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\t\t\t\tcontextWindow: 128000,\n\t\t\t\t\tmaxTokens: 16384,\n\t\t\t\t},\n\t\t\t];\n\tconst models = modelDefinitions.map((definition) => ({\n\t\tid: definition.id,\n\t\tname: definition.name ?? definition.id,\n\t\tapi,\n\t\tprovider,\n\t\tbaseUrl: DEFAULT_BASE_URL,\n\t\treasoning: definition.reasoning ?? false,\n\t\tinput: definition.input ?? [\"text\", \"image\"],\n\t\tcost: definition.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: definition.contextWindow ?? 128000,\n\t\tmaxTokens: definition.maxTokens ?? 16384,\n\t})) as [Model<string>, ...Model<string>[]];\n\n\tconst stream: StreamFunction<string, StreamOptions> = (requestModel, context, streamOptions) => {\n\t\tconst outer = createAssistantMessageEventStream();\n\t\tconst step = pendingResponses.shift();\n\t\tstate.callCount++;\n\n\t\tqueueMicrotask(async () => {\n\t\t\ttry {\n\t\t\t\tawait streamOptions?.onResponse?.({ status: 200, headers: {} }, requestModel);\n\t\t\t\tif (!step) {\n\t\t\t\t\tlet message = createErrorMessage(\n\t\t\t\t\t\tnew Error(\"No more faux responses queued\"),\n\t\t\t\t\t\tapi,\n\t\t\t\t\t\tprovider,\n\t\t\t\t\t\trequestModel.id,\n\t\t\t\t\t);\n\t\t\t\t\tmessage = withUsageEstimate(message, context, streamOptions, promptCache);\n\t\t\t\t\touter.push({ type: \"error\", reason: \"error\", error: message });\n\t\t\t\t\touter.end(message);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst resolved =\n\t\t\t\t\ttypeof step === \"function\" ? await step(context, streamOptions, state, requestModel) : step;\n\t\t\t\tlet message = cloneMessage(resolved, api, provider, requestModel.id);\n\t\t\t\tmessage = withUsageEstimate(message, context, streamOptions, promptCache);\n\t\t\t\tawait streamWithDeltas(outer, message, minTokenSize, maxTokenSize, tokensPerSecond, streamOptions?.signal);\n\t\t\t} catch (error) {\n\t\t\t\tconst message = createErrorMessage(error, api, provider, requestModel.id);\n\t\t\t\touter.push({ type: \"error\", reason: \"error\", error: message });\n\t\t\t\touter.end(message);\n\t\t\t}\n\t\t});\n\n\t\treturn outer;\n\t};\n\n\tconst streamSimple: StreamFunction<string, SimpleStreamOptions> = (streamModel, context, streamOptions) =>\n\t\tstream(streamModel, context, streamOptions);\n\n\tfunction getModel(): Model<string>;\n\tfunction getModel(requestedModelId: string): Model<string> | undefined;\n\tfunction getModel(requestedModelId?: string): Model<string> | undefined {\n\t\tif (!requestedModelId) {\n\t\t\treturn models[0];\n\t\t}\n\t\treturn models.find((candidate) => candidate.id === requestedModelId);\n\t}\n\n\treturn {\n\t\tapi,\n\t\tprovider,\n\t\tmodels,\n\t\tstream,\n\t\tstreamSimple,\n\t\tgetModel,\n\t\tstate,\n\t\tsetResponses(responses: FauxResponseStep[]) {\n\t\t\tpendingResponses = [...responses];\n\t\t},\n\t\tappendResponses(responses: FauxResponseStep[]) {\n\t\t\tpendingResponses.push(...responses);\n\t\t},\n\t\tgetPendingResponseCount() {\n\t\t\treturn pendingResponses.length;\n\t\t},\n\t};\n}\n\n/**\n * Faux provider for tests built on explicit `Models` collections:\n *\n * ```ts\n * const faux = fauxProvider();\n * const models = createModels();\n * models.setProvider(faux.provider);\n * faux.setResponses([fauxAssistantMessage(\"hi\")]);\n * ```\n */\nexport function fauxProvider(options: RegisterFauxProviderOptions = {}): FauxProviderHandle {\n\tconst core = createFauxCore(options);\n\tconst provider = createProvider({\n\t\tid: core.provider,\n\t\tauth: { apiKey: { name: \"Faux\", resolve: async () => ({ auth: {} }) } },\n\t\tmodels: core.models,\n\t\tapi: { stream: core.stream, streamSimple: core.streamSimple },\n\t});\n\treturn {\n\t\tprovider,\n\t\tapi: core.api,\n\t\tmodels: core.models,\n\t\tgetModel: core.getModel,\n\t\tstate: core.state,\n\t\tsetResponses: core.setResponses,\n\t\tappendResponses: core.appendResponses,\n\t\tgetPendingResponseCount: core.getPendingResponseCount,\n\t};\n}\n"]}
1
+ {"version":3,"file":"faux.js","sourceRoot":"","sources":["../../src/providers/faux.ts"],"names":[],"mappings":"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","sourcesContent":["import { createProvider, type Provider } from \"../models.ts\";\nimport type {\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tContext,\n\tDeferredCancelOptions,\n\tDeferredFetchOptions,\n\tDeferredHandle,\n\tImageContent,\n\tMessage,\n\tModel,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n\tToolCall,\n\tToolResultMessage,\n\tUsage,\n} from \"../types.ts\";\nimport { createAssistantMessageEventStream } from \"../utils/event-stream.ts\";\n\nconst DEFAULT_API = \"faux\";\nconst DEFAULT_PROVIDER = \"faux\";\nconst DEFAULT_MODEL_ID = \"faux-1\";\nconst DEFAULT_MODEL_NAME = \"Faux Model\";\nconst DEFAULT_BASE_URL = \"http://localhost:0\";\nconst DEFAULT_MIN_TOKEN_SIZE = 3;\nconst DEFAULT_MAX_TOKEN_SIZE = 5;\n\nconst DEFAULT_USAGE: Usage = {\n\tinput: 0,\n\toutput: 0,\n\tcacheRead: 0,\n\tcacheWrite: 0,\n\ttotalTokens: 0,\n\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n};\n\nexport interface FauxModelDefinition {\n\tid: string;\n\tname?: string;\n\treasoning?: boolean;\n\tinput?: (\"text\" | \"image\")[];\n\tcost?: { input: number; output: number; cacheRead: number; cacheWrite: number };\n\tcontextWindow?: number;\n\tmaxTokens?: number;\n}\n\nexport type FauxContentBlock = TextContent | ThinkingContent | ToolCall;\n\nexport function fauxText(text: string): TextContent {\n\treturn { type: \"text\", text };\n}\n\nexport function fauxThinking(thinking: string): ThinkingContent {\n\treturn { type: \"thinking\", thinking };\n}\n\nexport function fauxToolCall(name: string, arguments_: ToolCall[\"arguments\"], options: { id?: string } = {}): ToolCall {\n\treturn {\n\t\ttype: \"toolCall\",\n\t\tid: options.id ?? randomId(\"tool\"),\n\t\tname,\n\t\targuments: arguments_,\n\t};\n}\n\nfunction normalizeFauxAssistantContent(content: string | FauxContentBlock | FauxContentBlock[]): FauxContentBlock[] {\n\tif (typeof content === \"string\") {\n\t\treturn [fauxText(content)];\n\t}\n\treturn Array.isArray(content) ? content : [content];\n}\n\nexport function fauxAssistantMessage(\n\tcontent: string | FauxContentBlock | FauxContentBlock[],\n\toptions: {\n\t\tstopReason?: AssistantMessage[\"stopReason\"];\n\t\tdeferred?: DeferredHandle;\n\t\terrorMessage?: string;\n\t\tresponseId?: string;\n\t\ttimestamp?: number;\n\t} = {},\n): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: normalizeFauxAssistantContent(content),\n\t\tapi: DEFAULT_API,\n\t\tprovider: DEFAULT_PROVIDER,\n\t\tmodel: DEFAULT_MODEL_ID,\n\t\tusage: DEFAULT_USAGE,\n\t\tstopReason: options.stopReason ?? \"stop\",\n\t\tdeferred: options.deferred,\n\t\terrorMessage: options.errorMessage,\n\t\tresponseId: options.responseId,\n\t\ttimestamp: options.timestamp ?? Date.now(),\n\t};\n}\n\nexport interface FauxProviderState {\n\tcallCount: number;\n\tdeferredFetchCount: number;\n\tcancelledDeferred: DeferredHandle[];\n}\n\nexport type FauxResponseFactory = (\n\tcontext: Context,\n\toptions: SimpleStreamOptions | undefined,\n\tstate: FauxProviderState,\n\tmodel: Model<string>,\n) => AssistantMessage | Promise<AssistantMessage>;\n\nexport type FauxResponseStep = AssistantMessage | FauxResponseFactory;\n\nexport interface RegisterFauxProviderOptions {\n\tapi?: string;\n\tprovider?: string;\n\tmodels?: FauxModelDefinition[];\n\tdeferred?: {\n\t\t/** Number of fetches that return the original handle before the scripted response becomes ready. */\n\t\tpendingFetches?: number;\n\t\tpollAfterMs?: number;\n\t};\n\ttokensPerSecond?: number;\n\ttokenSize?: {\n\t\tmin?: number;\n\t\tmax?: number;\n\t};\n}\n\nexport interface FauxProviderRegistration {\n\tapi: string;\n\tmodels: [Model<string>, ...Model<string>[]];\n\tgetModel(): Model<string>;\n\tgetModel(modelId: string): Model<string> | undefined;\n\tstate: FauxProviderState;\n\tsetResponses: (responses: FauxResponseStep[]) => void;\n\tappendResponses: (responses: FauxResponseStep[]) => void;\n\tgetPendingResponseCount: () => number;\n\tunregister: () => void;\n}\n\nexport interface FauxProviderHandle {\n\tprovider: Provider;\n\tapi: string;\n\tmodels: [Model<string>, ...Model<string>[]];\n\tgetModel(): Model<string>;\n\tgetModel(modelId: string): Model<string> | undefined;\n\tstate: FauxProviderState;\n\tsetResponses: (responses: FauxResponseStep[]) => void;\n\tappendResponses: (responses: FauxResponseStep[]) => void;\n\tgetPendingResponseCount: () => number;\n}\n\nfunction estimateTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\nfunction randomId(prefix: string): string {\n\treturn `${prefix}:${Date.now()}:${Math.random().toString(36).slice(2)}`;\n}\n\nfunction contentToText(content: string | Array<TextContent | ImageContent>): string {\n\tif (typeof content === \"string\") {\n\t\treturn content;\n\t}\n\treturn content\n\t\t.map((block) => {\n\t\t\tif (block.type === \"text\") {\n\t\t\t\treturn block.text;\n\t\t\t}\n\t\t\treturn `[image:${block.mimeType}:${block.data.length}]`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n\nfunction assistantContentToText(content: Array<TextContent | ThinkingContent | ToolCall>): string {\n\treturn content\n\t\t.map((block) => {\n\t\t\tif (block.type === \"text\") {\n\t\t\t\treturn block.text;\n\t\t\t}\n\t\t\tif (block.type === \"thinking\") {\n\t\t\t\treturn block.thinking;\n\t\t\t}\n\t\t\treturn `${block.name}:${JSON.stringify(block.arguments)}`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n\nfunction toolResultToText(message: ToolResultMessage): string {\n\treturn [message.toolName, ...message.content.map((block) => contentToText([block]))].join(\"\\n\");\n}\n\nfunction messageToText(message: Message): string {\n\tif (message.role === \"user\") {\n\t\treturn contentToText(message.content);\n\t}\n\tif (message.role === \"assistant\") {\n\t\treturn assistantContentToText(message.content);\n\t}\n\treturn toolResultToText(message);\n}\n\nfunction serializeContext(context: Context): string {\n\tconst parts: string[] = [];\n\tif (context.systemPrompt) {\n\t\tparts.push(`system:${context.systemPrompt}`);\n\t}\n\tfor (const message of context.messages) {\n\t\tparts.push(`${message.role}:${messageToText(message)}`);\n\t}\n\tif (context.tools?.length) {\n\t\tparts.push(`tools:${JSON.stringify(context.tools)}`);\n\t}\n\treturn parts.join(\"\\n\\n\");\n}\n\nfunction commonPrefixLength(a: string, b: string): number {\n\tconst length = Math.min(a.length, b.length);\n\tlet index = 0;\n\twhile (index < length && a[index] === b[index]) {\n\t\tindex++;\n\t}\n\treturn index;\n}\n\nfunction withUsageEstimate(\n\tmessage: AssistantMessage,\n\tcontext: Context,\n\toptions: StreamOptions | undefined,\n\tpromptCache: Map<string, string>,\n): AssistantMessage {\n\tconst promptText = serializeContext(context);\n\tconst promptTokens = estimateTokens(promptText);\n\tconst outputTokens = estimateTokens(assistantContentToText(message.content));\n\tlet input = promptTokens;\n\tlet cacheRead = 0;\n\tlet cacheWrite = 0;\n\tconst sessionId = options?.sessionId;\n\n\tif (sessionId && options?.cacheRetention !== \"none\") {\n\t\tconst previousPrompt = promptCache.get(sessionId);\n\t\tif (previousPrompt) {\n\t\t\tconst cachedChars = commonPrefixLength(previousPrompt, promptText);\n\t\t\tcacheRead = estimateTokens(previousPrompt.slice(0, cachedChars));\n\t\t\tcacheWrite = estimateTokens(promptText.slice(cachedChars));\n\t\t\tinput = Math.max(0, promptTokens - cacheRead);\n\t\t} else {\n\t\t\tcacheWrite = promptTokens;\n\t\t}\n\t\tpromptCache.set(sessionId, promptText);\n\t}\n\n\treturn {\n\t\t...message,\n\t\tusage: {\n\t\t\tinput,\n\t\t\toutput: outputTokens,\n\t\t\tcacheRead,\n\t\t\tcacheWrite,\n\t\t\ttotalTokens: input + outputTokens + cacheRead + cacheWrite,\n\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t},\n\t};\n}\n\nfunction splitStringByTokenSize(text: string, minTokenSize: number, maxTokenSize: number): string[] {\n\tconst chunks: string[] = [];\n\tlet index = 0;\n\twhile (index < text.length) {\n\t\tconst tokenSize = minTokenSize + Math.floor(Math.random() * (maxTokenSize - minTokenSize + 1));\n\t\tconst charSize = Math.max(1, tokenSize * 4);\n\t\tchunks.push(text.slice(index, index + charSize));\n\t\tindex += charSize;\n\t}\n\treturn chunks.length > 0 ? chunks : [\"\"];\n}\n\nfunction cloneMessage(message: AssistantMessage, api: string, provider: string, modelId: string): AssistantMessage {\n\tconst cloned = structuredClone(message);\n\treturn {\n\t\t...cloned,\n\t\tapi,\n\t\tprovider,\n\t\tmodel: modelId,\n\t\ttimestamp: cloned.timestamp ?? Date.now(),\n\t\tusage: cloned.usage ?? DEFAULT_USAGE,\n\t};\n}\n\nfunction createDeferredMessage(model: Model<string>, handle: DeferredHandle): AssistantMessage {\n\treturn {\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: DEFAULT_USAGE,\n\t\tstopReason: \"deferred\",\n\t\tdeferred: handle,\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction createErrorMessage(error: unknown, api: string, provider: string, modelId: string): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi,\n\t\tprovider,\n\t\tmodel: modelId,\n\t\tusage: DEFAULT_USAGE,\n\t\tstopReason: \"error\",\n\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction createAbortedMessage(partial: AssistantMessage): AssistantMessage {\n\treturn {\n\t\t...partial,\n\t\tstopReason: \"aborted\",\n\t\terrorMessage: \"Request was aborted\",\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction scheduleChunk(chunk: string, tokensPerSecond: number | undefined): Promise<void> {\n\tif (!tokensPerSecond || tokensPerSecond <= 0) {\n\t\treturn new Promise((resolve) => queueMicrotask(resolve));\n\t}\n\tconst delayMs = (estimateTokens(chunk) / tokensPerSecond) * 1000;\n\treturn new Promise((resolve) => setTimeout(resolve, delayMs));\n}\n\nasync function streamWithDeltas(\n\tstream: AssistantMessageEventStream,\n\tmessage: AssistantMessage,\n\tminTokenSize: number,\n\tmaxTokenSize: number,\n\ttokensPerSecond: number | undefined,\n\tsignal: AbortSignal | undefined,\n): Promise<void> {\n\tconst partial: AssistantMessage = { ...message, content: [], stopReason: \"pending\" };\n\tif (signal?.aborted) {\n\t\tconst aborted = createAbortedMessage(partial);\n\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\tstream.end(aborted);\n\t\treturn;\n\t}\n\n\tstream.push({ type: \"start\", partial: { ...partial } });\n\n\tfor (let index = 0; index < message.content.length; index++) {\n\t\tif (signal?.aborted) {\n\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\tstream.end(aborted);\n\t\t\treturn;\n\t\t}\n\n\t\tconst block = message.content[index];\n\n\t\tif (block.type === \"thinking\") {\n\t\t\tpartial.content = [...partial.content, { type: \"thinking\", thinking: \"\" }];\n\t\t\tstream.push({ type: \"thinking_start\", contentIndex: index, partial: { ...partial } });\n\t\t\tfor (const chunk of splitStringByTokenSize(block.thinking, minTokenSize, maxTokenSize)) {\n\t\t\t\tawait scheduleChunk(chunk, tokensPerSecond);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\t\t\tstream.end(aborted);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t(partial.content[index] as ThinkingContent).thinking += chunk;\n\t\t\t\tstream.push({ type: \"thinking_delta\", contentIndex: index, delta: chunk, partial: { ...partial } });\n\t\t\t}\n\t\t\tstream.push({\n\t\t\t\ttype: \"thinking_end\",\n\t\t\t\tcontentIndex: index,\n\t\t\t\tcontent: block.thinking,\n\t\t\t\tpartial: { ...partial },\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (block.type === \"text\") {\n\t\t\tpartial.content = [...partial.content, { type: \"text\", text: \"\" }];\n\t\t\tstream.push({ type: \"text_start\", contentIndex: index, partial: { ...partial } });\n\t\t\tfor (const chunk of splitStringByTokenSize(block.text, minTokenSize, maxTokenSize)) {\n\t\t\t\tawait scheduleChunk(chunk, tokensPerSecond);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\t\t\tstream.end(aborted);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t(partial.content[index] as TextContent).text += chunk;\n\t\t\t\tstream.push({ type: \"text_delta\", contentIndex: index, delta: chunk, partial: { ...partial } });\n\t\t\t}\n\t\t\tstream.push({ type: \"text_end\", contentIndex: index, content: block.text, partial: { ...partial } });\n\t\t\tcontinue;\n\t\t}\n\n\t\tpartial.content = [...partial.content, { type: \"toolCall\", id: block.id, name: block.name, arguments: {} }];\n\t\tstream.push({ type: \"toolcall_start\", contentIndex: index, partial: { ...partial } });\n\t\tfor (const chunk of splitStringByTokenSize(JSON.stringify(block.arguments), minTokenSize, maxTokenSize)) {\n\t\t\tawait scheduleChunk(chunk, tokensPerSecond);\n\t\t\tif (signal?.aborted) {\n\t\t\t\tconst aborted = createAbortedMessage(partial);\n\t\t\t\tstream.push({ type: \"error\", reason: \"aborted\", error: aborted });\n\t\t\t\tstream.end(aborted);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstream.push({ type: \"toolcall_delta\", contentIndex: index, delta: chunk, partial: { ...partial } });\n\t\t}\n\t\t(partial.content[index] as ToolCall).arguments = block.arguments;\n\t\tstream.push({ type: \"toolcall_end\", contentIndex: index, toolCall: block, partial: { ...partial } });\n\t}\n\n\tif (message.stopReason === \"pending\") {\n\t\tthrow new Error(\"Faux response ended without a stop reason\");\n\t}\n\tif (message.stopReason === \"error\" || message.stopReason === \"aborted\") {\n\t\tstream.push({ type: \"error\", reason: message.stopReason, error: message });\n\t\tstream.end(message);\n\t\treturn;\n\t}\n\n\tstream.push({ type: \"done\", reason: message.stopReason, message });\n\tstream.end(message);\n}\n\nexport function createFauxCore(options: RegisterFauxProviderOptions) {\n\tconst api = options.api ?? randomId(DEFAULT_API);\n\tconst provider = options.provider ?? DEFAULT_PROVIDER;\n\tconst minTokenSize = Math.max(\n\t\t1,\n\t\tMath.min(options.tokenSize?.min ?? DEFAULT_MIN_TOKEN_SIZE, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE),\n\t);\n\tconst maxTokenSize = Math.max(minTokenSize, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE);\n\tlet pendingResponses: FauxResponseStep[] = [];\n\tconst tokensPerSecond = options.tokensPerSecond;\n\tconst state: FauxProviderState = { callCount: 0, deferredFetchCount: 0, cancelledDeferred: [] };\n\tconst promptCache = new Map<string, string>();\n\tconst deferredResponses = new Map<\n\t\tstring,\n\t\t{\n\t\t\thandle: DeferredHandle;\n\t\t\tstep: FauxResponseStep;\n\t\t\tcontext: Context;\n\t\t\toptions: SimpleStreamOptions | undefined;\n\t\t\tmodel: Model<string>;\n\t\t\tpendingFetches: number;\n\t\t\tcancelled: boolean;\n\t\t\tfinal?: AssistantMessage;\n\t\t}\n\t>();\n\n\tconst modelDefinitions = options.models?.length\n\t\t? options.models\n\t\t: [\n\t\t\t\t{\n\t\t\t\t\tid: DEFAULT_MODEL_ID,\n\t\t\t\t\tname: DEFAULT_MODEL_NAME,\n\t\t\t\t\treasoning: false,\n\t\t\t\t\tinput: [\"text\", \"image\"] as (\"text\" | \"image\")[],\n\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\t\t\t\tcontextWindow: 128000,\n\t\t\t\t\tmaxTokens: 16384,\n\t\t\t\t},\n\t\t\t];\n\tconst models = modelDefinitions.map((definition) => ({\n\t\tid: definition.id,\n\t\tname: definition.name ?? definition.id,\n\t\tapi,\n\t\tprovider,\n\t\tbaseUrl: DEFAULT_BASE_URL,\n\t\treasoning: definition.reasoning ?? false,\n\t\tinput: definition.input ?? [\"text\", \"image\"],\n\t\tcost: definition.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: definition.contextWindow ?? 128000,\n\t\tmaxTokens: definition.maxTokens ?? 16384,\n\t})) as [Model<string>, ...Model<string>[]];\n\n\tconst resolveResponse = async (\n\t\tstep: FauxResponseStep,\n\t\tcontext: Context,\n\t\tstreamOptions: SimpleStreamOptions | undefined,\n\t\trequestModel: Model<string>,\n\t): Promise<AssistantMessage> => {\n\t\tconst resolved = typeof step === \"function\" ? await step(context, streamOptions, state, requestModel) : step;\n\t\treturn withUsageEstimate(\n\t\t\tcloneMessage(resolved, api, provider, requestModel.id),\n\t\t\tcontext,\n\t\t\tstreamOptions,\n\t\t\tpromptCache,\n\t\t);\n\t};\n\n\tconst stream: StreamFunction<string, SimpleStreamOptions> = (requestModel, context, streamOptions) => {\n\t\tconst outer = createAssistantMessageEventStream();\n\t\tconst step = pendingResponses.shift();\n\t\tstate.callCount++;\n\n\t\tqueueMicrotask(async () => {\n\t\t\ttry {\n\t\t\t\tawait streamOptions?.onResponse?.({ status: 200, headers: {} }, requestModel);\n\t\t\t\tif (!step) {\n\t\t\t\t\tlet message = createErrorMessage(\n\t\t\t\t\t\tnew Error(\"No more faux responses queued\"),\n\t\t\t\t\t\tapi,\n\t\t\t\t\t\tprovider,\n\t\t\t\t\t\trequestModel.id,\n\t\t\t\t\t);\n\t\t\t\t\tmessage = withUsageEstimate(message, context, streamOptions, promptCache);\n\t\t\t\t\touter.push({ type: \"error\", reason: \"error\", error: message });\n\t\t\t\t\touter.end(message);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (streamOptions?.deferred) {\n\t\t\t\t\tconst handle: DeferredHandle = {\n\t\t\t\t\t\tprovider: requestModel.provider,\n\t\t\t\t\t\tmodelId: requestModel.id,\n\t\t\t\t\t\tapi: requestModel.api,\n\t\t\t\t\t\tid: randomId(\"deferred\"),\n\t\t\t\t\t\t...(options.deferred?.pollAfterMs !== undefined ? { pollAfterMs: options.deferred.pollAfterMs } : {}),\n\t\t\t\t\t};\n\t\t\t\t\tdeferredResponses.set(handle.id, {\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\tstep,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\toptions: streamOptions,\n\t\t\t\t\t\tmodel: requestModel,\n\t\t\t\t\t\tpendingFetches: Math.max(0, Math.floor(options.deferred?.pendingFetches ?? 0)),\n\t\t\t\t\t\tcancelled: false,\n\t\t\t\t\t});\n\t\t\t\t\tawait streamWithDeltas(\n\t\t\t\t\t\touter,\n\t\t\t\t\t\tcreateDeferredMessage(requestModel, handle),\n\t\t\t\t\t\tminTokenSize,\n\t\t\t\t\t\tmaxTokenSize,\n\t\t\t\t\t\ttokensPerSecond,\n\t\t\t\t\t\tstreamOptions.signal,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst message = await resolveResponse(step, context, streamOptions, requestModel);\n\t\t\t\tawait streamWithDeltas(outer, message, minTokenSize, maxTokenSize, tokensPerSecond, streamOptions?.signal);\n\t\t\t} catch (error) {\n\t\t\t\tconst message = createErrorMessage(error, api, provider, requestModel.id);\n\t\t\t\touter.push({ type: \"error\", reason: \"error\", error: message });\n\t\t\t\touter.end(message);\n\t\t\t}\n\t\t});\n\n\t\treturn outer;\n\t};\n\n\tconst streamSimple: StreamFunction<string, SimpleStreamOptions> = (streamModel, context, streamOptions) =>\n\t\tstream(streamModel, context, streamOptions);\n\n\tconst fetchDeferred = (\n\t\trequestModel: Model<string>,\n\t\thandle: DeferredHandle,\n\t\tfetchOptions?: DeferredFetchOptions,\n\t): AssistantMessageEventStream => {\n\t\tconst outer = createAssistantMessageEventStream();\n\t\tstate.deferredFetchCount++;\n\n\t\tqueueMicrotask(async () => {\n\t\t\ttry {\n\t\t\t\tawait fetchOptions?.onResponse?.({ status: 200, headers: {} }, requestModel);\n\t\t\t\tconst entry = deferredResponses.get(handle.id);\n\t\t\t\tif (\n\t\t\t\t\t!entry ||\n\t\t\t\t\tentry.handle.provider !== handle.provider ||\n\t\t\t\t\tentry.handle.modelId !== handle.modelId ||\n\t\t\t\t\tentry.handle.api !== handle.api\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(`Unknown faux deferred response: ${handle.id}`);\n\t\t\t\t}\n\t\t\t\tif (entry.cancelled) throw new Error(`Faux deferred response was cancelled: ${handle.id}`);\n\n\t\t\t\tif (entry.pendingFetches > 0) {\n\t\t\t\t\tentry.pendingFetches--;\n\t\t\t\t\tawait streamWithDeltas(\n\t\t\t\t\t\touter,\n\t\t\t\t\t\tcreateDeferredMessage(requestModel, entry.handle),\n\t\t\t\t\t\tminTokenSize,\n\t\t\t\t\t\tmaxTokenSize,\n\t\t\t\t\t\ttokensPerSecond,\n\t\t\t\t\t\tfetchOptions?.signal,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!entry.final) {\n\t\t\t\t\tconst {\n\t\t\t\t\t\tdeferred: _deferred,\n\t\t\t\t\t\tsignal: _submissionSignal,\n\t\t\t\t\t\tonResponse: _submissionOnResponse,\n\t\t\t\t\t\t...submissionOptions\n\t\t\t\t\t} = entry.options ?? {};\n\t\t\t\t\ttry {\n\t\t\t\t\t\tentry.final = await resolveResponse(entry.step, entry.context, submissionOptions, entry.model);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tentry.final = createErrorMessage(error, api, provider, entry.model.id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tawait streamWithDeltas(\n\t\t\t\t\touter,\n\t\t\t\t\tentry.final,\n\t\t\t\t\tminTokenSize,\n\t\t\t\t\tmaxTokenSize,\n\t\t\t\t\ttokensPerSecond,\n\t\t\t\t\tfetchOptions?.signal,\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tconst message = createErrorMessage(error, api, provider, requestModel.id);\n\t\t\t\touter.push({ type: \"error\", reason: \"error\", error: message });\n\t\t\t\touter.end(message);\n\t\t\t}\n\t\t});\n\n\t\treturn outer;\n\t};\n\n\tconst cancelDeferred = async (\n\t\trequestModel: Model<string>,\n\t\thandle: DeferredHandle,\n\t\tcancelOptions?: DeferredCancelOptions,\n\t): Promise<void> => {\n\t\tstate.cancelledDeferred.push(structuredClone(handle));\n\t\tconst entry = deferredResponses.get(handle.id);\n\t\tif (entry) entry.cancelled = true;\n\t\tawait cancelOptions?.onResponse?.({ status: 200, headers: {} }, requestModel);\n\t};\n\n\tfunction getModel(): Model<string>;\n\tfunction getModel(requestedModelId: string): Model<string> | undefined;\n\tfunction getModel(requestedModelId?: string): Model<string> | undefined {\n\t\tif (!requestedModelId) {\n\t\t\treturn models[0];\n\t\t}\n\t\treturn models.find((candidate) => candidate.id === requestedModelId);\n\t}\n\n\treturn {\n\t\tapi,\n\t\tprovider,\n\t\tmodels,\n\t\tstream,\n\t\tstreamSimple,\n\t\tfetchDeferred,\n\t\tcancelDeferred,\n\t\tgetModel,\n\t\tstate,\n\t\tsetResponses(responses: FauxResponseStep[]) {\n\t\t\tpendingResponses = [...responses];\n\t\t},\n\t\tappendResponses(responses: FauxResponseStep[]) {\n\t\t\tpendingResponses.push(...responses);\n\t\t},\n\t\tgetPendingResponseCount() {\n\t\t\treturn pendingResponses.length;\n\t\t},\n\t};\n}\n\n/**\n * Faux provider for tests built on explicit `Models` collections:\n *\n * ```ts\n * const faux = fauxProvider();\n * const models = createModels();\n * models.setProvider(faux.provider);\n * faux.setResponses([fauxAssistantMessage(\"hi\")]);\n * ```\n */\nexport function fauxProvider(options: RegisterFauxProviderOptions = {}): FauxProviderHandle {\n\tconst core = createFauxCore(options);\n\tconst provider = createProvider({\n\t\tid: core.provider,\n\t\tauth: { apiKey: { name: \"Faux\", resolve: async () => ({ auth: {} }) } },\n\t\tmodels: core.models,\n\t\tapi: {\n\t\t\tstream: core.stream,\n\t\t\tstreamSimple: core.streamSimple,\n\t\t\tfetchDeferred: core.fetchDeferred,\n\t\t\tcancelDeferred: core.cancelDeferred,\n\t\t},\n\t});\n\treturn {\n\t\tprovider,\n\t\tapi: core.api,\n\t\tmodels: core.models,\n\t\tgetModel: core.getModel,\n\t\tstate: core.state,\n\t\tsetResponses: core.setResponses,\n\t\tappendResponses: core.appendResponses,\n\t\tgetPendingResponseCount: core.getPendingResponseCount,\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"github-copilot.d.ts","sourceRoot":"","sources":["../../src/providers/github-copilot.ts"],"names":[],"mappings":"AAKA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7D,wBAAgB,qBAAqB,IAAI,QAAQ,CAAC,oBAAoB,GAAG,oBAAoB,GAAG,kBAAkB,CAAC,CAyBlH","sourcesContent":["import { anthropicMessagesApi } from \"../api/anthropic-messages.lazy.ts\";\nimport { openAICompletionsApi } from \"../api/openai-completions.lazy.ts\";\nimport { openAIResponsesApi } from \"../api/openai-responses.lazy.ts\";\nimport { envApiKeyAuth, lazyOAuth } from \"../auth/helpers.ts\";\nimport { loadGitHubCopilotOAuth } from \"../auth/oauth/load.ts\";\nimport { createProvider, type Provider } from \"../models.ts\";\nimport { GITHUB_COPILOT_MODELS } from \"./github-copilot.models.ts\";\n\nexport function githubCopilotProvider(): Provider<\"anthropic-messages\" | \"openai-completions\" | \"openai-responses\"> {\n\treturn createProvider({\n\t\tid: \"github-copilot\",\n\t\tname: \"GitHub Copilot\",\n\t\tbaseUrl: \"https://api.individual.githubcopilot.com\",\n\t\tauth: {\n\t\t\tapiKey: envApiKeyAuth(\"GitHub Copilot token\", [\"COPILOT_GITHUB_TOKEN\"]),\n\t\t\toauth: lazyOAuth({ name: \"GitHub Copilot\", load: loadGitHubCopilotOAuth }),\n\t\t},\n\t\tmodels: Object.values(GITHUB_COPILOT_MODELS),\n\t\tfilterModels: (models, credential) => {\n\t\t\tif (credential?.type !== \"oauth\") return models;\n\t\t\tconst availableModelIds = credential.availableModelIds;\n\t\t\tif (!Array.isArray(availableModelIds) || !availableModelIds.every((id) => typeof id === \"string\")) {\n\t\t\t\treturn models;\n\t\t\t}\n\t\t\tconst available = new Set(availableModelIds);\n\t\t\treturn models.filter((model) => available.has(model.id));\n\t\t},\n\t\tapi: {\n\t\t\t\"anthropic-messages\": anthropicMessagesApi(),\n\t\t\t\"openai-completions\": openAICompletionsApi(),\n\t\t\t\"openai-responses\": openAIResponsesApi(),\n\t\t},\n\t});\n}\n"]}
1
+ {"version":3,"file":"github-copilot.d.ts","sourceRoot":"","sources":["../../src/providers/github-copilot.ts"],"names":[],"mappings":"AAKA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7D,wBAAgB,qBAAqB,IAAI,QAAQ,CAAC,oBAAoB,GAAG,oBAAoB,GAAG,kBAAkB,CAAC,CAyBlH","sourcesContent":["import { anthropicMessagesApi } from \"../api/anthropic-messages.lazy.ts\";\nimport { openAICompletionsApi } from \"../api/openai-completions.lazy.ts\";\nimport { openAIResponsesApi } from \"../api/openai-responses.lazy.ts\";\nimport { envApiKeyAuth, lazyOAuth } from \"../auth/helpers.ts\";\nimport { loadGitHubCopilotOAuth } from \"../auth/oauth/load.ts\";\nimport { createProvider, type Provider } from \"../models.ts\";\nimport { GITHUB_COPILOT_MODELS } from \"./github-copilot.models.ts\";\n\nexport function githubCopilotProvider(): Provider<\"anthropic-messages\" | \"openai-completions\" | \"openai-responses\"> {\n\treturn createProvider({\n\t\tid: \"github-copilot\",\n\t\tname: \"GitHub Copilot\",\n\t\tbaseUrl: \"https://api.individual.githubcopilot.com\",\n\t\tauth: {\n\t\t\tapiKey: envApiKeyAuth(\"GitHub Copilot token\", [\"COPILOT_GITHUB_TOKEN\"]),\n\t\t\toauth: lazyOAuth({ name: \"GitHub Copilot\", isSubscription: true, load: loadGitHubCopilotOAuth }),\n\t\t},\n\t\tmodels: Object.values(GITHUB_COPILOT_MODELS),\n\t\tfilterModels: (models, credential) => {\n\t\t\tif (credential?.type !== \"oauth\") return models;\n\t\t\tconst availableModelIds = credential.availableModelIds;\n\t\t\tif (!Array.isArray(availableModelIds) || !availableModelIds.every((id) => typeof id === \"string\")) {\n\t\t\t\treturn models;\n\t\t\t}\n\t\t\tconst available = new Set(availableModelIds);\n\t\t\treturn models.filter((model) => available.has(model.id));\n\t\t},\n\t\tapi: {\n\t\t\t\"anthropic-messages\": anthropicMessagesApi(),\n\t\t\t\"openai-completions\": openAICompletionsApi(),\n\t\t\t\"openai-responses\": openAIResponsesApi(),\n\t\t},\n\t});\n}\n"]}
@@ -12,7 +12,7 @@ export function githubCopilotProvider() {
12
12
  baseUrl: "https://api.individual.githubcopilot.com",
13
13
  auth: {
14
14
  apiKey: envApiKeyAuth("GitHub Copilot token", ["COPILOT_GITHUB_TOKEN"]),
15
- oauth: lazyOAuth({ name: "GitHub Copilot", load: loadGitHubCopilotOAuth }),
15
+ oauth: lazyOAuth({ name: "GitHub Copilot", isSubscription: true, load: loadGitHubCopilotOAuth }),
16
16
  },
17
17
  models: Object.values(GITHUB_COPILOT_MODELS),
18
18
  filterModels: (models, credential) => {
@@ -1 +1 @@
1
- {"version":3,"file":"github-copilot.js","sourceRoot":"","sources":["../../src/providers/github-copilot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAiB,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,MAAM,UAAU,qBAAqB,GAA+E;IACnH,OAAO,cAAc,CAAC;QACrB,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,0CAA0C;QACnD,IAAI,EAAE;YACL,MAAM,EAAE,aAAa,CAAC,sBAAsB,EAAE,CAAC,sBAAsB,CAAC,CAAC;YACvE,KAAK,EAAE,SAAS,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,sBAAsB,EAAE,CAAC;SAC1E;QACD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAAC;QAC5C,YAAY,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,CAAC;YACrC,IAAI,UAAU,EAAE,IAAI,KAAK,OAAO;gBAAE,OAAO,MAAM,CAAC;YAChD,MAAM,iBAAiB,GAAG,UAAU,CAAC,iBAAiB,CAAC;YACvD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,EAAE,CAAC;gBACnG,OAAO,MAAM,CAAC;YACf,CAAC;YACD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,iBAAiB,CAAC,CAAC;YAC7C,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAAA,CACzD;QACD,GAAG,EAAE;YACJ,oBAAoB,EAAE,oBAAoB,EAAE;YAC5C,oBAAoB,EAAE,oBAAoB,EAAE;YAC5C,kBAAkB,EAAE,kBAAkB,EAAE;SACxC;KACD,CAAC,CAAC;AAAA,CACH","sourcesContent":["import { anthropicMessagesApi } from \"../api/anthropic-messages.lazy.ts\";\nimport { openAICompletionsApi } from \"../api/openai-completions.lazy.ts\";\nimport { openAIResponsesApi } from \"../api/openai-responses.lazy.ts\";\nimport { envApiKeyAuth, lazyOAuth } from \"../auth/helpers.ts\";\nimport { loadGitHubCopilotOAuth } from \"../auth/oauth/load.ts\";\nimport { createProvider, type Provider } from \"../models.ts\";\nimport { GITHUB_COPILOT_MODELS } from \"./github-copilot.models.ts\";\n\nexport function githubCopilotProvider(): Provider<\"anthropic-messages\" | \"openai-completions\" | \"openai-responses\"> {\n\treturn createProvider({\n\t\tid: \"github-copilot\",\n\t\tname: \"GitHub Copilot\",\n\t\tbaseUrl: \"https://api.individual.githubcopilot.com\",\n\t\tauth: {\n\t\t\tapiKey: envApiKeyAuth(\"GitHub Copilot token\", [\"COPILOT_GITHUB_TOKEN\"]),\n\t\t\toauth: lazyOAuth({ name: \"GitHub Copilot\", load: loadGitHubCopilotOAuth }),\n\t\t},\n\t\tmodels: Object.values(GITHUB_COPILOT_MODELS),\n\t\tfilterModels: (models, credential) => {\n\t\t\tif (credential?.type !== \"oauth\") return models;\n\t\t\tconst availableModelIds = credential.availableModelIds;\n\t\t\tif (!Array.isArray(availableModelIds) || !availableModelIds.every((id) => typeof id === \"string\")) {\n\t\t\t\treturn models;\n\t\t\t}\n\t\t\tconst available = new Set(availableModelIds);\n\t\t\treturn models.filter((model) => available.has(model.id));\n\t\t},\n\t\tapi: {\n\t\t\t\"anthropic-messages\": anthropicMessagesApi(),\n\t\t\t\"openai-completions\": openAICompletionsApi(),\n\t\t\t\"openai-responses\": openAIResponsesApi(),\n\t\t},\n\t});\n}\n"]}
1
+ {"version":3,"file":"github-copilot.js","sourceRoot":"","sources":["../../src/providers/github-copilot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAiB,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,MAAM,UAAU,qBAAqB,GAA+E;IACnH,OAAO,cAAc,CAAC;QACrB,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,0CAA0C;QACnD,IAAI,EAAE;YACL,MAAM,EAAE,aAAa,CAAC,sBAAsB,EAAE,CAAC,sBAAsB,CAAC,CAAC;YACvE,KAAK,EAAE,SAAS,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,CAAC;SAChG;QACD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAAC;QAC5C,YAAY,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,CAAC;YACrC,IAAI,UAAU,EAAE,IAAI,KAAK,OAAO;gBAAE,OAAO,MAAM,CAAC;YAChD,MAAM,iBAAiB,GAAG,UAAU,CAAC,iBAAiB,CAAC;YACvD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,EAAE,CAAC;gBACnG,OAAO,MAAM,CAAC;YACf,CAAC;YACD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,iBAAiB,CAAC,CAAC;YAC7C,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAAA,CACzD;QACD,GAAG,EAAE;YACJ,oBAAoB,EAAE,oBAAoB,EAAE;YAC5C,oBAAoB,EAAE,oBAAoB,EAAE;YAC5C,kBAAkB,EAAE,kBAAkB,EAAE;SACxC;KACD,CAAC,CAAC;AAAA,CACH","sourcesContent":["import { anthropicMessagesApi } from \"../api/anthropic-messages.lazy.ts\";\nimport { openAICompletionsApi } from \"../api/openai-completions.lazy.ts\";\nimport { openAIResponsesApi } from \"../api/openai-responses.lazy.ts\";\nimport { envApiKeyAuth, lazyOAuth } from \"../auth/helpers.ts\";\nimport { loadGitHubCopilotOAuth } from \"../auth/oauth/load.ts\";\nimport { createProvider, type Provider } from \"../models.ts\";\nimport { GITHUB_COPILOT_MODELS } from \"./github-copilot.models.ts\";\n\nexport function githubCopilotProvider(): Provider<\"anthropic-messages\" | \"openai-completions\" | \"openai-responses\"> {\n\treturn createProvider({\n\t\tid: \"github-copilot\",\n\t\tname: \"GitHub Copilot\",\n\t\tbaseUrl: \"https://api.individual.githubcopilot.com\",\n\t\tauth: {\n\t\t\tapiKey: envApiKeyAuth(\"GitHub Copilot token\", [\"COPILOT_GITHUB_TOKEN\"]),\n\t\t\toauth: lazyOAuth({ name: \"GitHub Copilot\", isSubscription: true, load: loadGitHubCopilotOAuth }),\n\t\t},\n\t\tmodels: Object.values(GITHUB_COPILOT_MODELS),\n\t\tfilterModels: (models, credential) => {\n\t\t\tif (credential?.type !== \"oauth\") return models;\n\t\t\tconst availableModelIds = credential.availableModelIds;\n\t\t\tif (!Array.isArray(availableModelIds) || !availableModelIds.every((id) => typeof id === \"string\")) {\n\t\t\t\treturn models;\n\t\t\t}\n\t\t\tconst available = new Set(availableModelIds);\n\t\t\treturn models.filter((model) => available.has(model.id));\n\t\t},\n\t\tapi: {\n\t\t\t\"anthropic-messages\": anthropicMessagesApi(),\n\t\t\t\"openai-completions\": openAICompletionsApi(),\n\t\t\t\"openai-responses\": openAIResponsesApi(),\n\t\t},\n\t});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"google-vertex.d.ts","sourceRoot":"","sources":["../../src/providers/google-vertex.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAkF7D,wBAAgB,oBAAoB,IAAI,QAAQ,CAAC,eAAe,CAAC,CAQhE","sourcesContent":["import { googleVertexApi } from \"../api/google-vertex.lazy.ts\";\nimport type { ApiKeyAuth } from \"../auth/types.ts\";\nimport { createProvider, type Provider } from \"../models.ts\";\nimport { GOOGLE_VERTEX_MODELS } from \"./google-vertex.models.ts\";\n\nconst VERTEX_ADC_PATH = \"~/.config/gcloud/application_default_credentials.json\";\n\n/**\n * Vertex accepts an explicit API key or Application Default Credentials\n * (`gcloud auth application-default login`). ADC additionally requires\n * project and location env vars, which the implementation reads itself.\n */\nconst vertexAuth: ApiKeyAuth = {\n\tname: \"Google Cloud credentials\",\n\tlogin: async (interaction) => {\n\t\tconst method = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage: \"Select Google Vertex AI authentication method:\",\n\t\t\toptions: [\n\t\t\t\t{ id: \"api-key\", label: \"Google Cloud API key\" },\n\t\t\t\t{ id: \"adc\", label: \"Application Default Credentials\" },\n\t\t\t\t{ id: \"service-account\", label: \"Service account credentials file\" },\n\t\t\t],\n\t\t});\n\t\tif (method === \"api-key\") {\n\t\t\treturn {\n\t\t\t\ttype: \"api_key\",\n\t\t\t\tkey: await interaction.prompt({ type: \"secret\", message: \"Enter Google Cloud API key\" }),\n\t\t\t};\n\t\t}\n\t\tif (method !== \"adc\" && method !== \"service-account\") {\n\t\t\tthrow new Error(`Unknown Google Vertex AI auth method: ${method}`);\n\t\t}\n\t\tinteraction.notify({\n\t\t\ttype: \"info\",\n\t\t\tmessage:\n\t\t\t\tmethod === \"adc\"\n\t\t\t\t\t? \"Run `gcloud auth application-default login`, then provide the project and location.\"\n\t\t\t\t\t: \"Provide a service account credentials file, project, and location.\",\n\t\t\tlinks: [\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Application Default Credentials\",\n\t\t\t\t\turl: \"https://cloud.google.com/docs/authentication/provide-credentials-adc\",\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t\tconst project = await interaction.prompt({ type: \"text\", message: \"Enter Google Cloud project ID\" });\n\t\tconst location = await interaction.prompt({ type: \"text\", message: \"Enter Google Cloud location\" });\n\t\tconst credentialsPath =\n\t\t\tmethod === \"service-account\"\n\t\t\t\t? await interaction.prompt({ type: \"text\", message: \"Enter service account credentials file path\" })\n\t\t\t\t: undefined;\n\t\treturn {\n\t\t\ttype: \"api_key\",\n\t\t\tenv: {\n\t\t\t\tGOOGLE_CLOUD_PROJECT: project,\n\t\t\t\tGOOGLE_CLOUD_LOCATION: location,\n\t\t\t\t...(credentialsPath ? { GOOGLE_APPLICATION_CREDENTIALS: credentialsPath } : {}),\n\t\t\t},\n\t\t};\n\t},\n\tresolve: async ({ ctx, credential }) => {\n\t\tconst key = credential?.key ?? (await ctx.env(\"GOOGLE_CLOUD_API_KEY\"));\n\t\tif (key) return { auth: { apiKey: key }, source: credential?.key ? \"stored credential\" : \"GOOGLE_CLOUD_API_KEY\" };\n\n\t\tconst adcPath =\n\t\t\tcredential?.env?.GOOGLE_APPLICATION_CREDENTIALS ?? (await ctx.env(\"GOOGLE_APPLICATION_CREDENTIALS\"));\n\t\tconst hasCredentials = await ctx.fileExists(adcPath ?? VERTEX_ADC_PATH);\n\t\tconst project =\n\t\t\tcredential?.env?.GOOGLE_CLOUD_PROJECT ??\n\t\t\t(await ctx.env(\"GOOGLE_CLOUD_PROJECT\")) ??\n\t\t\t(await ctx.env(\"GCLOUD_PROJECT\"));\n\t\tconst location = credential?.env?.GOOGLE_CLOUD_LOCATION ?? (await ctx.env(\"GOOGLE_CLOUD_LOCATION\"));\n\t\tif (hasCredentials && project && location) {\n\t\t\treturn {\n\t\t\t\tauth: {},\n\t\t\t\tenv: credential?.env,\n\t\t\t\tsource: credential ? \"stored credential\" : \"gcloud application default credentials\",\n\t\t\t};\n\t\t}\n\t\treturn undefined;\n\t},\n};\n\nexport function googleVertexProvider(): Provider<\"google-vertex\"> {\n\treturn createProvider({\n\t\tid: \"google-vertex\",\n\t\tname: \"Google Vertex AI\",\n\t\tauth: { apiKey: vertexAuth },\n\t\tmodels: Object.values(GOOGLE_VERTEX_MODELS),\n\t\tapi: googleVertexApi(),\n\t});\n}\n"]}
1
+ {"version":3,"file":"google-vertex.d.ts","sourceRoot":"","sources":["../../src/providers/google-vertex.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAyF7D,wBAAgB,oBAAoB,IAAI,QAAQ,CAAC,eAAe,CAAC,CAQhE","sourcesContent":["import { googleVertexApi } from \"../api/google-vertex.lazy.ts\";\nimport type { ApiKeyAuth } from \"../auth/types.ts\";\nimport { createProvider, type Provider } from \"../models.ts\";\nimport { GOOGLE_VERTEX_MODELS } from \"./google-vertex.models.ts\";\n\nconst VERTEX_ADC_PATH = \"~/.config/gcloud/application_default_credentials.json\";\n\n/**\n * Vertex accepts an explicit API key or Application Default Credentials\n * (`gcloud auth application-default login`). ADC additionally requires\n * project and location env vars, which the implementation reads itself.\n */\nconst vertexAuth: ApiKeyAuth = {\n\tname: \"Google Cloud credentials\",\n\tlogin: async (interaction) => {\n\t\tinteraction.signal.throwIfAborted();\n\t\tconst method = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage: \"Select Google Vertex AI authentication method:\",\n\t\t\toptions: [\n\t\t\t\t{ id: \"api-key\", label: \"Google Cloud API key\" },\n\t\t\t\t{ id: \"adc\", label: \"Application Default Credentials\" },\n\t\t\t\t{ id: \"service-account\", label: \"Service account credentials file\" },\n\t\t\t],\n\t\t});\n\t\tinteraction.signal.throwIfAborted();\n\t\tif (method === \"api-key\") {\n\t\t\treturn {\n\t\t\t\ttype: \"api_key\",\n\t\t\t\tkey: await interaction.prompt({ type: \"secret\", message: \"Enter Google Cloud API key\" }),\n\t\t\t};\n\t\t}\n\t\tif (method !== \"adc\" && method !== \"service-account\") {\n\t\t\tthrow new Error(`Unknown Google Vertex AI auth method: ${method}`);\n\t\t}\n\t\tinteraction.notify({\n\t\t\ttype: \"info\",\n\t\t\tmessage:\n\t\t\t\tmethod === \"adc\"\n\t\t\t\t\t? \"Run `gcloud auth application-default login`, then provide the project and location.\"\n\t\t\t\t\t: \"Provide a service account credentials file, project, and location.\",\n\t\t\tlinks: [\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Application Default Credentials\",\n\t\t\t\t\turl: \"https://cloud.google.com/docs/authentication/provide-credentials-adc\",\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t\tconst project = await interaction.prompt({ type: \"text\", message: \"Enter Google Cloud project ID\" });\n\t\tconst location = await interaction.prompt({ type: \"text\", message: \"Enter Google Cloud location\" });\n\t\tconst credentialsPath =\n\t\t\tmethod === \"service-account\"\n\t\t\t\t? await interaction.prompt({ type: \"text\", message: \"Enter service account credentials file path\" })\n\t\t\t\t: undefined;\n\t\treturn {\n\t\t\ttype: \"api_key\",\n\t\t\tenv: {\n\t\t\t\tGOOGLE_CLOUD_PROJECT: project,\n\t\t\t\tGOOGLE_CLOUD_LOCATION: location,\n\t\t\t\t...(credentialsPath ? { GOOGLE_APPLICATION_CREDENTIALS: credentialsPath } : {}),\n\t\t\t},\n\t\t};\n\t},\n\tresolve: async ({ ctx, credential, signal }) => {\n\t\tconst env = async (name: string) => {\n\t\t\tsignal.throwIfAborted();\n\t\t\tconst value = await ctx.env(name);\n\t\t\tsignal.throwIfAborted();\n\t\t\treturn value;\n\t\t};\n\t\tconst key = credential?.key ?? (await env(\"GOOGLE_CLOUD_API_KEY\"));\n\t\tif (key) return { auth: { apiKey: key }, source: credential?.key ? \"stored credential\" : \"GOOGLE_CLOUD_API_KEY\" };\n\n\t\tconst adcPath = credential?.env?.GOOGLE_APPLICATION_CREDENTIALS ?? (await env(\"GOOGLE_APPLICATION_CREDENTIALS\"));\n\t\tsignal.throwIfAborted();\n\t\tconst hasCredentials = await ctx.fileExists(adcPath ?? VERTEX_ADC_PATH);\n\t\tsignal.throwIfAborted();\n\t\tconst project =\n\t\t\tcredential?.env?.GOOGLE_CLOUD_PROJECT ?? (await env(\"GOOGLE_CLOUD_PROJECT\")) ?? (await env(\"GCLOUD_PROJECT\"));\n\t\tconst location = credential?.env?.GOOGLE_CLOUD_LOCATION ?? (await env(\"GOOGLE_CLOUD_LOCATION\"));\n\t\tif (hasCredentials && project && location) {\n\t\t\treturn {\n\t\t\t\tauth: {},\n\t\t\t\tenv: credential?.env,\n\t\t\t\tsource: credential ? \"stored credential\" : \"gcloud application default credentials\",\n\t\t\t};\n\t\t}\n\t\treturn undefined;\n\t},\n};\n\nexport function googleVertexProvider(): Provider<\"google-vertex\"> {\n\treturn createProvider({\n\t\tid: \"google-vertex\",\n\t\tname: \"Google Vertex AI\",\n\t\tauth: { apiKey: vertexAuth },\n\t\tmodels: Object.values(GOOGLE_VERTEX_MODELS),\n\t\tapi: googleVertexApi(),\n\t});\n}\n"]}