@venturekit-pro/ai 0.0.0-dev.20260525024212 → 0.0.0-dev.20260602193331

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 (97) hide show
  1. package/dist/chat/anthropic.d.ts +31 -0
  2. package/dist/chat/anthropic.d.ts.map +1 -0
  3. package/dist/chat/anthropic.js +134 -0
  4. package/dist/chat/anthropic.js.map +1 -0
  5. package/dist/chat/client.d.ts +53 -0
  6. package/dist/chat/client.d.ts.map +1 -0
  7. package/dist/chat/client.js +61 -0
  8. package/dist/chat/client.js.map +1 -0
  9. package/dist/chat/cost-util.d.ts +37 -0
  10. package/dist/chat/cost-util.d.ts.map +1 -0
  11. package/dist/chat/cost-util.js +50 -0
  12. package/dist/chat/cost-util.js.map +1 -0
  13. package/dist/chat/google.d.ts +31 -0
  14. package/dist/chat/google.d.ts.map +1 -0
  15. package/dist/chat/google.js +119 -0
  16. package/dist/chat/google.js.map +1 -0
  17. package/dist/chat/index.d.ts +15 -0
  18. package/dist/chat/index.d.ts.map +1 -0
  19. package/dist/chat/index.js +17 -0
  20. package/dist/chat/index.js.map +1 -0
  21. package/dist/chat/openai.d.ts +28 -0
  22. package/dist/chat/openai.d.ts.map +1 -0
  23. package/dist/chat/openai.js +102 -0
  24. package/dist/chat/openai.js.map +1 -0
  25. package/dist/chat/types.d.ts +135 -0
  26. package/dist/chat/types.d.ts.map +1 -0
  27. package/dist/chat/types.js +14 -0
  28. package/dist/chat/types.js.map +1 -0
  29. package/dist/cost/catalog.d.ts +31 -0
  30. package/dist/cost/catalog.d.ts.map +1 -0
  31. package/dist/cost/catalog.js +43 -0
  32. package/dist/cost/catalog.js.map +1 -0
  33. package/dist/cost/estimate.d.ts +60 -0
  34. package/dist/cost/estimate.d.ts.map +1 -0
  35. package/dist/cost/estimate.js +65 -0
  36. package/dist/cost/estimate.js.map +1 -0
  37. package/dist/cost/index.d.ts +9 -0
  38. package/dist/cost/index.d.ts.map +1 -0
  39. package/dist/cost/index.js +6 -0
  40. package/dist/cost/index.js.map +1 -0
  41. package/dist/cost/types.d.ts +75 -0
  42. package/dist/cost/types.d.ts.map +1 -0
  43. package/dist/cost/types.js +22 -0
  44. package/dist/cost/types.js.map +1 -0
  45. package/dist/cost-ledger/index.d.ts +13 -0
  46. package/dist/cost-ledger/index.d.ts.map +1 -0
  47. package/dist/cost-ledger/index.js +11 -0
  48. package/dist/cost-ledger/index.js.map +1 -0
  49. package/dist/cost-ledger/migrations/vk_ai_cost_0001_init.sql +74 -0
  50. package/dist/cost-ledger/migrations/vk_ai_cost_0002_llm_models.sql +128 -0
  51. package/dist/cost-ledger/path.d.ts +10 -0
  52. package/dist/cost-ledger/path.d.ts.map +1 -0
  53. package/dist/cost-ledger/path.js +17 -0
  54. package/dist/cost-ledger/path.js.map +1 -0
  55. package/dist/cost-ledger/query.d.ts +64 -0
  56. package/dist/cost-ledger/query.d.ts.map +1 -0
  57. package/dist/cost-ledger/query.js +139 -0
  58. package/dist/cost-ledger/query.js.map +1 -0
  59. package/dist/cost-ledger/record.d.ts +14 -0
  60. package/dist/cost-ledger/record.d.ts.map +1 -0
  61. package/dist/cost-ledger/record.js +113 -0
  62. package/dist/cost-ledger/record.js.map +1 -0
  63. package/dist/cost-ledger/types.d.ts +122 -0
  64. package/dist/cost-ledger/types.d.ts.map +1 -0
  65. package/dist/cost-ledger/types.js +22 -0
  66. package/dist/cost-ledger/types.js.map +1 -0
  67. package/dist/fallback/fallback.d.ts +49 -0
  68. package/dist/fallback/fallback.d.ts.map +1 -0
  69. package/dist/fallback/fallback.js +54 -0
  70. package/dist/fallback/fallback.js.map +1 -0
  71. package/dist/fallback/index.d.ts +14 -0
  72. package/dist/fallback/index.d.ts.map +1 -0
  73. package/dist/fallback/index.js +12 -0
  74. package/dist/fallback/index.js.map +1 -0
  75. package/dist/fallback/retry.d.ts +61 -0
  76. package/dist/fallback/retry.d.ts.map +1 -0
  77. package/dist/fallback/retry.js +99 -0
  78. package/dist/fallback/retry.js.map +1 -0
  79. package/dist/index.d.ts +14 -1
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js +16 -3
  82. package/dist/index.js.map +1 -1
  83. package/dist/prompts/index.d.ts +13 -0
  84. package/dist/prompts/index.d.ts.map +1 -0
  85. package/dist/prompts/index.js +12 -0
  86. package/dist/prompts/index.js.map +1 -0
  87. package/dist/prompts/template.d.ts +57 -0
  88. package/dist/prompts/template.d.ts.map +1 -0
  89. package/dist/prompts/template.js +119 -0
  90. package/dist/prompts/template.js.map +1 -0
  91. package/dist/prompts/types.d.ts +77 -0
  92. package/dist/prompts/types.d.ts.map +1 -0
  93. package/dist/prompts/types.js +25 -0
  94. package/dist/prompts/types.js.map +1 -0
  95. package/package.json +8 -4
  96. package/src/cost-ledger/migrations/vk_ai_cost_0001_init.sql +74 -0
  97. package/src/cost-ledger/migrations/vk_ai_cost_0002_llm_models.sql +128 -0
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Anthropic chat-completion adapter.
3
+ *
4
+ * Calls Anthropic's Messages REST API directly with `fetch()` rather
5
+ * than depending on `@anthropic-ai/sdk`. Same rationale as `openai.ts`
6
+ * and `google.ts`:
7
+ * - single-turn chat completion is a trivial REST POST; the SDK
8
+ * adds ~MB of streaming + tool-use plumbing this module doesn't
9
+ * need.
10
+ * - keeps the package's peer-dep surface tighter (no
11
+ * `@anthropic-ai/sdk` peer requirement).
12
+ * - retries + fallback are owned by the `fallback/` module, not
13
+ * the SDK.
14
+ *
15
+ * Anthropic's API splits the system prompt out of the message array
16
+ * (sent as a top-level `system` field) — adapter handles that
17
+ * translation so callers can keep using the provider-neutral
18
+ * `ChatMessage[]` shape.
19
+ */
20
+ import type { ChatCompletionRequest, ChatCompletionResult } from './types.js';
21
+ export interface AnthropicAdapterConfig {
22
+ apiKey: string;
23
+ /** Override the Anthropic API host. Defaults to `https://api.anthropic.com`. */
24
+ baseUrl?: string;
25
+ /** API version header. Pinned to a known-good date if omitted. */
26
+ apiVersion?: string;
27
+ /** Request timeout in milliseconds. Default 60s. */
28
+ timeoutMs?: number;
29
+ }
30
+ export declare function completeWithAnthropic(config: AnthropicAdapterConfig, request: ChatCompletionRequest): Promise<ChatCompletionResult>;
31
+ //# sourceMappingURL=anthropic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/chat/anthropic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EAGrB,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAWD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CA+E/B"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Anthropic chat-completion adapter.
3
+ *
4
+ * Calls Anthropic's Messages REST API directly with `fetch()` rather
5
+ * than depending on `@anthropic-ai/sdk`. Same rationale as `openai.ts`
6
+ * and `google.ts`:
7
+ * - single-turn chat completion is a trivial REST POST; the SDK
8
+ * adds ~MB of streaming + tool-use plumbing this module doesn't
9
+ * need.
10
+ * - keeps the package's peer-dep surface tighter (no
11
+ * `@anthropic-ai/sdk` peer requirement).
12
+ * - retries + fallback are owned by the `fallback/` module, not
13
+ * the SDK.
14
+ *
15
+ * Anthropic's API splits the system prompt out of the message array
16
+ * (sent as a top-level `system` field) — adapter handles that
17
+ * translation so callers can keep using the provider-neutral
18
+ * `ChatMessage[]` shape.
19
+ */
20
+ import { stampCost } from './cost-util.js';
21
+ /** Default `anthropic-version` header. Bump alongside SDK pinning. */
22
+ const DEFAULT_ANTHROPIC_VERSION = '2023-06-01';
23
+ export async function completeWithAnthropic(config, request) {
24
+ const startedAt = Date.now();
25
+ const baseUrl = (config.baseUrl ?? 'https://api.anthropic.com').replace(/\/+$/, '');
26
+ const apiVersion = config.apiVersion ?? DEFAULT_ANTHROPIC_VERSION;
27
+ const timeoutMs = request.timeoutMs ?? config.timeoutMs ?? 60_000;
28
+ // Anthropic puts `system` outside the messages array. Pull the
29
+ // first message off if it's a system; reject any later system
30
+ // messages (Anthropic doesn't accept multiple).
31
+ const { system, conversation } = splitSystem(request.messages);
32
+ const body = {
33
+ model: request.model,
34
+ max_tokens: request.maxTokens ?? 4096,
35
+ messages: conversation.map((m) => ({ role: m.role, content: m.content })),
36
+ };
37
+ if (request.temperature !== undefined)
38
+ body.temperature = request.temperature;
39
+ if (request.topP !== undefined)
40
+ body.top_p = request.topP;
41
+ if (request.stop && request.stop.length > 0)
42
+ body.stop_sequences = request.stop;
43
+ if (system !== undefined)
44
+ body.system = system;
45
+ const controller = new AbortController();
46
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
47
+ let response;
48
+ try {
49
+ response = await fetch(`${baseUrl}/v1/messages`, {
50
+ method: 'POST',
51
+ headers: {
52
+ 'x-api-key': config.apiKey,
53
+ 'anthropic-version': apiVersion,
54
+ 'Content-Type': 'application/json',
55
+ ...(request.idempotencyKey ? { 'Idempotency-Key': request.idempotencyKey } : {}),
56
+ },
57
+ body: JSON.stringify(body),
58
+ signal: controller.signal,
59
+ });
60
+ }
61
+ finally {
62
+ clearTimeout(timer);
63
+ }
64
+ if (!response.ok) {
65
+ const text = (await response.text()).slice(0, 500);
66
+ throw new Error(`[ai/chat/anthropic] ${response.status} ${response.statusText}: ${text}`);
67
+ }
68
+ const json = (await response.json());
69
+ // Anthropic returns a `content` array of blocks; we concatenate
70
+ // all `text` blocks. Tool-use blocks pass through silently (this
71
+ // module doesn't support tools — if a caller routes a tool-using
72
+ // prompt here, they'll see an empty completion and our error
73
+ // below will fire).
74
+ const output = (json.content ?? [])
75
+ .filter((b) => b.type === 'text' && typeof b.text === 'string')
76
+ .map((b) => b.text)
77
+ .join('');
78
+ if (output.length === 0) {
79
+ throw new Error(`[ai/chat/anthropic] Empty completion (stop_reason=${json.stop_reason ?? 'unknown'})`);
80
+ }
81
+ const usage = {
82
+ tokensIn: json.usage?.input_tokens ?? null,
83
+ tokensOut: json.usage?.output_tokens ?? null,
84
+ };
85
+ return {
86
+ output,
87
+ provider: 'anthropic',
88
+ model: request.model,
89
+ usage,
90
+ cost: stampCost(usage, request.pricing),
91
+ latencyMs: Date.now() - startedAt,
92
+ finishReason: mapFinishReason(json.stop_reason ?? null),
93
+ };
94
+ }
95
+ /**
96
+ * Split a leading `system` message off the conversation. Anthropic
97
+ * rejects multiple system messages with HTTP 400 — surface that
98
+ * up-front as a clearer client-side error.
99
+ */
100
+ function splitSystem(messages) {
101
+ let system;
102
+ const conversation = [];
103
+ for (const m of messages) {
104
+ if (m.role === 'system') {
105
+ if (system !== undefined || conversation.length > 0) {
106
+ throw new Error('[ai/chat/anthropic] Only a single leading `system` message is allowed');
107
+ }
108
+ system = m.content;
109
+ }
110
+ else {
111
+ conversation.push({ role: m.role, content: m.content });
112
+ }
113
+ }
114
+ if (conversation.length === 0) {
115
+ throw new Error('[ai/chat/anthropic] No `user` or `assistant` messages supplied');
116
+ }
117
+ return { system, conversation };
118
+ }
119
+ function mapFinishReason(raw) {
120
+ if (!raw)
121
+ return null;
122
+ switch (raw) {
123
+ case 'end_turn':
124
+ case 'stop_sequence':
125
+ return 'stop';
126
+ case 'max_tokens':
127
+ return 'length';
128
+ case 'tool_use':
129
+ return 'tool_calls';
130
+ default:
131
+ return raw;
132
+ }
133
+ }
134
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/chat/anthropic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Chat completion client — provider-neutral entry point.
3
+ *
4
+ * The CMS (or any other caller) constructs one client per
5
+ * (provider, apiKey) pair via `createChatClient()` and calls
6
+ * `.complete()` against it. The factory switches on `provider`
7
+ * exactly once, at construction — no per-call branch.
8
+ *
9
+ * Why a class-shaped client rather than a stateless function?
10
+ * - Lets adapters keep SDK instances warm (Anthropic's SDK
11
+ * constructs an axios instance internally; reconstructing per
12
+ * call would erase its connection-pool benefit).
13
+ * - Gives `fallback/withFallback()` and other higher-order
14
+ * orchestrators a stable handle to bind to.
15
+ *
16
+ * The interface deliberately matches what the CMS's `persona.ts`
17
+ * needs and nothing else: `provider` for audit-row labeling,
18
+ * `complete()` for the actual call. Tool use, streaming, batching,
19
+ * and embedding lookups are out of scope here and live in their
20
+ * dedicated modules.
21
+ */
22
+ import type { ChatCompletionRequest, ChatCompletionResult, ChatProvider } from './types.js';
23
+ import { type AnthropicAdapterConfig } from './anthropic.js';
24
+ import { type OpenAiAdapterConfig } from './openai.js';
25
+ import { type GoogleAdapterConfig } from './google.js';
26
+ /**
27
+ * A minimal interface for chat completion. Implementations are
28
+ * per-provider thin wrappers that hold the API key + base URL +
29
+ * timeout and translate to the provider's REST or SDK shape.
30
+ */
31
+ export interface ChatCompletionClient {
32
+ readonly provider: ChatProvider;
33
+ complete(request: ChatCompletionRequest): Promise<ChatCompletionResult>;
34
+ }
35
+ /**
36
+ * Construct-time configuration. The provider-specific fields are
37
+ * carried as a union discriminated by `provider` so TypeScript can
38
+ * narrow `baseUrl` / `apiVersion` to only the providers that accept
39
+ * them.
40
+ */
41
+ export type ChatClientConfig = ({
42
+ provider: 'anthropic';
43
+ } & AnthropicAdapterConfig) | ({
44
+ provider: 'openai';
45
+ } & OpenAiAdapterConfig) | ({
46
+ provider: 'google';
47
+ } & GoogleAdapterConfig);
48
+ /**
49
+ * Build a client. Throws synchronously on an unknown provider so the
50
+ * caller fails fast rather than at the first `.complete()` call.
51
+ */
52
+ export declare function createChatClient(config: ChatClientConfig): ChatCompletionClient;
53
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/chat/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC5F,OAAO,EAAyB,KAAK,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACpF,OAAO,EAAsB,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAsB,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE3E;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;CACzE;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GACxB,CAAC;IAAE,QAAQ,EAAE,WAAW,CAAA;CAAE,GAAG,sBAAsB,CAAC,GACpD,CAAC;IAAE,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAAG,mBAAmB,CAAC,GAC9C,CAAC;IAAE,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAAG,mBAAmB,CAAC,CAAC;AAEnD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,oBAAoB,CAiC/E"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Chat completion client — provider-neutral entry point.
3
+ *
4
+ * The CMS (or any other caller) constructs one client per
5
+ * (provider, apiKey) pair via `createChatClient()` and calls
6
+ * `.complete()` against it. The factory switches on `provider`
7
+ * exactly once, at construction — no per-call branch.
8
+ *
9
+ * Why a class-shaped client rather than a stateless function?
10
+ * - Lets adapters keep SDK instances warm (Anthropic's SDK
11
+ * constructs an axios instance internally; reconstructing per
12
+ * call would erase its connection-pool benefit).
13
+ * - Gives `fallback/withFallback()` and other higher-order
14
+ * orchestrators a stable handle to bind to.
15
+ *
16
+ * The interface deliberately matches what the CMS's `persona.ts`
17
+ * needs and nothing else: `provider` for audit-row labeling,
18
+ * `complete()` for the actual call. Tool use, streaming, batching,
19
+ * and embedding lookups are out of scope here and live in their
20
+ * dedicated modules.
21
+ */
22
+ import { completeWithAnthropic } from './anthropic.js';
23
+ import { completeWithOpenAi } from './openai.js';
24
+ import { completeWithGoogle } from './google.js';
25
+ /**
26
+ * Build a client. Throws synchronously on an unknown provider so the
27
+ * caller fails fast rather than at the first `.complete()` call.
28
+ */
29
+ export function createChatClient(config) {
30
+ switch (config.provider) {
31
+ case 'anthropic': {
32
+ const { provider: _ignored, ...adapterConfig } = config;
33
+ void _ignored;
34
+ return {
35
+ provider: 'anthropic',
36
+ complete: (request) => completeWithAnthropic(adapterConfig, request),
37
+ };
38
+ }
39
+ case 'openai': {
40
+ const { provider: _ignored, ...adapterConfig } = config;
41
+ void _ignored;
42
+ return {
43
+ provider: 'openai',
44
+ complete: (request) => completeWithOpenAi(adapterConfig, request),
45
+ };
46
+ }
47
+ case 'google': {
48
+ const { provider: _ignored, ...adapterConfig } = config;
49
+ void _ignored;
50
+ return {
51
+ provider: 'google',
52
+ complete: (request) => completeWithGoogle(adapterConfig, request),
53
+ };
54
+ }
55
+ default: {
56
+ const _exhaustive = config;
57
+ throw new Error(`[ai/chat] Unsupported provider: ${_exhaustive.provider}`);
58
+ }
59
+ }
60
+ }
61
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/chat/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAAE,qBAAqB,EAA+B,MAAM,gBAAgB,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAA4B,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAA4B,MAAM,aAAa,CAAC;AAuB3E;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAwB;IACvD,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,CAAC;YACxD,KAAK,QAAQ,CAAC;YACd,OAAO;gBACL,QAAQ,EAAE,WAAW;gBACrB,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,qBAAqB,CAAC,aAAa,EAAE,OAAO,CAAC;aACrE,CAAC;QACJ,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,CAAC;YACxD,KAAK,QAAQ,CAAC;YACd,OAAO;gBACL,QAAQ,EAAE,QAAQ;gBAClB,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,kBAAkB,CAAC,aAAa,EAAE,OAAO,CAAC;aAClE,CAAC;QACJ,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,CAAC;YACxD,KAAK,QAAQ,CAAC;YACd,OAAO;gBACL,QAAQ,EAAE,QAAQ;gBAClB,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,kBAAkB,CAAC,aAAa,EAAE,OAAO,CAAC;aAClE,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,WAAW,GAAU,MAAM,CAAC;YAClC,MAAM,IAAI,KAAK,CACb,mCAAoC,WAAoC,CAAC,QAAQ,EAAE,CACpF,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Cost-stamping helper shared by chat adapters.
3
+ *
4
+ * Pulled into its own module (rather than living in `cost/`) because
5
+ * every provider adapter needs it and we don't want to import the
6
+ * full `cost/` barrel — that would introduce a circular reference
7
+ * once `cost/` learns to consume `chat/types.ts`.
8
+ *
9
+ * The math is intentionally trivial and lives close to the adapters
10
+ * so reviewers don't have to jump between modules to audit pricing:
11
+ * `(tokensIn / 1000) * costPer1kInputUsd +
12
+ * (tokensOut / 1000) * costPer1kOutputUsd`.
13
+ */
14
+ import type { ChatModelPricing, ChatTokenUsage, CostStamp } from './types.js';
15
+ /**
16
+ * Compute a USD `CostStamp` from raw usage counts + pricing.
17
+ *
18
+ * Returns `null` when:
19
+ * - `pricing` is omitted (caller didn't opt into cost stamping), OR
20
+ * - both `tokensIn` and `tokensOut` are `null` (vendor didn't report usage —
21
+ * we don't fake costs from string-length heuristics here; that's
22
+ * the `cost/estimate.ts` module's job, used by callers explicitly).
23
+ *
24
+ * If only one of `tokensIn` / `tokensOut` is `null`, the missing leg
25
+ * counts as zero — partial usage data is still better than no cost
26
+ * stamp, and audit views typically alarm on the absent leg rather
27
+ * than dropping the row.
28
+ */
29
+ export declare function stampCost(usage: ChatTokenUsage, pricing: ChatModelPricing | undefined): CostStamp | null;
30
+ /**
31
+ * Round to 8 decimal places — enough for sub-cent precision on a
32
+ * single 4096-token call, not so much that JSON serialization gets
33
+ * noisy. Public so unit tests can use the same rounding when
34
+ * computing fixtures.
35
+ */
36
+ export declare function round8(n: number): number;
37
+ //# sourceMappingURL=cost-util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-util.d.ts","sourceRoot":"","sources":["../../src/chat/cost-util.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE9E;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,gBAAgB,GAAG,SAAS,GACpC,SAAS,GAAG,IAAI,CAWlB;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAExC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Cost-stamping helper shared by chat adapters.
3
+ *
4
+ * Pulled into its own module (rather than living in `cost/`) because
5
+ * every provider adapter needs it and we don't want to import the
6
+ * full `cost/` barrel — that would introduce a circular reference
7
+ * once `cost/` learns to consume `chat/types.ts`.
8
+ *
9
+ * The math is intentionally trivial and lives close to the adapters
10
+ * so reviewers don't have to jump between modules to audit pricing:
11
+ * `(tokensIn / 1000) * costPer1kInputUsd +
12
+ * (tokensOut / 1000) * costPer1kOutputUsd`.
13
+ */
14
+ /**
15
+ * Compute a USD `CostStamp` from raw usage counts + pricing.
16
+ *
17
+ * Returns `null` when:
18
+ * - `pricing` is omitted (caller didn't opt into cost stamping), OR
19
+ * - both `tokensIn` and `tokensOut` are `null` (vendor didn't report usage —
20
+ * we don't fake costs from string-length heuristics here; that's
21
+ * the `cost/estimate.ts` module's job, used by callers explicitly).
22
+ *
23
+ * If only one of `tokensIn` / `tokensOut` is `null`, the missing leg
24
+ * counts as zero — partial usage data is still better than no cost
25
+ * stamp, and audit views typically alarm on the absent leg rather
26
+ * than dropping the row.
27
+ */
28
+ export function stampCost(usage, pricing) {
29
+ if (!pricing)
30
+ return null;
31
+ if (usage.tokensIn === null && usage.tokensOut === null)
32
+ return null;
33
+ const inputCostUsd = ((usage.tokensIn ?? 0) / 1000) * pricing.costPer1kInputUsd;
34
+ const outputCostUsd = ((usage.tokensOut ?? 0) / 1000) * pricing.costPer1kOutputUsd;
35
+ const costUsd = round8(inputCostUsd + outputCostUsd);
36
+ // Integer micro-USD for SQL SUM() without float drift. Round
37
+ // half-up at the ULP because audit rows accumulate.
38
+ const costMicroUsd = Math.round(costUsd * 1_000_000);
39
+ return { costUsd, costMicroUsd, pricing: { ...pricing } };
40
+ }
41
+ /**
42
+ * Round to 8 decimal places — enough for sub-cent precision on a
43
+ * single 4096-token call, not so much that JSON serialization gets
44
+ * noisy. Public so unit tests can use the same rounding when
45
+ * computing fixtures.
46
+ */
47
+ export function round8(n) {
48
+ return Math.round(n * 1e8) / 1e8;
49
+ }
50
+ //# sourceMappingURL=cost-util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-util.js","sourceRoot":"","sources":["../../src/chat/cost-util.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,SAAS,CACvB,KAAqB,EACrB,OAAqC;IAErC,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAErE,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAChF,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC;IACnF,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,GAAG,aAAa,CAAC,CAAC;IACrD,6DAA6D;IAC7D,oDAAoD;IACpD,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;IACrD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,EAAE,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,CAAS;IAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;AACnC,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Google (Gemini) chat-completion adapter.
3
+ *
4
+ * Implemented with `fetch()` against the public REST endpoint. The
5
+ * `@google/generative-ai` SDK exists but adds ~300KB and pins on a
6
+ * Node version we'd rather not constrain; for single-turn chat the
7
+ * REST surface is simple enough to call directly.
8
+ *
9
+ * Notable Gemini quirks the adapter translates:
10
+ * - The system prompt is a separate top-level `systemInstruction`
11
+ * object, not a `role: 'system'` message.
12
+ * - Conversation roles are `'user'` and `'model'` (not `'assistant'`).
13
+ * - `Content` blocks wrap a `parts: [{ text: string }]` array.
14
+ * - Generation params live under `generationConfig.*` rather than
15
+ * being siblings of `model` / `messages`.
16
+ * - Gemini doesn't natively support an Idempotency-Key header, so
17
+ * `request.idempotencyKey` is ignored (documented behavior in
18
+ * `chat/types.ts`).
19
+ */
20
+ import type { ChatCompletionRequest, ChatCompletionResult } from './types.js';
21
+ export interface GoogleAdapterConfig {
22
+ apiKey: string;
23
+ /** Override the API host. Defaults to `https://generativelanguage.googleapis.com`. */
24
+ baseUrl?: string;
25
+ /** API version. Defaults to `v1beta` (still the recommended path for Gemini 1.5+). */
26
+ apiVersion?: string;
27
+ /** Request timeout in milliseconds. Default 60s. */
28
+ timeoutMs?: number;
29
+ }
30
+ export declare function completeWithGoogle(config: GoogleAdapterConfig, request: ChatCompletionRequest): Promise<ChatCompletionResult>;
31
+ //# sourceMappingURL=google.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../src/chat/google.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EAGrB,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sFAAsF;IACtF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAaD,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CA6E/B"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Google (Gemini) chat-completion adapter.
3
+ *
4
+ * Implemented with `fetch()` against the public REST endpoint. The
5
+ * `@google/generative-ai` SDK exists but adds ~300KB and pins on a
6
+ * Node version we'd rather not constrain; for single-turn chat the
7
+ * REST surface is simple enough to call directly.
8
+ *
9
+ * Notable Gemini quirks the adapter translates:
10
+ * - The system prompt is a separate top-level `systemInstruction`
11
+ * object, not a `role: 'system'` message.
12
+ * - Conversation roles are `'user'` and `'model'` (not `'assistant'`).
13
+ * - `Content` blocks wrap a `parts: [{ text: string }]` array.
14
+ * - Generation params live under `generationConfig.*` rather than
15
+ * being siblings of `model` / `messages`.
16
+ * - Gemini doesn't natively support an Idempotency-Key header, so
17
+ * `request.idempotencyKey` is ignored (documented behavior in
18
+ * `chat/types.ts`).
19
+ */
20
+ import { stampCost } from './cost-util.js';
21
+ export async function completeWithGoogle(config, request) {
22
+ const startedAt = Date.now();
23
+ const baseUrl = (config.baseUrl ?? 'https://generativelanguage.googleapis.com').replace(/\/+$/, '');
24
+ const apiVersion = config.apiVersion ?? 'v1beta';
25
+ const timeoutMs = request.timeoutMs ?? config.timeoutMs ?? 60_000;
26
+ const { system, conversation } = splitSystem(request.messages);
27
+ const body = {
28
+ contents: conversation.map((m) => ({
29
+ role: m.role === 'assistant' ? 'model' : 'user',
30
+ parts: [{ text: m.content }],
31
+ })),
32
+ generationConfig: {
33
+ maxOutputTokens: request.maxTokens ?? 4096,
34
+ ...(request.temperature !== undefined ? { temperature: request.temperature } : {}),
35
+ ...(request.topP !== undefined ? { topP: request.topP } : {}),
36
+ ...(request.stop && request.stop.length > 0 ? { stopSequences: request.stop } : {}),
37
+ },
38
+ };
39
+ if (system) {
40
+ body.systemInstruction = { parts: [{ text: system }] };
41
+ }
42
+ // Gemini's API-key auth uses a query param (no header form for the
43
+ // REST endpoint that's actually documented). We escape via
44
+ // encodeURIComponent so a future tenant-keyed format doesn't break
45
+ // the URL.
46
+ const url = `${baseUrl}/${apiVersion}/models/${encodeURIComponent(request.model)}:generateContent?key=${encodeURIComponent(config.apiKey)}`;
47
+ const controller = new AbortController();
48
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
49
+ let response;
50
+ try {
51
+ response = await fetch(url, {
52
+ method: 'POST',
53
+ headers: { 'Content-Type': 'application/json' },
54
+ body: JSON.stringify(body),
55
+ signal: controller.signal,
56
+ });
57
+ }
58
+ finally {
59
+ clearTimeout(timer);
60
+ }
61
+ if (!response.ok) {
62
+ const text = (await response.text()).slice(0, 500);
63
+ throw new Error(`[ai/chat/google] ${response.status} ${response.statusText}: ${text}`);
64
+ }
65
+ const json = (await response.json());
66
+ const candidate = json.candidates?.[0];
67
+ const text = candidate?.content?.parts?.map((p) => p.text ?? '').join('') ?? '';
68
+ if (text.length === 0) {
69
+ throw new Error(`[ai/chat/google] Empty completion (finishReason=${candidate?.finishReason ?? 'unknown'})`);
70
+ }
71
+ const usage = {
72
+ tokensIn: json.usageMetadata?.promptTokenCount ?? null,
73
+ tokensOut: json.usageMetadata?.candidatesTokenCount ?? null,
74
+ };
75
+ return {
76
+ output: text,
77
+ provider: 'google',
78
+ model: request.model,
79
+ usage,
80
+ cost: stampCost(usage, request.pricing),
81
+ latencyMs: Date.now() - startedAt,
82
+ finishReason: mapFinishReason(candidate?.finishReason ?? null),
83
+ };
84
+ }
85
+ function splitSystem(messages) {
86
+ let system;
87
+ const conversation = [];
88
+ for (const m of messages) {
89
+ if (m.role === 'system') {
90
+ if (system !== undefined || conversation.length > 0) {
91
+ throw new Error('[ai/chat/google] Only a single leading `system` message is allowed');
92
+ }
93
+ system = m.content;
94
+ }
95
+ else {
96
+ conversation.push(m);
97
+ }
98
+ }
99
+ if (conversation.length === 0) {
100
+ throw new Error('[ai/chat/google] No `user` or `assistant` messages supplied');
101
+ }
102
+ return { system, conversation };
103
+ }
104
+ function mapFinishReason(raw) {
105
+ if (!raw)
106
+ return null;
107
+ switch (raw) {
108
+ case 'STOP':
109
+ return 'stop';
110
+ case 'MAX_TOKENS':
111
+ return 'length';
112
+ case 'SAFETY':
113
+ case 'RECITATION':
114
+ return 'content_filter';
115
+ default:
116
+ return raw;
117
+ }
118
+ }
119
+ //# sourceMappingURL=google.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google.js","sourceRoot":"","sources":["../../src/chat/google.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAuB3C,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAA2B,EAC3B,OAA8B;IAE9B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,2CAA2C,CAAC,CAAC,OAAO,CACrF,MAAM,EACN,EAAE,CACH,CAAC;IACF,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,QAAQ,CAAC;IACjD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC;IAElE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE/D,MAAM,IAAI,GAA4B;QACpC,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjC,IAAI,EAAE,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;YAC/C,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;SAC7B,CAAC,CAAC;QACH,gBAAgB,EAAE;YAChB,eAAe,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;YAC1C,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClF,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpF;KACF,CAAC;IACF,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,CAAC,iBAAiB,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACzD,CAAC;IAED,mEAAmE;IACnE,2DAA2D;IAC3D,mEAAmE;IACnE,WAAW;IACX,MAAM,GAAG,GAAG,GAAG,OAAO,IAAI,UAAU,WAAW,kBAAkB,CAC/D,OAAO,CAAC,KAAK,CACd,wBAAwB,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IAE7D,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;IAC9D,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC1B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAC1B,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,oBAAoB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC,CAAC;IACzF,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAkC,CAAC;IACtE,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;IAChF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,mDAAmD,SAAS,EAAE,YAAY,IAAI,SAAS,GAAG,CAC3F,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG;QACZ,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,gBAAgB,IAAI,IAAI;QACtD,SAAS,EAAE,IAAI,CAAC,aAAa,EAAE,oBAAoB,IAAI,IAAI;KAC5D,CAAC;IAEF,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,KAAK;QACL,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC;QACvC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;QACjC,YAAY,EAAE,eAAe,CAAC,SAAS,EAAE,YAAY,IAAI,IAAI,CAAC;KAC/D,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,QAAuB;IAI1C,IAAI,MAA0B,CAAC;IAC/B,MAAM,YAAY,GAAkB,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACxB,IAAI,MAAM,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpD,MAAM,IAAI,KAAK,CACb,oEAAoE,CACrE,CAAC;YACJ,CAAC;YACD,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;AAClC,CAAC;AAED,SAAS,eAAe,CAAC,GAAkB;IACzC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,YAAY;YACf,OAAO,QAAQ,CAAC;QAClB,KAAK,QAAQ,CAAC;QACd,KAAK,YAAY;YACf,OAAO,gBAAgB,CAAC;QAC1B;YACE,OAAO,GAAG,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Chat completion — provider-neutral single-turn or multi-turn text
3
+ * generation with cost stamping. Tool use lives in `agents/`.
4
+ */
5
+ export type { ChatProvider, ChatMessage, ChatModelPricing, ChatCompletionRequest, ChatCompletionResult, ChatTokenUsage, ChatFinishReason, CostStamp, } from './types.js';
6
+ export { createChatClient } from './client.js';
7
+ export type { ChatClientConfig, ChatCompletionClient } from './client.js';
8
+ export { completeWithAnthropic } from './anthropic.js';
9
+ export type { AnthropicAdapterConfig } from './anthropic.js';
10
+ export { completeWithOpenAi } from './openai.js';
11
+ export type { OpenAiAdapterConfig } from './openai.js';
12
+ export { completeWithGoogle } from './google.js';
13
+ export type { GoogleAdapterConfig } from './google.js';
14
+ export { stampCost, round8 } from './cost-util.js';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,YAAY,EACV,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAChB,SAAS,GACV,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAM1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAKvD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Chat completion — provider-neutral single-turn or multi-turn text
3
+ * generation with cost stamping. Tool use lives in `agents/`.
4
+ */
5
+ export { createChatClient } from './client.js';
6
+ // Provider adapters are exported as named functions for callers that
7
+ // want to bypass the factory (e.g. for a custom retry policy bound
8
+ // directly to one provider). Re-exported configs let those callers
9
+ // share the same type for `apiKey` / `baseUrl`.
10
+ export { completeWithAnthropic } from './anthropic.js';
11
+ export { completeWithOpenAi } from './openai.js';
12
+ export { completeWithGoogle } from './google.js';
13
+ // `stampCost` is exposed for callers that drive the chat call
14
+ // themselves (e.g. through `agents/` with tool-use) but still want
15
+ // the standard cost-stamp computation.
16
+ export { stampCost, round8 } from './cost-util.js';
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,qEAAqE;AACrE,mEAAmE;AACnE,mEAAmE;AACnE,gDAAgD;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD,8DAA8D;AAC9D,mEAAmE;AACnE,uCAAuC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * OpenAI chat-completion adapter.
3
+ *
4
+ * Implemented with `fetch()` rather than the `openai` SDK on purpose:
5
+ * - keeps the package's peer-dep surface optional (`openai` is
6
+ * already declared in `package.json` for the agents/ tool-use
7
+ * path, which still uses the SDK because tool-use streaming is
8
+ * painful to write by hand).
9
+ * - single-turn chat-completion is a trivial REST POST; vendoring
10
+ * in the SDK just for this would add ~1MB to the bundle.
11
+ * - the SDK pins `Node>=18` and uses native `AbortSignal`/`fetch`
12
+ * under the hood anyway, so we lose nothing by going direct.
13
+ *
14
+ * Uses the Chat Completions endpoint (`/v1/chat/completions`) — not
15
+ * the newer Responses API — because Responses doesn't expose
16
+ * `max_completion_tokens` the same way and the migration story is
17
+ * still unsettled at v1 ship-time.
18
+ */
19
+ import type { ChatCompletionRequest, ChatCompletionResult } from './types.js';
20
+ export interface OpenAiAdapterConfig {
21
+ apiKey: string;
22
+ /** Override the OpenAI API host. Defaults to `https://api.openai.com`. */
23
+ baseUrl?: string;
24
+ /** Request timeout in milliseconds. Default 60s. */
25
+ timeoutMs?: number;
26
+ }
27
+ export declare function completeWithOpenAi(config: OpenAiAdapterConfig, request: ChatCompletionRequest): Promise<ChatCompletionResult>;
28
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/chat/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EAGrB,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAaD,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAkE/B"}