@mastra/code-sdk 1.10.2-alpha.0 → 1.11.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/acp/agent.d.ts +3 -3
  2. package/dist/acp/agent.d.ts.map +1 -1
  3. package/dist/acp/agent.js +95 -22
  4. package/dist/acp/agent.js.map +1 -1
  5. package/dist/acp/runtime.d.ts.map +1 -1
  6. package/dist/acp/runtime.js +18 -10
  7. package/dist/acp/runtime.js.map +1 -1
  8. package/dist/agents/memory.d.ts +3 -1
  9. package/dist/agents/memory.d.ts.map +1 -1
  10. package/dist/agents/memory.js +34 -23
  11. package/dist/agents/memory.js.map +1 -1
  12. package/dist/agents/model.d.ts +4 -39
  13. package/dist/agents/model.d.ts.map +1 -1
  14. package/dist/agents/model.js +31 -93
  15. package/dist/agents/model.js.map +1 -1
  16. package/dist/agents/prompts/agent-instructions.js +1 -1
  17. package/dist/auth/account-rotation-processor.d.ts +26 -54
  18. package/dist/auth/account-rotation-processor.d.ts.map +1 -1
  19. package/dist/auth/account-rotation-processor.js +105 -154
  20. package/dist/auth/account-rotation-processor.js.map +1 -1
  21. package/dist/auth/index.js +2 -2
  22. package/dist/auth/providers/kimi-coding.js +2 -1
  23. package/dist/auth/providers/kimi-coding.js.map +1 -1
  24. package/dist/auth/providers/xai.js +2 -1
  25. package/dist/auth/providers/xai.js.map +1 -1
  26. package/dist/auth/storage.js +1 -1
  27. package/dist/auth/types.d.ts +1 -0
  28. package/dist/auth/types.d.ts.map +1 -1
  29. package/dist/clipboard/index.js +1 -1
  30. package/dist/constants.d.ts +2 -0
  31. package/dist/constants.d.ts.map +1 -1
  32. package/dist/constants.js +3 -1
  33. package/dist/constants.js.map +1 -1
  34. package/dist/headless/cli.d.ts.map +1 -1
  35. package/dist/headless/cli.js +9 -4
  36. package/dist/headless/cli.js.map +1 -1
  37. package/dist/headless/run-mc.d.ts.map +1 -1
  38. package/dist/headless/run-mc.js +46 -42
  39. package/dist/headless/run-mc.js.map +1 -1
  40. package/dist/index.d.ts +5 -5
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +33 -28
  43. package/dist/index.js.map +1 -1
  44. package/dist/lsp/server.js +1 -1
  45. package/dist/onboarding/om-settings.d.ts +1 -0
  46. package/dist/onboarding/om-settings.d.ts.map +1 -1
  47. package/dist/onboarding/om-settings.js +10 -1
  48. package/dist/onboarding/om-settings.js.map +1 -1
  49. package/dist/onboarding/settings.js +2 -2
  50. package/dist/providers/openai-codex.js +1 -1
  51. package/dist/schedules/run-script.js +1 -1
  52. package/dist/schema.d.ts +34 -19
  53. package/dist/schema.d.ts.map +1 -1
  54. package/dist/schema.js +11 -5
  55. package/dist/schema.js.map +1 -1
  56. package/dist/utils/open-url.d.ts +10 -0
  57. package/dist/utils/open-url.d.ts.map +1 -0
  58. package/dist/utils/open-url.js +30 -0
  59. package/dist/utils/open-url.js.map +1 -0
  60. package/dist/utils/project.js +2 -2
  61. package/dist/utils/signals-pubsub.d.ts +32 -4
  62. package/dist/utils/signals-pubsub.d.ts.map +1 -1
  63. package/dist/utils/signals-pubsub.js +207 -28
  64. package/dist/utils/signals-pubsub.js.map +1 -1
  65. package/dist/utils/slash-command-processor.js +1 -1
  66. package/dist/utils/update-check.js +1 -1
  67. package/package.json +10 -10
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","names":[],"sources":["../../src/agents/memory.ts"],"sourcesContent":["import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { GatewayLanguageModel } from '@mastra/core/llm';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport type { MastraCompositeStore } from '@mastra/core/storage';\nimport type { MastraVector } from '@mastra/core/vector';\nimport { fastembed } from '@mastra/fastembed';\nimport { Memory, Subconscious } from '@mastra/memory';\nimport { DEFAULT_OM_MODEL_ID, DEFAULT_OBS_THRESHOLD, DEFAULT_REF_THRESHOLD } from '../constants.js';\nimport { LOCAL_KNOWLEDGE_ORG_ID, resolveKnowledgeScopeIdentity } from '../knowledge-scope.js';\nimport { loadSettings } from '../onboarding/settings.js';\nimport { ANTHROPIC_PROMPT_CACHE_TTL } from '../providers/anthropic-prompt-cache.js';\nimport type { MastraCodeState } from '../schema.js';\nimport { getOmScope } from '../utils/project.js';\nimport { resolveModel, resolvePackMemoryModelChain } from './model.js';\nimport type { PackMemoryModelChainEntry } from './model.js';\n\n/**\n * Resolve one OM role's model for this invocation. Lookup order:\n * 1. The explicit role override (`observerModelOverride` / `reflectorModelOverride`).\n * 2. The active mode pack's optional `models.memory`, walking the pack's fallback\n * chain so OM fails over alongside (and independently of) the main agent.\n * The pending pack-hop marker wins over the settled pack id so an immediate\n * retrigger observes on the landed pack.\n * 3. The standalone OM configuration seeded into controller state\n * (`observerModelId` / `reflectorModelId`), then the default OM model.\n */\nfunction resolveOmRoleModelForRequest(\n role: 'observer' | 'reflector',\n requestContext: RequestContext,\n settingsPath?: string,\n): GatewayLanguageModel | PackMemoryModelChainEntry[] {\n const controller = requestContext.get('controller') as AgentControllerRequestContext<MastraCodeState> | undefined;\n const state = controller?.getState() as MastraCodeState | undefined;\n // OM calls send different content every time, so only their shared instructions are worth caching.\n const resolveOptions = { remapForCodexOAuth: true, requestContext, anthropicPromptCacheScope: 'system' } as const;\n\n // The configured settings file, not the default one: a caller that points the\n // agent at another settings path must get the same pack/override resolution\n // for observational memory as it does for the main model.\n const settings = loadSettings(settingsPath);\n const roleOverride =\n role === 'observer' ? settings.models?.observerModelOverride : settings.models?.reflectorModelOverride;\n if (roleOverride) return resolveModel(roleOverride, resolveOptions);\n\n const pendingState = state?.mastracodePendingPackFallback as\n | { toPackId?: unknown; threadId?: unknown }\n | null\n | undefined;\n const pendingPackId =\n pendingState &&\n (pendingState.threadId === undefined || pendingState.threadId === controller?.threadId) &&\n typeof pendingState.toPackId === 'string' &&\n pendingState.toPackId.length > 0\n ? pendingState.toPackId\n : undefined;\n const packId = pendingPackId ?? state?.activeModelPackId ?? settings.models?.activeModelPackId;\n if (typeof packId === 'string' && packId.length > 0) {\n const chained = resolvePackMemoryModelChain(settings, packId, resolveOptions);\n if (chained) return chained;\n }\n\n const stateModelId = role === 'observer' ? state?.observerModelId : state?.reflectorModelId;\n return resolveModel(stateModelId ?? DEFAULT_OM_MODEL_ID, resolveOptions);\n}\n\nconst DYNAMIC_AGENTS_MD_INSTRUCTION =\n 'Messages wrapped in <system-reminder type=\"dynamic-agents-md\" ...>...</system-reminder> are ephemeral project-context instructions injected from files on disk. Do NOT observe or extract information from these messages — they are reloaded automatically when needed and should not be stored in memory.';\n\n// Derived from https://github.com/JuliusBrussee/caveman and adapted for OM use with fixed full-level compression.\nconst CAVEMAN_OM_INSTRUCTION = `Respond terse like smart caveman. All technical substance stay. Only fluff die.\n\nUse full caveman compression style.\n\nDrop: articles (a/an/the), filler (just/really/basically/actually/simply), pleasantries (sure/certainly/of course/happy to), hedging. Fragments OK. Short synonyms (big not extensive, fix not \"implement a solution for\"). Technical terms exact. Code blocks unchanged. Errors quoted exact. Leave out the words \"agent\" and \"assistant\" at the start of each observation line, it is assumed each line is referring to the assistant unless it specifically says it was about the user. Leave out parenthesis and other text characters like * that would not contribute to understanding the observations.\n\nPattern: \\`[thing] [action] [reason]. [next step]\\`\n\nNot: \"Sure! I'd be happy to help you with that. The issue you're experiencing is likely caused by...\"\nYes: \"Bug in auth middleware. Token expiry check use < not <=. Fix:\"\n\nExample 1\n🔴 14:31 user asks why React component rerenders\n🟡 14:32 saw inline object prop create new ref each render, cause rerender\n✅ 14:34 fixed render issue by wrap object in useMemo\n\nExample 2\n🟡 15:10 explained pool reuse DB connections, skip repeat handshake overhead\n\nDon't say \"Agent did x\", say \"did x\". It will be assumed the agent did what was observed. The who should only be specified for the user or other third parties: \"user asked x\"\n\nDrop caveman for: security warnings, irreversible action confirmations, multi-step sequences where fragment order risks misread, user asks to clarify or repeats question, and anything that requires remembering verbatim content. Resume caveman after clear part done`;\n\nexport { LOCAL_KNOWLEDGE_ORG_ID };\n\n// One error per session, not per memory resolution. Keyed on the session id\n// rather than the controller object: the controller is read off the request\n// context on every resolution, so it is a fresh object per request and would\n// dedupe nothing. Bounded so a long-running Factory process cannot grow this\n// without limit — refusing sessions are rare, and losing the oldest ids only\n// costs one extra log line.\nconst REPORTED_ORG_UNRESOLVED_LIMIT = 500;\nconst reportedOrgUnresolved = new Set<string>();\n\nfunction reportOrgUnresolved(\n controller: AgentControllerRequestContext<MastraCodeState> | undefined,\n factoryProjectId: string | undefined,\n reason?: string,\n) {\n const sessionId = controller?.session?.id;\n if (sessionId) {\n if (reportedOrgUnresolved.has(sessionId)) return;\n if (reportedOrgUnresolved.size >= REPORTED_ORG_UNRESOLVED_LIMIT) {\n reportedOrgUnresolved.delete(reportedOrgUnresolved.values().next().value as string);\n }\n reportedOrgUnresolved.add(sessionId);\n }\n const session = controller?.session;\n console.error(\n `[Subconscious] Knowledge curation disabled: no organization resolved for session ${session?.id ?? 'unknown'} (project ${factoryProjectId ?? 'none'})${reason ? `: ${reason}` : ''}. Knowledge is not written rather than written where it cannot be read.`,\n );\n}\n\n/**\n * Whether the experimental subconscious (knowledge graph + reminder sidekick)\n * is switched on for this process: it needs a vector store and the opt-in flag.\n */\nexport function isSubconsciousEnabled(vector: MastraVector | undefined): boolean {\n return Boolean(vector) && process.env.MASTRACODE_EXPERIMENTAL_SUBCONSCIOUS === '1';\n}\n\n/**\n * Whether the subconscious tools (`knowledge_*`, `ask_memory`) are registered\n * for a given session. Beyond the process-level switch, a Factory-owned\n * session that cannot resolve its org refuses the subconscious entirely (see\n * `getDynamicMemory`, which applies the same two checks inline because it also\n * needs the resolved identity). The system prompt's tool guidance calls here so\n * it never advertises tools that `getDynamicMemory` did not register.\n */\nexport function hasSubconsciousTools(vector: MastraVector | undefined, state: MastraCodeState | undefined): boolean {\n return isSubconsciousEnabled(vector) && resolveKnowledgeScopeIdentity(state).resolved;\n}\n\n/**\n * Dynamic memory factory function.\n * Reads OM thresholds from controller state via requestContext.\n * Model functions also read from requestContext (no mutable bridge needed).\n */\nexport function getDynamicMemory(storage: MastraCompositeStore, vector?: MastraVector, settingsPath?: string) {\n // Cache is scoped per storage instance (per getDynamicMemory call) so a\n // Memory bound to one storage is never reused after storage changes.\n let cachedMemory: Memory | null = null;\n let cachedMemoryKey: string | null = null;\n\n // Observer/reflector model functions — read the current model ID from\n // controller state via requestContext (propagated by OM's agent.generate).\n // Bound here so the configured settings path reaches role overrides and pack\n // memory-model resolution.\n const getObserverModel = ({ requestContext }: { requestContext: RequestContext }) =>\n resolveOmRoleModelForRequest('observer', requestContext, settingsPath);\n const getReflectorModel = ({ requestContext }: { requestContext: RequestContext }) =>\n resolveOmRoleModelForRequest('reflector', requestContext, settingsPath);\n\n return ({ requestContext }: { requestContext: RequestContext }) => {\n const controller = requestContext.get('controller') as AgentControllerRequestContext<MastraCodeState> | undefined;\n const state = controller?.getState() as MastraCodeState | undefined;\n const subconsciousEnabled = isSubconsciousEnabled(vector);\n const factoryProjectId = state?.factoryProjectId;\n const isFactory = typeof factoryProjectId === 'string' && factoryProjectId.trim().length > 0;\n\n // A Factory-owned session that could not resolve its org refuses to curate:\n // writing under a substituted identity produces knowledge the fail-closed\n // read path can never see.\n let orgUnresolvedRefusal = false;\n\n if (subconsciousEnabled) {\n const identity = resolveKnowledgeScopeIdentity(state);\n if (identity.resolved) {\n requestContext.set('organizationId', identity.organizationId);\n } else {\n orgUnresolvedRefusal = true;\n reportOrgUnresolved(controller, identity.knowledgeResourceId, identity.reason);\n }\n if (identity.knowledgeResourceId) {\n requestContext.set('knowledgeResourceId', identity.knowledgeResourceId);\n }\n }\n\n const subconsciousAvailable = subconsciousEnabled && !orgUnresolvedRefusal;\n\n const omScope = state?.omScope ?? getOmScope(state?.projectPath);\n\n const obsThreshold = state?.observationThreshold ?? DEFAULT_OBS_THRESHOLD;\n const refThreshold = state?.reflectionThreshold ?? DEFAULT_REF_THRESHOLD;\n const caveman = state?.cavemanObservations ?? false;\n\n const observerPreviousObservationTokens = 1000;\n const observeAttachments = state?.observeAttachments;\n // Factory sessions get a factory-only Subconscious config, so the cache key\n // carries a factory presence bit to keep the two configs from cross-serving.\n const cacheKey = `${obsThreshold}:${refThreshold}:${omScope}:${observerPreviousObservationTokens}:${caveman ? 1 : 0}:${observeAttachments}:${isFactory ? 1 : 0}:${subconsciousAvailable ? 1 : 0}`;\n if (cachedMemory && cachedMemoryKey === cacheKey) {\n return cachedMemory;\n }\n\n // Async buffering is not supported with resource scope — disable it\n const isResourceScope = omScope === 'resource';\n\n const observerInstruction = caveman\n ? `${DYNAMIC_AGENTS_MD_INSTRUCTION}\\n\\n${CAVEMAN_OM_INSTRUCTION}`\n : DYNAMIC_AGENTS_MD_INSTRUCTION;\n const reflectionInstruction = caveman ? CAVEMAN_OM_INSTRUCTION : undefined;\n\n cachedMemory = new Memory({\n storage,\n vector: vector || false,\n embedder: vector ? fastembed.small : undefined,\n options: {\n // Generate a durable title from the first user message. Every client uses\n // the same title in its thread list and active-session chrome. Title\n // generation takes the primary OM model only — its model field does not\n // accept fallback arrays.\n generateTitle: {\n model: ({ requestContext }) => {\n const resolved = getObserverModel({ requestContext });\n return Array.isArray(resolved) ? resolved[0]!.model : resolved;\n },\n },\n observationalMemory: {\n enabled: true,\n temporalMarkers: true,\n retrieval: vector ? { vector: true } : true,\n experimental_subconscious: subconsciousAvailable\n ? new Subconscious({\n defaultScope: 'resource',\n maxScope: 'resource',\n pins: true,\n ...(isFactory ? { maxSteps: 25 } : {}),\n })\n : undefined,\n scope: omScope,\n // The main agent writes Anthropic cache entries with this TTL; 'auto' can't see it.\n activateAfterIdle: { default: 'auto', anthropic: ANTHROPIC_PROMPT_CACHE_TTL },\n activateOnProviderChange: true,\n observation: {\n bufferTokens: isResourceScope ? false : 1 / 5,\n bufferActivation: isResourceScope ? undefined : 2000,\n model: getObserverModel,\n messageTokens: obsThreshold,\n blockAfter: 2,\n previousObserverTokens: observerPreviousObservationTokens,\n threadTitle: true,\n instruction: observerInstruction,\n observeAttachments,\n },\n reflection: {\n bufferActivation: isResourceScope ? undefined : 1 / 2,\n blockAfter: 1.1,\n model: getReflectorModel,\n observationTokens: refThreshold,\n instruction: reflectionInstruction,\n },\n },\n },\n });\n cachedMemoryKey = cacheKey;\n\n return cachedMemory;\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"memory.js","names":[],"sources":["../../src/agents/memory.ts"],"sourcesContent":["import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { GatewayLanguageModel } from '@mastra/core/llm';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport type { MastraCompositeStore } from '@mastra/core/storage';\nimport type { MastraVector } from '@mastra/core/vector';\nimport { fastembed } from '@mastra/fastembed';\nimport { Memory, Subconscious } from '@mastra/memory';\nimport {\n DEFAULT_OM_MODEL_ID,\n DEFAULT_OBS_THRESHOLD,\n DEFAULT_REF_THRESHOLD,\n MODEL_ROUTE_MAX_ENTRIES,\n} from '../constants.js';\nimport { LOCAL_KNOWLEDGE_ORG_ID, resolveKnowledgeScopeIdentity } from '../knowledge-scope.js';\nimport { loadSettings } from '../onboarding/settings.js';\nimport { ANTHROPIC_PROMPT_CACHE_TTL } from '../providers/anthropic-prompt-cache.js';\nimport type { MastraCodeState } from '../schema.js';\nimport { getOmScope } from '../utils/project.js';\nimport { resolveModel } from './model.js';\n\n/** Route-backed OM fallback entry. */\ntype MemoryModelRouteEntry = { id: string; model: GatewayLanguageModel };\n\n/** Resolve one OM role's model for this invocation. */\nfunction resolveOmRoleModelForRequest(\n role: 'observer' | 'reflector',\n requestContext: RequestContext,\n settingsPath?: string,\n options?: { disableSettingsOmSeed?: boolean },\n): GatewayLanguageModel | MemoryModelRouteEntry[] {\n const controller = requestContext.get('controller') as AgentControllerRequestContext<MastraCodeState> | undefined;\n const state = controller?.getState() as MastraCodeState | undefined;\n const resolveOptions = { remapForCodexOAuth: true, requestContext, anthropicPromptCacheScope: 'system' } as const;\n\n if (!options?.disableSettingsOmSeed) {\n const settings = loadSettings(settingsPath);\n const roleOverride =\n role === 'observer' ? settings.models?.observerModelOverride : settings.models?.reflectorModelOverride;\n if (roleOverride) return resolveModel(roleOverride, resolveOptions);\n }\n\n const pending = state?.mastracodePendingModelFallback;\n const sameThreadPending =\n pending && (pending.threadId === undefined || pending.threadId === controller?.threadId) ? pending : undefined;\n const routeEntries = state?.modelRoute?.entries?.slice(0, MODEL_ROUTE_MAX_ENTRIES) ?? [];\n const pendingIndex = sameThreadPending\n ? routeEntries.findIndex(entry => entry.id === sameThreadPending.toEntryId)\n : -1;\n const memoryRoute = pendingIndex >= 0 ? routeEntries.slice(pendingIndex) : routeEntries;\n const seenModelIds = new Set<string>();\n const appearances = new Map<string, number>();\n const entries: MemoryModelRouteEntry[] = [];\n for (const entry of memoryRoute) {\n if (!entry.memoryModelId || seenModelIds.has(entry.memoryModelId)) continue;\n seenModelIds.add(entry.memoryModelId);\n const occurrence = (appearances.get(entry.id) ?? 0) + 1;\n appearances.set(entry.id, occurrence);\n try {\n entries.push({\n id: `${entry.id}:memory${occurrence === 1 ? '' : `#${occurrence}`}`,\n model: resolveModel(entry.memoryModelId, resolveOptions),\n });\n } catch {\n break;\n }\n }\n if (entries.length === 1) return entries[0]!.model;\n if (entries.length > 1) return entries;\n\n const stateModelId = role === 'observer' ? state?.observerModelId : state?.reflectorModelId;\n return resolveModel(stateModelId ?? DEFAULT_OM_MODEL_ID, resolveOptions);\n}\n\nconst DYNAMIC_AGENTS_MD_INSTRUCTION =\n 'Messages wrapped in <system-reminder type=\"dynamic-agents-md\" ...>...</system-reminder> are ephemeral project-context instructions injected from files on disk. Do NOT observe or extract information from these messages — they are reloaded automatically when needed and should not be stored in memory.';\n\n// Derived from https://github.com/JuliusBrussee/caveman and adapted for OM use with fixed full-level compression.\nconst CAVEMAN_OM_INSTRUCTION = `Respond terse like smart caveman. All technical substance stay. Only fluff die.\n\nUse full caveman compression style.\n\nDrop: articles (a/an/the), filler (just/really/basically/actually/simply), pleasantries (sure/certainly/of course/happy to), hedging. Fragments OK. Short synonyms (big not extensive, fix not \"implement a solution for\"). Technical terms exact. Code blocks unchanged. Errors quoted exact. Leave out the words \"agent\" and \"assistant\" at the start of each observation line, it is assumed each line is referring to the assistant unless it specifically says it was about the user. Leave out parenthesis and other text characters like * that would not contribute to understanding the observations.\n\nPattern: \\`[thing] [action] [reason]. [next step]\\`\n\nNot: \"Sure! I'd be happy to help you with that. The issue you're experiencing is likely caused by...\"\nYes: \"Bug in auth middleware. Token expiry check use < not <=. Fix:\"\n\nExample 1\n🔴 14:31 user asks why React component rerenders\n🟡 14:32 saw inline object prop create new ref each render, cause rerender\n✅ 14:34 fixed render issue by wrap object in useMemo\n\nExample 2\n🟡 15:10 explained pool reuse DB connections, skip repeat handshake overhead\n\nDon't say \"Agent did x\", say \"did x\". It will be assumed the agent did what was observed. The who should only be specified for the user or other third parties: \"user asked x\"\n\nDrop caveman for: security warnings, irreversible action confirmations, multi-step sequences where fragment order risks misread, user asks to clarify or repeats question, and anything that requires remembering verbatim content. Resume caveman after clear part done`;\n\nexport { LOCAL_KNOWLEDGE_ORG_ID };\n\n// One error per session, not per memory resolution. Keyed on the session id\n// rather than the controller object: the controller is read off the request\n// context on every resolution, so it is a fresh object per request and would\n// dedupe nothing. Bounded so a long-running Factory process cannot grow this\n// without limit — refusing sessions are rare, and losing the oldest ids only\n// costs one extra log line.\nconst REPORTED_ORG_UNRESOLVED_LIMIT = 500;\nconst reportedOrgUnresolved = new Set<string>();\n\nfunction reportOrgUnresolved(\n controller: AgentControllerRequestContext<MastraCodeState> | undefined,\n factoryProjectId: string | undefined,\n reason?: string,\n) {\n const sessionId = controller?.session?.id;\n if (sessionId) {\n if (reportedOrgUnresolved.has(sessionId)) return;\n if (reportedOrgUnresolved.size >= REPORTED_ORG_UNRESOLVED_LIMIT) {\n reportedOrgUnresolved.delete(reportedOrgUnresolved.values().next().value as string);\n }\n reportedOrgUnresolved.add(sessionId);\n }\n const session = controller?.session;\n console.error(\n `[Subconscious] Knowledge curation disabled: no organization resolved for session ${session?.id ?? 'unknown'} (project ${factoryProjectId ?? 'none'})${reason ? `: ${reason}` : ''}. Knowledge is not written rather than written where it cannot be read.`,\n );\n}\n\n/**\n * Whether the experimental subconscious (knowledge graph + reminder sidekick)\n * is switched on for this process: it needs a vector store and the opt-in flag.\n */\nexport function isSubconsciousEnabled(vector: MastraVector | undefined): boolean {\n return Boolean(vector) && process.env.MASTRACODE_EXPERIMENTAL_SUBCONSCIOUS === '1';\n}\n\n/**\n * Whether the subconscious tools (`knowledge_*`, `ask_memory`) are registered\n * for a given session. Beyond the process-level switch, a Factory-owned\n * session that cannot resolve its org refuses the subconscious entirely (see\n * `getDynamicMemory`, which applies the same two checks inline because it also\n * needs the resolved identity). The system prompt's tool guidance calls here so\n * it never advertises tools that `getDynamicMemory` did not register.\n */\nexport function hasSubconsciousTools(vector: MastraVector | undefined, state: MastraCodeState | undefined): boolean {\n return isSubconsciousEnabled(vector) && resolveKnowledgeScopeIdentity(state).resolved;\n}\n\n/**\n * Dynamic memory factory function.\n * Reads OM thresholds from controller state via requestContext.\n * Model functions also read from requestContext (no mutable bridge needed).\n */\nexport function getDynamicMemory(\n storage: MastraCompositeStore,\n vector?: MastraVector,\n settingsPath?: string,\n options?: { disableSettingsOmSeed?: boolean },\n) {\n // Cache is scoped per storage instance (per getDynamicMemory call) so a\n // Memory bound to one storage is never reused after storage changes.\n let cachedMemory: Memory | null = null;\n let cachedMemoryKey: string | null = null;\n\n // Observer/reflector model functions — read the current model ID from\n // controller state via requestContext (propagated by OM's agent.generate).\n // Bound here so the configured settings path reaches role overrides and pack\n // memory-model resolution.\n const getObserverModel = ({ requestContext }: { requestContext: RequestContext }) =>\n resolveOmRoleModelForRequest('observer', requestContext, settingsPath, options);\n const getReflectorModel = ({ requestContext }: { requestContext: RequestContext }) =>\n resolveOmRoleModelForRequest('reflector', requestContext, settingsPath, options);\n\n return ({ requestContext }: { requestContext: RequestContext }) => {\n const controller = requestContext.get('controller') as AgentControllerRequestContext<MastraCodeState> | undefined;\n const state = controller?.getState() as MastraCodeState | undefined;\n const subconsciousEnabled = isSubconsciousEnabled(vector);\n const factoryProjectId = state?.factoryProjectId;\n const isFactory = typeof factoryProjectId === 'string' && factoryProjectId.trim().length > 0;\n\n // A Factory-owned session that could not resolve its org refuses to curate:\n // writing under a substituted identity produces knowledge the fail-closed\n // read path can never see.\n let orgUnresolvedRefusal = false;\n\n if (subconsciousEnabled) {\n const identity = resolveKnowledgeScopeIdentity(state);\n if (identity.resolved) {\n requestContext.set('organizationId', identity.organizationId);\n } else {\n orgUnresolvedRefusal = true;\n reportOrgUnresolved(controller, identity.knowledgeResourceId, identity.reason);\n }\n if (identity.knowledgeResourceId) {\n requestContext.set('knowledgeResourceId', identity.knowledgeResourceId);\n }\n }\n\n const subconsciousAvailable = subconsciousEnabled && !orgUnresolvedRefusal;\n\n const omScope = state?.omScope ?? getOmScope(state?.projectPath);\n\n const obsThreshold = state?.observationThreshold ?? DEFAULT_OBS_THRESHOLD;\n const refThreshold = state?.reflectionThreshold ?? DEFAULT_REF_THRESHOLD;\n const caveman = state?.cavemanObservations ?? false;\n\n const observerPreviousObservationTokens = 1000;\n const observeAttachments = state?.observeAttachments;\n // Factory sessions get a factory-only Subconscious config, so the cache key\n // carries a factory presence bit to keep the two configs from cross-serving.\n const cacheKey = `${obsThreshold}:${refThreshold}:${omScope}:${observerPreviousObservationTokens}:${caveman ? 1 : 0}:${observeAttachments}:${isFactory ? 1 : 0}:${subconsciousAvailable ? 1 : 0}`;\n if (cachedMemory && cachedMemoryKey === cacheKey) {\n return cachedMemory;\n }\n\n // Async buffering is not supported with resource scope — disable it\n const isResourceScope = omScope === 'resource';\n\n const observerInstruction = caveman\n ? `${DYNAMIC_AGENTS_MD_INSTRUCTION}\\n\\n${CAVEMAN_OM_INSTRUCTION}`\n : DYNAMIC_AGENTS_MD_INSTRUCTION;\n const reflectionInstruction = caveman ? CAVEMAN_OM_INSTRUCTION : undefined;\n\n cachedMemory = new Memory({\n storage,\n vector: vector || false,\n embedder: vector ? fastembed.small : undefined,\n options: {\n // Generate a durable title from the first user message. Every client uses\n // the same title in its thread list and active-session chrome. Title\n // generation takes the primary OM model only — its model field does not\n // accept fallback arrays.\n generateTitle: {\n model: ({ requestContext }) => {\n const resolved = getObserverModel({ requestContext });\n return Array.isArray(resolved) ? resolved[0]!.model : resolved;\n },\n },\n observationalMemory: {\n enabled: true,\n temporalMarkers: true,\n retrieval: vector ? { vector: true } : true,\n experimental_subconscious: subconsciousAvailable\n ? new Subconscious({\n defaultScope: 'resource',\n maxScope: 'resource',\n pins: true,\n ...(isFactory ? { maxSteps: 25 } : {}),\n })\n : undefined,\n scope: omScope,\n // The main agent writes Anthropic cache entries with this TTL; 'auto' can't see it.\n activateAfterIdle: { default: 'auto', anthropic: ANTHROPIC_PROMPT_CACHE_TTL },\n activateOnProviderChange: true,\n observation: {\n bufferTokens: isResourceScope ? false : 1 / 5,\n bufferActivation: isResourceScope ? undefined : 2000,\n model: getObserverModel,\n messageTokens: obsThreshold,\n blockAfter: 2,\n previousObserverTokens: observerPreviousObservationTokens,\n threadTitle: true,\n instruction: observerInstruction,\n observeAttachments,\n },\n reflection: {\n bufferActivation: isResourceScope ? undefined : 1 / 2,\n blockAfter: 1.1,\n model: getReflectorModel,\n observationTokens: refThreshold,\n instruction: reflectionInstruction,\n },\n },\n },\n });\n cachedMemoryKey = cacheKey;\n\n return cachedMemory;\n };\n}\n"],"mappings":"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"}
@@ -2,7 +2,6 @@ import type { ModelWithRetries } from '@mastra/core/agent';
2
2
  import type { GatewayLanguageModel, MastraModelGatewayInterface } from '@mastra/core/llm';
3
3
  import type { RequestContext } from '@mastra/core/request-context';
4
4
  import type { CredentialStore } from '../auth/types.js';
5
- import { loadSettings } from '../onboarding/settings.js';
6
5
  import type { AnthropicPromptCacheScope } from '../providers/anthropic-prompt-cache.js';
7
6
  import type { ThinkingLevelSetting } from '../thinking.js';
8
7
  import { MastraCodeGateway } from './mastracode-gateway.js';
@@ -60,49 +59,15 @@ export interface ThinkingRequestContext {
60
59
  * (rule-driven) Factory runs that nobody ever opens interactively.
61
60
  */
62
61
  export declare function resolveRequestThinkingLevel(agentControllerContext: ThinkingRequestContext | undefined, settingsPath?: string): ThinkingLevelSetting;
63
- /** Structural pack shape for fallback resolution (custom pack models are partial by nature). */
64
- export interface ResolvableModePack {
65
- id: string;
66
- name: string;
67
- models: Record<string, string>;
68
- }
69
- /** All packs a fallback chain may reference: every builtin plus saved customs. */
70
- export declare function listResolvableModePacks(settings: ReturnType<typeof loadSettings>): ResolvableModePack[];
71
62
  /**
72
- * Dynamic model function that reads the current model from controller state.
73
- * This allows runtime model switching via the /models picker.
74
- *
75
- * When the session's model came from a pack with a fallback chain configured
76
- * (`settings.models.packFallbacks`), returns core's `ModelWithRetries[]`
77
- * fallback array instead of a bare model: the active pack's model first, then
78
- * each fallback pack's model for the same mode. Core advances the array when
79
- * the error processors decline to retry (pool exhausted / persistent outage —
80
- * see AccountRotationProcessor). Entry ids are unique per occurrence — the
81
- * one allowed revisit of a pack gets `<packId>#2` — because core re-resolves
82
- * the active fallback index by id across agentic steps.
63
+ * Dynamic model function that reads the current model and optional ordered
64
+ * fallback route from controller state. Route entry ids are opaque host-owned
65
+ * identifiers; repeated ids receive occurrence suffixes because core tracks the
66
+ * active fallback index by id across agentic steps.
83
67
  */
84
68
  export declare function getDynamicModel({ requestContext }: {
85
69
  requestContext: RequestContext;
86
70
  }, settingsPath?: string): ResolvedModel | ModelWithRetries[];
87
- /** OM fallback-chain entry: a pack's OM model resolved through the gateway. Assignable to `ModelWithRetries`. */
88
- export type PackMemoryModelChainEntry = {
89
- id: string;
90
- model: GatewayLanguageModel;
91
- };
92
- /**
93
- * Resolve the observational-memory model for the active mode pack, walking the
94
- * pack's fallback chain (`settings.models.packFallbacks`) and collecting each
95
- * pack's optional `models.memory` entry. Packs without an OM model are skipped
96
- * (the field is optional, so absence must not truncate the chain); duplicate
97
- * model ids collapse so an A⇄B cycle never retries an identical OM model.
98
- *
99
- * Returns a bare model for a single entry, a fallback array for multiple
100
- * entries (OM's internal agents run the same agentic loop, so the array gives
101
- * OM its own cross-pack failover), or `undefined` when no pack in the chain
102
- * defines an OM model — callers then fall back to the standalone OM
103
- * configuration.
104
- */
105
- export declare function resolvePackMemoryModelChain(settings: ReturnType<typeof loadSettings>, startPackId: string, resolveOptions: Parameters<typeof resolveModel>[1]): GatewayLanguageModel | PackMemoryModelChainEntry[] | undefined;
106
71
  /**
107
72
  * Goal judge model resolver for the agent's `goal.judge` config. Resolves the
108
73
  * configured goal judge model through mastracode's gateway so provider
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/agents/model.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/agents/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAGnE,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,kBAAkB,CAAC;AAQ5E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AAExF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAG3D,OAAO,EAGL,iBAAiB,EAIlB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAExE,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,6BAA6B,EAC7B,WAAW,GACZ,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,+BAA+B,GAChC,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAC1F,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEzE,KAAK,aAAa,GAAG,oBAAoB,CAAC;AAkB1C,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,eAAe,EACrB,cAAc,CAAC,EAAE,cAAc,GAC9B,eAAe,CAqDjB;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAE5F;AAED,wBAAgB,oCAAoC,CAAC,OAAO,EAAE,2BAA2B,6DAIxF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IACR,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,yBAAyB,CAAC,EAAE,yBAAyB,CAAC;CACvD,GACA,oBAAoB,CAuFtB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACpC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/B;AACD;;;;;;;;;;;;GAYG;AAEH,wBAAgB,2BAA2B,CACzC,sBAAsB,EAAE,sBAAsB,GAAG,SAAS,EAC1D,YAAY,CAAC,EAAE,MAAM,GACpB,oBAAoB,CAKtB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,EAAE,cAAc,EAAE,EAAE;IAAE,cAAc,EAAE,cAAc,CAAA;CAAE,EACtD,YAAY,CAAC,EAAE,MAAM,GACpB,aAAa,GAAG,gBAAgB,EAAE,CAuEpC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,cAAc,EAAE,EAAE;IAAE,cAAc,EAAE,cAAc,CAAA;CAAE,EACtD,YAAY,CAAC,EAAE,MAAM,GACpB,aAAa,GAAG,SAAS,CAI3B"}
@@ -1,8 +1,8 @@
1
- import { isThinkingLevelSetting } from "../thinking.js";
1
+ import "../constants.js";
2
2
  import { MASTRA_GATEWAY_PREFIX, remapOpenAIModelForCodexOAuth, stripMastraGatewayPrefix } from "../providers/model-ids.js";
3
3
  import { ProviderAuthRequiredError } from "../auth/provider-auth-error.js";
4
- import { listBuiltinModePacks, resolveModePackFallbackChain } from "../onboarding/packs.js";
5
- import { findModePackForModel, loadSettings, resolveDefaultThinkingLevel, resolveModePackModels, stripMastraCodeCustomProviderPrefix } from "../onboarding/settings.js";
4
+ import { isThinkingLevelSetting } from "../thinking.js";
5
+ import { loadSettings, resolveDefaultThinkingLevel, stripMastraCodeCustomProviderPrefix } from "../onboarding/settings.js";
6
6
  import { hasCredentialStoreProvider, resolveCredentialStore, resolveTenantFromRequestContext, setCredentialStoreProvider } from "./credential-resolver.js";
7
7
  import { getRequestAccountSelection, isRequestAccountRoutingExhausted } from "../auth/account-routing-context.js";
8
8
  import { AMAZON_BEDROCK_GATEWAY_ID, createAmazonBedrockGateway } from "../providers/amazon-bedrock-gateway.js";
@@ -151,118 +151,56 @@ function resolveRequestThinkingLevel(agentControllerContext, settingsPath) {
151
151
  const modeId = agentControllerContext?.session?.modeId;
152
152
  return resolveDefaultThinkingLevel(loadSettings(settingsPath), modeId).level;
153
153
  }
154
- /** All packs a fallback chain may reference: every builtin plus saved customs. */
155
- function listResolvableModePacks(settings) {
156
- return [...listBuiltinModePacks(), ...settings.customModelPacks.map((pack) => ({
157
- id: `custom:${pack.name}`,
158
- name: pack.name,
159
- models: { ...pack.models }
160
- }))];
161
- }
162
154
  /**
163
- * Dynamic model function that reads the current model from controller state.
164
- * This allows runtime model switching via the /models picker.
165
- *
166
- * When the session's model came from a pack with a fallback chain configured
167
- * (`settings.models.packFallbacks`), returns core's `ModelWithRetries[]`
168
- * fallback array instead of a bare model: the active pack's model first, then
169
- * each fallback pack's model for the same mode. Core advances the array when
170
- * the error processors decline to retry (pool exhausted / persistent outage —
171
- * see AccountRotationProcessor). Entry ids are unique per occurrence — the
172
- * one allowed revisit of a pack gets `<packId>#2` — because core re-resolves
173
- * the active fallback index by id across agentic steps.
155
+ * Dynamic model function that reads the current model and optional ordered
156
+ * fallback route from controller state. Route entry ids are opaque host-owned
157
+ * identifiers; repeated ids receive occurrence suffixes because core tracks the
158
+ * active fallback index by id across agentic steps.
174
159
  */
175
160
  function getDynamicModel({ requestContext }, settingsPath) {
176
- const agentControllerContext = requestContext.get("controller");
177
- const controllerState = agentControllerContext?.getState?.();
178
- const pendingState = controllerState?.mastracodePendingPackFallback;
179
- const pendingFallback = pendingState && (pendingState.threadId === void 0 || typeof pendingState.threadId === "string" && pendingState.threadId === agentControllerContext?.threadId) ? pendingState : void 0;
180
- const modelId = (pendingFallback && typeof pendingFallback.toModelId === "string" && pendingFallback.toModelId.length > 0 ? pendingFallback.toModelId : void 0) ?? agentControllerContext?.session?.modelId;
161
+ const controller = requestContext.get("controller");
162
+ const state = controller?.getState?.();
163
+ const pendingState = state?.mastracodePendingModelFallback;
164
+ const pendingFallback = pendingState && (pendingState.threadId === void 0 || typeof pendingState.threadId === "string" && pendingState.threadId === controller?.threadId) ? pendingState : void 0;
165
+ const modelId = (pendingFallback && typeof pendingFallback.toModelId === "string" && pendingFallback.toModelId.length > 0 ? pendingFallback.toModelId : void 0) ?? controller?.session?.modelId;
181
166
  if (!modelId) {
182
- if (!agentControllerContext) throw new Error("No model available: this run started without a controller session context, so no model selection could be resolved.");
167
+ if (!controller) throw new Error("No model available: this run started without a controller session context, so no model selection could be resolved.");
183
168
  throw new Error("No model selected. Use /models to select a model first.");
184
169
  }
185
170
  const resolveOptions = {
186
- thinkingLevel: resolveRequestThinkingLevel(agentControllerContext, settingsPath),
171
+ thinkingLevel: resolveRequestThinkingLevel(controller, settingsPath),
187
172
  remapForCodexOAuth: true,
188
173
  requestContext
189
174
  };
190
175
  const primary = resolveModel(modelId, resolveOptions);
191
- const settings = loadSettings(settingsPath);
192
- const fallbacks = settings.models?.packFallbacks ?? {};
193
- if (Object.keys(fallbacks).length === 0) return primary;
194
- const modeId = agentControllerContext?.session?.modeId ?? "build";
195
- const packs = listResolvableModePacks(settings);
196
- const statePackId = (pendingFallback && typeof pendingFallback.toPackId === "string" && pendingFallback.toPackId.length > 0 ? pendingFallback.toPackId : void 0) ?? controllerState?.activeModelPackId ?? settings.models.activeModelPackId;
197
- const activePack = findModePackForModel(settings, packs, modelId, modeId, typeof statePackId === "string" ? statePackId : void 0);
198
- if (!activePack) return primary;
199
- const chain = resolveModePackFallbackChain(fallbacks, activePack.id, settings.customModelPacks);
200
- if (chain.length < 2) return primary;
176
+ const route = state?.modelRoute?.entries?.slice(0, 32);
177
+ const pendingEntryId = pendingFallback && typeof pendingFallback.toEntryId === "string" ? pendingFallback.toEntryId : void 0;
178
+ const startIndex = pendingEntryId ? route?.findIndex((entry) => entry.id === pendingEntryId) : 0;
179
+ const activeRoute = route && startIndex !== void 0 && startIndex >= 0 ? route.slice(startIndex) : void 0;
180
+ if (!activeRoute || activeRoute.length < 2 || activeRoute[0]?.modelId !== modelId) return primary;
181
+ const firstId = typeof activeRoute[0]?.id === "string" && activeRoute[0].id.length > 0 ? activeRoute[0].id : void 0;
182
+ if (!firstId) return primary;
201
183
  const entries = [{
202
- id: activePack.id,
184
+ id: firstId,
203
185
  model: primary
204
186
  }];
205
- const appearances = /* @__PURE__ */ new Map([[activePack.id, 1]]);
206
- for (const packId of chain.slice(1)) {
207
- const pack = packs.find((candidate) => candidate.id === packId);
208
- if (!pack) break;
209
- const entryModelId = resolveModePackModels(settings, pack)[modeId];
210
- if (!entryModelId) break;
211
- let entryModel;
212
- try {
213
- entryModel = resolveModel(entryModelId, resolveOptions);
214
- } catch {
215
- break;
216
- }
217
- const occurrence = (appearances.get(packId) ?? 0) + 1;
218
- appearances.set(packId, occurrence);
219
- entries.push({
220
- id: occurrence === 1 ? packId : `${packId}#${occurrence}`,
221
- model: entryModel
222
- });
223
- }
224
- if (entries.length < 2) return primary;
225
- return entries;
226
- }
227
- /**
228
- * Resolve the observational-memory model for the active mode pack, walking the
229
- * pack's fallback chain (`settings.models.packFallbacks`) and collecting each
230
- * pack's optional `models.memory` entry. Packs without an OM model are skipped
231
- * (the field is optional, so absence must not truncate the chain); duplicate
232
- * model ids collapse so an A⇄B cycle never retries an identical OM model.
233
- *
234
- * Returns a bare model for a single entry, a fallback array for multiple
235
- * entries (OM's internal agents run the same agentic loop, so the array gives
236
- * OM its own cross-pack failover), or `undefined` when no pack in the chain
237
- * defines an OM model — callers then fall back to the standalone OM
238
- * configuration.
239
- */
240
- function resolvePackMemoryModelChain(settings, startPackId, resolveOptions) {
241
- const packs = listResolvableModePacks(settings);
242
- if (!packs.some((pack) => pack.id === startPackId)) return void 0;
243
- const chain = resolveModePackFallbackChain(settings.models?.packFallbacks ?? {}, startPackId, settings.customModelPacks);
244
- const seenModelIds = /* @__PURE__ */ new Set();
245
- const entries = [];
246
- for (const packId of chain) {
247
- const pack = packs.find((candidate) => candidate.id === packId);
248
- if (!pack) break;
249
- const memoryModelId = resolveModePackModels(settings, pack).memory;
250
- if (!memoryModelId || seenModelIds.has(memoryModelId)) continue;
251
- seenModelIds.add(memoryModelId);
187
+ const appearances = /* @__PURE__ */ new Map([[firstId, 1]]);
188
+ for (const routeEntry of activeRoute.slice(1)) {
189
+ if (typeof routeEntry.id !== "string" || routeEntry.id.length === 0 || typeof routeEntry.modelId !== "string" || routeEntry.modelId.length === 0) break;
252
190
  let entryModel;
253
191
  try {
254
- entryModel = resolveModel(memoryModelId, resolveOptions);
192
+ entryModel = resolveModel(routeEntry.modelId, resolveOptions);
255
193
  } catch {
256
194
  break;
257
195
  }
196
+ const occurrence = (appearances.get(routeEntry.id) ?? 0) + 1;
197
+ appearances.set(routeEntry.id, occurrence);
258
198
  entries.push({
259
- id: `${packId}:memory`,
199
+ id: occurrence === 1 ? routeEntry.id : `${routeEntry.id}#${occurrence}`,
260
200
  model: entryModel
261
201
  });
262
202
  }
263
- if (entries.length === 0) return void 0;
264
- if (entries.length === 1) return entries[0].model;
265
- return entries;
203
+ return entries.length < 2 ? primary : entries;
266
204
  }
267
205
  /**
268
206
  * Goal judge model resolver for the agent's `goal.judge` config. Resolves the
@@ -287,6 +225,6 @@ function getGoalJudgeModel({ requestContext }, settingsPath) {
287
225
  });
288
226
  }
289
227
  //#endregion
290
- 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 };
228
+ export { MASTRACODE_GATEWAY_ID, MastraCodeGateway, createMastraCodeGateway, createMastraCodeModelCatalogProvider, createRequestScopedCredentialStore, getAnthropicApiKey, getDynamicModel, getGoalJudgeModel, getOpenAIApiKey, hasCredentialStoreProvider, hasCustomProvidersSource, remapOpenAIModelForCodexOAuth, resolveAuth, resolveCustomProviders, resolveModel, resolveModelId, resolveRequestThinkingLevel, resolveTenantFromRequestContext, setCredentialStoreProvider, setCustomProvidersSource };
291
229
 
292
230
  //# sourceMappingURL=model.js.map
@@ -1 +1 @@
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 { ProviderAuthRequiredError } from '../auth/provider-auth-error.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 type { AnthropicPromptCacheScope } from '../providers/anthropic-prompt-cache.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?: {\n thinkingLevel?: ThinkingLevelSetting;\n remapForCodexOAuth?: boolean;\n requestContext?: RequestContext;\n anthropicPromptCacheScope?: AnthropicPromptCacheScope;\n },\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 anthropicPromptCacheScope: options?.anthropicPromptCacheScope,\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 ProviderAuthRequiredError(\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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"}
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 { ProviderAuthRequiredError } from '../auth/provider-auth-error.js';\nimport type { CredentialStore, OAuthAccountRecord } from '../auth/types.js';\nimport { MODEL_ROUTE_MAX_ENTRIES } from '../constants.js';\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 type { AnthropicPromptCacheScope } from '../providers/anthropic-prompt-cache.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?: {\n thinkingLevel?: ThinkingLevelSetting;\n remapForCodexOAuth?: boolean;\n requestContext?: RequestContext;\n anthropicPromptCacheScope?: AnthropicPromptCacheScope;\n },\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 anthropicPromptCacheScope: options?.anthropicPromptCacheScope,\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 ProviderAuthRequiredError(\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 and optional ordered\n * fallback route from controller state. Route entry ids are opaque host-owned\n * identifiers; repeated ids receive occurrence suffixes because core tracks the\n * active fallback index by id across agentic steps.\n */\nexport function getDynamicModel(\n { requestContext }: { requestContext: RequestContext },\n settingsPath?: string,\n): ResolvedModel | ModelWithRetries[] {\n const controller = requestContext.get('controller') as AgentControllerRequestContext<any> | undefined;\n const state = controller?.getState?.() as\n | {\n modelRoute?: {\n entries?: Array<{ id?: unknown; modelId?: unknown }>;\n };\n mastracodePendingModelFallback?: { toEntryId?: unknown; toModelId?: unknown; threadId?: unknown } | null;\n }\n | undefined;\n const pendingState = state?.mastracodePendingModelFallback;\n const pendingFallback =\n pendingState &&\n (pendingState.threadId === undefined ||\n (typeof pendingState.threadId === 'string' && pendingState.threadId === controller?.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 ?? controller?.session?.modelId;\n if (!modelId) {\n if (!controller) {\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(controller, settingsPath);\n const resolveOptions = { thinkingLevel, remapForCodexOAuth: true, requestContext } as const;\n const primary = resolveModel(modelId, resolveOptions);\n const route = state?.modelRoute?.entries?.slice(0, MODEL_ROUTE_MAX_ENTRIES);\n const pendingEntryId =\n pendingFallback && typeof pendingFallback.toEntryId === 'string' ? pendingFallback.toEntryId : undefined;\n const startIndex = pendingEntryId ? route?.findIndex(entry => entry.id === pendingEntryId) : 0;\n const activeRoute = route && startIndex !== undefined && startIndex >= 0 ? route.slice(startIndex) : undefined;\n if (!activeRoute || activeRoute.length < 2 || activeRoute[0]?.modelId !== modelId) return primary;\n\n const firstId =\n typeof activeRoute[0]?.id === 'string' && activeRoute[0].id.length > 0 ? activeRoute[0].id : undefined;\n if (!firstId) return primary;\n\n const entries: ModelWithRetries[] = [{ id: firstId, model: primary }];\n const appearances = new Map<string, number>([[firstId, 1]]);\n for (const routeEntry of activeRoute.slice(1)) {\n if (\n typeof routeEntry.id !== 'string' ||\n routeEntry.id.length === 0 ||\n typeof routeEntry.modelId !== 'string' ||\n routeEntry.modelId.length === 0\n ) {\n break;\n }\n let entryModel: ResolvedModel;\n try {\n entryModel = resolveModel(routeEntry.modelId, resolveOptions);\n } catch {\n break;\n }\n const occurrence = (appearances.get(routeEntry.id) ?? 0) + 1;\n appearances.set(routeEntry.id, occurrence);\n entries.push({\n id: occurrence === 1 ? routeEntry.id : `${routeEntry.id}#${occurrence}`,\n model: entryModel,\n });\n }\n\n return entries.length < 2 ? primary : 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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"}
@@ -1,7 +1,7 @@
1
1
  import { DEFAULT_CONFIG_DIR } from "../../constants.js";
2
2
  import { dirname, isAbsolute, join, normalize, relative, resolve, sep } from "path";
3
- import { execFileSync } from "child_process";
4
3
  import { existsSync, readFileSync, realpathSync, statSync } from "fs";
4
+ import { execFileSync } from "child_process";
5
5
  import { homedir } from "os";
6
6
  //#region src/agents/prompts/agent-instructions.ts
7
7
  /**
@@ -33,38 +33,28 @@ export type RotationCredentialStore = CredentialStore & {
33
33
  */
34
34
  forceRefreshActiveAccount?(providerId: string, accountInstanceId?: string): Promise<string | undefined>;
35
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 {
36
+ /** Persisted data-part type for a model-route hop. */
37
+ export declare const MODEL_FALLBACK_PART_TYPE: "data-mastracode-model-fallback";
38
+ /** Non-secret transcript payload for a model-route hop. */
39
+ export interface ModelFallbackPartData {
44
40
  from: {
45
- packId: string;
41
+ entryId: string;
46
42
  label: string;
47
43
  };
48
44
  to: {
49
- packId: string;
45
+ entryId: string;
50
46
  label: string;
51
47
  };
52
48
  reason: 'pool-exhausted' | 'persistent-outage';
53
49
  at: string;
54
50
  }
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. */
51
+ /** Session-state key set when account rotation advances the model route. */
52
+ export declare const MODEL_FALLBACK_STATE_KEY: "mastracodePendingModelFallback";
53
+ /** Payload written to session state under MODEL_FALLBACK_STATE_KEY. */
54
+ export interface PendingModelFallback {
55
+ fromEntryId: string;
56
+ toEntryId: string;
66
57
  toModelId: string;
67
- /** Originating thread. Absent only on pending hops written by older clients. */
68
58
  threadId?: string;
69
59
  reason: 'pool-exhausted' | 'persistent-outage';
70
60
  at: string;
@@ -105,21 +95,16 @@ export declare function isAccountSwitchReason(value: unknown): value is AccountS
105
95
  * history rendering of the persisted part — one formatter, identical text.
106
96
  */
107
97
  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;
98
+ /** Transcript line for a model-route hop; shared by the live info event and the TUI's history render. */
99
+ export declare function modelFallbackNoticeText(data: ModelFallbackPartData): string;
110
100
  /**
111
- * Whether a persisted pack-fallback reason is one this build understands.
101
+ * Whether a persisted model-fallback reason is one this build understands.
112
102
  * `REASON_TEXT` also covers the account-switch reasons, so the notice text
113
103
  * 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
104
+ * model-fallback reason; history parsed from another build's part must be
115
105
  * rejected instead.
116
106
  */
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
- */
107
+ export declare function isModelFallbackReason(value: unknown): value is ModelFallbackPartData['reason'];
123
108
  export type RoutingControllerContext = {
124
109
  session?: {
125
110
  modelId?: unknown;
@@ -147,20 +132,15 @@ export declare class AccountRotationProcessor implements Processor {
147
132
  retry: boolean;
148
133
  }>;
149
134
  /**
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.
135
+ * Resolve the request's host-supplied model route once and cache the reachable
136
+ * prefix in processor state. Resolution mirrors getDynamicModel so a hop is
137
+ * never announced for an entry core cannot reach.
158
138
  */
159
- private getPackCascade;
139
+ private getModelRouteCascade;
160
140
  /**
161
- * Q14 gate: 400/unknown/unattributable errors never hop packs. Core's
141
+ * Q14 gate: 400/unknown/unattributable errors never advance routes. Core's
162
142
  * 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
143
+ * (llm-execution-step.ts), so when the session route has another entry and the
164
144
  * current entry is non-last, a bare `retry: false` would silently hop on an
165
145
  * error class the user excluded from hop triggers. TripWire is the only
166
146
  * no-advance escape: the runner rethrows it and the fallback loop declines
@@ -168,19 +148,12 @@ export declare class AccountRotationProcessor implements Processor {
168
148
  * plain `retry: false` surface the error exactly as before.
169
149
  */
170
150
  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;
151
+ /** Announce and persist the next model-route hop before core advances. */
152
+ private emitModelFallbackPart;
180
153
  /**
181
154
  * Pool done for this request: every instance recorded in the tried-set and
182
155
  * a `to: null` part emitted. Returns `retry: false` so core's fallback
183
- * array can hop to the next pack (announced by `emitPackFallbackPart`).
156
+ * array can hop to the next route entry (announced by `emitModelFallbackPart`).
184
157
  * Silent on the account part when the provider has no registry at all —
185
158
  * there are no accounts to declare unavailable, but the hop still applies.
186
159
  */
@@ -200,7 +173,6 @@ export declare class AccountStartNoticeProcessor implements Processor {
200
173
  readonly id: "mastracode-account-start-notice";
201
174
  constructor(options: {
202
175
  credentialStore: CredentialStore;
203
- settingsPath?: string;
204
176
  });
205
177
  processInput(args: ProcessInputArgs): Promise<ProcessInputResult>;
206
178
  }