@genesislcap/foundation-ai 15.32.1 → 15.33.1-GENC-1601.1

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.
@@ -10,6 +10,10 @@ export { GeminiTransport, MalformedFunctionCallError } from './transports/gemini
10
10
  export { DEFAULT_PROVIDER_REFUSED_MESSAGE, PROVIDER_REFUSED_CODE, ProviderRefusedError, } from './transports/provider-refused';
11
11
  export type { ProviderRefusalKind } from './transports/provider-refused';
12
12
  export { ContextOverflowError, contextOverflowOf, DEFAULT_CONTEXT_OVERFLOW_MESSAGE, } from './transports/context-overflow-error';
13
+ export { AI_TIER_IDS, AI_TIER_VENDORS, DEFAULT_AI_TIERS, resolveAITiers } from './tiers/ai-tiers';
14
+ export type { AITierId, AITierOverrides, AITiers, AITierVendor, AnthropicTierConfig, GeminiTierConfig, } from './tiers/ai-tiers';
15
+ export { buildTierProviders } from './tiers/build-tier-providers';
16
+ export type { BuildTierProvidersOptions } from './tiers/build-tier-providers';
13
17
  export { AI_FEATURE_FLAG, isAIFeatureEnabled } from './utils/feature-flags';
14
18
  export { ChatTemperature } from './utils/temperature';
15
19
  export { ANTHROPIC_CACHE_READ_MULTIPLIER, ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER, ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER, anthropicRatesFor, anthropicTokenCost, GEMINI_CACHED_INPUT_MULTIPLIER, GEMINI_LONG_CONTEXT_THRESHOLD, geminiRatesFor, geminiTokenCost, } from './utils/token-cost';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ import type { AnthropicModelId, GeminiModelId } from '../types';
2
+ /**
3
+ * The platform's tier → model table (GENC-1610).
4
+ *
5
+ * @remarks
6
+ * Pure data, and deliberately so: this module imports nothing but types, never
7
+ * `ai-provider-di` (the one `@microsoft/fast-foundation` importer) and never
8
+ * `@genesislcap/web-core`, so it loads in bare Node. It is re-exported by name from
9
+ * `@genesislcap/ai-assistant/chat-driver`, which a server-side host requires at runtime —
10
+ * an `export *` or a DOM import anywhere in its closure crashes that host at require time.
11
+ * Provider construction lives next door in `build-tier-providers.ts`, which is browser-only.
12
+ *
13
+ * @packageDocumentation
14
+ */
15
+ /**
16
+ * The tier a caller asks for, rather than a model id.
17
+ *
18
+ * Tier-shaped names are what let an app swap vendor (or re-bench a tier onto a
19
+ * newer model) without touching a single agent config — agents resolve `'high'`,
20
+ * not `claude-sonnet-5`.
21
+ *
22
+ * @beta
23
+ */
24
+ export type AITierId = 'low' | 'high' | 'reasoning';
25
+ /**
26
+ * Every tier id, in ascending capability order. Derived-from rather than restating
27
+ * {@link AITierId} — a tier added to the union without being added here is a compile error.
28
+ *
29
+ * @beta
30
+ */
31
+ export declare const AI_TIER_IDS: readonly ["low", "high", "reasoning"];
32
+ /**
33
+ * The cloud vendors the tier table covers — the two the platform's proxy meters.
34
+ *
35
+ * @beta
36
+ */
37
+ export type AITierVendor = 'anthropic' | 'gemini';
38
+ /**
39
+ * Every vendor in the table, so a caller can list them without `Object.keys` casts.
40
+ *
41
+ * @beta
42
+ */
43
+ export declare const AI_TIER_VENDORS: readonly ["anthropic", "gemini"];
44
+ /**
45
+ * What one tier is worth on Anthropic: the model, its output ceiling, and the two clocks.
46
+ *
47
+ * @beta
48
+ */
49
+ export interface AnthropicTierConfig {
50
+ model: AnthropicModelId;
51
+ /**
52
+ * `max_tokens` for every request on this tier. Part of the tier, not an optional
53
+ * extra: Anthropic requires the field and the transport defaults it to 4096, which
54
+ * truncates a large single-call file write mid-stream (`stop_reason: max_tokens`)
55
+ * and leaves the tool input unparseable. Values sit inside each model's documented
56
+ * output ceiling.
57
+ */
58
+ maxTokens: number;
59
+ /** Inactivity window on a stream that has started. */
60
+ stallTimeoutMs: number;
61
+ /** Ceiling on the wait for the FIRST byte — a different clock from the stall one. */
62
+ timeoutMs: number;
63
+ }
64
+ /**
65
+ * What one tier is worth on Gemini.
66
+ *
67
+ * No `maxTokens`: `GeminiAIConfig` has no such field and the provider's own (much
68
+ * larger) default applies, so Gemini writes never hit the Anthropic wall above.
69
+ *
70
+ * @beta
71
+ */
72
+ export interface GeminiTierConfig {
73
+ model: GeminiModelId;
74
+ /** Inactivity window on a stream that has started. */
75
+ stallTimeoutMs: number;
76
+ /** Ceiling on the wait for the FIRST byte — a different clock from the stall one. */
77
+ timeoutMs: number;
78
+ }
79
+ /**
80
+ * The whole table: every tier, for every vendor.
81
+ *
82
+ * Total records, not partials — a tier a vendor cannot serve is not a tier, it is a
83
+ * gap that only shows up when an agent resolves it at runtime.
84
+ *
85
+ * @beta
86
+ */
87
+ export interface AITiers {
88
+ anthropic: Record<AITierId, AnthropicTierConfig>;
89
+ gemini: Record<AITierId, GeminiTierConfig>;
90
+ }
91
+ /**
92
+ * The platform's default tier table.
93
+ *
94
+ * @remarks
95
+ * Frozen, because it is shared by every app in the process: {@link resolveAITiers} returns
96
+ * a fresh object for callers that override, and hands this back untouched for callers that
97
+ * do not.
98
+ *
99
+ * The models are the ones Genesis Create has been running these tiers on in production, and
100
+ * they are a **benchmark result, not a preference** — re-bench before moving one. Two dates
101
+ * are already on the calendar for that: `gemini-3.8-flash` sits on an introductory rate that
102
+ * doubles on 2027-01-01 (at which point it is dearer on input than the model it replaced),
103
+ * and `token-cost.test.ts` fails the build that day; `ai-tiers.test.ts` fails alongside it
104
+ * saying the High tier is the thing to re-bench.
105
+ *
106
+ * Every model here must be in `SUPPORTED_*_MODEL_IDS` with a context limit and a price —
107
+ * pinned by tests, because an unpriced model silently bills at nothing.
108
+ *
109
+ * @beta
110
+ */
111
+ export declare const DEFAULT_AI_TIERS: AITiers;
112
+ /**
113
+ * Per-tier overrides, shallow-merged field by field over the defaults.
114
+ *
115
+ * @beta
116
+ */
117
+ export interface AITierOverrides {
118
+ anthropic?: Partial<Record<AITierId, Partial<AnthropicTierConfig>>>;
119
+ gemini?: Partial<Record<AITierId, Partial<GeminiTierConfig>>>;
120
+ }
121
+ /**
122
+ * The table an app should actually use: {@link DEFAULT_AI_TIERS} with `overrides` applied
123
+ * per field, so an app that wants one model moved says only that and keeps the platform's
124
+ * clocks and ceilings.
125
+ *
126
+ * @remarks
127
+ * Returns the frozen default itself when there is nothing to override, and a fresh
128
+ * (unfrozen) object otherwise. Either way the default is never mutated, which matters
129
+ * because it is shared across every app in the process.
130
+ *
131
+ * @example
132
+ * ```ts
133
+ * // Keep everything, but run the reasoning tier on the newest Opus.
134
+ * const tiers = resolveAITiers({ anthropic: { reasoning: { model: 'claude-opus-4-8' } } });
135
+ * ```
136
+ *
137
+ * @beta
138
+ */
139
+ export declare function resolveAITiers(overrides?: AITierOverrides): AITiers;
140
+ //# sourceMappingURL=ai-tiers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-tiers.d.ts","sourceRoot":"","sources":["../../../src/tiers/ai-tiers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEhE;;;;;;;;;;;;GAYG;AAEH;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,uCAAsE,CAAC;AAE/F;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;AAElD;;;;GAIG;AACH,eAAO,MAAM,eAAe,kCAAqE,CAAC;AAElG;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,gBAAgB,CAAC;IACxB;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,cAAc,EAAE,MAAM,CAAC;IACvB,qFAAqF;IACrF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,aAAa,CAAC;IACrB,sDAAsD;IACtD,cAAc,EAAE,MAAM,CAAC;IACvB,qFAAqF;IACrF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;IACjD,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;CAC5C;AAsBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,gBAAgB,EAAE,OA2ClB,CAAC;AAEd;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IACpE,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;CAC/D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,eAAe,GAAG,OAAO,CAMnE"}
@@ -0,0 +1,67 @@
1
+ import { type AIProvider } from '../ai-provider';
2
+ import type { AnthropicAIConfig, GeminiAIConfig } from '../types';
3
+ import { type AITierId, type AITiers, type AITierVendor } from './ai-tiers';
4
+ /**
5
+ * Turns the tier table into live providers (GENC-1610).
6
+ *
7
+ * @remarks
8
+ * Split from `ai-tiers.ts` because this half is **browser-only**: `createAIProvider` checks
9
+ * the AI feature flag, which reads `window.location`. The table is what a Node host needs
10
+ * (model ids and pricing); provider construction is not, so only the table is re-exported
11
+ * from the `@genesislcap/ai-assistant/chat-driver` Node entry.
12
+ *
13
+ * @packageDocumentation
14
+ */
15
+ /**
16
+ * Options for {@link buildTierProviders}.
17
+ *
18
+ * @beta
19
+ */
20
+ export interface BuildTierProvidersOptions {
21
+ /** Which vendor's models to build. */
22
+ vendor: AITierVendor;
23
+ /**
24
+ * The proxy endpoint every tier posts to — a string, or a function of the vendor for a
25
+ * caller that builds more than one vendor from one rule (see the example below).
26
+ *
27
+ * Always a server endpoint, never an API key: these providers are meant for an app whose
28
+ * keys stay on its server. An empty endpoint throws here rather than at the first turn.
29
+ */
30
+ serverEndpoint: string | ((vendor: AITierVendor) => string);
31
+ /** The table to build from. Defaults to {@link DEFAULT_AI_TIERS}. */
32
+ tiers?: AITiers;
33
+ }
34
+ /**
35
+ * Builds one {@link AIProvider} per tier for a vendor, ready to register under the tier
36
+ * names agents resolve (`low` / `high` / `reasoning`).
37
+ *
38
+ * @remarks
39
+ * Each provider carries its tier's model, output ceiling (Anthropic) and both clocks, so no
40
+ * tier can silently fall back to the transport defaults — which is how a large tool write
41
+ * ends up truncated at 4096 tokens.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * registerAIProviders(
46
+ * container,
47
+ * buildTierProviders({ vendor: 'gemini', serverEndpoint: (v) => `/gwf/ai-service/${v}/chat` }),
48
+ * { default: 'high' },
49
+ * );
50
+ * ```
51
+ *
52
+ * @beta
53
+ */
54
+ export declare function buildTierProviders(options: BuildTierProvidersOptions): Record<AITierId, AIProvider>;
55
+ /**
56
+ * The provider configs {@link buildTierProviders} builds from, before they reach
57
+ * `createAIProvider`.
58
+ *
59
+ * A seam rather than an inline literal, because what is being asserted is exactly what a
60
+ * constructed provider hides: a transport keeps `maxTokens` and both clocks private, so a
61
+ * tier silently falling back to the 4096-token default would be invisible from the outside
62
+ * — which is the failure this table exists to prevent.
63
+ *
64
+ * @internal
65
+ */
66
+ export declare function tierProviderConfigs(options: BuildTierProvidersOptions): Record<AITierId, AnthropicAIConfig | GeminiAIConfig>;
67
+ //# sourceMappingURL=build-tier-providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-tier-providers.d.ts","sourceRoot":"","sources":["../../../src/tiers/build-tier-providers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,KAAK,YAAY,EAClB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;GAUG;AAEH;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,sCAAsC;IACtC,MAAM,EAAE,YAAY,CAAC;IACrB;;;;;;OAMG;IACH,cAAc,EAAE,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,YAAY,KAAK,MAAM,CAAC,CAAC;IAC5D,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,yBAAyB,GACjC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAO9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,yBAAyB,GACjC,MAAM,CAAC,QAAQ,EAAE,iBAAiB,GAAG,cAAc,CAAC,CAkCtD"}
@@ -144,6 +144,20 @@ export declare const GEMINI_LONG_CONTEXT_THRESHOLD = 200000;
144
144
  * @beta
145
145
  */
146
146
  export declare const GEMINI_CACHED_INPUT_MULTIPLIER = 0.1;
147
+ /**
148
+ * The day `gemini-3.8-flash` leaves its introductory rate (see `GEMINI_PRICING` below).
149
+ *
150
+ * A constant rather than a literal in the test that enforces it, because a SECOND dated
151
+ * assertion now hangs off the same day: the High tier picked that model while it was the
152
+ * cheaper one, so the flip is also the trigger to re-bench the tier (`tiers/ai-tiers.test.ts`).
153
+ * Two hand-copied dates would drift the moment either is corrected, and a re-bench reminder
154
+ * that fires on the wrong day is no reminder at all.
155
+ *
156
+ * Not part of the package's public surface — it exists for those two tests.
157
+ *
158
+ * @internal
159
+ */
160
+ export declare const GEMINI_3_8_FLASH_INTRO_RATE_ENDS: number;
147
161
  /**
148
162
  * Resolve the per-million-token rates for a model given the request's prompt size,
149
163
  * selecting the long-context tier for tiered models when the prompt exceeds
@@ -1 +1 @@
1
- {"version":3,"file":"token-cost.d.ts","sourceRoot":"","sources":["../../../src/utils/token-cost.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAkDhE;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;;OAQG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,SAAS,EAAE,kBAAkB,CAAC;CAC/B;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,YAAY,EAAE,MAAM,CAAC;CACtB;AAiCD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,UAAU,CAErE;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,+BAA+B,MAAM,CAAC;AACnD,YAAY;AACZ,eAAO,MAAM,mCAAmC,OAAO,CAAC;AACxD,YAAY;AACZ,eAAO,MAAM,mCAAmC,IAAI,CAAC;AAErD;;;;;;;;;GASG;AACH,MAAM,WAAW,oBAAoB;IACnC,wFAAwF;IACxF,mBAAmB,EAAE,MAAM,CAAC;IAC5B,4FAA4F;IAC5F,YAAY,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,eAAe,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;;;;;OASG;IACH,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,gBAAgB,EACvB,KAAK,EAAE,oBAAoB,GAC1B,SAAS,CAiCX;AAMD;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,SAAU,CAAC;AAErD;;;;;;;;;GASG;AACH,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAsDlD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,GAAG,UAAU,CAMrF;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,YAAY,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,eAAe,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,iBAAiB,GAAG,SAAS,CAuBzF"}
1
+ {"version":3,"file":"token-cost.d.ts","sourceRoot":"","sources":["../../../src/utils/token-cost.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAkDhE;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;;OAQG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,SAAS,EAAE,kBAAkB,CAAC;CAC/B;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,YAAY,EAAE,MAAM,CAAC;CACtB;AAiCD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,UAAU,CAErE;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,+BAA+B,MAAM,CAAC;AACnD,YAAY;AACZ,eAAO,MAAM,mCAAmC,OAAO,CAAC;AACxD,YAAY;AACZ,eAAO,MAAM,mCAAmC,IAAI,CAAC;AAErD;;;;;;;;;GASG;AACH,MAAM,WAAW,oBAAoB;IACnC,wFAAwF;IACxF,mBAAmB,EAAE,MAAM,CAAC;IAC5B,4FAA4F;IAC5F,YAAY,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,eAAe,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;;;;;OASG;IACH,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,gBAAgB,EACvB,KAAK,EAAE,oBAAoB,GAC1B,SAAS,CAiCX;AAMD;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,SAAU,CAAC;AAErD;;;;;;;;;GASG;AACH,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAElD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gCAAgC,QAAqC,CAAC;AAsDnF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,GAAG,UAAU,CAMrF;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,YAAY,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,eAAe,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,iBAAiB,GAAG,SAAS,CAuBzF"}
package/dist/esm/index.js CHANGED
@@ -15,6 +15,13 @@ export { GeminiTransport, MalformedFunctionCallError } from './transports/gemini
15
15
  // first reword.
16
16
  export { DEFAULT_PROVIDER_REFUSED_MESSAGE, PROVIDER_REFUSED_CODE, ProviderRefusedError, } from './transports/provider-refused';
17
17
  export { ContextOverflowError, contextOverflowOf, DEFAULT_CONTEXT_OVERFLOW_MESSAGE, } from './transports/context-overflow-error';
18
+ // The platform tier table (GENC-1610) — what a `low` / `high` / `reasoning` slot resolves to
19
+ // per vendor, including the Anthropic output ceiling and both timeout clocks. Named exports,
20
+ // and the data half is deliberately free of DOM and DI imports so it also rides the
21
+ // `@genesislcap/ai-assistant/chat-driver` Node bundle; `buildTierProviders` does NOT, because
22
+ // it constructs providers through the feature-flag gate (see `tiers/build-tier-providers.ts`).
23
+ export { AI_TIER_IDS, AI_TIER_VENDORS, DEFAULT_AI_TIERS, resolveAITiers } from './tiers/ai-tiers';
24
+ export { buildTierProviders } from './tiers/build-tier-providers';
18
25
  export { AI_FEATURE_FLAG, isAIFeatureEnabled } from './utils/feature-flags';
19
26
  export { ChatTemperature } from './utils/temperature';
20
27
  // Request pricing. Exported so a host that prices its own calls — a server proxy, a usage ledger,
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Every tier id, in ascending capability order. Derived-from rather than restating
3
+ * {@link AITierId} — a tier added to the union without being added here is a compile error.
4
+ *
5
+ * @beta
6
+ */
7
+ export const AI_TIER_IDS = ['low', 'high', 'reasoning'];
8
+ /**
9
+ * Every vendor in the table, so a caller can list them without `Object.keys` casts.
10
+ *
11
+ * @beta
12
+ */
13
+ export const AI_TIER_VENDORS = ['anthropic', 'gemini'];
14
+ /**
15
+ * 60s inactivity backstop on a stream that has already started.
16
+ *
17
+ * `foundation-ai` defaults this to 30s, which is TIGHTER than the platform proxy's own
18
+ * 45s mid-stream watchdog — so the client won every race and aborted the request before
19
+ * the server could notice, classify or log the stall. A stall is not retried; it surfaces
20
+ * as a dead turn. 60s puts the proxy back in charge of detecting upstream stalls.
21
+ */
22
+ const AI_STALL_TIMEOUT_MS = 60000;
23
+ /**
24
+ * 300s ceiling on the wait for the first byte — nothing has arrived yet.
25
+ *
26
+ * Distinct from {@link AI_STALL_TIMEOUT_MS}, which is only armed once the body starts.
27
+ * It stays generous because on the legacy (unframed) proxy path the response is buffered,
28
+ * so the first byte only lands when generation is complete; a tight value there would cap
29
+ * total generation time. Set explicitly rather than inherited, so it is a decision on the record.
30
+ */
31
+ const AI_NO_RESPONSE_TIMEOUT_MS = 300000;
32
+ /**
33
+ * The platform's default tier table.
34
+ *
35
+ * @remarks
36
+ * Frozen, because it is shared by every app in the process: {@link resolveAITiers} returns
37
+ * a fresh object for callers that override, and hands this back untouched for callers that
38
+ * do not.
39
+ *
40
+ * The models are the ones Genesis Create has been running these tiers on in production, and
41
+ * they are a **benchmark result, not a preference** — re-bench before moving one. Two dates
42
+ * are already on the calendar for that: `gemini-3.8-flash` sits on an introductory rate that
43
+ * doubles on 2027-01-01 (at which point it is dearer on input than the model it replaced),
44
+ * and `token-cost.test.ts` fails the build that day; `ai-tiers.test.ts` fails alongside it
45
+ * saying the High tier is the thing to re-bench.
46
+ *
47
+ * Every model here must be in `SUPPORTED_*_MODEL_IDS` with a context limit and a price —
48
+ * pinned by tests, because an unpriced model silently bills at nothing.
49
+ *
50
+ * @beta
51
+ */
52
+ export const DEFAULT_AI_TIERS = Object.freeze({
53
+ anthropic: Object.freeze({
54
+ low: Object.freeze({
55
+ model: 'claude-haiku-4-5-20251001',
56
+ maxTokens: 16000,
57
+ stallTimeoutMs: AI_STALL_TIMEOUT_MS,
58
+ timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS,
59
+ }),
60
+ // The heavy tier: whole-file writes, and adaptive thinking out of the same budget
61
+ // wherever a caller leaves thinking on — hence Sonnet 5's full 128K ceiling rather
62
+ // than a figure that only fits one of the two.
63
+ high: Object.freeze({
64
+ model: 'claude-sonnet-5',
65
+ maxTokens: 128000,
66
+ stallTimeoutMs: AI_STALL_TIMEOUT_MS,
67
+ timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS,
68
+ }),
69
+ // One-shot judgement calls rather than tool loops, so a smaller ceiling is ample:
70
+ // `max_tokens` is only a cap, and this tier never emits a whole file.
71
+ reasoning: Object.freeze({
72
+ model: 'claude-opus-4-7',
73
+ maxTokens: 32000,
74
+ stallTimeoutMs: AI_STALL_TIMEOUT_MS,
75
+ timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS,
76
+ }),
77
+ }),
78
+ gemini: Object.freeze({
79
+ low: Object.freeze({
80
+ model: 'gemini-3.1-flash-lite',
81
+ stallTimeoutMs: AI_STALL_TIMEOUT_MS,
82
+ timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS,
83
+ }),
84
+ high: Object.freeze({
85
+ model: 'gemini-3.8-flash',
86
+ stallTimeoutMs: AI_STALL_TIMEOUT_MS,
87
+ timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS,
88
+ }),
89
+ reasoning: Object.freeze({
90
+ model: 'gemini-3.1-pro-preview',
91
+ stallTimeoutMs: AI_STALL_TIMEOUT_MS,
92
+ timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS,
93
+ }),
94
+ }),
95
+ });
96
+ /**
97
+ * The table an app should actually use: {@link DEFAULT_AI_TIERS} with `overrides` applied
98
+ * per field, so an app that wants one model moved says only that and keeps the platform's
99
+ * clocks and ceilings.
100
+ *
101
+ * @remarks
102
+ * Returns the frozen default itself when there is nothing to override, and a fresh
103
+ * (unfrozen) object otherwise. Either way the default is never mutated, which matters
104
+ * because it is shared across every app in the process.
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * // Keep everything, but run the reasoning tier on the newest Opus.
109
+ * const tiers = resolveAITiers({ anthropic: { reasoning: { model: 'claude-opus-4-8' } } });
110
+ * ```
111
+ *
112
+ * @beta
113
+ */
114
+ export function resolveAITiers(overrides) {
115
+ if (!(overrides === null || overrides === void 0 ? void 0 : overrides.anthropic) && !(overrides === null || overrides === void 0 ? void 0 : overrides.gemini))
116
+ return DEFAULT_AI_TIERS;
117
+ return {
118
+ anthropic: mergeVendor(DEFAULT_AI_TIERS.anthropic, overrides.anthropic),
119
+ gemini: mergeVendor(DEFAULT_AI_TIERS.gemini, overrides.gemini),
120
+ };
121
+ }
122
+ function mergeVendor(defaults, overrides) {
123
+ const merged = {};
124
+ for (const tier of AI_TIER_IDS) {
125
+ merged[tier] = Object.assign(Object.assign({}, defaults[tier]), overrides === null || overrides === void 0 ? void 0 : overrides[tier]);
126
+ }
127
+ return merged;
128
+ }
@@ -0,0 +1,72 @@
1
+ import { createAIProvider } from '../ai-provider';
2
+ import { AI_TIER_IDS, DEFAULT_AI_TIERS, } from './ai-tiers';
3
+ /**
4
+ * Builds one {@link AIProvider} per tier for a vendor, ready to register under the tier
5
+ * names agents resolve (`low` / `high` / `reasoning`).
6
+ *
7
+ * @remarks
8
+ * Each provider carries its tier's model, output ceiling (Anthropic) and both clocks, so no
9
+ * tier can silently fall back to the transport defaults — which is how a large tool write
10
+ * ends up truncated at 4096 tokens.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * registerAIProviders(
15
+ * container,
16
+ * buildTierProviders({ vendor: 'gemini', serverEndpoint: (v) => `/gwf/ai-service/${v}/chat` }),
17
+ * { default: 'high' },
18
+ * );
19
+ * ```
20
+ *
21
+ * @beta
22
+ */
23
+ export function buildTierProviders(options) {
24
+ const configs = tierProviderConfigs(options);
25
+ const providers = {};
26
+ for (const tier of AI_TIER_IDS) {
27
+ providers[tier] = createAIProvider(configs[tier]);
28
+ }
29
+ return providers;
30
+ }
31
+ /**
32
+ * The provider configs {@link buildTierProviders} builds from, before they reach
33
+ * `createAIProvider`.
34
+ *
35
+ * A seam rather than an inline literal, because what is being asserted is exactly what a
36
+ * constructed provider hides: a transport keeps `maxTokens` and both clocks private, so a
37
+ * tier silently falling back to the 4096-token default would be invisible from the outside
38
+ * — which is the failure this table exists to prevent.
39
+ *
40
+ * @internal
41
+ */
42
+ export function tierProviderConfigs(options) {
43
+ const { vendor, tiers = DEFAULT_AI_TIERS } = options;
44
+ const serverEndpoint = typeof options.serverEndpoint === 'function'
45
+ ? options.serverEndpoint(vendor)
46
+ : options.serverEndpoint;
47
+ if (!serverEndpoint) {
48
+ throw new Error(`buildTierProviders: no serverEndpoint for '${vendor}'. Every tier posts to your app's ` +
49
+ 'AI proxy; there is no browser-key mode here.');
50
+ }
51
+ const configs = {};
52
+ for (const tier of AI_TIER_IDS) {
53
+ configs[tier] =
54
+ vendor === 'anthropic'
55
+ ? {
56
+ providerType: 'anthropic',
57
+ model: tiers.anthropic[tier].model,
58
+ maxTokens: tiers.anthropic[tier].maxTokens,
59
+ serverEndpoint,
60
+ stallTimeout: tiers.anthropic[tier].stallTimeoutMs,
61
+ timeout: tiers.anthropic[tier].timeoutMs,
62
+ }
63
+ : {
64
+ providerType: 'gemini',
65
+ model: tiers.gemini[tier].model,
66
+ serverEndpoint,
67
+ stallTimeout: tiers.gemini[tier].stallTimeoutMs,
68
+ timeout: tiers.gemini[tier].timeoutMs,
69
+ };
70
+ }
71
+ return configs;
72
+ }
@@ -161,6 +161,20 @@ export const GEMINI_LONG_CONTEXT_THRESHOLD = 200000;
161
161
  * @beta
162
162
  */
163
163
  export const GEMINI_CACHED_INPUT_MULTIPLIER = 0.1;
164
+ /**
165
+ * The day `gemini-3.8-flash` leaves its introductory rate (see `GEMINI_PRICING` below).
166
+ *
167
+ * A constant rather than a literal in the test that enforces it, because a SECOND dated
168
+ * assertion now hangs off the same day: the High tier picked that model while it was the
169
+ * cheaper one, so the flip is also the trigger to re-bench the tier (`tiers/ai-tiers.test.ts`).
170
+ * Two hand-copied dates would drift the moment either is corrected, and a re-bench reminder
171
+ * that fires on the wrong day is no reminder at all.
172
+ *
173
+ * Not part of the package's public surface — it exists for those two tests.
174
+ *
175
+ * @internal
176
+ */
177
+ export const GEMINI_3_8_FLASH_INTRO_RATE_ENDS = Date.parse('2027-01-01T00:00:00Z');
164
178
  /**
165
179
  * Paid Standard tier rates (USD per million tokens) —
166
180
  * https://ai.google.dev/gemini-api/docs/pricing