@mastra/code-sdk 1.8.0-alpha.6 → 1.8.0-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/mastracode-gateway.d.ts +2 -0
- package/dist/agents/mastracode-gateway.d.ts.map +1 -1
- package/dist/agents/mastracode-gateway.js +29 -10
- package/dist/agents/mastracode-gateway.js.map +1 -1
- package/dist/agents/memory.d.ts +1 -1
- package/dist/agents/memory.d.ts.map +1 -1
- package/dist/agents/memory.js +32 -25
- package/dist/agents/memory.js.map +1 -1
- package/dist/agents/model.d.ts +41 -1
- package/dist/agents/model.d.ts.map +1 -1
- package/dist/agents/model.js +141 -7
- package/dist/agents/model.js.map +1 -1
- package/dist/auth/account-rotation-processor.d.ts +207 -0
- package/dist/auth/account-rotation-processor.d.ts.map +1 -0
- package/dist/auth/account-rotation-processor.js +669 -0
- package/dist/auth/account-rotation-processor.js.map +1 -0
- package/dist/auth/account-routing-context.d.ts +13 -0
- package/dist/auth/account-routing-context.d.ts.map +1 -0
- package/dist/auth/account-routing-context.js +41 -0
- package/dist/auth/account-routing-context.js.map +1 -0
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +2 -1
- package/dist/auth/providers/anthropic.d.ts.map +1 -1
- package/dist/auth/providers/anthropic.js +2 -8
- package/dist/auth/providers/anthropic.js.map +1 -1
- package/dist/auth/providers/github-copilot.d.ts.map +1 -1
- package/dist/auth/providers/github-copilot.js +34 -12
- package/dist/auth/providers/github-copilot.js.map +1 -1
- package/dist/auth/providers/kimi-coding.d.ts.map +1 -1
- package/dist/auth/providers/kimi-coding.js +2 -6
- package/dist/auth/providers/kimi-coding.js.map +1 -1
- package/dist/auth/providers/openai-codex.d.ts +3 -1
- package/dist/auth/providers/openai-codex.d.ts.map +1 -1
- package/dist/auth/providers/openai-codex.js +50 -24
- package/dist/auth/providers/openai-codex.js.map +1 -1
- package/dist/auth/providers/xai.d.ts +1 -1
- package/dist/auth/providers/xai.d.ts.map +1 -1
- package/dist/auth/providers/xai.js +36 -16
- package/dist/auth/providers/xai.js.map +1 -1
- package/dist/auth/storage.d.ts +130 -8
- package/dist/auth/storage.d.ts.map +1 -1
- package/dist/auth/storage.js +602 -39
- package/dist/auth/storage.js.map +1 -1
- package/dist/auth/types.d.ts +69 -2
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +88 -23
- package/dist/index.js.map +1 -1
- package/dist/onboarding/custom-packs.d.ts.map +1 -1
- package/dist/onboarding/custom-packs.js +3 -0
- package/dist/onboarding/custom-packs.js.map +1 -1
- package/dist/onboarding/index.js +1 -1
- package/dist/onboarding/packs.d.ts +44 -0
- package/dist/onboarding/packs.d.ts.map +1 -1
- package/dist/onboarding/packs.js +80 -2
- package/dist/onboarding/packs.js.map +1 -1
- package/dist/onboarding/settings.d.ts +28 -0
- package/dist/onboarding/settings.d.ts.map +1 -1
- package/dist/onboarding/settings.js +81 -8
- package/dist/onboarding/settings.js.map +1 -1
- package/dist/providers/claude-max.d.ts.map +1 -1
- package/dist/providers/claude-max.js +4 -5
- package/dist/providers/claude-max.js.map +1 -1
- package/dist/providers/github-copilot.d.ts +1 -1
- package/dist/providers/github-copilot.d.ts.map +1 -1
- package/dist/providers/github-copilot.js +89 -37
- package/dist/providers/github-copilot.js.map +1 -1
- package/dist/providers/kimi-coding.d.ts.map +1 -1
- package/dist/providers/kimi-coding.js +16 -2
- package/dist/providers/kimi-coding.js.map +1 -1
- package/dist/providers/openai-codex.d.ts.map +1 -1
- package/dist/providers/openai-codex.js +42 -27
- package/dist/providers/openai-codex.js.map +1 -1
- package/dist/schema.d.ts +28 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +9 -0
- package/dist/schema.js.map +1 -1
- package/dist/tools/workflows/save-workflow.d.ts +1009 -2
- package/dist/tools/workflows/save-workflow.d.ts.map +1 -1
- package/package.json +7 -7
package/dist/agents/model.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { isThinkingLevelSetting } from "../thinking.js";
|
|
2
|
-
import {
|
|
2
|
+
import { listBuiltinModePacks, resolveModePackFallbackChain } from "../onboarding/packs.js";
|
|
3
|
+
import { findModePackForModel, loadSettings, resolveDefaultThinkingLevel, resolveModePackModels, stripMastraCodeCustomProviderPrefix } from "../onboarding/settings.js";
|
|
3
4
|
import { hasCredentialStoreProvider, resolveCredentialStore, resolveTenantFromRequestContext, setCredentialStoreProvider } from "./credential-resolver.js";
|
|
5
|
+
import { getRequestAccountSelection, isRequestAccountRoutingExhausted } from "../auth/account-routing-context.js";
|
|
4
6
|
import { AMAZON_BEDROCK_GATEWAY_ID, createAmazonBedrockGateway } from "../providers/amazon-bedrock-gateway.js";
|
|
5
7
|
import { hasCustomProvidersSource, resolveCustomProviders, setCustomProvidersSource } from "./custom-provider-source.js";
|
|
6
|
-
import { MASTRACODE_GATEWAY_ID, MASTRA_GATEWAY_PREFIX, MastraCodeGateway, getAnthropicApiKey, getOpenAIApiKey, reloadAuthStorage, remapOpenAIModelForCodexOAuth, resolveAuth, stripMastraGatewayPrefix } from "./mastracode-gateway.js";
|
|
8
|
+
import { MASTRACODE_GATEWAY_ID, MASTRA_GATEWAY_PREFIX, MastraCodeGateway, getAnthropicApiKey, getGlobalAuthStorage, getOpenAIApiKey, reloadAuthStorage, remapOpenAIModelForCodexOAuth, resolveAuth, stripMastraGatewayPrefix } from "./mastracode-gateway.js";
|
|
7
9
|
//#region src/agents/model.ts
|
|
8
10
|
function getAgentControllerHeaders(requestContext) {
|
|
9
11
|
const agentControllerContext = requestContext?.get("controller");
|
|
@@ -13,6 +15,42 @@ function getAgentControllerHeaders(requestContext) {
|
|
|
13
15
|
};
|
|
14
16
|
return Object.keys(headers).length > 0 ? headers : void 0;
|
|
15
17
|
}
|
|
18
|
+
function accountCredential(account) {
|
|
19
|
+
const { type: _type, id: _id, label: _label, addedAt: _addedAt, active: _active, ...credential } = account;
|
|
20
|
+
return {
|
|
21
|
+
type: "oauth",
|
|
22
|
+
...credential
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function createRequestScopedCredentialStore(base, requestContext) {
|
|
26
|
+
const selectedId = (providerId) => getRequestAccountSelection(requestContext, providerId);
|
|
27
|
+
const selectedAccount = (providerId) => {
|
|
28
|
+
const accountInstanceId = selectedId(providerId);
|
|
29
|
+
return accountInstanceId ? base.listAccounts?.(providerId).find((account) => account.id === accountInstanceId) : void 0;
|
|
30
|
+
};
|
|
31
|
+
const rejectAll = (providerId) => isRequestAccountRoutingExhausted(requestContext, providerId);
|
|
32
|
+
return {
|
|
33
|
+
allowEnvironmentFallback: base.allowEnvironmentFallback,
|
|
34
|
+
reload: () => base.reload(),
|
|
35
|
+
get: (providerId) => {
|
|
36
|
+
if (rejectAll(providerId)) return void 0;
|
|
37
|
+
if (selectedId(providerId) === void 0) return base.get(providerId);
|
|
38
|
+
const selected = selectedAccount(providerId);
|
|
39
|
+
return selected ? accountCredential(selected) : void 0;
|
|
40
|
+
},
|
|
41
|
+
getStoredApiKey: (providerId) => {
|
|
42
|
+
if (rejectAll(providerId)) return void 0;
|
|
43
|
+
if (selectedId(providerId) !== void 0) return void 0;
|
|
44
|
+
return base.getStoredApiKey(providerId);
|
|
45
|
+
},
|
|
46
|
+
getApiKey: (providerId) => rejectAll(providerId) ? Promise.resolve(void 0) : base.getApiKey(providerId, selectedId(providerId)),
|
|
47
|
+
getOAuthCredential: base.getOAuthCredential ? (providerId) => rejectAll(providerId) ? Promise.resolve(void 0) : base.getOAuthCredential(providerId, selectedId(providerId)) : void 0,
|
|
48
|
+
listAccounts: base.listAccounts ? (providerId) => base.listAccounts(providerId) : void 0,
|
|
49
|
+
getActiveAccount: base.getActiveAccount ? (providerId) => base.getActiveAccount(providerId) : void 0,
|
|
50
|
+
activateAccount: base.activateAccount ? (providerId, accountInstanceId) => base.activateAccount(providerId, accountInstanceId) : void 0,
|
|
51
|
+
removeAccount: base.removeAccount ? (providerId, accountInstanceId) => base.removeAccount(providerId, accountInstanceId) : void 0
|
|
52
|
+
};
|
|
53
|
+
}
|
|
16
54
|
function createMastraCodeGateway(options) {
|
|
17
55
|
return new MastraCodeGateway(options);
|
|
18
56
|
}
|
|
@@ -68,7 +106,7 @@ function resolveModel(modelId, options) {
|
|
|
68
106
|
const routerId = `${MASTRACODE_GATEWAY_ID}/${normalizedModelId}`;
|
|
69
107
|
const mgApiKey = MastraCodeGateway.getMastraGatewayApiKey();
|
|
70
108
|
const rawGatewayBase = settings.memoryGateway?.baseUrl ?? process.env["MASTRA_GATEWAY_URL"] ?? "https://gateway-api.mastra.ai";
|
|
71
|
-
const credentialStore = resolveCredentialStore(options?.requestContext);
|
|
109
|
+
const credentialStore = createRequestScopedCredentialStore(resolveCredentialStore(options?.requestContext) ?? getGlobalAuthStorage(), options?.requestContext);
|
|
72
110
|
const gateway = createMastraCodeGateway({
|
|
73
111
|
mastraGatewayBaseUrl: rawGatewayBase.replace(/\/+$/, "").replace(/\/v1$/, ""),
|
|
74
112
|
mastraGatewayApiKey: mgApiKey,
|
|
@@ -110,22 +148,118 @@ function resolveRequestThinkingLevel(agentControllerContext, settingsPath) {
|
|
|
110
148
|
const modeId = agentControllerContext?.session?.modeId;
|
|
111
149
|
return resolveDefaultThinkingLevel(loadSettings(settingsPath), modeId).level;
|
|
112
150
|
}
|
|
151
|
+
/** All packs a fallback chain may reference: every builtin plus saved customs. */
|
|
152
|
+
function listResolvableModePacks(settings) {
|
|
153
|
+
return [...listBuiltinModePacks(), ...settings.customModelPacks.map((pack) => ({
|
|
154
|
+
id: `custom:${pack.name}`,
|
|
155
|
+
name: pack.name,
|
|
156
|
+
models: { ...pack.models }
|
|
157
|
+
}))];
|
|
158
|
+
}
|
|
113
159
|
/**
|
|
114
160
|
* Dynamic model function that reads the current model from controller state.
|
|
115
161
|
* This allows runtime model switching via the /models picker.
|
|
162
|
+
*
|
|
163
|
+
* When the session's model came from a pack with a fallback chain configured
|
|
164
|
+
* (`settings.models.packFallbacks`), returns core's `ModelWithRetries[]`
|
|
165
|
+
* fallback array instead of a bare model: the active pack's model first, then
|
|
166
|
+
* each fallback pack's model for the same mode. Core advances the array when
|
|
167
|
+
* the error processors decline to retry (pool exhausted / persistent outage —
|
|
168
|
+
* see AccountRotationProcessor). Entry ids are unique per occurrence — the
|
|
169
|
+
* one allowed revisit of a pack gets `<packId>#2` — because core re-resolves
|
|
170
|
+
* the active fallback index by id across agentic steps.
|
|
116
171
|
*/
|
|
117
172
|
function getDynamicModel({ requestContext }, settingsPath) {
|
|
118
173
|
const agentControllerContext = requestContext.get("controller");
|
|
119
|
-
const
|
|
174
|
+
const controllerState = agentControllerContext?.getState?.();
|
|
175
|
+
const pendingState = controllerState?.mastracodePendingPackFallback;
|
|
176
|
+
const pendingFallback = pendingState && (pendingState.threadId === void 0 || typeof pendingState.threadId === "string" && pendingState.threadId === agentControllerContext?.threadId) ? pendingState : void 0;
|
|
177
|
+
const modelId = (pendingFallback && typeof pendingFallback.toModelId === "string" && pendingFallback.toModelId.length > 0 ? pendingFallback.toModelId : void 0) ?? agentControllerContext?.session?.modelId;
|
|
120
178
|
if (!modelId) {
|
|
121
179
|
if (!agentControllerContext) throw new Error("No model available: this run started without a controller session context, so no model selection could be resolved.");
|
|
122
180
|
throw new Error("No model selected. Use /models to select a model first.");
|
|
123
181
|
}
|
|
124
|
-
|
|
182
|
+
const resolveOptions = {
|
|
125
183
|
thinkingLevel: resolveRequestThinkingLevel(agentControllerContext, settingsPath),
|
|
126
184
|
remapForCodexOAuth: true,
|
|
127
185
|
requestContext
|
|
128
|
-
}
|
|
186
|
+
};
|
|
187
|
+
const primary = resolveModel(modelId, resolveOptions);
|
|
188
|
+
const settings = loadSettings(settingsPath);
|
|
189
|
+
const fallbacks = settings.models?.packFallbacks ?? {};
|
|
190
|
+
if (Object.keys(fallbacks).length === 0) return primary;
|
|
191
|
+
const modeId = agentControllerContext?.session?.modeId ?? "build";
|
|
192
|
+
const packs = listResolvableModePacks(settings);
|
|
193
|
+
const statePackId = (pendingFallback && typeof pendingFallback.toPackId === "string" && pendingFallback.toPackId.length > 0 ? pendingFallback.toPackId : void 0) ?? controllerState?.activeModelPackId ?? settings.models.activeModelPackId;
|
|
194
|
+
const activePack = findModePackForModel(settings, packs, modelId, modeId, typeof statePackId === "string" ? statePackId : void 0);
|
|
195
|
+
if (!activePack) return primary;
|
|
196
|
+
const chain = resolveModePackFallbackChain(fallbacks, activePack.id, settings.customModelPacks);
|
|
197
|
+
if (chain.length < 2) return primary;
|
|
198
|
+
const entries = [{
|
|
199
|
+
id: activePack.id,
|
|
200
|
+
model: primary
|
|
201
|
+
}];
|
|
202
|
+
const appearances = /* @__PURE__ */ new Map([[activePack.id, 1]]);
|
|
203
|
+
for (const packId of chain.slice(1)) {
|
|
204
|
+
const pack = packs.find((candidate) => candidate.id === packId);
|
|
205
|
+
if (!pack) break;
|
|
206
|
+
const entryModelId = resolveModePackModels(settings, pack)[modeId];
|
|
207
|
+
if (!entryModelId) break;
|
|
208
|
+
let entryModel;
|
|
209
|
+
try {
|
|
210
|
+
entryModel = resolveModel(entryModelId, resolveOptions);
|
|
211
|
+
} catch {
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
const occurrence = (appearances.get(packId) ?? 0) + 1;
|
|
215
|
+
appearances.set(packId, occurrence);
|
|
216
|
+
entries.push({
|
|
217
|
+
id: occurrence === 1 ? packId : `${packId}#${occurrence}`,
|
|
218
|
+
model: entryModel
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
if (entries.length < 2) return primary;
|
|
222
|
+
return entries;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Resolve the observational-memory model for the active mode pack, walking the
|
|
226
|
+
* pack's fallback chain (`settings.models.packFallbacks`) and collecting each
|
|
227
|
+
* pack's optional `models.memory` entry. Packs without an OM model are skipped
|
|
228
|
+
* (the field is optional, so absence must not truncate the chain); duplicate
|
|
229
|
+
* model ids collapse so an A⇄B cycle never retries an identical OM model.
|
|
230
|
+
*
|
|
231
|
+
* Returns a bare model for a single entry, a fallback array for multiple
|
|
232
|
+
* entries (OM's internal agents run the same agentic loop, so the array gives
|
|
233
|
+
* OM its own cross-pack failover), or `undefined` when no pack in the chain
|
|
234
|
+
* defines an OM model — callers then fall back to the standalone OM
|
|
235
|
+
* configuration.
|
|
236
|
+
*/
|
|
237
|
+
function resolvePackMemoryModelChain(settings, startPackId, resolveOptions) {
|
|
238
|
+
const packs = listResolvableModePacks(settings);
|
|
239
|
+
if (!packs.some((pack) => pack.id === startPackId)) return void 0;
|
|
240
|
+
const chain = resolveModePackFallbackChain(settings.models?.packFallbacks ?? {}, startPackId, settings.customModelPacks);
|
|
241
|
+
const seenModelIds = /* @__PURE__ */ new Set();
|
|
242
|
+
const entries = [];
|
|
243
|
+
for (const packId of chain) {
|
|
244
|
+
const pack = packs.find((candidate) => candidate.id === packId);
|
|
245
|
+
if (!pack) break;
|
|
246
|
+
const memoryModelId = resolveModePackModels(settings, pack).memory;
|
|
247
|
+
if (!memoryModelId || seenModelIds.has(memoryModelId)) continue;
|
|
248
|
+
seenModelIds.add(memoryModelId);
|
|
249
|
+
let entryModel;
|
|
250
|
+
try {
|
|
251
|
+
entryModel = resolveModel(memoryModelId, resolveOptions);
|
|
252
|
+
} catch {
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
entries.push({
|
|
256
|
+
id: `${packId}:memory`,
|
|
257
|
+
model: entryModel
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
if (entries.length === 0) return void 0;
|
|
261
|
+
if (entries.length === 1) return entries[0].model;
|
|
262
|
+
return entries;
|
|
129
263
|
}
|
|
130
264
|
/**
|
|
131
265
|
* Goal judge model resolver for the agent's `goal.judge` config. Resolves the
|
|
@@ -150,6 +284,6 @@ function getGoalJudgeModel({ requestContext }, settingsPath) {
|
|
|
150
284
|
});
|
|
151
285
|
}
|
|
152
286
|
//#endregion
|
|
153
|
-
export { MASTRACODE_GATEWAY_ID, MastraCodeGateway, createMastraCodeGateway, createMastraCodeModelCatalogProvider, getAnthropicApiKey, getDynamicModel, getGoalJudgeModel, getOpenAIApiKey, hasCredentialStoreProvider, hasCustomProvidersSource, remapOpenAIModelForCodexOAuth, resolveAuth, resolveCustomProviders, resolveModel, resolveModelId, resolveRequestThinkingLevel, resolveTenantFromRequestContext, setCredentialStoreProvider, setCustomProvidersSource };
|
|
287
|
+
export { MASTRACODE_GATEWAY_ID, MastraCodeGateway, createMastraCodeGateway, createMastraCodeModelCatalogProvider, createRequestScopedCredentialStore, getAnthropicApiKey, getDynamicModel, getGoalJudgeModel, getOpenAIApiKey, hasCredentialStoreProvider, hasCustomProvidersSource, listResolvableModePacks, remapOpenAIModelForCodexOAuth, resolveAuth, resolveCustomProviders, resolveModel, resolveModelId, resolvePackMemoryModelChain, resolveRequestThinkingLevel, resolveTenantFromRequestContext, setCredentialStoreProvider, setCustomProvidersSource };
|
|
154
288
|
|
|
155
289
|
//# sourceMappingURL=model.js.map
|
package/dist/agents/model.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","names":[],"sources":["../../src/agents/model.ts"],"sourcesContent":["import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { GatewayLanguageModel, MastraModelGatewayInterface } from '@mastra/core/llm';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport {\n loadSettings,\n resolveDefaultThinkingLevel,\n stripMastraCodeCustomProviderPrefix,\n} from '../onboarding/settings.js';\nimport { AMAZON_BEDROCK_GATEWAY_ID, createAmazonBedrockGateway } from '../providers/amazon-bedrock-gateway.js';\nimport { isThinkingLevelSetting } from '../thinking.js';\nimport type { ThinkingLevelSetting } from '../thinking.js';\nimport { resolveCredentialStore } from './credential-resolver.js';\nimport { resolveCustomProviders } from './custom-provider-source.js';\nimport {\n MASTRA_GATEWAY_PREFIX,\n MASTRACODE_GATEWAY_ID,\n MastraCodeGateway,\n reloadAuthStorage,\n stripMastraGatewayPrefix,\n} from './mastracode-gateway.js';\nimport type { MastraCodeGatewayOptions } from './mastracode-gateway.js';\n\nexport {\n getAnthropicApiKey,\n getOpenAIApiKey,\n MASTRACODE_GATEWAY_ID,\n MastraCodeGateway,\n remapOpenAIModelForCodexOAuth,\n resolveAuth,\n} from './mastracode-gateway.js';\nexport type { MastraCodeCustomProvider, MastraCodeGatewayOptions } from './mastracode-gateway.js';\nexport {\n setCredentialStoreProvider,\n hasCredentialStoreProvider,\n resolveTenantFromRequestContext,\n} from './credential-resolver.js';\nexport type { CredentialTenant, CredentialStoreProvider } from './credential-resolver.js';\nexport {\n setCustomProvidersSource,\n hasCustomProvidersSource,\n resolveCustomProviders,\n} from './custom-provider-source.js';\nexport type { CustomProvidersSource } from './custom-provider-source.js';\n\ntype ResolvedModel = GatewayLanguageModel;\ntype ModelRequestHeaders = Record<string, string>;\n\nfunction getAgentControllerHeaders(requestContext?: RequestContext): ModelRequestHeaders | undefined {\n const agentControllerContext = requestContext?.get('controller') as AgentControllerRequestContext<any> | undefined;\n const headers = {\n ...(agentControllerContext?.threadId ? { 'x-thread-id': agentControllerContext.threadId } : {}),\n ...(agentControllerContext?.resourceId ? { 'x-resource-id': agentControllerContext.resourceId } : {}),\n };\n\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n\nexport function createMastraCodeGateway(options: MastraCodeGatewayOptions): MastraCodeGateway {\n return new MastraCodeGateway(options);\n}\n\nexport function createMastraCodeModelCatalogProvider(gateway: MastraModelGatewayInterface) {\n return gateway instanceof MastraCodeGateway\n ? gateway.createModelCatalogProvider()\n : MastraCodeGateway.createModelCatalogProvider(gateway);\n}\n\n/**\n * Placeholder for future model ID normalization.\n * Currently returns the input unchanged, but exists as a seam\n * for aliasing, casing fixes, or validation in the future.\n */\nexport function resolveModelId(modelId: string): string {\n return modelId;\n}\n\n/**\n * Resolve a model ID to the correct provider instance.\n * Shared by the main agent, observer, and reflector.\n *\n * - For anthropic/* models: Uses stored OAuth credentials when present, otherwise direct API key\n * - For openai/* models: Uses OAuth when configured, otherwise direct API key from AuthStorage\n * - For moonshotai/* models: Uses Moonshot AI Anthropic-compatible endpoint\n * - For all other providers: Uses Mastra's model router (models.dev gateway)\n */\nexport function resolveModel(\n modelId: string,\n options?: { thinkingLevel?: ThinkingLevelSetting; remapForCodexOAuth?: boolean; requestContext?: RequestContext },\n): GatewayLanguageModel {\n reloadAuthStorage();\n const headers = getAgentControllerHeaders(options?.requestContext);\n const settings = loadSettings();\n // Bedrock was previously cataloged under the MastraCode gateway namespace\n // (`mastracode/amazon-bedrock/<model>`). Normalize any legacy saved ids to the\n // standalone `amazon-bedrock/<model>` form so they resolve through the\n // dedicated Bedrock gateway.\n const bedrockLegacyPrefix = `${MASTRACODE_GATEWAY_ID}/amazon-bedrock/`;\n const bedrockNormalizedInput = modelId.startsWith(bedrockLegacyPrefix)\n ? modelId.slice(MASTRACODE_GATEWAY_ID.length + 1)\n : modelId;\n // Deployed web registers a custom providers source (DB-backed, tenant\n // scoped); when registered it is authoritative and settings.json custom\n // providers are ignored. Undefined = local settings-based behavior.\n const customProviders = resolveCustomProviders(options?.requestContext) ?? settings.customProviders;\n // Ids selected from the shared /models catalog were previously persisted in\n // the gateway-qualified `mastracode/<customProviderId>/<model>` form, which\n // parses the provider as `mastracode` and breaks provider config lookup.\n // Normalize at resolution time (in addition to stripping at selection time)\n // so already-saved ids and any surface that persists the raw catalog id\n // still resolve to the custom provider.\n const normalizedInput = stripMastraCodeCustomProviderPrefix(bedrockNormalizedInput, customProviders);\n const isMastraGatewayModel = normalizedInput.startsWith(MASTRA_GATEWAY_PREFIX);\n const normalizedModelId = stripMastraGatewayPrefix(normalizedInput);\n const [providerId, ...modelParts] = normalizedModelId.split('/');\n const bareModelId = modelParts.join('/');\n if (!providerId || !bareModelId) {\n throw new Error(`Invalid model id: ${modelId}`);\n }\n\n if (providerId === AMAZON_BEDROCK_GATEWAY_ID) {\n const bedrockGateway = createAmazonBedrockGateway();\n const routerId = `${AMAZON_BEDROCK_GATEWAY_ID}/${bareModelId}`;\n const auth = bedrockGateway.resolveAuth({\n gatewayId: AMAZON_BEDROCK_GATEWAY_ID,\n providerId: AMAZON_BEDROCK_GATEWAY_ID,\n modelId: bareModelId,\n routerId,\n });\n return bedrockGateway.resolveLanguageModel({\n providerId: AMAZON_BEDROCK_GATEWAY_ID,\n modelId: bareModelId,\n apiKey: auth?.apiKey ?? '',\n headers,\n });\n }\n\n const routerId = `${MASTRACODE_GATEWAY_ID}/${normalizedModelId}`;\n\n const mgApiKey = MastraCodeGateway.getMastraGatewayApiKey();\n const rawGatewayBase =\n settings.memoryGateway?.baseUrl ?? process.env['MASTRA_GATEWAY_URL'] ?? 'https://gateway-api.mastra.ai';\n // Deployed web registers a per-tenant credential store provider; when the\n // request carries an authenticated tenant, resolve credentials through the\n // caller's own store (user > org > env). Undefined = global AuthStorage.\n const credentialStore = resolveCredentialStore(options?.requestContext);\n const gateway = createMastraCodeGateway({\n mastraGatewayBaseUrl: rawGatewayBase.replace(/\\/+$/, '').replace(/\\/v1$/, ''),\n mastraGatewayApiKey: mgApiKey,\n routeThroughMastraGateway: Boolean(mgApiKey && isMastraGatewayModel),\n thinkingLevel: options?.thinkingLevel,\n customProviders,\n credentialStore,\n });\n\n const auth = gateway.resolveAuth({\n gatewayId: MASTRACODE_GATEWAY_ID,\n providerId,\n modelId: bareModelId,\n routerId,\n });\n\n if (!auth && credentialStore?.allowEnvironmentFallback === false) {\n throw new Error(\n `No usable ${providerId} credential is configured for this signed-in Factory account. Connect the provider or add an organization credential, then try again.`,\n );\n }\n\n return gateway.resolveLanguageModel({\n providerId,\n modelId: bareModelId,\n apiKey: auth?.apiKey ?? '',\n headers,\n });\n}\n\nexport interface ThinkingRequestContext {\n state?: { thinkingLevel?: unknown };\n session?: { modeId?: string };\n}\n/**\n * Resolve the effective thinking level for the current request.\n *\n * Precedence:\n * 1. Session override (`state.thinkingLevel`, set via /think or the session\n * settings panel).\n * 2. Per-mode default from settings (`models.modeThinkingDefaults[mode]`).\n * 3. Global default (`preferences.thinkingLevel`).\n *\n * Resolved per-request (not seeded at session start) so configuration changes\n * apply to the next request of every session — including automated\n * (rule-driven) Factory runs that nobody ever opens interactively.\n */\n\nexport function resolveRequestThinkingLevel(\n agentControllerContext: ThinkingRequestContext | undefined,\n settingsPath?: string,\n): ThinkingLevelSetting {\n const override = agentControllerContext?.state?.thinkingLevel;\n if (isThinkingLevelSetting(override)) return override;\n const modeId = agentControllerContext?.session?.modeId;\n return resolveDefaultThinkingLevel(loadSettings(settingsPath), modeId).level;\n}\n\n/**\n * Dynamic model function that reads the current model from controller state.\n * This allows runtime model switching via the /models picker.\n */\nexport function getDynamicModel(\n { requestContext }: { requestContext: RequestContext },\n settingsPath?: string,\n): ResolvedModel {\n const agentControllerContext = requestContext.get('controller') as AgentControllerRequestContext<any> | undefined;\n\n const modelId = agentControllerContext?.session?.modelId;\n if (!modelId) {\n // A missing controller context means the run was started without session\n // request context at all (e.g. a signal delivered to an idle thread) —\n // \"use /models\" would mislead there, the user's selection was never the\n // problem.\n if (!agentControllerContext) {\n throw new Error(\n 'No model available: this run started without a controller session context, so no model selection could be resolved.',\n );\n }\n throw new Error('No model selected. Use /models to select a model first.');\n }\n\n const thinkingLevel = resolveRequestThinkingLevel(agentControllerContext, settingsPath);\n\n return resolveModel(modelId, { thinkingLevel, remapForCodexOAuth: true, requestContext });\n}\n\n/**\n * Goal judge model resolver for the agent's `goal.judge` config. Resolves the\n * configured goal judge model through mastracode's gateway so provider\n * credentials (stored in auth storage, not just env) are injected — a bare model\n * id handed to core's default model router would fail to find the API key.\n *\n * Returns `undefined` when no judge model is configured, which keeps the goal\n * step a complete no-op (the goal mechanism requires a judge to do anything).\n *\n * `settingsPath` must be the same source `createMastraCode()` reads from so the\n * judge model and the goal budget (`goalMaxTurns`) come from one config — with a\n * custom `settingsPath` a bare `loadSettings()` here could read a different file\n * and silently turn the goal step into a no-op.\n */\nexport function getGoalJudgeModel(\n { requestContext }: { requestContext: RequestContext },\n settingsPath?: string,\n): ResolvedModel | undefined {\n const judgeModelId = loadSettings(settingsPath).models.goalJudgeModel;\n if (!judgeModelId) return undefined;\n return resolveModel(judgeModelId, { remapForCodexOAuth: true, requestContext });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"model.js","names":[],"sources":["../../src/agents/model.ts"],"sourcesContent":["import type { ModelWithRetries } from '@mastra/core/agent';\nimport type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { GatewayLanguageModel, MastraModelGatewayInterface } from '@mastra/core/llm';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport { getRequestAccountSelection, isRequestAccountRoutingExhausted } from '../auth/account-routing-context.js';\nimport type { CredentialStore, OAuthAccountRecord } from '../auth/types.js';\nimport { listBuiltinModePacks, resolveModePackFallbackChain } from '../onboarding/packs.js';\nimport {\n findModePackForModel,\n loadSettings,\n resolveDefaultThinkingLevel,\n resolveModePackModels,\n stripMastraCodeCustomProviderPrefix,\n} from '../onboarding/settings.js';\nimport { AMAZON_BEDROCK_GATEWAY_ID, createAmazonBedrockGateway } from '../providers/amazon-bedrock-gateway.js';\nimport { isThinkingLevelSetting } from '../thinking.js';\nimport type { ThinkingLevelSetting } from '../thinking.js';\nimport { resolveCredentialStore } from './credential-resolver.js';\nimport { resolveCustomProviders } from './custom-provider-source.js';\nimport {\n MASTRA_GATEWAY_PREFIX,\n MASTRACODE_GATEWAY_ID,\n MastraCodeGateway,\n getGlobalAuthStorage,\n reloadAuthStorage,\n stripMastraGatewayPrefix,\n} from './mastracode-gateway.js';\nimport type { MastraCodeGatewayOptions } from './mastracode-gateway.js';\n\nexport {\n getAnthropicApiKey,\n getOpenAIApiKey,\n MASTRACODE_GATEWAY_ID,\n MastraCodeGateway,\n remapOpenAIModelForCodexOAuth,\n resolveAuth,\n} from './mastracode-gateway.js';\nexport type { MastraCodeCustomProvider, MastraCodeGatewayOptions } from './mastracode-gateway.js';\nexport {\n setCredentialStoreProvider,\n hasCredentialStoreProvider,\n resolveTenantFromRequestContext,\n} from './credential-resolver.js';\nexport type { CredentialTenant, CredentialStoreProvider } from './credential-resolver.js';\nexport {\n setCustomProvidersSource,\n hasCustomProvidersSource,\n resolveCustomProviders,\n} from './custom-provider-source.js';\nexport type { CustomProvidersSource } from './custom-provider-source.js';\n\ntype ResolvedModel = GatewayLanguageModel;\ntype ModelRequestHeaders = Record<string, string>;\n\nfunction getAgentControllerHeaders(requestContext?: RequestContext): ModelRequestHeaders | undefined {\n const agentControllerContext = requestContext?.get('controller') as AgentControllerRequestContext<any> | undefined;\n const headers = {\n ...(agentControllerContext?.threadId ? { 'x-thread-id': agentControllerContext.threadId } : {}),\n ...(agentControllerContext?.resourceId ? { 'x-resource-id': agentControllerContext.resourceId } : {}),\n };\n\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n\nfunction accountCredential(account: OAuthAccountRecord) {\n const { type: _type, id: _id, label: _label, addedAt: _addedAt, active: _active, ...credential } = account;\n return { type: 'oauth' as const, ...credential };\n}\n\nexport function createRequestScopedCredentialStore(\n base: CredentialStore,\n requestContext?: RequestContext,\n): CredentialStore {\n const selectedId = (providerId: string) => getRequestAccountSelection(requestContext, providerId);\n const selectedAccount = (providerId: string) => {\n const accountInstanceId = selectedId(providerId);\n return accountInstanceId\n ? base.listAccounts?.(providerId).find(account => account.id === accountInstanceId)\n : undefined;\n };\n // Routing rejected every account for this provider on this request. Fail\n // closed on every credential read: falling through to `base` would use the\n // provider's active account — the exhausted one routing just refused.\n const rejectAll = (providerId: string) => isRequestAccountRoutingExhausted(requestContext, providerId);\n\n return {\n allowEnvironmentFallback: base.allowEnvironmentFallback,\n reload: () => base.reload(),\n get: providerId => {\n if (rejectAll(providerId)) return undefined;\n // A selection that no longer resolves (the account was removed between\n // routing and the credential read) must not fall through to the active\n // account — that is the account routing deliberately passed over.\n const accountInstanceId = selectedId(providerId);\n if (accountInstanceId === undefined) return base.get(providerId);\n const selected = selectedAccount(providerId);\n return selected ? accountCredential(selected) : undefined;\n },\n getStoredApiKey: providerId => {\n if (rejectAll(providerId)) return undefined;\n // The provider-wide `apikey:` slot is never the credential routing\n // selected, so serving it to a routed request is an OAuth -> API-key\n // fallback of the same provider — the one combination this feature\n // forbids. Unlike `get`, this read has no account argument to pass\n // through, so a selection fails it closed instead.\n if (selectedId(providerId) !== undefined) return undefined;\n return base.getStoredApiKey(providerId);\n },\n getApiKey: providerId =>\n rejectAll(providerId) ? Promise.resolve(undefined) : base.getApiKey(providerId, selectedId(providerId)),\n getOAuthCredential: base.getOAuthCredential\n ? providerId =>\n rejectAll(providerId)\n ? Promise.resolve(undefined)\n : base.getOAuthCredential!(providerId, selectedId(providerId))\n : undefined,\n listAccounts: base.listAccounts ? providerId => base.listAccounts!(providerId) : undefined,\n getActiveAccount: base.getActiveAccount ? providerId => base.getActiveAccount!(providerId) : undefined,\n activateAccount: base.activateAccount\n ? (providerId, accountInstanceId) => base.activateAccount!(providerId, accountInstanceId)\n : undefined,\n removeAccount: base.removeAccount\n ? (providerId, accountInstanceId) => base.removeAccount!(providerId, accountInstanceId)\n : undefined,\n };\n}\n\nexport function createMastraCodeGateway(options: MastraCodeGatewayOptions): MastraCodeGateway {\n return new MastraCodeGateway(options);\n}\n\nexport function createMastraCodeModelCatalogProvider(gateway: MastraModelGatewayInterface) {\n return gateway instanceof MastraCodeGateway\n ? gateway.createModelCatalogProvider()\n : MastraCodeGateway.createModelCatalogProvider(gateway);\n}\n\n/**\n * Placeholder for future model ID normalization.\n * Currently returns the input unchanged, but exists as a seam\n * for aliasing, casing fixes, or validation in the future.\n */\nexport function resolveModelId(modelId: string): string {\n return modelId;\n}\n\n/**\n * Resolve a model ID to the correct provider instance.\n * Shared by the main agent, observer, and reflector.\n *\n * - For anthropic/* models: Uses stored OAuth credentials when present, otherwise direct API key\n * - For openai/* models: Uses OAuth when configured, otherwise direct API key from AuthStorage\n * - For moonshotai/* models: Uses Moonshot AI Anthropic-compatible endpoint\n * - For all other providers: Uses Mastra's model router (models.dev gateway)\n */\nexport function resolveModel(\n modelId: string,\n options?: { thinkingLevel?: ThinkingLevelSetting; remapForCodexOAuth?: boolean; requestContext?: RequestContext },\n): GatewayLanguageModel {\n reloadAuthStorage();\n const headers = getAgentControllerHeaders(options?.requestContext);\n const settings = loadSettings();\n // Bedrock was previously cataloged under the MastraCode gateway namespace\n // (`mastracode/amazon-bedrock/<model>`). Normalize any legacy saved ids to the\n // standalone `amazon-bedrock/<model>` form so they resolve through the\n // dedicated Bedrock gateway.\n const bedrockLegacyPrefix = `${MASTRACODE_GATEWAY_ID}/amazon-bedrock/`;\n const bedrockNormalizedInput = modelId.startsWith(bedrockLegacyPrefix)\n ? modelId.slice(MASTRACODE_GATEWAY_ID.length + 1)\n : modelId;\n // Deployed web registers a custom providers source (DB-backed, tenant\n // scoped); when registered it is authoritative and settings.json custom\n // providers are ignored. Undefined = local settings-based behavior.\n const customProviders = resolveCustomProviders(options?.requestContext) ?? settings.customProviders;\n // Ids selected from the shared /models catalog were previously persisted in\n // the gateway-qualified `mastracode/<customProviderId>/<model>` form, which\n // parses the provider as `mastracode` and breaks provider config lookup.\n // Normalize at resolution time (in addition to stripping at selection time)\n // so already-saved ids and any surface that persists the raw catalog id\n // still resolve to the custom provider.\n const normalizedInput = stripMastraCodeCustomProviderPrefix(bedrockNormalizedInput, customProviders);\n const isMastraGatewayModel = normalizedInput.startsWith(MASTRA_GATEWAY_PREFIX);\n const normalizedModelId = stripMastraGatewayPrefix(normalizedInput);\n const [providerId, ...modelParts] = normalizedModelId.split('/');\n const bareModelId = modelParts.join('/');\n if (!providerId || !bareModelId) {\n throw new Error(`Invalid model id: ${modelId}`);\n }\n\n if (providerId === AMAZON_BEDROCK_GATEWAY_ID) {\n const bedrockGateway = createAmazonBedrockGateway();\n const routerId = `${AMAZON_BEDROCK_GATEWAY_ID}/${bareModelId}`;\n const auth = bedrockGateway.resolveAuth({\n gatewayId: AMAZON_BEDROCK_GATEWAY_ID,\n providerId: AMAZON_BEDROCK_GATEWAY_ID,\n modelId: bareModelId,\n routerId,\n });\n return bedrockGateway.resolveLanguageModel({\n providerId: AMAZON_BEDROCK_GATEWAY_ID,\n modelId: bareModelId,\n apiKey: auth?.apiKey ?? '',\n headers,\n });\n }\n\n const routerId = `${MASTRACODE_GATEWAY_ID}/${normalizedModelId}`;\n\n const mgApiKey = MastraCodeGateway.getMastraGatewayApiKey();\n const rawGatewayBase =\n settings.memoryGateway?.baseUrl ?? process.env['MASTRA_GATEWAY_URL'] ?? 'https://gateway-api.mastra.ai';\n // Deployed web registers a per-tenant credential store provider; when the\n // request carries an authenticated tenant, resolve credentials through the\n // caller's own store (user > org > env). Undefined = global AuthStorage.\n const baseCredentialStore = resolveCredentialStore(options?.requestContext) ?? getGlobalAuthStorage();\n const credentialStore = createRequestScopedCredentialStore(baseCredentialStore, options?.requestContext);\n const gateway = createMastraCodeGateway({\n mastraGatewayBaseUrl: rawGatewayBase.replace(/\\/+$/, '').replace(/\\/v1$/, ''),\n mastraGatewayApiKey: mgApiKey,\n routeThroughMastraGateway: Boolean(mgApiKey && isMastraGatewayModel),\n thinkingLevel: options?.thinkingLevel,\n customProviders,\n credentialStore,\n });\n\n const auth = gateway.resolveAuth({\n gatewayId: MASTRACODE_GATEWAY_ID,\n providerId,\n modelId: bareModelId,\n routerId,\n });\n\n if (!auth && credentialStore?.allowEnvironmentFallback === false) {\n throw new Error(\n `No usable ${providerId} credential is configured for this signed-in Factory account. Connect the provider or add an organization credential, then try again.`,\n );\n }\n\n return gateway.resolveLanguageModel({\n providerId,\n modelId: bareModelId,\n apiKey: auth?.apiKey ?? '',\n headers,\n });\n}\n\nexport interface ThinkingRequestContext {\n state?: { thinkingLevel?: unknown };\n session?: { modeId?: string };\n}\n/**\n * Resolve the effective thinking level for the current request.\n *\n * Precedence:\n * 1. Session override (`state.thinkingLevel`, set via /think or the session\n * settings panel).\n * 2. Per-mode default from settings (`models.modeThinkingDefaults[mode]`).\n * 3. Global default (`preferences.thinkingLevel`).\n *\n * Resolved per-request (not seeded at session start) so configuration changes\n * apply to the next request of every session — including automated\n * (rule-driven) Factory runs that nobody ever opens interactively.\n */\n\nexport function resolveRequestThinkingLevel(\n agentControllerContext: ThinkingRequestContext | undefined,\n settingsPath?: string,\n): ThinkingLevelSetting {\n const override = agentControllerContext?.state?.thinkingLevel;\n if (isThinkingLevelSetting(override)) return override;\n const modeId = agentControllerContext?.session?.modeId;\n return resolveDefaultThinkingLevel(loadSettings(settingsPath), modeId).level;\n}\n\n/** Structural pack shape for fallback resolution (custom pack models are partial by nature). */\nexport interface ResolvableModePack {\n id: string;\n name: string;\n models: Record<string, string>;\n}\n\n/** All packs a fallback chain may reference: every builtin plus saved customs. */\nexport function listResolvableModePacks(settings: ReturnType<typeof loadSettings>): ResolvableModePack[] {\n return [\n ...listBuiltinModePacks(),\n ...settings.customModelPacks.map(pack => ({\n id: `custom:${pack.name}`,\n name: pack.name,\n models: { ...pack.models },\n })),\n ];\n}\n\n/**\n * Dynamic model function that reads the current model from controller state.\n * This allows runtime model switching via the /models picker.\n *\n * When the session's model came from a pack with a fallback chain configured\n * (`settings.models.packFallbacks`), returns core's `ModelWithRetries[]`\n * fallback array instead of a bare model: the active pack's model first, then\n * each fallback pack's model for the same mode. Core advances the array when\n * the error processors decline to retry (pool exhausted / persistent outage —\n * see AccountRotationProcessor). Entry ids are unique per occurrence — the\n * one allowed revisit of a pack gets `<packId>#2` — because core re-resolves\n * the active fallback index by id across agentic steps.\n */\nexport function getDynamicModel(\n { requestContext }: { requestContext: RequestContext },\n settingsPath?: string,\n): ResolvedModel | ModelWithRetries[] {\n const agentControllerContext = requestContext.get('controller') as AgentControllerRequestContext<any> | undefined;\n\n const controllerState = agentControllerContext?.getState?.() as\n | {\n activeModelPackId?: unknown;\n mastracodePendingPackFallback?: { toPackId?: unknown; toModelId?: unknown; threadId?: unknown } | null;\n }\n | undefined;\n const pendingState = controllerState?.mastracodePendingPackFallback;\n const pendingFallback =\n pendingState &&\n (pendingState.threadId === undefined ||\n (typeof pendingState.threadId === 'string' && pendingState.threadId === agentControllerContext?.threadId))\n ? pendingState\n : undefined;\n const pendingModelId =\n pendingFallback && typeof pendingFallback.toModelId === 'string' && pendingFallback.toModelId.length > 0\n ? pendingFallback.toModelId\n : undefined;\n const modelId = pendingModelId ?? agentControllerContext?.session?.modelId;\n if (!modelId) {\n // A missing controller context means the run was started without session\n // request context at all (e.g. a signal delivered to an idle thread) —\n // \"use /models\" would mislead there, the user's selection was never the\n // problem.\n if (!agentControllerContext) {\n throw new Error(\n 'No model available: this run started without a controller session context, so no model selection could be resolved.',\n );\n }\n throw new Error('No model selected. Use /models to select a model first.');\n }\n\n const thinkingLevel = resolveRequestThinkingLevel(agentControllerContext, settingsPath);\n const resolveOptions = { thinkingLevel, remapForCodexOAuth: true, requestContext } as const;\n const primary = resolveModel(modelId, resolveOptions);\n\n const settings = loadSettings(settingsPath);\n // `models?` tolerates partial settings mocks; loaded settings always carry it.\n const fallbacks = settings.models?.packFallbacks ?? {};\n if (Object.keys(fallbacks).length === 0) return primary;\n\n const modeId = agentControllerContext?.session?.modeId ?? 'build';\n const packs = listResolvableModePacks(settings);\n const pendingPackId =\n pendingFallback && typeof pendingFallback.toPackId === 'string' && pendingFallback.toPackId.length > 0\n ? pendingFallback.toPackId\n : undefined;\n const statePackId = pendingPackId ?? controllerState?.activeModelPackId ?? settings.models.activeModelPackId;\n const activePack = findModePackForModel(\n settings,\n packs,\n modelId,\n modeId,\n typeof statePackId === 'string' ? statePackId : undefined,\n );\n if (!activePack) return primary;\n\n const chain = resolveModePackFallbackChain(fallbacks, activePack.id, settings.customModelPacks);\n if (chain.length < 2) return primary;\n\n const entries: ModelWithRetries[] = [{ id: activePack.id, model: primary }];\n const appearances = new Map<string, number>([[activePack.id, 1]]);\n for (const packId of chain.slice(1)) {\n const pack = packs.find(candidate => candidate.id === packId);\n if (!pack) break;\n const entryModelId = resolveModePackModels(settings, pack)[modeId];\n if (!entryModelId) break;\n // Best-effort resolution: an unresolvable fallback (e.g. unconnected\n // provider in deployed fail-closed mode) truncates the chain here rather\n // than failing the request before the primary is ever tried.\n let entryModel: ResolvedModel;\n try {\n entryModel = resolveModel(entryModelId, resolveOptions);\n } catch {\n break;\n }\n const occurrence = (appearances.get(packId) ?? 0) + 1;\n appearances.set(packId, occurrence);\n entries.push({\n id: occurrence === 1 ? packId : `${packId}#${occurrence}`,\n model: entryModel,\n });\n }\n // A chain that truncated to the primary alone is indistinguishable from no\n // chain — return the bare model so core never sees a one-entry array.\n if (entries.length < 2) return primary;\n return entries;\n}\n\n/** OM fallback-chain entry: a pack's OM model resolved through the gateway. Assignable to `ModelWithRetries`. */\nexport type PackMemoryModelChainEntry = { id: string; model: GatewayLanguageModel };\n\n/**\n * Resolve the observational-memory model for the active mode pack, walking the\n * pack's fallback chain (`settings.models.packFallbacks`) and collecting each\n * pack's optional `models.memory` entry. Packs without an OM model are skipped\n * (the field is optional, so absence must not truncate the chain); duplicate\n * model ids collapse so an A⇄B cycle never retries an identical OM model.\n *\n * Returns a bare model for a single entry, a fallback array for multiple\n * entries (OM's internal agents run the same agentic loop, so the array gives\n * OM its own cross-pack failover), or `undefined` when no pack in the chain\n * defines an OM model — callers then fall back to the standalone OM\n * configuration.\n */\nexport function resolvePackMemoryModelChain(\n settings: ReturnType<typeof loadSettings>,\n startPackId: string,\n resolveOptions: Parameters<typeof resolveModel>[1],\n): GatewayLanguageModel | PackMemoryModelChainEntry[] | undefined {\n const packs = listResolvableModePacks(settings);\n if (!packs.some(pack => pack.id === startPackId)) return undefined;\n\n const chain = resolveModePackFallbackChain(\n settings.models?.packFallbacks ?? {},\n startPackId,\n settings.customModelPacks,\n );\n const seenModelIds = new Set<string>();\n const entries: PackMemoryModelChainEntry[] = [];\n for (const packId of chain) {\n const pack = packs.find(candidate => candidate.id === packId);\n if (!pack) break;\n const memoryModelId = resolveModePackModels(settings, pack).memory;\n if (!memoryModelId || seenModelIds.has(memoryModelId)) continue;\n seenModelIds.add(memoryModelId);\n // Best-effort resolution: an unresolvable OM entry (e.g. unconnected\n // provider in deployed fail-closed mode) truncates the chain here rather\n // than failing observation before the pack's own OM model is tried.\n let entryModel: ResolvedModel;\n try {\n entryModel = resolveModel(memoryModelId, resolveOptions);\n } catch {\n break;\n }\n entries.push({ id: `${packId}:memory`, model: entryModel });\n }\n\n if (entries.length === 0) return undefined;\n if (entries.length === 1) return entries[0]!.model;\n return entries;\n}\n\n/**\n * Goal judge model resolver for the agent's `goal.judge` config. Resolves the\n * configured goal judge model through mastracode's gateway so provider\n * credentials (stored in auth storage, not just env) are injected — a bare model\n * id handed to core's default model router would fail to find the API key.\n *\n * Returns `undefined` when no judge model is configured, which keeps the goal\n * step a complete no-op (the goal mechanism requires a judge to do anything).\n *\n * `settingsPath` must be the same source `createMastraCode()` reads from so the\n * judge model and the goal budget (`goalMaxTurns`) come from one config — with a\n * custom `settingsPath` a bare `loadSettings()` here could read a different file\n * and silently turn the goal step into a no-op.\n */\nexport function getGoalJudgeModel(\n { requestContext }: { requestContext: RequestContext },\n settingsPath?: string,\n): ResolvedModel | undefined {\n const judgeModelId = loadSettings(settingsPath).models.goalJudgeModel;\n if (!judgeModelId) return undefined;\n return resolveModel(judgeModelId, { remapForCodexOAuth: true, requestContext });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import type { ProcessAPIErrorArgs, ProcessInputArgs, ProcessInputResult, Processor } from '@mastra/core/processors';
|
|
2
|
+
import type { CredentialStore } from './types.js';
|
|
3
|
+
export declare const ACCOUNT_SWITCH_PART_TYPE = "data-mastracode-account-switch";
|
|
4
|
+
/** Labels and instance ids only — never token material (do-not list). */
|
|
5
|
+
export interface AccountSwitchPartData {
|
|
6
|
+
provider: string;
|
|
7
|
+
from: {
|
|
8
|
+
id: string;
|
|
9
|
+
label: string;
|
|
10
|
+
} | null;
|
|
11
|
+
to: {
|
|
12
|
+
id: string;
|
|
13
|
+
label: string;
|
|
14
|
+
} | null;
|
|
15
|
+
reason: 'rate-limit' | 'quota-exhausted' | 'auth-failed' | 'pool-exhausted' | 'persistent-outage' | 'preferred-routing' | 'starting-on-account';
|
|
16
|
+
at: string;
|
|
17
|
+
/**
|
|
18
|
+
* Set on a `to: null` part when a route pinned to a single account reported
|
|
19
|
+
* that account unusable. The provider's other subscriptions were never
|
|
20
|
+
* consulted (A12), so "all accounts unavailable" would misreport what
|
|
21
|
+
* happened.
|
|
22
|
+
*/
|
|
23
|
+
exclusive?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** The store surface rotation needs; `AuthStorage` satisfies it structurally. */
|
|
26
|
+
export type RotationCredentialStore = CredentialStore & {
|
|
27
|
+
/**
|
|
28
|
+
* Force one refresh of the active account's tokens regardless of expiry
|
|
29
|
+
* (401/403 path — a rejected-but-unexpired token usually means clock skew
|
|
30
|
+
* or a refresh race). `AuthStorage` provides it; deployed per-tenant stores
|
|
31
|
+
* don't, and the auth path degrades to plain rotation (which itself no-ops
|
|
32
|
+
* without registry methods).
|
|
33
|
+
*/
|
|
34
|
+
forceRefreshActiveAccount?(providerId: string, accountInstanceId?: string): Promise<string | undefined>;
|
|
35
|
+
};
|
|
36
|
+
/** Persisted data-part type for a fallback-pack hop. */
|
|
37
|
+
export declare const PACK_FALLBACK_PART_TYPE: "data-mastracode-pack-fallback";
|
|
38
|
+
/**
|
|
39
|
+
* Payload of a pack-fallback part: the pack the cascade is leaving, the pack
|
|
40
|
+
* core's fallback array advances to, and why. Labels and pack ids only —
|
|
41
|
+
* never credential material.
|
|
42
|
+
*/
|
|
43
|
+
export interface PackFallbackPartData {
|
|
44
|
+
from: {
|
|
45
|
+
packId: string;
|
|
46
|
+
label: string;
|
|
47
|
+
};
|
|
48
|
+
to: {
|
|
49
|
+
packId: string;
|
|
50
|
+
label: string;
|
|
51
|
+
};
|
|
52
|
+
reason: 'pool-exhausted' | 'persistent-outage';
|
|
53
|
+
at: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Session-state key the processor sets when a pack hop happens. The TUI
|
|
57
|
+
* listens for it on the typed `state_changed` controller event (data parts
|
|
58
|
+
* never ride controller message events) and applies thread stickiness.
|
|
59
|
+
*/
|
|
60
|
+
export declare const PACK_FALLBACK_STATE_KEY: "mastracodePendingPackFallback";
|
|
61
|
+
/** Payload written to session state under PACK_FALLBACK_STATE_KEY. */
|
|
62
|
+
export interface PendingPackFallback {
|
|
63
|
+
fromPackId: string;
|
|
64
|
+
toPackId: string;
|
|
65
|
+
/** Landed pack's model for the mode the cascade is serving. */
|
|
66
|
+
toModelId: string;
|
|
67
|
+
/** Originating thread. Absent only on pending hops written by older clients. */
|
|
68
|
+
threadId?: string;
|
|
69
|
+
reason: 'pool-exhausted' | 'persistent-outage';
|
|
70
|
+
at: string;
|
|
71
|
+
}
|
|
72
|
+
export type RotationClassification = {
|
|
73
|
+
kind: 'rotate';
|
|
74
|
+
reason: 'rate-limit' | 'quota-exhausted' | 'auth-failed';
|
|
75
|
+
} | {
|
|
76
|
+
kind: 'hop';
|
|
77
|
+
} | {
|
|
78
|
+
kind: 'never';
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* The locked Q7 taxonomy. 429/402/usage-limit rotate immediately (429 is not
|
|
82
|
+
* covered by any transient matcher, so it arrives here on first occurrence);
|
|
83
|
+
* 401/403 and `ProviderAuthRequiredError` rotate after one forced refresh;
|
|
84
|
+
* 5xx/network hop only when the transient retry budget is already spent (they
|
|
85
|
+
* reach this processor because `StreamErrorRetryProcessor` declined); 400 and
|
|
86
|
+
* everything unknown never touch the registry.
|
|
87
|
+
*/
|
|
88
|
+
export declare function classifyRotationError(error: unknown): RotationClassification;
|
|
89
|
+
/** Provider id off a router model id: `mastracode/<provider>/<model>` or `<provider>/<model>`. */
|
|
90
|
+
export declare function providerFromModelId(modelId: string): string | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Identify the provider an error came from: the request URL's hostname
|
|
93
|
+
* (`APICallError.url`, cause chain included), falling back to the router
|
|
94
|
+
* model id. Unknown → undefined (caller treats as never-rotate).
|
|
95
|
+
*/
|
|
96
|
+
export declare function providerFromError(error: unknown): string | undefined;
|
|
97
|
+
/** Friendly names for the part/notice copy (display only — never auth data). */
|
|
98
|
+
export declare const PROVIDER_DISPLAY_NAMES: Record<string, string>;
|
|
99
|
+
/** Validates untrusted `reason` values (e.g. persisted message parts). */
|
|
100
|
+
export declare function isAccountSwitchReason(value: unknown): value is AccountSwitchPartData['reason'];
|
|
101
|
+
/**
|
|
102
|
+
* One-line transcript copy for a switch part. Shared by the live `info`
|
|
103
|
+
* controller event (the TUI shows controller `info` events as transcript
|
|
104
|
+
* lines, and no message event carries data parts mid-run) and by the TUI's
|
|
105
|
+
* history rendering of the persisted part — one formatter, identical text.
|
|
106
|
+
*/
|
|
107
|
+
export declare function accountSwitchNoticeText(data: AccountSwitchPartData): string;
|
|
108
|
+
/** Transcript line for a pack-fallback hop; shared by the live info event and the TUI's history render. */
|
|
109
|
+
export declare function packFallbackNoticeText(data: PackFallbackPartData): string;
|
|
110
|
+
/**
|
|
111
|
+
* Whether a persisted pack-fallback reason is one this build understands.
|
|
112
|
+
* `REASON_TEXT` also covers the account-switch reasons, so the notice text
|
|
113
|
+
* alone would happily render a foreign value such as `rate-limit` as a
|
|
114
|
+
* pack-fallback reason; history parsed from another build's part must be
|
|
115
|
+
* rejected instead.
|
|
116
|
+
*/
|
|
117
|
+
export declare function isPackFallbackReason(value: unknown): value is PackFallbackPartData['reason'];
|
|
118
|
+
/**
|
|
119
|
+
* Controller-shaped accessors for a thread's routing metadata. Core supplies this
|
|
120
|
+
* via `requestContext.get('controller')`; the TUI builds the same shape from its
|
|
121
|
+
* session so both writers share one serialization key and one read source.
|
|
122
|
+
*/
|
|
123
|
+
export type RoutingControllerContext = {
|
|
124
|
+
session?: {
|
|
125
|
+
modelId?: unknown;
|
|
126
|
+
modeId?: unknown;
|
|
127
|
+
};
|
|
128
|
+
threadId?: unknown;
|
|
129
|
+
getState?: () => Record<string, unknown>;
|
|
130
|
+
setState?: (updates: Record<string, unknown>) => Promise<void>;
|
|
131
|
+
getThreadSetting?: (key: string) => Promise<unknown>;
|
|
132
|
+
setThreadSetting?: (setting: {
|
|
133
|
+
key: string;
|
|
134
|
+
value: unknown;
|
|
135
|
+
}) => Promise<void>;
|
|
136
|
+
isThreadActive?: () => boolean;
|
|
137
|
+
};
|
|
138
|
+
export declare class AccountRotationProcessor implements Processor {
|
|
139
|
+
private readonly options;
|
|
140
|
+
readonly id: "mastracode-account-rotation";
|
|
141
|
+
constructor(options: {
|
|
142
|
+
credentialStore: RotationCredentialStore;
|
|
143
|
+
maxProcessorRetries: number;
|
|
144
|
+
settingsPath?: string;
|
|
145
|
+
});
|
|
146
|
+
processAPIError(args: ProcessAPIErrorArgs): Promise<{
|
|
147
|
+
retry: boolean;
|
|
148
|
+
}>;
|
|
149
|
+
/**
|
|
150
|
+
* The request's pack cascade, computed once from the session's pack and
|
|
151
|
+
* cached in processor state. Truncated at the first pack that lacks the
|
|
152
|
+
* session mode's model — mirroring getDynamicModel's truncation — so the
|
|
153
|
+
* cascade never promises a hop core's fallback array cannot make. The
|
|
154
|
+
* position advances per hop, so a second hop in the same turn reports B→C
|
|
155
|
+
* even though the session modelId still points at pack A (stickiness lands
|
|
156
|
+
* TUI-side only after the part renders). Returns null when the session has
|
|
157
|
+
* no active pack or the pack has no fallback chain.
|
|
158
|
+
*/
|
|
159
|
+
private getPackCascade;
|
|
160
|
+
/**
|
|
161
|
+
* Q14 gate: 400/unknown/unattributable errors never hop packs. Core's
|
|
162
|
+
* fallback array advances on ANY thrown error except TripWire
|
|
163
|
+
* (llm-execution-step.ts), so when the session's pack has a chain and the
|
|
164
|
+
* current entry is non-last, a bare `retry: false` would silently hop on an
|
|
165
|
+
* error class the user excluded from hop triggers. TripWire is the only
|
|
166
|
+
* no-advance escape: the runner rethrows it and the fallback loop declines
|
|
167
|
+
* to advance. No chain (or already on the last entry) → return and let the
|
|
168
|
+
* plain `retry: false` surface the error exactly as before.
|
|
169
|
+
*/
|
|
170
|
+
private gateChainHop;
|
|
171
|
+
/**
|
|
172
|
+
* Emit the pack-fallback part when a configured chain has a next pack and
|
|
173
|
+
* queue the thread stickiness trigger. Core's fallback array does the hop
|
|
174
|
+
* itself on `retry: false`; this only announces it. The cascade is
|
|
175
|
+
* truncated exactly like getDynamicModel's chain (missing mode model or
|
|
176
|
+
* unresolvable model), so an announced hop is always one core can make;
|
|
177
|
+
* the toModelId guard stays as defense against a stale cache.
|
|
178
|
+
*/
|
|
179
|
+
private emitPackFallbackPart;
|
|
180
|
+
/**
|
|
181
|
+
* Pool done for this request: every instance recorded in the tried-set and
|
|
182
|
+
* a `to: null` part emitted. Returns `retry: false` so core's fallback
|
|
183
|
+
* array can hop to the next pack (announced by `emitPackFallbackPart`).
|
|
184
|
+
* Silent on the account part when the provider has no registry at all —
|
|
185
|
+
* there are no accounts to declare unavailable, but the hop still applies.
|
|
186
|
+
*/
|
|
187
|
+
private declarePoolUnavailable;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Emits the "starting on a non-default account" notice (Q19) once per
|
|
191
|
+
* request when the active registry account is not the first entry.
|
|
192
|
+
*
|
|
193
|
+
* TYPE CONSTRAINT: this class must NEVER implement `processAPIError`. It
|
|
194
|
+
* lives in `inputProcessors`; the runner walks input processors first when
|
|
195
|
+
* running `processAPIError`, so adding the method here would classify and
|
|
196
|
+
* rotate errors BEFORE `StreamErrorRetryProcessor`'s transient retries run.
|
|
197
|
+
*/
|
|
198
|
+
export declare class AccountStartNoticeProcessor implements Processor {
|
|
199
|
+
private readonly options;
|
|
200
|
+
readonly id: "mastracode-account-start-notice";
|
|
201
|
+
constructor(options: {
|
|
202
|
+
credentialStore: CredentialStore;
|
|
203
|
+
settingsPath?: string;
|
|
204
|
+
});
|
|
205
|
+
processInput(args: ProcessInputArgs): Promise<ProcessInputResult>;
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=account-rotation-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-rotation-processor.d.ts","sourceRoot":"","sources":["../../src/auth/account-rotation-processor.ts"],"names":[],"mappings":"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"}
|