@genesislcap/foundation-ai 15.33.1-GENC-1601.2 → 15.34.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.
@@ -101,8 +101,10 @@ export interface AITiers {
101
101
  * a fresh object for callers that override, and hands this back untouched for callers that
102
102
  * do not.
103
103
  *
104
- * The models are the ones Genesis Create has been running these tiers on in production, and
105
- * they are a **benchmark result, not a preference** — re-bench before moving one. Two dates
104
+ * The models are the ones Genesis Create has been running these tiers on in production — except
105
+ * Anthropic's `reasoning`, moved to `claude-opus-4-8` (see its entry) — and they are a
106
+ * **benchmark result, not a preference**: re-bench before moving one. Two of the Gemini
107
+ * defaults carry a caveat recorded beside them, a preview model and an introductory rate. Two dates
106
108
  * are already on the calendar for that: `gemini-3.8-flash` sits on an introductory rate that
107
109
  * doubles on 2027-01-01 (at which point it is dearer on input than the model it replaced),
108
110
  * and `token-cost.test.ts` fails the build that day; `ai-tiers.test.ts` fails alongside it
@@ -129,14 +131,21 @@ export interface AITierOverrides {
129
131
  * clocks and ceilings.
130
132
  *
131
133
  * @remarks
132
- * Returns the frozen default itself when there is nothing to override, and a fresh
133
- * (unfrozen) object otherwise. Either way the default is never mutated, which matters
134
- * because it is shared across every app in the process.
134
+ * An override field set to `undefined` is skipped, exactly as if it had been left out. The
135
+ * common caller passes an optional config value straight through
136
+ * (`{ high: { model: appConfig.model } }`), and copying `undefined` over the default would
137
+ * hand the transport no model at all — it then quietly falls back to its own default, with
138
+ * nothing logged.
139
+ *
140
+ * The result is frozen whether or not anything was overridden, so whether mutating it throws
141
+ * does not depend on what the caller passed. The default itself is returned untouched when
142
+ * there is nothing to override, and is never mutated, which matters because it is shared
143
+ * across every app in the process.
135
144
  *
136
145
  * @example
137
146
  * ```ts
138
- * // Keep everything, but run the reasoning tier on the newest Opus.
139
- * const tiers = resolveAITiers({ anthropic: { reasoning: { model: 'claude-opus-4-8' } } });
147
+ * // Keep everything, but run the reasoning tier on Fable.
148
+ * const tiers = resolveAITiers({ anthropic: { reasoning: { model: 'claude-fable-5' } } });
140
149
  * ```
141
150
  *
142
151
  * @beta
@@ -1 +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;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,uCAAwC,CAAC;AAEjE;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,eAAe,kCAAmC,CAAC;AAEhE;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D;;;;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"}
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;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,uCAAwC,CAAC;AAEjE;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,eAAe,kCAAmC,CAAC;AAEhE;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D;;;;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;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,gBAAgB,EAAE,OAsD7B,CAAC;AAEH;;;;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;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,eAAe,GAAG,OAAO,CAMnE"}
@@ -55,8 +55,10 @@ const AI_NO_RESPONSE_TIMEOUT_MS = 300000;
55
55
  * a fresh object for callers that override, and hands this back untouched for callers that
56
56
  * do not.
57
57
  *
58
- * The models are the ones Genesis Create has been running these tiers on in production, and
59
- * they are a **benchmark result, not a preference** — re-bench before moving one. Two dates
58
+ * The models are the ones Genesis Create has been running these tiers on in production — except
59
+ * Anthropic's `reasoning`, moved to `claude-opus-4-8` (see its entry) — and they are a
60
+ * **benchmark result, not a preference**: re-bench before moving one. Two of the Gemini
61
+ * defaults carry a caveat recorded beside them, a preview model and an introductory rate. Two dates
60
62
  * are already on the calendar for that: `gemini-3.8-flash` sits on an introductory rate that
61
63
  * doubles on 2027-01-01 (at which point it is dearer on input than the model it replaced),
62
64
  * and `token-cost.test.ts` fails the build that day; `ai-tiers.test.ts` fails alongside it
@@ -86,8 +88,12 @@ export const DEFAULT_AI_TIERS = Object.freeze({
86
88
  }),
87
89
  // One-shot judgement calls rather than tool loops, so a smaller ceiling is ample:
88
90
  // `max_tokens` is only a cap, and this tier never emits a whole file.
91
+ //
92
+ // Opus 4.8 rather than the 4.7 Create benched: the same price ($5 / $25) and the same 1M
93
+ // window, but 4.8 supports native structured output where 4.7 takes the forced-tool
94
+ // fallback — and structured judgement is what this tier is asked for most (review of #2540).
89
95
  reasoning: Object.freeze({
90
- model: 'claude-opus-4-7',
96
+ model: 'claude-opus-4-8',
91
97
  maxTokens: 32000,
92
98
  stallTimeoutMs: AI_STALL_TIMEOUT_MS,
93
99
  timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS,
@@ -99,11 +105,18 @@ export const DEFAULT_AI_TIERS = Object.freeze({
99
105
  stallTimeoutMs: AI_STALL_TIMEOUT_MS,
100
106
  timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS,
101
107
  }),
108
+ // On an INTRODUCTORY rate that doubles to $1.50 / $7.50 on 2027-01-01, from which point it
109
+ // is dearer on input than the gemini-3.5-flash it replaced. Chosen at the introductory rate
110
+ // knowingly; `ai-tiers.test.ts` fails that day to force the re-bench.
102
111
  high: Object.freeze({
103
112
  model: 'gemini-3.8-flash',
104
113
  stallTimeoutMs: AI_STALL_TIMEOUT_MS,
105
114
  timeoutMs: AI_NO_RESPONSE_TIMEOUT_MS,
106
115
  }),
116
+ // A PREVIEW model: no stability guarantee, and it may be withdrawn at short notice (its
117
+ // transport warns on every construction). Accepted knowingly as the platform default because
118
+ // no stable Gemini Pro was on offer when the tiers were benched; revisit as soon as Google
119
+ // promotes, deprecates or withdraws it, since every app on this default inherits the risk.
107
120
  reasoning: Object.freeze({
108
121
  model: 'gemini-3.1-pro-preview',
109
122
  stallTimeoutMs: AI_STALL_TIMEOUT_MS,
@@ -117,14 +130,21 @@ export const DEFAULT_AI_TIERS = Object.freeze({
117
130
  * clocks and ceilings.
118
131
  *
119
132
  * @remarks
120
- * Returns the frozen default itself when there is nothing to override, and a fresh
121
- * (unfrozen) object otherwise. Either way the default is never mutated, which matters
122
- * because it is shared across every app in the process.
133
+ * An override field set to `undefined` is skipped, exactly as if it had been left out. The
134
+ * common caller passes an optional config value straight through
135
+ * (`{ high: { model: appConfig.model } }`), and copying `undefined` over the default would
136
+ * hand the transport no model at all — it then quietly falls back to its own default, with
137
+ * nothing logged.
138
+ *
139
+ * The result is frozen whether or not anything was overridden, so whether mutating it throws
140
+ * does not depend on what the caller passed. The default itself is returned untouched when
141
+ * there is nothing to override, and is never mutated, which matters because it is shared
142
+ * across every app in the process.
123
143
  *
124
144
  * @example
125
145
  * ```ts
126
- * // Keep everything, but run the reasoning tier on the newest Opus.
127
- * const tiers = resolveAITiers({ anthropic: { reasoning: { model: 'claude-opus-4-8' } } });
146
+ * // Keep everything, but run the reasoning tier on Fable.
147
+ * const tiers = resolveAITiers({ anthropic: { reasoning: { model: 'claude-fable-5' } } });
128
148
  * ```
129
149
  *
130
150
  * @beta
@@ -132,15 +152,22 @@ export const DEFAULT_AI_TIERS = Object.freeze({
132
152
  export function resolveAITiers(overrides) {
133
153
  if (!(overrides === null || overrides === void 0 ? void 0 : overrides.anthropic) && !(overrides === null || overrides === void 0 ? void 0 : overrides.gemini))
134
154
  return DEFAULT_AI_TIERS;
135
- return {
155
+ return Object.freeze({
136
156
  anthropic: mergeVendor(DEFAULT_AI_TIERS.anthropic, overrides.anthropic),
137
157
  gemini: mergeVendor(DEFAULT_AI_TIERS.gemini, overrides.gemini),
138
- };
158
+ });
139
159
  }
140
160
  function mergeVendor(defaults, overrides) {
161
+ var _a;
141
162
  const merged = {};
142
163
  for (const tier of AI_TIER_IDS) {
143
- merged[tier] = Object.assign(Object.assign({}, defaults[tier]), overrides === null || overrides === void 0 ? void 0 : overrides[tier]);
164
+ const defined = Object.fromEntries(Object.entries((_a = overrides === null || overrides === void 0 ? void 0 : overrides[tier]) !== null && _a !== void 0 ? _a : {}).filter(([, value]) => value !== undefined));
165
+ // Frozen in place rather than through `Object.freeze`'s return value, whose overloads
166
+ // widen a generic `T` to an index signature; the typed reference is the one we keep.
167
+ const entry = Object.assign(Object.assign({}, defaults[tier]), defined);
168
+ Object.freeze(entry);
169
+ merged[tier] = entry;
144
170
  }
171
+ Object.freeze(merged);
145
172
  return merged;
146
173
  }
@@ -9484,7 +9484,7 @@
9484
9484
  {
9485
9485
  "kind": "Variable",
9486
9486
  "canonicalReference": "@genesislcap/foundation-ai!DEFAULT_AI_TIERS:var",
9487
- "docComment": "/**\n * The platform's default tier table.\n *\n * @remarks\n *\n * Frozen, because it is shared by every app in the process: {@link resolveAITiers} returns a fresh object for callers that override, and hands this back untouched for callers that do not.\n *\n * The models are the ones Genesis Create has been running these tiers on in production, and they are a **benchmark result, not a preference** — re-bench before moving one. Two dates are already on the calendar for that: `gemini-3.8-flash` sits on an introductory rate that doubles on 2027-01-01 (at which point it is dearer on input than the model it replaced), and `token-cost.test.ts` fails the build that day; `ai-tiers.test.ts` fails alongside it saying the High tier is the thing to re-bench.\n *\n * Every model here must be in `SUPPORTED_*_MODEL_IDS` with a context limit and a price — pinned by tests, because an unpriced model silently bills at nothing.\n *\n * @beta\n */\n",
9487
+ "docComment": "/**\n * The platform's default tier table.\n *\n * @remarks\n *\n * Frozen, because it is shared by every app in the process: {@link resolveAITiers} returns a fresh object for callers that override, and hands this back untouched for callers that do not.\n *\n * The models are the ones Genesis Create has been running these tiers on in production — except Anthropic's `reasoning`, moved to `claude-opus-4-8` (see its entry) — and they are a **benchmark result, not a preference**: re-bench before moving one. Two of the Gemini defaults carry a caveat recorded beside them, a preview model and an introductory rate. Two dates are already on the calendar for that: `gemini-3.8-flash` sits on an introductory rate that doubles on 2027-01-01 (at which point it is dearer on input than the model it replaced), and `token-cost.test.ts` fails the build that day; `ai-tiers.test.ts` fails alongside it saying the High tier is the thing to re-bench.\n *\n * Every model here must be in `SUPPORTED_*_MODEL_IDS` with a context limit and a price — pinned by tests, because an unpriced model silently bills at nothing.\n *\n * @beta\n */\n",
9488
9488
  "excerptTokens": [
9489
9489
  {
9490
9490
  "kind": "Content",
@@ -13099,7 +13099,7 @@
13099
13099
  {
13100
13100
  "kind": "Function",
13101
13101
  "canonicalReference": "@genesislcap/foundation-ai!resolveAITiers:function(1)",
13102
- "docComment": "/**\n * The table an app should actually use: {@link DEFAULT_AI_TIERS} with `overrides` applied per field, so an app that wants one model moved says only that and keeps the platform's clocks and ceilings.\n *\n * @remarks\n *\n * Returns the frozen default itself when there is nothing to override, and a fresh (unfrozen) object otherwise. Either way the default is never mutated, which matters because it is shared across every app in the process.\n *\n * @example\n * ```ts\n * // Keep everything, but run the reasoning tier on the newest Opus.\n * const tiers = resolveAITiers({ anthropic: { reasoning: { model: 'claude-opus-4-8' } } });\n * ```\n *\n * @beta\n */\n",
13102
+ "docComment": "/**\n * The table an app should actually use: {@link DEFAULT_AI_TIERS} with `overrides` applied per field, so an app that wants one model moved says only that and keeps the platform's clocks and ceilings.\n *\n * @remarks\n *\n * An override field set to `undefined` is skipped, exactly as if it had been left out. The common caller passes an optional config value straight through (`{ high: { model: appConfig.model } }`), and copying `undefined` over the default would hand the transport no model at all — it then quietly falls back to its own default, with nothing logged.\n *\n * The result is frozen whether or not anything was overridden, so whether mutating it throws does not depend on what the caller passed. The default itself is returned untouched when there is nothing to override, and is never mutated, which matters because it is shared across every app in the process.\n *\n * @example\n * ```ts\n * // Keep everything, but run the reasoning tier on Fable.\n * const tiers = resolveAITiers({ anthropic: { reasoning: { model: 'claude-fable-5' } } });\n * ```\n *\n * @beta\n */\n",
13103
13103
  "excerptTokens": [
13104
13104
  {
13105
13105
  "kind": "Content",
@@ -2551,8 +2551,10 @@ export declare interface CriteriaInterpretContext {
2551
2551
  * a fresh object for callers that override, and hands this back untouched for callers that
2552
2552
  * do not.
2553
2553
  *
2554
- * The models are the ones Genesis Create has been running these tiers on in production, and
2555
- * they are a **benchmark result, not a preference** — re-bench before moving one. Two dates
2554
+ * The models are the ones Genesis Create has been running these tiers on in production — except
2555
+ * Anthropic's `reasoning`, moved to `claude-opus-4-8` (see its entry) — and they are a
2556
+ * **benchmark result, not a preference**: re-bench before moving one. Two of the Gemini
2557
+ * defaults carry a caveat recorded beside them, a preview model and an introductory rate. Two dates
2556
2558
  * are already on the calendar for that: `gemini-3.8-flash` sits on an introductory rate that
2557
2559
  * doubles on 2027-01-01 (at which point it is dearer on input than the model it replaced),
2558
2560
  * and `token-cost.test.ts` fails the build that day; `ai-tiers.test.ts` fails alongside it
@@ -3402,14 +3404,21 @@ export declare interface ResolveAIConfigOptions {
3402
3404
  * clocks and ceilings.
3403
3405
  *
3404
3406
  * @remarks
3405
- * Returns the frozen default itself when there is nothing to override, and a fresh
3406
- * (unfrozen) object otherwise. Either way the default is never mutated, which matters
3407
- * because it is shared across every app in the process.
3407
+ * An override field set to `undefined` is skipped, exactly as if it had been left out. The
3408
+ * common caller passes an optional config value straight through
3409
+ * (`{ high: { model: appConfig.model } }`), and copying `undefined` over the default would
3410
+ * hand the transport no model at all — it then quietly falls back to its own default, with
3411
+ * nothing logged.
3412
+ *
3413
+ * The result is frozen whether or not anything was overridden, so whether mutating it throws
3414
+ * does not depend on what the caller passed. The default itself is returned untouched when
3415
+ * there is nothing to override, and is never mutated, which matters because it is shared
3416
+ * across every app in the process.
3408
3417
  *
3409
3418
  * @example
3410
3419
  * ```ts
3411
- * // Keep everything, but run the reasoning tier on the newest Opus.
3412
- * const tiers = resolveAITiers({ anthropic: { reasoning: { model: 'claude-opus-4-8' } } });
3420
+ * // Keep everything, but run the reasoning tier on Fable.
3421
+ * const tiers = resolveAITiers({ anthropic: { reasoning: { model: 'claude-fable-5' } } });
3413
3422
  * ```
3414
3423
  *
3415
3424
  * @beta
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/foundation-ai",
3
3
  "description": "Genesis Foundation AI - Provider-agnostic AI configuration and shared utilities",
4
- "version": "15.33.1-GENC-1601.2",
4
+ "version": "15.34.0",
5
5
  "sideEffects": false,
6
6
  "license": "SEE LICENSE IN license.txt",
7
7
  "main": "dist/esm/index.js",
@@ -52,17 +52,17 @@
52
52
  }
53
53
  },
54
54
  "devDependencies": {
55
- "@genesislcap/foundation-testing": "15.33.1-GENC-1601.2",
56
- "@genesislcap/genx": "15.33.1-GENC-1601.2",
57
- "@genesislcap/rollup-builder": "15.33.1-GENC-1601.2",
58
- "@genesislcap/ts-builder": "15.33.1-GENC-1601.2",
59
- "@genesislcap/uvu-playwright-builder": "15.33.1-GENC-1601.2",
60
- "@genesislcap/vite-builder": "15.33.1-GENC-1601.2",
61
- "@genesislcap/webpack-builder": "15.33.1-GENC-1601.2"
55
+ "@genesislcap/foundation-testing": "15.34.0",
56
+ "@genesislcap/genx": "15.34.0",
57
+ "@genesislcap/rollup-builder": "15.34.0",
58
+ "@genesislcap/ts-builder": "15.34.0",
59
+ "@genesislcap/uvu-playwright-builder": "15.34.0",
60
+ "@genesislcap/vite-builder": "15.34.0",
61
+ "@genesislcap/webpack-builder": "15.34.0"
62
62
  },
63
63
  "dependencies": {
64
- "@genesislcap/foundation-logger": "15.33.1-GENC-1601.2",
65
- "@genesislcap/foundation-utils": "15.33.1-GENC-1601.2",
64
+ "@genesislcap/foundation-logger": "15.34.0",
65
+ "@genesislcap/foundation-utils": "15.34.0",
66
66
  "@microsoft/fast-foundation": "2.50.0"
67
67
  },
68
68
  "repository": {