@mastra/code-sdk 1.9.0 → 1.10.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/agent-connections/tools.d.ts.map +1 -1
- package/dist/agent-connections/tools.js +5 -5
- package/dist/agent-connections/tools.js.map +1 -1
- package/dist/analytics.d.ts.map +1 -1
- package/dist/analytics.js +2 -3
- package/dist/analytics.js.map +1 -1
- package/dist/auth/account-rotation-processor.d.ts.map +1 -1
- package/dist/auth/account-rotation-processor.js +17 -10
- package/dist/auth/account-rotation-processor.js.map +1 -1
- package/dist/auth/providers/kimi-coding.d.ts.map +1 -1
- package/dist/auth/providers/kimi-coding.js +1 -2
- package/dist/auth/providers/kimi-coding.js.map +1 -1
- package/dist/auth/providers/openai-codex.d.ts +1 -1
- package/dist/auth/providers/openai-codex.d.ts.map +1 -1
- package/dist/auth/providers/openai-codex.js +7 -19
- package/dist/auth/providers/openai-codex.js.map +1 -1
- package/dist/auth/storage.js +3 -3
- package/dist/auth/storage.js.map +1 -1
- package/dist/experimental-agent.d.ts +11 -0
- package/dist/experimental-agent.d.ts.map +1 -0
- package/dist/experimental-agent.js +36 -0
- package/dist/experimental-agent.js.map +1 -0
- package/dist/goal-manager.d.ts.map +1 -1
- package/dist/goal-manager.js +3 -4
- package/dist/goal-manager.js.map +1 -1
- package/dist/headless/run-mc.d.ts.map +1 -1
- package/dist/headless/run-mc.js +1 -1
- package/dist/headless/run-mc.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -7
- package/dist/index.js.map +1 -1
- package/dist/knowledge-inspector.d.ts.map +1 -1
- package/dist/knowledge-inspector.js +1 -2
- package/dist/knowledge-inspector.js.map +1 -1
- package/dist/onboarding/settings.d.ts +9 -0
- package/dist/onboarding/settings.d.ts.map +1 -1
- package/dist/onboarding/settings.js +36 -4
- package/dist/onboarding/settings.js.map +1 -1
- package/dist/plugins/loader.d.ts.map +1 -1
- package/dist/plugins/loader.js +1 -2
- package/dist/plugins/loader.js.map +1 -1
- package/dist/process-memory-diagnostics.d.ts.map +1 -1
- package/dist/process-memory-diagnostics.js +1 -2
- package/dist/process-memory-diagnostics.js.map +1 -1
- package/dist/tools/workflows/ephemeral-memory.d.ts +21 -0
- package/dist/tools/workflows/ephemeral-memory.d.ts.map +1 -1
- package/dist/tools/workflows/ephemeral-memory.js +1 -2
- package/dist/tools/workflows/ephemeral-memory.js.map +1 -1
- package/dist/utils/signals-pubsub.d.ts.map +1 -1
- package/dist/utils/signals-pubsub.js +1 -2
- package/dist/utils/signals-pubsub.js.map +1 -1
- package/package.json +11 -11
package/dist/goal-manager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal-manager.js","names":[],"sources":["../src/goal-manager.ts"],"sourcesContent":["/**\n * GoalManager — persistent cross-turn goals, backed by the Agent's native goal\n * mechanism.\n *\n * The objective lives in the durable `threadState` `'goal'` slot (via\n * `agent.setObjective`/`getObjective`/`clearObjective`/`updateObjectiveOptions`)\n * and is judged in-loop by the core goal step. This manager is a thin adapter:\n * it keeps a synchronous in-memory view of the current objective for the TUI\n * (status line, modal, keyboard shortcuts) and delegates persistence to the\n * agent. There is no standalone judge agent and no between-turn re-invocation —\n * the core goal step drives continuation and surfaces progress via `goal` stream\n * chunks.\n */\nimport { randomUUID } from 'node:crypto';\nimport { getGoalActivityDurationMs } from '@mastra/core/agent';\nimport type { Agent } from '@mastra/core/agent';\nimport type { AgentController, Session } from '@mastra/core/agent-controller';\nimport type { GoalObjectiveRecord } from '@mastra/core/storage';\nimport { loadSettings } from './onboarding/settings.js';\n\nexport interface GoalManagerState<TState extends Record<string, unknown> = Record<string, unknown>> {\n controller: AgentController<TState>;\n session: Session<TState>;\n}\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type GoalStatus = 'active' | 'paused' | 'done';\n\n/**\n * TUI-facing view of a goal. Derived from the durable {@link GoalObjectiveRecord}\n * plus the effective judge/max-runs settings, with display-only timer fields and\n * a stable `id` used to match plan-started goals.\n */\nexport interface GoalState {\n id: string;\n objective: string;\n status: GoalStatus;\n turnsUsed: number;\n maxTurns: number;\n judgeModelId: string;\n startedAt: string;\n activeStartedAt?: string;\n activeDurationMs?: number;\n /** Why the goal paused (judge failure, budget exhaustion, ...). Only set while paused. */\n pausedReason?: string;\n}\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nexport const DEFAULT_MAX_TURNS = 50;\nconst THREAD_GOAL_KEY = 'goal';\n\nfunction normalizeActiveDurationMs(value: number | undefined): number {\n return value !== undefined && Number.isFinite(value) && value >= 0 ? value : 0;\n}\n\n// =============================================================================\n// GoalManager\n// =============================================================================\n\nexport class GoalManager {\n /** Synchronous in-memory view of the active objective record (source of truth is ThreadState). */\n private record: (GoalObjectiveRecord & { id: string }) | null = null;\n private threadId: string | undefined;\n private agentId: string | undefined;\n private persistGoalOnNextThreadCreate = false;\n /**\n * Set by {@link clear} to the thread the goal was cleared on: the next save\n * with an empty mirror on that same thread deletes the goal. A goal hydrated\n * from legacy metadata has no known thread, so its clear applies to whichever\n * thread the next save runs on (the pre-existing behaviour).\n */\n private pendingDelete: { threadId: string | undefined; goalId?: string } | null = null;\n\n // ---------------------------------------------------------------------------\n // Synchronous TUI surface\n // ---------------------------------------------------------------------------\n\n getGoal(): GoalState | null {\n if (!this.record) return null;\n const { judgeModelId, maxTurns } = this.effectiveSettings(this.record);\n return {\n id: this.record.id,\n objective: this.record.objective,\n status: this.record.status,\n turnsUsed: this.record.runsUsed,\n maxTurns,\n judgeModelId,\n startedAt: new Date(this.record.startedAt).toISOString(),\n ...(this.record.pausedReason ? { pausedReason: this.record.pausedReason } : {}),\n activeDurationMs:\n this.agentId && this.threadId\n ? getGoalActivityDurationMs({\n agentId: this.agentId,\n threadId: this.threadId,\n objectiveId: this.record.id,\n activeDurationMs: this.record.activeDurationMs,\n })\n : normalizeActiveDurationMs(this.record.activeDurationMs),\n };\n }\n\n isActive(): boolean {\n return this.record?.status === 'active';\n }\n\n persistOnNextThreadCreate(): void {\n this.persistGoalOnNextThreadCreate = true;\n }\n\n consumePersistOnNextThreadCreate(): boolean {\n if (!this.persistGoalOnNextThreadCreate) return false;\n this.persistGoalOnNextThreadCreate = false;\n return true;\n }\n\n // ---------------------------------------------------------------------------\n // Objective lifecycle (ThreadState-backed via the agent)\n // ---------------------------------------------------------------------------\n\n /**\n * Set a new objective. Persists to ThreadState via `agent.setObjective` and\n * updates the in-memory view. Only the provided settings are persisted into\n * the record; unset ones fall back to the agent's `goal` config at read time.\n */\n async setGoal(\n state: GoalManagerState,\n objective: string,\n judgeModelId: string,\n maxTurns: number = DEFAULT_MAX_TURNS,\n ): Promise<GoalState | null> {\n const threadId = state.session.thread.getId();\n const agent = this.getAgent(state);\n const now = Date.now();\n const id = randomUUID();\n this.pendingDelete = null;\n this.threadId = threadId ?? undefined;\n this.agentId = agent?.id;\n\n if (agent && threadId) {\n const persisted = await agent.setObjective(objective, {\n id,\n threadId,\n resourceId: state.session.identity.getResourceId(),\n ...(judgeModelId ? { judgeModelId } : {}),\n maxRuns: maxTurns,\n });\n this.record = persisted\n ? { ...persisted, id: persisted.id ?? id }\n : this.localRecord(objective, judgeModelId, maxTurns, now, id);\n } else {\n this.record = this.localRecord(objective, judgeModelId, maxTurns, now, id);\n }\n\n return this.getGoal();\n }\n\n /**\n * Update the judge model / max-runs defaults. Persists into the active record\n * (so the override is remembered in thread state) when a goal is set.\n */\n async updateJudgeDefaults(\n state: GoalManagerState,\n judgeModelId: string,\n maxTurns: number,\n ): Promise<GoalState | null> {\n if (!this.record) return null;\n const threadId = state.session.thread.getId();\n const agent = this.getAgent(state);\n if (agent && threadId) {\n const updated = await agent.updateObjectiveOptions({\n threadId,\n ...(judgeModelId ? { judgeModelId } : {}),\n maxRuns: maxTurns,\n });\n if (updated) this.record = { ...updated, id: this.record.id };\n } else {\n this.record = {\n ...this.record,\n ...(judgeModelId ? { judgeModelId } : {}),\n maxRuns: maxTurns,\n updatedAt: Date.now(),\n };\n }\n return this.getGoal();\n }\n\n pause(reason?: string): GoalState | null {\n if (this.record && this.record.status === 'active') {\n this.record = { ...this.record, status: 'paused', pausedReason: reason, updatedAt: Date.now() };\n }\n return this.getGoal();\n }\n\n resume(): GoalState | null {\n if (this.record && this.record.status === 'paused') {\n this.record = { ...this.record, status: 'active', pausedReason: undefined, updatedAt: Date.now() };\n }\n return this.getGoal();\n }\n\n markDone(): void {\n if (this.record) {\n this.record = { ...this.record, status: 'done', pausedReason: undefined, updatedAt: Date.now() };\n }\n }\n\n clear(): void {\n this.pendingDelete = { threadId: this.threadId, goalId: this.record?.id };\n this.record = null;\n this.threadId = undefined;\n this.agentId = undefined;\n this.persistGoalOnNextThreadCreate = false;\n }\n\n /**\n * Sync the latest objective record from ThreadState into the in-memory view.\n * Called from the `goal` stream-chunk handler after each evaluation.\n */\n applyEvaluation(update: { runsUsed: number; status: GoalStatus; pausedReason?: string }): GoalState | null {\n if (!this.record) return null;\n const pausedReason =\n update.status === 'paused'\n ? (update.pausedReason ?? (this.record.status === 'paused' ? this.record.pausedReason : undefined))\n : undefined;\n this.record = {\n ...this.record,\n runsUsed: update.runsUsed,\n status: update.status,\n // The cause lasts for one pause; leaving paused retires it.\n pausedReason,\n updatedAt: Date.now(),\n };\n return this.getGoal();\n }\n\n // ---------------------------------------------------------------------------\n // Persistence\n // ---------------------------------------------------------------------------\n\n /**\n * Persist the active objective to ThreadState via the agent. The objective\n * record is the source of truth; the legacy thread-metadata key is cleared on\n * a save that actually wrote, so stale state from older sessions cannot\n * shadow the record — and a save that wrote nothing leaves it alone.\n *\n * An empty in-memory mirror means \"I have nothing *loaded*\", which is not the\n * same statement as \"there is nothing\": the mirror is also emptied by storage\n * failures and thread switches. So a save with an empty mirror deletes the\n * goal (durable record and legacy key) only right after an explicit\n * {@link clear} on the same thread (or any thread, for a legacy-hydrated goal\n * whose thread is unknown), and is a complete no-op otherwise.\n */\n async saveToThread(state: GoalManagerState): Promise<void> {\n const threadId = state.session.thread.getId();\n const agent = this.getAgent(state);\n if (!this.record && this.pendingDelete) {\n const clearedThreadId = this.pendingDelete.threadId;\n if (clearedThreadId === undefined || clearedThreadId === threadId) {\n await this.deleteFromThread(state);\n }\n return;\n }\n try {\n if (agent && threadId) {\n if (this.record) {\n // Push the current status/options into the existing record. If no\n // record is persisted yet (e.g. first save), create one.\n const updated = await agent.updateObjectiveOptions({\n threadId,\n status: this.record.status,\n ...(this.record.pausedReason ? { pausedReason: this.record.pausedReason } : {}),\n ...(this.record.judgeModelId ? { judgeModelId: this.record.judgeModelId } : {}),\n ...(this.record.maxRuns !== undefined ? { maxRuns: this.record.maxRuns } : {}),\n });\n if (!updated) {\n // No persisted record yet: create one. `setObjective` always writes\n // `status: 'active'`, so re-apply the in-memory status afterwards if\n // the local goal was already paused/done — otherwise the resumed\n // thread state would no longer match the in-memory state.\n const desiredStatus = this.record.status;\n const created = await agent.setObjective(this.record.objective, {\n id: this.record.id,\n threadId,\n resourceId: state.session.identity.getResourceId(),\n activeDurationMs: normalizeActiveDurationMs(this.record.activeDurationMs),\n ...(this.record.judgeModelId ? { judgeModelId: this.record.judgeModelId } : {}),\n ...(this.record.maxRuns !== undefined ? { maxRuns: this.record.maxRuns } : {}),\n });\n // Nothing durable was written (no goal store, or no thread), so\n // there is no record for a legacy key to shadow — and wiping it\n // would take a pre-migration thread's only copy with it.\n if (!created) return;\n if (desiredStatus !== 'active') {\n await agent.updateObjectiveOptions({\n threadId,\n status: desiredStatus,\n ...(this.record.pausedReason ? { pausedReason: this.record.pausedReason } : {}),\n });\n }\n }\n // Clear any legacy thread-metadata goal so it can't shadow the\n // record we just wrote. Only on the path that actually wrote: on the\n // no-op path a pre-migration thread's only goal may live in that key.\n await state.session.thread.setSetting({ key: THREAD_GOAL_KEY, value: undefined });\n }\n }\n } catch {\n // Persistence is not critical.\n }\n }\n\n /**\n * Remove the objective from the thread, whatever the in-memory mirror holds.\n *\n * The durable record needs an agent and a thread; the legacy thread-metadata\n * key does not, so it is wiped either way — unlike {@link saveToThread}, which\n * writes nothing with an empty mirror unless {@link clear} ran. That asymmetry is deliberate: a\n * pre-migration goal must not resurface from the legacy key after a clear.\n * Like the save, this is best-effort: a failed durable delete also skips the\n * legacy wipe. A pending {@link clear} stays pending until both writes\n * succeed, so a later save retries it; loading the thread retries it once\n * and then drops it. Resolves to whether the delete landed.\n */\n async deleteFromThread(state: GoalManagerState): Promise<boolean> {\n const threadId = state.session.thread.getId();\n const agent = this.getAgent(state);\n try {\n if (agent && threadId) {\n await agent.clearObjective({ threadId });\n }\n await state.session.thread.setSetting({ key: THREAD_GOAL_KEY, value: undefined });\n this.pendingDelete = null;\n return true;\n } catch {\n // Persistence is not critical, but keep the retry scoped to the thread\n // this delete targeted so an empty save elsewhere cannot delete a goal.\n // An unknown thread would widen the retry to every thread, so keep the old scope then.\n if (threadId) this.pendingDelete = { threadId, goalId: this.pendingDelete?.goalId };\n return false;\n }\n }\n\n /**\n * Load the objective from ThreadState (called on thread switch). Falls back to\n * the legacy thread-metadata goal for threads created before this migration.\n *\n * A clear whose delete failed is retried here when it targeted this thread and\n * the stored goal is the one that was cleared; otherwise the stored goal loads,\n * so the mirror never hides a goal core is still judging. Resolves to whether\n * that retried delete landed.\n */\n async loadFromThread(state: GoalManagerState, isCurrent: () => boolean = () => true): Promise<boolean> {\n const pending = this.pendingDelete;\n const threadId = state.session.thread.getId();\n const agent = this.getAgent(state);\n let nextRecord: typeof this.record = null;\n let storedId: string | undefined;\n if (agent && threadId) {\n try {\n const record = await agent.getObjective({ threadId });\n if (record) {\n storedId = record.id;\n nextRecord = {\n ...record,\n id: record.id ?? randomUUID(),\n activeDurationMs: normalizeActiveDurationMs(record.activeDurationMs),\n };\n }\n } catch {\n // fall through to legacy metadata\n }\n }\n if (!isCurrent()) return false;\n // A goal set or cleared during the read replaced this intent; keep the newer state.\n if (pending && this.pendingDelete !== pending) return false;\n let retriedDelete = false;\n if (pending?.goalId && pending.threadId === threadId && storedId === pending.goalId) {\n retriedDelete = await this.deleteFromThread(state);\n if (retriedDelete) nextRecord = null;\n if (!isCurrent()) return false;\n }\n this.persistGoalOnNextThreadCreate = false;\n this.pendingDelete = null;\n this.threadId = threadId ?? undefined;\n this.agentId = agent?.id;\n this.record = nextRecord;\n return retriedDelete;\n }\n\n /**\n * Legacy entry point retained for thread-switch call sites that only have the\n * thread metadata available. Hydrates from a previously-persisted GoalState.\n */\n loadFromThreadMetadata(metadata: Record<string, unknown> | undefined): void {\n const saved = metadata?.[THREAD_GOAL_KEY] as Partial<GoalState> | undefined;\n this.persistGoalOnNextThreadCreate = false;\n this.pendingDelete = null;\n this.threadId = undefined;\n this.agentId = undefined;\n if (saved && saved.objective && saved.status) {\n this.record = {\n objective: saved.objective,\n status: saved.status,\n runsUsed: saved.turnsUsed ?? 0,\n activeDurationMs: normalizeActiveDurationMs(saved.activeDurationMs),\n maxRuns: saved.maxTurns ?? DEFAULT_MAX_TURNS,\n judgeModelId: saved.judgeModelId ?? '',\n ...(saved.pausedReason ? { pausedReason: saved.pausedReason } : {}),\n startedAt: saved.startedAt ? Date.parse(saved.startedAt) || Date.now() : Date.now(),\n updatedAt: Date.now(),\n id: saved.id ?? randomUUID(),\n };\n } else {\n this.record = null;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private\n // ---------------------------------------------------------------------------\n\n private getAgent(state: GoalManagerState): Agent | undefined {\n try {\n return state.controller.getCurrentAgent(state.session);\n } catch {\n return undefined;\n }\n }\n\n /** Resolve effective judge model + max runs (record value → settings default). */\n private effectiveSettings(record: GoalObjectiveRecord): { judgeModelId: string; maxTurns: number } {\n const settings = loadSettings();\n return {\n judgeModelId: record.judgeModelId ?? settings.models.goalJudgeModel ?? '',\n maxTurns: record.maxRuns ?? settings.models.goalMaxTurns ?? DEFAULT_MAX_TURNS,\n };\n }\n\n private localRecord(\n objective: string,\n judgeModelId: string,\n maxTurns: number,\n now: number,\n id: string,\n ): GoalObjectiveRecord & { id: string } {\n return {\n objective,\n status: 'active',\n runsUsed: 0,\n activeDurationMs: 0,\n maxRuns: maxTurns,\n ...(judgeModelId ? { judgeModelId } : {}),\n startedAt: now,\n updatedAt: now,\n id,\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"goal-manager.js","names":[],"sources":["../src/goal-manager.ts"],"sourcesContent":["/**\n * GoalManager — persistent cross-turn goals, backed by the Agent's native goal\n * mechanism.\n *\n * The objective lives in the durable `threadState` `'goal'` slot (via\n * `agent.setObjective`/`getObjective`/`clearObjective`/`updateObjectiveOptions`)\n * and is judged in-loop by the core goal step. This manager is a thin adapter:\n * it keeps a synchronous in-memory view of the current objective for the TUI\n * (status line, modal, keyboard shortcuts) and delegates persistence to the\n * agent. There is no standalone judge agent and no between-turn re-invocation —\n * the core goal step drives continuation and surfaces progress via `goal` stream\n * chunks.\n */\nimport { getGoalActivityDurationMs } from '@mastra/core/agent';\nimport type { Agent } from '@mastra/core/agent';\nimport type { AgentController, Session } from '@mastra/core/agent-controller';\nimport type { GoalObjectiveRecord } from '@mastra/core/storage';\nimport { loadSettings } from './onboarding/settings.js';\n\nexport interface GoalManagerState<TState extends Record<string, unknown> = Record<string, unknown>> {\n controller: AgentController<TState>;\n session: Session<TState>;\n}\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type GoalStatus = 'active' | 'paused' | 'done';\n\n/**\n * TUI-facing view of a goal. Derived from the durable {@link GoalObjectiveRecord}\n * plus the effective judge/max-runs settings, with display-only timer fields and\n * a stable `id` used to match plan-started goals.\n */\nexport interface GoalState {\n id: string;\n objective: string;\n status: GoalStatus;\n turnsUsed: number;\n maxTurns: number;\n judgeModelId: string;\n startedAt: string;\n activeStartedAt?: string;\n activeDurationMs?: number;\n /** Why the goal paused (judge failure, budget exhaustion, ...). Only set while paused. */\n pausedReason?: string;\n}\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nexport const DEFAULT_MAX_TURNS = 50;\nconst THREAD_GOAL_KEY = 'goal';\n\nfunction normalizeActiveDurationMs(value: number | undefined): number {\n return value !== undefined && Number.isFinite(value) && value >= 0 ? value : 0;\n}\n\n// =============================================================================\n// GoalManager\n// =============================================================================\n\nexport class GoalManager {\n /** Synchronous in-memory view of the active objective record (source of truth is ThreadState). */\n private record: (GoalObjectiveRecord & { id: string }) | null = null;\n private threadId: string | undefined;\n private agentId: string | undefined;\n private persistGoalOnNextThreadCreate = false;\n /**\n * Set by {@link clear} to the thread the goal was cleared on: the next save\n * with an empty mirror on that same thread deletes the goal. A goal hydrated\n * from legacy metadata has no known thread, so its clear applies to whichever\n * thread the next save runs on (the pre-existing behaviour).\n */\n private pendingDelete: { threadId: string | undefined; goalId?: string } | null = null;\n\n // ---------------------------------------------------------------------------\n // Synchronous TUI surface\n // ---------------------------------------------------------------------------\n\n getGoal(): GoalState | null {\n if (!this.record) return null;\n const { judgeModelId, maxTurns } = this.effectiveSettings(this.record);\n return {\n id: this.record.id,\n objective: this.record.objective,\n status: this.record.status,\n turnsUsed: this.record.runsUsed,\n maxTurns,\n judgeModelId,\n startedAt: new Date(this.record.startedAt).toISOString(),\n ...(this.record.pausedReason ? { pausedReason: this.record.pausedReason } : {}),\n activeDurationMs:\n this.agentId && this.threadId\n ? getGoalActivityDurationMs({\n agentId: this.agentId,\n threadId: this.threadId,\n objectiveId: this.record.id,\n activeDurationMs: this.record.activeDurationMs,\n })\n : normalizeActiveDurationMs(this.record.activeDurationMs),\n };\n }\n\n isActive(): boolean {\n return this.record?.status === 'active';\n }\n\n persistOnNextThreadCreate(): void {\n this.persistGoalOnNextThreadCreate = true;\n }\n\n consumePersistOnNextThreadCreate(): boolean {\n if (!this.persistGoalOnNextThreadCreate) return false;\n this.persistGoalOnNextThreadCreate = false;\n return true;\n }\n\n // ---------------------------------------------------------------------------\n // Objective lifecycle (ThreadState-backed via the agent)\n // ---------------------------------------------------------------------------\n\n /**\n * Set a new objective. Persists to ThreadState via `agent.setObjective` and\n * updates the in-memory view. Only the provided settings are persisted into\n * the record; unset ones fall back to the agent's `goal` config at read time.\n */\n async setGoal(\n state: GoalManagerState,\n objective: string,\n judgeModelId: string,\n maxTurns: number = DEFAULT_MAX_TURNS,\n ): Promise<GoalState | null> {\n const threadId = state.session.thread.getId();\n const agent = this.getAgent(state);\n const now = Date.now();\n const id = globalThis.crypto.randomUUID();\n this.pendingDelete = null;\n this.threadId = threadId ?? undefined;\n this.agentId = agent?.id;\n\n if (agent && threadId) {\n const persisted = await agent.setObjective(objective, {\n id,\n threadId,\n resourceId: state.session.identity.getResourceId(),\n ...(judgeModelId ? { judgeModelId } : {}),\n maxRuns: maxTurns,\n });\n this.record = persisted\n ? { ...persisted, id: persisted.id ?? id }\n : this.localRecord(objective, judgeModelId, maxTurns, now, id);\n } else {\n this.record = this.localRecord(objective, judgeModelId, maxTurns, now, id);\n }\n\n return this.getGoal();\n }\n\n /**\n * Update the judge model / max-runs defaults. Persists into the active record\n * (so the override is remembered in thread state) when a goal is set.\n */\n async updateJudgeDefaults(\n state: GoalManagerState,\n judgeModelId: string,\n maxTurns: number,\n ): Promise<GoalState | null> {\n if (!this.record) return null;\n const threadId = state.session.thread.getId();\n const agent = this.getAgent(state);\n if (agent && threadId) {\n const updated = await agent.updateObjectiveOptions({\n threadId,\n ...(judgeModelId ? { judgeModelId } : {}),\n maxRuns: maxTurns,\n });\n if (updated) this.record = { ...updated, id: this.record.id };\n } else {\n this.record = {\n ...this.record,\n ...(judgeModelId ? { judgeModelId } : {}),\n maxRuns: maxTurns,\n updatedAt: Date.now(),\n };\n }\n return this.getGoal();\n }\n\n pause(reason?: string): GoalState | null {\n if (this.record && this.record.status === 'active') {\n this.record = { ...this.record, status: 'paused', pausedReason: reason, updatedAt: Date.now() };\n }\n return this.getGoal();\n }\n\n resume(): GoalState | null {\n if (this.record && this.record.status === 'paused') {\n this.record = { ...this.record, status: 'active', pausedReason: undefined, updatedAt: Date.now() };\n }\n return this.getGoal();\n }\n\n markDone(): void {\n if (this.record) {\n this.record = { ...this.record, status: 'done', pausedReason: undefined, updatedAt: Date.now() };\n }\n }\n\n clear(): void {\n this.pendingDelete = { threadId: this.threadId, goalId: this.record?.id };\n this.record = null;\n this.threadId = undefined;\n this.agentId = undefined;\n this.persistGoalOnNextThreadCreate = false;\n }\n\n /**\n * Sync the latest objective record from ThreadState into the in-memory view.\n * Called from the `goal` stream-chunk handler after each evaluation.\n */\n applyEvaluation(update: { runsUsed: number; status: GoalStatus; pausedReason?: string }): GoalState | null {\n if (!this.record) return null;\n const pausedReason =\n update.status === 'paused'\n ? (update.pausedReason ?? (this.record.status === 'paused' ? this.record.pausedReason : undefined))\n : undefined;\n this.record = {\n ...this.record,\n runsUsed: update.runsUsed,\n status: update.status,\n // The cause lasts for one pause; leaving paused retires it.\n pausedReason,\n updatedAt: Date.now(),\n };\n return this.getGoal();\n }\n\n // ---------------------------------------------------------------------------\n // Persistence\n // ---------------------------------------------------------------------------\n\n /**\n * Persist the active objective to ThreadState via the agent. The objective\n * record is the source of truth; the legacy thread-metadata key is cleared on\n * a save that actually wrote, so stale state from older sessions cannot\n * shadow the record — and a save that wrote nothing leaves it alone.\n *\n * An empty in-memory mirror means \"I have nothing *loaded*\", which is not the\n * same statement as \"there is nothing\": the mirror is also emptied by storage\n * failures and thread switches. So a save with an empty mirror deletes the\n * goal (durable record and legacy key) only right after an explicit\n * {@link clear} on the same thread (or any thread, for a legacy-hydrated goal\n * whose thread is unknown), and is a complete no-op otherwise.\n */\n async saveToThread(state: GoalManagerState): Promise<void> {\n const threadId = state.session.thread.getId();\n const agent = this.getAgent(state);\n if (!this.record && this.pendingDelete) {\n const clearedThreadId = this.pendingDelete.threadId;\n if (clearedThreadId === undefined || clearedThreadId === threadId) {\n await this.deleteFromThread(state);\n }\n return;\n }\n try {\n if (agent && threadId) {\n if (this.record) {\n // Push the current status/options into the existing record. If no\n // record is persisted yet (e.g. first save), create one.\n const updated = await agent.updateObjectiveOptions({\n threadId,\n status: this.record.status,\n ...(this.record.pausedReason ? { pausedReason: this.record.pausedReason } : {}),\n ...(this.record.judgeModelId ? { judgeModelId: this.record.judgeModelId } : {}),\n ...(this.record.maxRuns !== undefined ? { maxRuns: this.record.maxRuns } : {}),\n });\n if (!updated) {\n // No persisted record yet: create one. `setObjective` always writes\n // `status: 'active'`, so re-apply the in-memory status afterwards if\n // the local goal was already paused/done — otherwise the resumed\n // thread state would no longer match the in-memory state.\n const desiredStatus = this.record.status;\n const created = await agent.setObjective(this.record.objective, {\n id: this.record.id,\n threadId,\n resourceId: state.session.identity.getResourceId(),\n activeDurationMs: normalizeActiveDurationMs(this.record.activeDurationMs),\n ...(this.record.judgeModelId ? { judgeModelId: this.record.judgeModelId } : {}),\n ...(this.record.maxRuns !== undefined ? { maxRuns: this.record.maxRuns } : {}),\n });\n // Nothing durable was written (no goal store, or no thread), so\n // there is no record for a legacy key to shadow — and wiping it\n // would take a pre-migration thread's only copy with it.\n if (!created) return;\n if (desiredStatus !== 'active') {\n await agent.updateObjectiveOptions({\n threadId,\n status: desiredStatus,\n ...(this.record.pausedReason ? { pausedReason: this.record.pausedReason } : {}),\n });\n }\n }\n // Clear any legacy thread-metadata goal so it can't shadow the\n // record we just wrote. Only on the path that actually wrote: on the\n // no-op path a pre-migration thread's only goal may live in that key.\n await state.session.thread.setSetting({ key: THREAD_GOAL_KEY, value: undefined });\n }\n }\n } catch {\n // Persistence is not critical.\n }\n }\n\n /**\n * Remove the objective from the thread, whatever the in-memory mirror holds.\n *\n * The durable record needs an agent and a thread; the legacy thread-metadata\n * key does not, so it is wiped either way — unlike {@link saveToThread}, which\n * writes nothing with an empty mirror unless {@link clear} ran. That asymmetry is deliberate: a\n * pre-migration goal must not resurface from the legacy key after a clear.\n * Like the save, this is best-effort: a failed durable delete also skips the\n * legacy wipe. A pending {@link clear} stays pending until both writes\n * succeed, so a later save retries it; loading the thread retries it once\n * and then drops it. Resolves to whether the delete landed.\n */\n async deleteFromThread(state: GoalManagerState): Promise<boolean> {\n const threadId = state.session.thread.getId();\n const agent = this.getAgent(state);\n try {\n if (agent && threadId) {\n await agent.clearObjective({ threadId });\n }\n await state.session.thread.setSetting({ key: THREAD_GOAL_KEY, value: undefined });\n this.pendingDelete = null;\n return true;\n } catch {\n // Persistence is not critical, but keep the retry scoped to the thread\n // this delete targeted so an empty save elsewhere cannot delete a goal.\n // An unknown thread would widen the retry to every thread, so keep the old scope then.\n if (threadId) this.pendingDelete = { threadId, goalId: this.pendingDelete?.goalId };\n return false;\n }\n }\n\n /**\n * Load the objective from ThreadState (called on thread switch). Falls back to\n * the legacy thread-metadata goal for threads created before this migration.\n *\n * A clear whose delete failed is retried here when it targeted this thread and\n * the stored goal is the one that was cleared; otherwise the stored goal loads,\n * so the mirror never hides a goal core is still judging. Resolves to whether\n * that retried delete landed.\n */\n async loadFromThread(state: GoalManagerState, isCurrent: () => boolean = () => true): Promise<boolean> {\n const pending = this.pendingDelete;\n const threadId = state.session.thread.getId();\n const agent = this.getAgent(state);\n let nextRecord: typeof this.record = null;\n let storedId: string | undefined;\n if (agent && threadId) {\n try {\n const record = await agent.getObjective({ threadId });\n if (record) {\n storedId = record.id;\n nextRecord = {\n ...record,\n id: record.id ?? globalThis.crypto.randomUUID(),\n activeDurationMs: normalizeActiveDurationMs(record.activeDurationMs),\n };\n }\n } catch {\n // fall through to legacy metadata\n }\n }\n if (!isCurrent()) return false;\n // A goal set or cleared during the read replaced this intent; keep the newer state.\n if (pending && this.pendingDelete !== pending) return false;\n let retriedDelete = false;\n if (pending?.goalId && pending.threadId === threadId && storedId === pending.goalId) {\n retriedDelete = await this.deleteFromThread(state);\n if (retriedDelete) nextRecord = null;\n if (!isCurrent()) return false;\n }\n this.persistGoalOnNextThreadCreate = false;\n this.pendingDelete = null;\n this.threadId = threadId ?? undefined;\n this.agentId = agent?.id;\n this.record = nextRecord;\n return retriedDelete;\n }\n\n /**\n * Legacy entry point retained for thread-switch call sites that only have the\n * thread metadata available. Hydrates from a previously-persisted GoalState.\n */\n loadFromThreadMetadata(metadata: Record<string, unknown> | undefined): void {\n const saved = metadata?.[THREAD_GOAL_KEY] as Partial<GoalState> | undefined;\n this.persistGoalOnNextThreadCreate = false;\n this.pendingDelete = null;\n this.threadId = undefined;\n this.agentId = undefined;\n if (saved && saved.objective && saved.status) {\n this.record = {\n objective: saved.objective,\n status: saved.status,\n runsUsed: saved.turnsUsed ?? 0,\n activeDurationMs: normalizeActiveDurationMs(saved.activeDurationMs),\n maxRuns: saved.maxTurns ?? DEFAULT_MAX_TURNS,\n judgeModelId: saved.judgeModelId ?? '',\n ...(saved.pausedReason ? { pausedReason: saved.pausedReason } : {}),\n startedAt: saved.startedAt ? Date.parse(saved.startedAt) || Date.now() : Date.now(),\n updatedAt: Date.now(),\n id: saved.id ?? globalThis.crypto.randomUUID(),\n };\n } else {\n this.record = null;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private\n // ---------------------------------------------------------------------------\n\n private getAgent(state: GoalManagerState): Agent | undefined {\n try {\n return state.controller.getCurrentAgent(state.session);\n } catch {\n return undefined;\n }\n }\n\n /** Resolve effective judge model + max runs (record value → settings default). */\n private effectiveSettings(record: GoalObjectiveRecord): { judgeModelId: string; maxTurns: number } {\n const settings = loadSettings();\n return {\n judgeModelId: record.judgeModelId ?? settings.models.goalJudgeModel ?? '',\n maxTurns: record.maxRuns ?? settings.models.goalMaxTurns ?? DEFAULT_MAX_TURNS,\n };\n }\n\n private localRecord(\n objective: string,\n judgeModelId: string,\n maxTurns: number,\n now: number,\n id: string,\n ): GoalObjectiveRecord & { id: string } {\n return {\n objective,\n status: 'active',\n runsUsed: 0,\n activeDurationMs: 0,\n maxRuns: maxTurns,\n ...(judgeModelId ? { judgeModelId } : {}),\n startedAt: now,\n updatedAt: now,\n id,\n };\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-mc.d.ts","sourceRoot":"","sources":["../../src/headless/run-mc.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,KAAK,EAAoB,YAAY,EAA4B,MAAM,YAAY,CAAC;AA0IlG;;;GAGG;AACH,wBAAgB,KAAK,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"run-mc.d.ts","sourceRoot":"","sources":["../../src/headless/run-mc.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,KAAK,EAAoB,YAAY,EAA4B,MAAM,YAAY,CAAC;AA0IlG;;;GAGG;AACH,wBAAgB,KAAK,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,KAAK,CA4SlG"}
|
package/dist/headless/run-mc.js
CHANGED
|
@@ -311,7 +311,7 @@ function runMC(options) {
|
|
|
311
311
|
const sorted = [...threads].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
|
|
312
312
|
await session.thread.switch({ threadId: sorted[0].id });
|
|
313
313
|
}
|
|
314
|
-
}
|
|
314
|
+
} else if (!thread?.clone) await session.thread.create();
|
|
315
315
|
} catch (err) {
|
|
316
316
|
return fail(`Failed to select thread: ${err.message}`);
|
|
317
317
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-mc.js","names":["#maxBuffer","#closed","#resolvers","#buffer"],"sources":["../../src/headless/run-mc.ts"],"sourcesContent":["/**\n * Core programmatic runner for MastraCode headless runs.\n *\n * `runMC` is a pure async runner: it takes an already-built `controller` +\n * `session` (from `createMastraCode(...)`), resolves run config, subscribes to\n * the session, applies a {@link ResolutionPolicy} for approvals/suspensions,\n * sends the prompt, and aggregates events into a {@link RunMCResult}.\n *\n * It never touches `process.*` and never calls `process.exit`. The returned\n * {@link MCRun} is async-iterable over controller events and also resolves to a\n * final result via `result`.\n */\nimport { isSessionStartupCancelledError } from '@mastra/core/agent-controller';\nimport type { AgentControllerEvent, Session } from '@mastra/core/agent-controller';\n\nimport { GoalManager } from '../goal-manager.js';\nimport { createGoalReminderSignal } from '../goal-signal.js';\n\nimport { autoApprovePolicy } from './policy.js';\nimport type { MCRun, ResolutionPolicy, RunMCOptions, RunMCResult, RunMCStatus } from './types.js';\n\nfunction exitCodeForStatus(status: RunMCStatus): number {\n switch (status) {\n case 'completed':\n case 'done':\n return 0;\n case 'timeout':\n return 2;\n default:\n return 1;\n }\n}\n\ninterface MutableResult {\n text: string;\n finishReason?: string;\n usage?: RunMCResult['usage'];\n toolCalls: RunMCResult['toolCalls'];\n toolResults: RunMCResult['toolResults'];\n error?: RunMCResult['error'];\n threadId?: string;\n activeAssistantMessageId?: string;\n}\n\nfunction aggregate(event: AgentControllerEvent, acc: MutableResult): void {\n switch (event.type) {\n case 'message_start':\n if (event.message.role === 'assistant') acc.activeAssistantMessageId = event.message.id;\n break;\n case 'message_update':\n if (event.event.type === 'text-delta' && event.id === acc.activeAssistantMessageId) {\n acc.text += event.event.delta;\n }\n break;\n case 'message_end':\n if (event.id === acc.activeAssistantMessageId) acc.activeAssistantMessageId = undefined;\n break;\n case 'tool_start':\n acc.toolCalls.push({ id: event.toolCallId, name: event.toolName, args: event.args });\n break;\n case 'tool_end': {\n const matching = acc.toolCalls.find(c => c.id === event.toolCallId);\n acc.toolResults.push({\n id: event.toolCallId,\n name: matching?.name ?? '',\n result: event.result,\n isError: event.isError,\n });\n break;\n }\n case 'usage_update':\n acc.usage = {\n inputTokens: event.usage.promptTokens,\n outputTokens: event.usage.completionTokens,\n totalTokens: event.usage.totalTokens,\n };\n break;\n case 'error':\n acc.error = {\n name: event.error.name,\n message: event.error.message,\n stack: event.error.stack,\n };\n break;\n }\n}\n\n/** Resolve a thread by its exact ID. Titles are not unique, so we don't match on them. */\nasync function resolveThread<TState extends Record<string, unknown>>(\n session: Session<TState>,\n threadId: string,\n): Promise<{ threadId: string } | { error: string }> {\n const threads = await session.thread.list();\n\n const byId = threads.find(t => t.id === threadId);\n if (byId) return { threadId: byId.id };\n\n return { error: `No thread found with ID \"${threadId}\"` };\n}\n\n/**\n * A simple back-pressured async queue. Events are pushed in; consumers pull via\n * the async iterator. `close()` ends iteration after draining buffered events.\n *\n * Buffered events are bounded by `maxBuffer`: if a consumer never iterates (the\n * result-only path, `await run.result` without `for await (...)`) — or simply\n * falls far behind — the oldest buffered events are dropped instead of growing\n * without limit. The aggregated {@link RunMCResult} is built independently of\n * this queue, so dropping buffered events never affects the final result.\n */\nclass EventQueue<T> {\n #buffer: T[] = [];\n #resolvers: Array<(r: IteratorResult<T>) => void> = [];\n #closed = false;\n readonly #maxBuffer: number;\n\n constructor(maxBuffer = 10_000) {\n this.#maxBuffer = maxBuffer;\n }\n\n push(value: T): void {\n if (this.#closed) return;\n const resolve = this.#resolvers.shift();\n if (resolve) {\n resolve({ value, done: false });\n return;\n }\n this.#buffer.push(value);\n if (this.#buffer.length > this.#maxBuffer) {\n // Bound memory: drop the oldest event once over the cap.\n this.#buffer.shift();\n }\n }\n\n close(): void {\n if (this.#closed) return;\n this.#closed = true;\n for (const resolve of this.#resolvers.splice(0)) {\n resolve({ value: undefined as unknown as T, done: true });\n }\n }\n\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return {\n next: (): Promise<IteratorResult<T>> => {\n if (this.#buffer.length > 0) {\n return Promise.resolve({ value: this.#buffer.shift()!, done: false });\n }\n if (this.#closed) {\n return Promise.resolve({ value: undefined as unknown as T, done: true });\n }\n return new Promise<IteratorResult<T>>(resolve => this.#resolvers.push(resolve));\n },\n };\n }\n}\n\n/**\n * Run a headless MastraCode turn. Returns an {@link MCRun} handle that is\n * async-iterable over controller events and resolves to a {@link RunMCResult}.\n */\nexport function runMC<TState extends Record<string, unknown>>(options: RunMCOptions<TState>): MCRun {\n const { controller, session } = options;\n const goal = options.goal;\n const policy: ResolutionPolicy = options.policy ?? autoApprovePolicy;\n\n const queue = new EventQueue<AgentControllerEvent>();\n const acc: MutableResult = { text: '', toolCalls: [], toolResults: [] };\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let timedOut = false;\n let aborted = false;\n let maxTurnsExceeded = false;\n let assistantTurns = 0;\n let activeAssistantMessageId: string | undefined;\n let settled = false;\n let unsubscribe: (() => void) | undefined;\n let resolveResult!: (r: RunMCResult) => void;\n\n const result = new Promise<RunMCResult>(resolve => {\n resolveResult = resolve;\n });\n\n function finish(status: RunMCStatus, data: Partial<RunMCResult> = {}): void {\n if (settled) return;\n settled = true;\n if (timeoutId) clearTimeout(timeoutId);\n unsubscribe?.();\n queue.close();\n resolveResult({\n status,\n text: acc.text,\n finishReason: acc.finishReason,\n usage: acc.usage,\n toolCalls: acc.toolCalls,\n toolResults: acc.toolResults,\n threadId: acc.threadId ?? session.thread.getId() ?? undefined,\n error: acc.error,\n exitCode: exitCodeForStatus(status),\n ...data,\n });\n }\n\n function fail(message: string, name = 'Error'): void {\n if (!acc.error) acc.error = { name, message };\n finish('error');\n }\n\n function abort(): void {\n if (settled) return;\n aborted = true;\n session.abort();\n }\n\n if (options.signal) {\n if (options.signal.aborted) {\n // Defer so the caller can attach iteration / result handlers first.\n queueMicrotask(() => abort());\n } else {\n options.signal.addEventListener('abort', () => abort(), { once: true });\n }\n }\n\n function armTimeout(): void {\n if (!options.timeoutMs || settled) return;\n if (timeoutId) clearTimeout(timeoutId);\n timeoutId = setTimeout(() => {\n timedOut = true;\n session.abort();\n if (goal) finish('timeout');\n }, options.timeoutMs);\n }\n\n // Kick off the run asynchronously so the MCRun handle is returned synchronously.\n void (async () => {\n armTimeout();\n\n // --- Config resolution (model / mode / thinking) ---\n try {\n if (options.model) {\n const available = await controller.listAvailableModels();\n const match = available.find(m => m.id === options.model);\n if (!match) return fail(`Unknown model: \"${options.model}\"`);\n if (!match.hasApiKey) {\n const keyHint = match.apiKeyEnvVar ? ` Set ${match.apiKeyEnvVar} to use this model.` : '';\n return fail(`Model \"${options.model}\" has no API key configured.${keyHint}`);\n }\n await session.model.switch({ modelId: options.model });\n } else if (options.mode) {\n const modelId = options.modeDefaults?.[options.mode];\n if (modelId) {\n const available = await controller.listAvailableModels();\n const match = available.find(m => m.id === modelId);\n if (!match) return fail(`Unknown model \"${modelId}\" configured for mode \"${options.mode}\"`);\n if (!match.hasApiKey) {\n const keyHint = match.apiKeyEnvVar ? ` Set ${match.apiKeyEnvVar} to use this model.` : '';\n return fail(`Model \"${modelId}\" (mode: ${options.mode}) has no API key configured.${keyHint}`);\n }\n await session.model.switch({ modelId });\n }\n // No configured model for mode → fall through to default (no failure).\n }\n\n if (options.thinkingLevel) {\n await session.state.set({ thinkingLevel: options.thinkingLevel } as unknown as Partial<TState>);\n }\n } catch (err) {\n return fail(`Failed to resolve run config: ${(err as Error).message}`);\n }\n\n // --- Subscribe ---\n unsubscribe = session.subscribe(event => {\n if (settled) return;\n if (goal) armTimeout();\n\n if (event.type === 'tool_approval_required') {\n let decision: 'approve' | 'deny';\n try {\n decision = policy.onToolApproval(event);\n } catch (err) {\n fail(`Resolution policy failed: ${(err as Error).message}`);\n return;\n }\n session.respondToToolApproval({\n decision: decision === 'approve' ? 'approve' : 'decline',\n toolCallId: event.toolCallId,\n });\n queue.push(event);\n return;\n }\n\n if (event.type === 'tool_suspended') {\n let outcome: ReturnType<ResolutionPolicy['onSuspension']>;\n try {\n outcome = policy.onSuspension(event);\n } catch (err) {\n fail(`Resolution policy failed: ${(err as Error).message}`);\n return;\n }\n if ('abort' in outcome) {\n queue.push(event);\n abort();\n return;\n }\n void session.respondToToolSuspension({ toolCallId: event.toolCallId, resumeData: outcome.resumeData });\n queue.push(event);\n return;\n }\n\n if (event.type === 'message_start' && event.message.role === 'assistant') {\n activeAssistantMessageId = event.message.id;\n }\n\n aggregate(event, acc);\n queue.push(event);\n\n if (event.type === 'error' && goal) {\n finish('error');\n return;\n }\n\n // Count agentic turns (one assistant response = one turn). When the cap is\n // reached, abort the run; agent_end then resolves as 'max_turns'.\n if (event.type === 'message_end' && event.id === activeAssistantMessageId && options.maxTurns !== undefined) {\n activeAssistantMessageId = undefined;\n assistantTurns += 1;\n if (assistantTurns >= options.maxTurns && !maxTurnsExceeded) {\n maxTurnsExceeded = true;\n abort();\n }\n }\n\n if (event.type === 'goal_evaluation' && goal && !event.payload.pending) {\n if (event.payload.status === 'done' || event.payload.status === 'paused') {\n finish(event.payload.status, {\n objective: goal.objective,\n goalEvent: event,\n reason: event.payload.reason ?? event.payload.results?.[0]?.reason,\n iterations: event.payload.iteration,\n maxRuns: event.payload.maxRuns,\n });\n }\n return;\n }\n\n if (event.type === 'agent_end') {\n acc.finishReason = event.reason;\n // Goal evaluations can arrive after the agent stream ends, so goal runs\n // remain active until a terminal goal_evaluation is emitted.\n if (goal) return;\n if (timedOut) {\n finish('timeout');\n } else if (event.reason === 'error') {\n finish('error');\n } else if (maxTurnsExceeded && event.reason !== 'complete') {\n // The cap forced an abort while the agent still had work to do.\n finish('max_turns');\n } else if ((event.reason === 'aborted' || aborted) && !maxTurnsExceeded) {\n finish('aborted');\n } else {\n finish('completed');\n }\n }\n });\n\n // --- Resource id ---\n try {\n if (options.resourceId) {\n await controller.setResourceId(session, { resourceId: options.resourceId });\n }\n } catch (err) {\n return fail(`Failed to set resource id: ${(err as Error).message}`);\n }\n\n // --- Thread selection ---\n try {\n const thread = options.thread;\n if (thread?.id) {\n const resolved = await resolveThread(session, thread.id);\n if ('error' in resolved) return fail(resolved.error);\n await session.thread.switch({ threadId: resolved.threadId });\n } else if (thread?.continueLatest) {\n const threads = await session.thread.list();\n if (threads.length > 0) {\n const sorted = [...threads].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());\n await session.thread.switch({ threadId: sorted[0]!.id });\n }\n }\n } catch (err) {\n return fail(`Failed to select thread: ${(err as Error).message}`);\n }\n\n // --- Clone ---\n if (options.thread?.clone) {\n try {\n await session.thread.clone();\n } catch (err) {\n return fail(`Failed to clone thread: ${(err as Error).message}`);\n }\n }\n\n // --- Title ---\n if (options.title) {\n try {\n await session.thread.rename({ title: options.title });\n } catch (err) {\n return fail(`Failed to set thread title: ${(err as Error).message}`);\n }\n }\n\n // --- Start ---\n try {\n if (goal) {\n const threadId = session.thread.getId();\n if (!threadId || !(await session.thread.getById({ threadId }))) {\n await session.thread.create();\n }\n\n const goalManager = goal.goalManager ?? new GoalManager();\n const state = {\n controller,\n session,\n goalManager,\n pendingNewThread: false,\n planStartedGoalId: undefined,\n } as any;\n const objective = await goalManager.setGoal(state, goal.objective, goal.judgeModelId, goal.maxRuns);\n if (!objective) return fail('Failed to set goal.');\n\n const agent = controller.getCurrentAgent(session);\n const persisted = await agent.getObjective({ threadId: session.thread.getId()! });\n if (!persisted || persisted.id !== objective.id) {\n return fail('Failed to persist goal objective before sending goal signal.');\n }\n\n await goalManager.saveToThread(state);\n if (!settled) await session.sendSignal(createGoalReminderSignal(objective)).accepted;\n } else {\n if (!options.prompt) return fail('A prompt or goal is required.');\n await session.sendMessage({ content: options.prompt });\n }\n } catch (err) {\n if (\n isSessionStartupCancelledError(err) ||\n (err instanceof Error && err.name === 'AbortError' && (aborted || timedOut || options.signal?.aborted))\n ) {\n return finish(timedOut ? 'timeout' : maxTurnsExceeded ? 'max_turns' : 'aborted');\n }\n return fail(`Failed to start run: ${(err as Error).message}`);\n }\n })();\n\n return {\n result,\n abort,\n [Symbol.asyncIterator](): AsyncIterator<AgentControllerEvent> {\n return queue[Symbol.asyncIterator]();\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"run-mc.js","names":["#maxBuffer","#closed","#resolvers","#buffer"],"sources":["../../src/headless/run-mc.ts"],"sourcesContent":["/**\n * Core programmatic runner for MastraCode headless runs.\n *\n * `runMC` is a pure async runner: it takes an already-built `controller` +\n * `session` (from `createMastraCode(...)`), resolves run config, subscribes to\n * the session, applies a {@link ResolutionPolicy} for approvals/suspensions,\n * sends the prompt, and aggregates events into a {@link RunMCResult}.\n *\n * It never touches `process.*` and never calls `process.exit`. The returned\n * {@link MCRun} is async-iterable over controller events and also resolves to a\n * final result via `result`.\n */\nimport { isSessionStartupCancelledError } from '@mastra/core/agent-controller';\nimport type { AgentControllerEvent, Session } from '@mastra/core/agent-controller';\n\nimport { GoalManager } from '../goal-manager.js';\nimport { createGoalReminderSignal } from '../goal-signal.js';\n\nimport { autoApprovePolicy } from './policy.js';\nimport type { MCRun, ResolutionPolicy, RunMCOptions, RunMCResult, RunMCStatus } from './types.js';\n\nfunction exitCodeForStatus(status: RunMCStatus): number {\n switch (status) {\n case 'completed':\n case 'done':\n return 0;\n case 'timeout':\n return 2;\n default:\n return 1;\n }\n}\n\ninterface MutableResult {\n text: string;\n finishReason?: string;\n usage?: RunMCResult['usage'];\n toolCalls: RunMCResult['toolCalls'];\n toolResults: RunMCResult['toolResults'];\n error?: RunMCResult['error'];\n threadId?: string;\n activeAssistantMessageId?: string;\n}\n\nfunction aggregate(event: AgentControllerEvent, acc: MutableResult): void {\n switch (event.type) {\n case 'message_start':\n if (event.message.role === 'assistant') acc.activeAssistantMessageId = event.message.id;\n break;\n case 'message_update':\n if (event.event.type === 'text-delta' && event.id === acc.activeAssistantMessageId) {\n acc.text += event.event.delta;\n }\n break;\n case 'message_end':\n if (event.id === acc.activeAssistantMessageId) acc.activeAssistantMessageId = undefined;\n break;\n case 'tool_start':\n acc.toolCalls.push({ id: event.toolCallId, name: event.toolName, args: event.args });\n break;\n case 'tool_end': {\n const matching = acc.toolCalls.find(c => c.id === event.toolCallId);\n acc.toolResults.push({\n id: event.toolCallId,\n name: matching?.name ?? '',\n result: event.result,\n isError: event.isError,\n });\n break;\n }\n case 'usage_update':\n acc.usage = {\n inputTokens: event.usage.promptTokens,\n outputTokens: event.usage.completionTokens,\n totalTokens: event.usage.totalTokens,\n };\n break;\n case 'error':\n acc.error = {\n name: event.error.name,\n message: event.error.message,\n stack: event.error.stack,\n };\n break;\n }\n}\n\n/** Resolve a thread by its exact ID. Titles are not unique, so we don't match on them. */\nasync function resolveThread<TState extends Record<string, unknown>>(\n session: Session<TState>,\n threadId: string,\n): Promise<{ threadId: string } | { error: string }> {\n const threads = await session.thread.list();\n\n const byId = threads.find(t => t.id === threadId);\n if (byId) return { threadId: byId.id };\n\n return { error: `No thread found with ID \"${threadId}\"` };\n}\n\n/**\n * A simple back-pressured async queue. Events are pushed in; consumers pull via\n * the async iterator. `close()` ends iteration after draining buffered events.\n *\n * Buffered events are bounded by `maxBuffer`: if a consumer never iterates (the\n * result-only path, `await run.result` without `for await (...)`) — or simply\n * falls far behind — the oldest buffered events are dropped instead of growing\n * without limit. The aggregated {@link RunMCResult} is built independently of\n * this queue, so dropping buffered events never affects the final result.\n */\nclass EventQueue<T> {\n #buffer: T[] = [];\n #resolvers: Array<(r: IteratorResult<T>) => void> = [];\n #closed = false;\n readonly #maxBuffer: number;\n\n constructor(maxBuffer = 10_000) {\n this.#maxBuffer = maxBuffer;\n }\n\n push(value: T): void {\n if (this.#closed) return;\n const resolve = this.#resolvers.shift();\n if (resolve) {\n resolve({ value, done: false });\n return;\n }\n this.#buffer.push(value);\n if (this.#buffer.length > this.#maxBuffer) {\n // Bound memory: drop the oldest event once over the cap.\n this.#buffer.shift();\n }\n }\n\n close(): void {\n if (this.#closed) return;\n this.#closed = true;\n for (const resolve of this.#resolvers.splice(0)) {\n resolve({ value: undefined as unknown as T, done: true });\n }\n }\n\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return {\n next: (): Promise<IteratorResult<T>> => {\n if (this.#buffer.length > 0) {\n return Promise.resolve({ value: this.#buffer.shift()!, done: false });\n }\n if (this.#closed) {\n return Promise.resolve({ value: undefined as unknown as T, done: true });\n }\n return new Promise<IteratorResult<T>>(resolve => this.#resolvers.push(resolve));\n },\n };\n }\n}\n\n/**\n * Run a headless MastraCode turn. Returns an {@link MCRun} handle that is\n * async-iterable over controller events and resolves to a {@link RunMCResult}.\n */\nexport function runMC<TState extends Record<string, unknown>>(options: RunMCOptions<TState>): MCRun {\n const { controller, session } = options;\n const goal = options.goal;\n const policy: ResolutionPolicy = options.policy ?? autoApprovePolicy;\n\n const queue = new EventQueue<AgentControllerEvent>();\n const acc: MutableResult = { text: '', toolCalls: [], toolResults: [] };\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let timedOut = false;\n let aborted = false;\n let maxTurnsExceeded = false;\n let assistantTurns = 0;\n let activeAssistantMessageId: string | undefined;\n let settled = false;\n let unsubscribe: (() => void) | undefined;\n let resolveResult!: (r: RunMCResult) => void;\n\n const result = new Promise<RunMCResult>(resolve => {\n resolveResult = resolve;\n });\n\n function finish(status: RunMCStatus, data: Partial<RunMCResult> = {}): void {\n if (settled) return;\n settled = true;\n if (timeoutId) clearTimeout(timeoutId);\n unsubscribe?.();\n queue.close();\n resolveResult({\n status,\n text: acc.text,\n finishReason: acc.finishReason,\n usage: acc.usage,\n toolCalls: acc.toolCalls,\n toolResults: acc.toolResults,\n threadId: acc.threadId ?? session.thread.getId() ?? undefined,\n error: acc.error,\n exitCode: exitCodeForStatus(status),\n ...data,\n });\n }\n\n function fail(message: string, name = 'Error'): void {\n if (!acc.error) acc.error = { name, message };\n finish('error');\n }\n\n function abort(): void {\n if (settled) return;\n aborted = true;\n session.abort();\n }\n\n if (options.signal) {\n if (options.signal.aborted) {\n // Defer so the caller can attach iteration / result handlers first.\n queueMicrotask(() => abort());\n } else {\n options.signal.addEventListener('abort', () => abort(), { once: true });\n }\n }\n\n function armTimeout(): void {\n if (!options.timeoutMs || settled) return;\n if (timeoutId) clearTimeout(timeoutId);\n timeoutId = setTimeout(() => {\n timedOut = true;\n session.abort();\n if (goal) finish('timeout');\n }, options.timeoutMs);\n }\n\n // Kick off the run asynchronously so the MCRun handle is returned synchronously.\n void (async () => {\n armTimeout();\n\n // --- Config resolution (model / mode / thinking) ---\n try {\n if (options.model) {\n const available = await controller.listAvailableModels();\n const match = available.find(m => m.id === options.model);\n if (!match) return fail(`Unknown model: \"${options.model}\"`);\n if (!match.hasApiKey) {\n const keyHint = match.apiKeyEnvVar ? ` Set ${match.apiKeyEnvVar} to use this model.` : '';\n return fail(`Model \"${options.model}\" has no API key configured.${keyHint}`);\n }\n await session.model.switch({ modelId: options.model });\n } else if (options.mode) {\n const modelId = options.modeDefaults?.[options.mode];\n if (modelId) {\n const available = await controller.listAvailableModels();\n const match = available.find(m => m.id === modelId);\n if (!match) return fail(`Unknown model \"${modelId}\" configured for mode \"${options.mode}\"`);\n if (!match.hasApiKey) {\n const keyHint = match.apiKeyEnvVar ? ` Set ${match.apiKeyEnvVar} to use this model.` : '';\n return fail(`Model \"${modelId}\" (mode: ${options.mode}) has no API key configured.${keyHint}`);\n }\n await session.model.switch({ modelId });\n }\n // No configured model for mode → fall through to default (no failure).\n }\n\n if (options.thinkingLevel) {\n await session.state.set({ thinkingLevel: options.thinkingLevel } as unknown as Partial<TState>);\n }\n } catch (err) {\n return fail(`Failed to resolve run config: ${(err as Error).message}`);\n }\n\n // --- Subscribe ---\n unsubscribe = session.subscribe(event => {\n if (settled) return;\n if (goal) armTimeout();\n\n if (event.type === 'tool_approval_required') {\n let decision: 'approve' | 'deny';\n try {\n decision = policy.onToolApproval(event);\n } catch (err) {\n fail(`Resolution policy failed: ${(err as Error).message}`);\n return;\n }\n session.respondToToolApproval({\n decision: decision === 'approve' ? 'approve' : 'decline',\n toolCallId: event.toolCallId,\n });\n queue.push(event);\n return;\n }\n\n if (event.type === 'tool_suspended') {\n let outcome: ReturnType<ResolutionPolicy['onSuspension']>;\n try {\n outcome = policy.onSuspension(event);\n } catch (err) {\n fail(`Resolution policy failed: ${(err as Error).message}`);\n return;\n }\n if ('abort' in outcome) {\n queue.push(event);\n abort();\n return;\n }\n void session.respondToToolSuspension({ toolCallId: event.toolCallId, resumeData: outcome.resumeData });\n queue.push(event);\n return;\n }\n\n if (event.type === 'message_start' && event.message.role === 'assistant') {\n activeAssistantMessageId = event.message.id;\n }\n\n aggregate(event, acc);\n queue.push(event);\n\n if (event.type === 'error' && goal) {\n finish('error');\n return;\n }\n\n // Count agentic turns (one assistant response = one turn). When the cap is\n // reached, abort the run; agent_end then resolves as 'max_turns'.\n if (event.type === 'message_end' && event.id === activeAssistantMessageId && options.maxTurns !== undefined) {\n activeAssistantMessageId = undefined;\n assistantTurns += 1;\n if (assistantTurns >= options.maxTurns && !maxTurnsExceeded) {\n maxTurnsExceeded = true;\n abort();\n }\n }\n\n if (event.type === 'goal_evaluation' && goal && !event.payload.pending) {\n if (event.payload.status === 'done' || event.payload.status === 'paused') {\n finish(event.payload.status, {\n objective: goal.objective,\n goalEvent: event,\n reason: event.payload.reason ?? event.payload.results?.[0]?.reason,\n iterations: event.payload.iteration,\n maxRuns: event.payload.maxRuns,\n });\n }\n return;\n }\n\n if (event.type === 'agent_end') {\n acc.finishReason = event.reason;\n // Goal evaluations can arrive after the agent stream ends, so goal runs\n // remain active until a terminal goal_evaluation is emitted.\n if (goal) return;\n if (timedOut) {\n finish('timeout');\n } else if (event.reason === 'error') {\n finish('error');\n } else if (maxTurnsExceeded && event.reason !== 'complete') {\n // The cap forced an abort while the agent still had work to do.\n finish('max_turns');\n } else if ((event.reason === 'aborted' || aborted) && !maxTurnsExceeded) {\n finish('aborted');\n } else {\n finish('completed');\n }\n }\n });\n\n // --- Resource id ---\n try {\n if (options.resourceId) {\n await controller.setResourceId(session, { resourceId: options.resourceId });\n }\n } catch (err) {\n return fail(`Failed to set resource id: ${(err as Error).message}`);\n }\n\n // --- Thread selection ---\n try {\n const thread = options.thread;\n if (thread?.id) {\n const resolved = await resolveThread(session, thread.id);\n if ('error' in resolved) return fail(resolved.error);\n await session.thread.switch({ threadId: resolved.threadId });\n } else if (thread?.continueLatest) {\n const threads = await session.thread.list();\n if (threads.length > 0) {\n const sorted = [...threads].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());\n await session.thread.switch({ threadId: sorted[0]!.id });\n }\n } else if (!thread?.clone) {\n await session.thread.create();\n }\n } catch (err) {\n return fail(`Failed to select thread: ${(err as Error).message}`);\n }\n\n // --- Clone ---\n if (options.thread?.clone) {\n try {\n await session.thread.clone();\n } catch (err) {\n return fail(`Failed to clone thread: ${(err as Error).message}`);\n }\n }\n\n // --- Title ---\n if (options.title) {\n try {\n await session.thread.rename({ title: options.title });\n } catch (err) {\n return fail(`Failed to set thread title: ${(err as Error).message}`);\n }\n }\n\n // --- Start ---\n try {\n if (goal) {\n const threadId = session.thread.getId();\n if (!threadId || !(await session.thread.getById({ threadId }))) {\n await session.thread.create();\n }\n\n const goalManager = goal.goalManager ?? new GoalManager();\n const state = {\n controller,\n session,\n goalManager,\n pendingNewThread: false,\n planStartedGoalId: undefined,\n } as any;\n const objective = await goalManager.setGoal(state, goal.objective, goal.judgeModelId, goal.maxRuns);\n if (!objective) return fail('Failed to set goal.');\n\n const agent = controller.getCurrentAgent(session);\n const persisted = await agent.getObjective({ threadId: session.thread.getId()! });\n if (!persisted || persisted.id !== objective.id) {\n return fail('Failed to persist goal objective before sending goal signal.');\n }\n\n await goalManager.saveToThread(state);\n if (!settled) await session.sendSignal(createGoalReminderSignal(objective)).accepted;\n } else {\n if (!options.prompt) return fail('A prompt or goal is required.');\n await session.sendMessage({ content: options.prompt });\n }\n } catch (err) {\n if (\n isSessionStartupCancelledError(err) ||\n (err instanceof Error && err.name === 'AbortError' && (aborted || timedOut || options.signal?.aborted))\n ) {\n return finish(timedOut ? 'timeout' : maxTurnsExceeded ? 'max_turns' : 'aborted');\n }\n return fail(`Failed to start run: ${(err as Error).message}`);\n }\n })();\n\n return {\n result,\n abort,\n [Symbol.asyncIterator](): AsyncIterator<AgentControllerEvent> {\n return queue[Symbol.asyncIterator]();\n },\n };\n}\n"],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EACV,eAAe,EACf,qBAAqB,EAErB,mBAAmB,EACnB,uBAAuB,EAEvB,OAAO,EACR,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGlD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { AuthStorage } from "./auth/storage.js";
|
|
|
5
5
|
import { setAuthStorage } from "./providers/openai-codex.js";
|
|
6
6
|
import { getAvailableModePacks, getAvailableOmPacks, selectPreferredOMPack } from "./onboarding/packs.js";
|
|
7
7
|
import { MASTRA_GATEWAY_PROVIDER, OBSERVABILITY_AUTH_PREFIX, THREAD_ACTIVE_MODEL_PACK_ID_KEY, loadSettings, resolveModelDefaults, resolveOmRoleModel, saveSettings } from "./onboarding/settings.js";
|
|
8
|
+
import { resolveExperimentalAgent, validateExperimentalAgent, wrapExperimentalAgent } from "./experimental-agent.js";
|
|
8
9
|
import { createSessionThreadAdvertisement } from "./agent-connections/session-advertisement.js";
|
|
9
10
|
import { AgentConnectionsSignalProvider } from "./agent-connections/signal-provider.js";
|
|
10
11
|
import { createBackgroundCompletionEvents } from "./agents/background-completion-events.js";
|
|
@@ -70,10 +71,10 @@ import { createHash } from "crypto";
|
|
|
70
71
|
import { readFile } from "fs/promises";
|
|
71
72
|
import { AgentController } from "@mastra/core/agent-controller";
|
|
72
73
|
import { createCodingAgent } from "@mastra/core/coding-agent";
|
|
73
|
-
import { PROVIDER_REGISTRY } from "@mastra/core/llm";
|
|
74
|
+
import { PROVIDER_REGISTRY, findGatewayForModel, getGatewayId } from "@mastra/core/llm";
|
|
74
75
|
import { Mastra } from "@mastra/core/mastra";
|
|
75
76
|
import { defaultNotificationDeliveryDecision } from "@mastra/core/notifications";
|
|
76
|
-
import { AgentsMDInjector, CyberRefusalHandler,
|
|
77
|
+
import { AgentsMDInjector, CyberRefusalHandler, ProviderHistoryCompat, StreamErrorRetryProcessor, createBackgroundWorkSignalProcessor, isBadRequestError } from "@mastra/core/processors";
|
|
77
78
|
import { RequestContext } from "@mastra/core/request-context";
|
|
78
79
|
import { TaskSignalProvider } from "@mastra/core/signals";
|
|
79
80
|
import { InMemoryHarness, MastraCompositeStore } from "@mastra/core/storage";
|
|
@@ -226,6 +227,15 @@ function resolveInjectedStorageBackend(storage, configuredBackend) {
|
|
|
226
227
|
if (storage instanceof PostgresStore || hasAncestorClassNamed(storage, "PostgresStore")) return "pg";
|
|
227
228
|
throw new Error("storageBackend is required when injecting a custom storage instance.");
|
|
228
229
|
}
|
|
230
|
+
/** Whether the model router would resolve `modelId` through a gateway outside `sdkGatewayIds`. */
|
|
231
|
+
function routesToOtherGateway(modelId, gateways, sdkGatewayIds) {
|
|
232
|
+
try {
|
|
233
|
+
return !sdkGatewayIds.has(getGatewayId(findGatewayForModel(modelId, gateways)));
|
|
234
|
+
} catch (error) {
|
|
235
|
+
if (error?.id === "MODEL_ROUTER_NO_GATEWAY_FOUND") return false;
|
|
236
|
+
throw error;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
229
239
|
async function createMastraCodeAgentController(config) {
|
|
230
240
|
const cwd = config?.cwd ?? process.cwd();
|
|
231
241
|
const homeDir = config?.homeDir ?? config?.initialState?.homeDir;
|
|
@@ -238,6 +248,7 @@ async function createMastraCodeAgentController(config) {
|
|
|
238
248
|
} catch {}
|
|
239
249
|
const authStorage = createAuthStorage();
|
|
240
250
|
const globalSettings = loadSettings(config?.settingsPath);
|
|
251
|
+
const experimentalAgent = resolveExperimentalAgent(globalSettings);
|
|
241
252
|
const backgroundToolsEnabled = globalSettings.backgroundTools?.enabled ?? false;
|
|
242
253
|
const storedGatewayKey = authStorage.getStoredApiKey(MASTRA_GATEWAY_PROVIDER);
|
|
243
254
|
const storedGatewayUrl = globalSettings.memoryGateway?.baseUrl;
|
|
@@ -562,8 +573,7 @@ async function createMastraCodeAgentController(config) {
|
|
|
562
573
|
const projectPath = state?.projectPath ?? project.rootPath;
|
|
563
574
|
return getStaticallyLoadedInstructionPaths(projectPath, void 0, state?.untrustedCheckout === true && typeof state?.baseRef === "string" ? createGitRefInstructionReader(projectPath, state.baseRef) : void 0);
|
|
564
575
|
}
|
|
565
|
-
})
|
|
566
|
-
new ProviderHistoryCompat()
|
|
576
|
+
})
|
|
567
577
|
];
|
|
568
578
|
const taskSignalProvider = new TaskSignalProvider();
|
|
569
579
|
const agentConnectionsSignalProvider = useCrossAgentSignals ? new AgentConnectionsSignalProvider(config?.agentConnections) : void 0;
|
|
@@ -597,7 +607,7 @@ async function createMastraCodeAgentController(config) {
|
|
|
597
607
|
return NO_PLUGIN_PROCESSORS;
|
|
598
608
|
}
|
|
599
609
|
};
|
|
600
|
-
const codeAgent = createCodingAgent({
|
|
610
|
+
const codeAgent = wrapExperimentalAgent(createCodingAgent({
|
|
601
611
|
id: CODE_AGENT_ID,
|
|
602
612
|
name: "Code Agent",
|
|
603
613
|
workspace: void 0,
|
|
@@ -687,7 +697,6 @@ async function createMastraCodeAgentController(config) {
|
|
|
687
697
|
onRetry: ({ error, retryCount, delayMs, requestContext }) => emitTransientRetry(error, retryCount, delayMs, requestContext)
|
|
688
698
|
}
|
|
689
699
|
] }),
|
|
690
|
-
new PrefillErrorHandler(),
|
|
691
700
|
new AccountRotationProcessor({
|
|
692
701
|
credentialStore: authStorage,
|
|
693
702
|
maxProcessorRetries: MASTRACODE_MAX_PROCESSOR_RETRIES,
|
|
@@ -695,7 +704,7 @@ async function createMastraCodeAgentController(config) {
|
|
|
695
704
|
})
|
|
696
705
|
],
|
|
697
706
|
maxProcessorRetries: MASTRACODE_MAX_PROCESSOR_RETRIES
|
|
698
|
-
});
|
|
707
|
+
}), experimentalAgent);
|
|
699
708
|
const defaultModes = [
|
|
700
709
|
{
|
|
701
710
|
...buildMode,
|
|
@@ -813,6 +822,11 @@ async function createMastraCodeAgentController(config) {
|
|
|
813
822
|
stateSchema: typedStateSchema,
|
|
814
823
|
agent: codeAgent,
|
|
815
824
|
subagents,
|
|
825
|
+
resolveSubagentModel: (modelId, { requestContext }) => routesToOtherGateway(modelId, Object.values(controller.getMastra()?.listGateways() ?? {}), /* @__PURE__ */ new Set([
|
|
826
|
+
mastraCodeGateway.id,
|
|
827
|
+
amazonBedrockGateway.id,
|
|
828
|
+
"models.dev"
|
|
829
|
+
])) ? modelId : resolveModel(modelId, { requestContext }),
|
|
816
830
|
gateways: [amazonBedrockGateway, mastraCodeGateway],
|
|
817
831
|
workspace: config?.workspace ?? ((args) => getDynamicWorkspace({
|
|
818
832
|
...args,
|
|
@@ -1008,6 +1022,7 @@ async function bootLocalAgentController(config) {
|
|
|
1008
1022
|
const base = await createMastraCodeAgentController(config);
|
|
1009
1023
|
const { controller, sessionId, ownerId, projectPath, codeAgent, mcpManager } = base;
|
|
1010
1024
|
await controller.init();
|
|
1025
|
+
validateExperimentalAgent(codeAgent, controller.getMastra());
|
|
1011
1026
|
const mastra = controller.getMastra();
|
|
1012
1027
|
if (mastra) await registerWorkflowBuilderPrimitives(mastra, {
|
|
1013
1028
|
projectPath,
|
|
@@ -1103,6 +1118,7 @@ async function prepareAgentControllerMount(config) {
|
|
|
1103
1118
|
};
|
|
1104
1119
|
const finalize = async () => {
|
|
1105
1120
|
await controller.init();
|
|
1121
|
+
validateExperimentalAgent(codeAgent, controller.getMastra());
|
|
1106
1122
|
if (weOwnTheMastra) {
|
|
1107
1123
|
const mastra = controller.getMastra();
|
|
1108
1124
|
if (mastra) await registerWorkflowBuilderPrimitives(mastra, {
|