@mastra/factory 0.21.0-alpha.5 → 0.21.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +2 -0
- package/dist/factory.js.map +1 -1
- package/dist/integrations/github/rules.d.ts +0 -7
- package/dist/integrations/github/rules.d.ts.map +1 -1
- package/dist/integrations/github/rules.js +14 -3
- package/dist/integrations/github/rules.js.map +1 -1
- package/dist/integrations/gitlab/rules.d.ts.map +1 -1
- package/dist/integrations/gitlab/rules.js +17 -3
- package/dist/integrations/gitlab/rules.js.map +1 -1
- package/dist/integrations/incidentio/rules.d.ts.map +1 -1
- package/dist/integrations/incidentio/rules.js +14 -3
- package/dist/integrations/incidentio/rules.js.map +1 -1
- package/dist/integrations/jira/rules.d.ts.map +1 -1
- package/dist/integrations/jira/rules.js +14 -3
- package/dist/integrations/jira/rules.js.map +1 -1
- package/dist/integrations/linear/rules.d.ts.map +1 -1
- package/dist/integrations/linear/rules.js +14 -3
- package/dist/integrations/linear/rules.js.map +1 -1
- package/dist/routes/automation-runs.d.ts.map +1 -1
- package/dist/routes/automation-runs.js +4 -1
- package/dist/routes/automation-runs.js.map +1 -1
- package/dist/routes/config.d.ts +6 -0
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +30 -2
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/surface.d.ts +2 -0
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +1 -0
- package/dist/routes/surface.js.map +1 -1
- package/dist/rules/dispatcher.d.ts.map +1 -1
- package/dist/rules/dispatcher.js +1 -0
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/storage/domains/work-items/base.d.ts +4 -0
- package/dist/storage/domains/work-items/base.d.ts.map +1 -1
- package/dist/storage/domains/work-items/base.js +4 -4
- package/dist/storage/domains/work-items/base.js.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"automation-runs.js","names":["#resolveScope","#resolveProject","#writeAudit"],"sources":["../../src/routes/automation-runs.ts"],"sourcesContent":["/**\n * Mastra `apiRoutes` for trusted external orchestrators to enqueue an\n * idempotent, deferred skill dispatch against a Factory work item.\n *\n * The endpoint is a constrained ingress in front of\n * `WorkItemsStorage.commitRuleEvaluation()`: it commits exactly one\n * `invokeSkill` decision, stamps a non-human system actor, and leaves\n * execution (session creation, auto-run/approval policy, retry, restart\n * recovery) to the `FactoryDecisionDispatcher`.\n *\n * Idempotency: the `requestId` becomes the ingress identity, so replaying the\n * same request returns the prior result without inserting a second decision.\n * Tenant-mode callers must administer the organization; local (no-auth)\n * deployments run under the shared `local` storage scope without inventing a\n * tenant user.\n */\n\nimport type { ApiRoute } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { Context } from 'hono';\n\nimport type { AuditAction } from '../storage/domains/audit/actions.js';\nimport type { AuditTarget } from '../storage/domains/audit/base.js';\nimport type { AuditEmitter, AuditRecorder } from '../storage/domains/audit/domain.js';\nimport { auditRequestContext } from '../storage/domains/audit/domain.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type { WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport { FACTORY_ROUTE_CONTRACTS } from './contracts.js';\nimport { Route } from './route.js';\nimport type { RouteDependencies } from './route.js';\n\nfunction loose(c: unknown): Context {\n return c as Context;\n}\n\n/** The invokeSkill payload this route commits, matched against a prior replay. */\ninterface AutomationInvokeSkillDecision {\n type: 'invokeSkill';\n idempotencyKey: string;\n role: string;\n skillName: string;\n arguments?: string;\n}\n\n/**\n * Whether a replayed rule-evaluation record describes the SAME operation as the\n * current request. `commitRuleEvaluation` keys idempotency on `(org, project,\n * ingress identity)` alone, so a reused `requestId` replays regardless of the\n * work item or decision payload. We reconstruct the prior `invokeSkill`\n * decision from the stored result and compare the item id, role, skill, and\n * arguments; any divergence is a collision, not a legitimate retry.\n */\nfunction replayMatchesRequest(\n result: { itemId?: string | null; decisions?: unknown[] },\n itemId: string,\n request: AutomationInvokeSkillDecision,\n): boolean {\n if (result.itemId != null && result.itemId !== itemId) return false;\n const decisions = Array.isArray(result.decisions) ? result.decisions : [];\n const prior = decisions.find(\n (candidate): candidate is Record<string, unknown> =>\n typeof candidate === 'object' &&\n candidate !== null &&\n (candidate as Record<string, unknown>).type === 'invokeSkill' &&\n (candidate as Record<string, unknown>).idempotencyKey === request.idempotencyKey,\n );\n if (!prior) return false;\n return (\n prior.role === request.role &&\n prior.skillName === request.skillName &&\n (prior.arguments ?? undefined) === (request.arguments ?? undefined)\n );\n}\n\nexport interface AutomationRunRoutesDeps extends RouteDependencies {\n audit: AuditEmitter & AuditRecorder;\n /** Factory projects domain — validates the `:id` project belongs to the caller's org. */\n projects: FactoryProjectsStorage;\n /** Work-items domain backing `commitRuleEvaluation`. */\n workItems: WorkItemsStorage;\n /** Config version stamped on the committed rule evaluation. */\n configVersion: string;\n}\n\n/** Resolved ingress scope for an automation-run request. */\ninterface AutomationRunScope {\n orgId: string;\n userId: string;\n factoryProjectId: string;\n}\n\nexport class AutomationRunRoutes extends Route<AutomationRunRoutesDeps> {\n /**\n * Resolve the `(orgId, userId)` ingress scope. Tenant mode requires a\n * signed-in organization administrator; local (no-auth) mode runs under the\n * shared `local` scope without inventing a user.\n */\n async #resolveScope(c: Context): Promise<{ orgId: string; userId: string } | { response: Response }> {\n const { auth } = this.deps;\n if (!auth.enabled()) {\n return { orgId: 'local', userId: 'local' };\n }\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant) return { response: c.json({ error: 'unauthorized' }, 401) };\n if (!tenant.orgId) {\n return {\n response: c.json(\n { error: 'organization_required', message: 'The Factory board requires an organization.' },\n 403,\n ),\n };\n }\n if (!(await auth.isOrganizationAdmin(c, tenant.orgId))) {\n return {\n response: c.json(\n { error: 'forbidden', message: 'Organization administrator access is required for automation ingress.' },\n 403,\n ),\n };\n }\n return { orgId: tenant.orgId, userId: tenant.userId };\n }\n\n /** Resolve the ingress scope AND the org-owned project from the `:id` param. */\n async #resolveProject(c: Context): Promise<AutomationRunScope | { response: Response }> {\n const scope = await this.#resolveScope(c);\n if ('response' in scope) return scope;\n\n const parsedPath = FACTORY_ROUTE_CONTRACTS.projectGet.pathSchema.safeParse({ id: c.req.param('id') });\n if (!parsedPath.success) {\n return { response: c.json({ error: 'Project not found' }, 404) };\n }\n const { projects } = this.deps;\n await projects.ensureReady();\n const project = await projects.get({ orgId: scope.orgId, id: parsedPath.data.id });\n if (!project) {\n return { response: c.json({ error: 'Project not found' }, 404) };\n }\n return { ...scope, factoryProjectId: parsedPath.data.id };\n }\n\n /**\n * Persist an audit event under the ingress-resolved scope. This route can run\n * under the synthetic `local` no-auth scope, where the tenant-gated\n * `audit.emit()` derives no org from the request and drops the event; writing\n * through `record()` with the explicit org + system actor keeps traceability\n * in every deployment mode.\n *\n * The `idempotencyKey` (`<action>:<requestId>`) makes the audit write itself\n * idempotent: replaying the same request re-enters this path, but the trail\n * keeps a single event per requestId instead of one duplicate per retry.\n */\n async #writeAudit(\n c: Context,\n scope: AutomationRunScope,\n action: AuditAction,\n requestId: string,\n targets: AuditTarget[],\n metadata: Record<string, unknown>,\n ): Promise<void> {\n await this.deps.audit.record({\n idempotencyKey: `${action}:${requestId}`,\n orgId: scope.orgId,\n actorId: 'factory-external-orchestrator',\n actorType: 'system',\n action,\n targets,\n metadata,\n factoryProjectId: scope.factoryProjectId,\n context: auditRequestContext(c),\n });\n }\n\n routes(): ApiRoute[] {\n const { workItems, configVersion } = this.deps;\n const contract = FACTORY_ROUTE_CONTRACTS.workItemAutomationRun;\n\n return [\n registerApiRoute(contract.path, {\n method: contract.method,\n handler: async c => {\n const context = loose(c);\n const resolved = await this.#resolveProject(context);\n if ('response' in resolved) return resolved.response;\n\n const parsedPath = contract.pathSchema.safeParse({\n id: c.req.param('id'),\n workItemId: c.req.param('workItemId'),\n });\n if (!parsedPath.success) return c.json({ error: 'Work item not found' }, 404);\n\n const body = await c.req.json().catch(() => undefined);\n if (body === undefined) return c.json({ error: 'Invalid JSON body' }, 400);\n const parsed = contract.bodySchema.safeParse(body);\n if (!parsed.success) return c.json({ error: 'invalid_automation_run_request' }, 400);\n const request = parsed.data as {\n requestId: string;\n expectedRevision: number;\n role: string;\n skillName: string;\n arguments?: string;\n };\n\n const item = await workItems.getForProject(\n resolved.orgId,\n resolved.factoryProjectId,\n (parsedPath.data as { workItemId: string }).workItemId,\n );\n if (!item) return c.json({ error: 'Work item not found' }, 404);\n\n const idempotencyKey = `external-orchestrator:${request.requestId}`;\n const decision = {\n type: 'invokeSkill' as const,\n idempotencyKey,\n role: request.role,\n skillName: request.skillName,\n ...(request.arguments !== undefined ? { arguments: request.arguments } : {}),\n };\n\n const now = new Date();\n const commit = await workItems.commitRuleEvaluation({\n orgId: resolved.orgId,\n factoryProjectId: resolved.factoryProjectId,\n workItemId: item.id,\n ingress: { identity: idempotencyKey, triggerType: 'external-orchestrator.invoke-skill' },\n configVersion,\n expectedRevision: request.expectedRevision,\n actor: { type: 'system', id: 'factory-external-orchestrator' },\n outcome: { status: 'accepted' },\n decisions: [decision],\n causalChain: [],\n now,\n });\n\n if (commit.status === 'missing') return c.json({ error: 'Work item not found' }, 404);\n\n const result = commit.result as {\n status?: string;\n code?: string;\n itemId?: string | null;\n decisions?: unknown[];\n };\n const resultStatus = result.status ?? 'accepted';\n const code = typeof result.code === 'string' ? result.code : undefined;\n const targets = [{ type: 'work_item' as const, id: item.id, name: item.title }];\n\n const auditMetadata = {\n requestId: request.requestId,\n role: request.role,\n skillName: request.skillName,\n commitStatus: commit.status,\n resultStatus,\n ...(code ? { code } : {}),\n };\n\n // A replay only means \"this request was already committed\" — it must\n // be the SAME operation. If the caller reused a requestId against a\n // different work item, role, skill, or arguments, returning\n // `replayed` would report durable success for work that was never\n // enqueued. Reject the collision instead of silently swallowing it.\n if (commit.status === 'replayed' && !replayMatchesRequest(result, item.id, decision)) {\n await this.#writeAudit(context, resolved, 'factory.run.rejected', request.requestId, targets, {\n ...auditMetadata,\n resultStatus: 'rejected',\n code: 'request_id_conflict',\n });\n return c.json(\n {\n status: 'rejected',\n code: 'request_id_conflict',\n requestId: request.requestId,\n },\n 409,\n );\n }\n\n if (resultStatus === 'accepted') {\n await this.#writeAudit(context, resolved, 'factory.run.queued', request.requestId, targets, auditMetadata);\n return c.json(\n { status: commit.status === 'replayed' ? 'replayed' : 'committed', requestId: request.requestId },\n commit.status === 'replayed' ? 200 : 202,\n );\n }\n\n await this.#writeAudit(context, resolved, 'factory.run.rejected', request.requestId, targets, auditMetadata);\n return c.json(\n { status: 'rejected', ...(code ? { code } : {}), requestId: request.requestId },\n code === 'stale' ? 409 : 422,\n );\n },\n }),\n ];\n }\n}\n\nexport function buildAutomationRunRoutes(deps: AutomationRunRoutesDeps): ApiRoute[] {\n return new AutomationRunRoutes(deps).routes();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"automation-runs.js","names":["#resolveScope","#resolveProject","#writeAudit"],"sources":["../../src/routes/automation-runs.ts"],"sourcesContent":["/**\n * Mastra `apiRoutes` for trusted external orchestrators to enqueue an\n * idempotent, deferred skill dispatch against a Factory work item.\n *\n * The endpoint is a constrained ingress in front of\n * `WorkItemsStorage.commitRuleEvaluation()`: it commits exactly one\n * `invokeSkill` decision, stamps a non-human system actor, and leaves\n * execution (session creation, auto-run/approval policy, retry, restart\n * recovery) to the `FactoryDecisionDispatcher`.\n *\n * Idempotency: the `requestId` becomes the ingress identity, so replaying the\n * same request returns the prior result without inserting a second decision.\n * Tenant-mode callers must administer the organization; local (no-auth)\n * deployments run under the shared `local` storage scope without inventing a\n * tenant user.\n */\n\nimport type { ApiRoute } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { Context } from 'hono';\n\nimport type { AuditAction } from '../storage/domains/audit/actions.js';\nimport type { AuditTarget } from '../storage/domains/audit/base.js';\nimport type { AuditEmitter, AuditRecorder } from '../storage/domains/audit/domain.js';\nimport { auditRequestContext } from '../storage/domains/audit/domain.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type { WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport { FACTORY_ROUTE_CONTRACTS } from './contracts.js';\nimport { Route } from './route.js';\nimport type { RouteDependencies } from './route.js';\n\nfunction loose(c: unknown): Context {\n return c as Context;\n}\n\n/** The invokeSkill payload this route commits, matched against a prior replay. */\ninterface AutomationInvokeSkillDecision {\n type: 'invokeSkill';\n idempotencyKey: string;\n role: string;\n skillName: string;\n arguments?: string;\n}\n\n/**\n * Whether a replayed rule-evaluation record describes the SAME operation as the\n * current request. `commitRuleEvaluation` keys idempotency on `(org, project,\n * ingress identity)` alone, so a reused `requestId` replays regardless of the\n * work item or decision payload. We reconstruct the prior `invokeSkill`\n * decision from the stored result and compare the item id, role, skill, and\n * arguments; any divergence is a collision, not a legitimate retry.\n */\nfunction replayMatchesRequest(\n result: { itemId?: string | null; decisions?: unknown[] },\n itemId: string,\n request: AutomationInvokeSkillDecision,\n): boolean {\n if (result.itemId != null && result.itemId !== itemId) return false;\n const decisions = Array.isArray(result.decisions) ? result.decisions : [];\n const prior = decisions.find(\n (candidate): candidate is Record<string, unknown> =>\n typeof candidate === 'object' &&\n candidate !== null &&\n (candidate as Record<string, unknown>).type === 'invokeSkill' &&\n (candidate as Record<string, unknown>).idempotencyKey === request.idempotencyKey,\n );\n if (!prior) return false;\n return (\n prior.role === request.role &&\n prior.skillName === request.skillName &&\n (prior.arguments ?? undefined) === (request.arguments ?? undefined)\n );\n}\n\nexport interface AutomationRunRoutesDeps extends RouteDependencies {\n audit: AuditEmitter & AuditRecorder;\n /** Factory projects domain — validates the `:id` project belongs to the caller's org. */\n projects: FactoryProjectsStorage;\n /** Work-items domain backing `commitRuleEvaluation`. */\n workItems: WorkItemsStorage;\n /** Config version stamped on the committed rule evaluation. */\n configVersion: string;\n}\n\n/** Resolved ingress scope for an automation-run request. */\ninterface AutomationRunScope {\n orgId: string;\n userId: string;\n factoryProjectId: string;\n}\n\nexport class AutomationRunRoutes extends Route<AutomationRunRoutesDeps> {\n /**\n * Resolve the `(orgId, userId)` ingress scope. Tenant mode requires a\n * signed-in organization administrator; local (no-auth) mode runs under the\n * shared `local` scope without inventing a user.\n */\n async #resolveScope(c: Context): Promise<{ orgId: string; userId: string } | { response: Response }> {\n const { auth } = this.deps;\n if (!auth.enabled()) {\n return { orgId: 'local', userId: 'local' };\n }\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant) return { response: c.json({ error: 'unauthorized' }, 401) };\n if (!tenant.orgId) {\n return {\n response: c.json(\n { error: 'organization_required', message: 'The Factory board requires an organization.' },\n 403,\n ),\n };\n }\n if (!(await auth.isOrganizationAdmin(c, tenant.orgId))) {\n return {\n response: c.json(\n { error: 'forbidden', message: 'Organization administrator access is required for automation ingress.' },\n 403,\n ),\n };\n }\n return { orgId: tenant.orgId, userId: tenant.userId };\n }\n\n /** Resolve the ingress scope AND the org-owned project from the `:id` param. */\n async #resolveProject(c: Context): Promise<AutomationRunScope | { response: Response }> {\n const scope = await this.#resolveScope(c);\n if ('response' in scope) return scope;\n\n const parsedPath = FACTORY_ROUTE_CONTRACTS.projectGet.pathSchema.safeParse({ id: c.req.param('id') });\n if (!parsedPath.success) {\n return { response: c.json({ error: 'Project not found' }, 404) };\n }\n const { projects } = this.deps;\n await projects.ensureReady();\n const project = await projects.get({ orgId: scope.orgId, id: parsedPath.data.id });\n if (!project) {\n return { response: c.json({ error: 'Project not found' }, 404) };\n }\n return { ...scope, factoryProjectId: parsedPath.data.id };\n }\n\n /**\n * Persist an audit event under the ingress-resolved scope. This route can run\n * under the synthetic `local` no-auth scope, where the tenant-gated\n * `audit.emit()` derives no org from the request and drops the event; writing\n * through `record()` with the explicit org + system actor keeps traceability\n * in every deployment mode.\n *\n * The `idempotencyKey` (`<action>:<requestId>`) makes the audit write itself\n * idempotent: replaying the same request re-enters this path, but the trail\n * keeps a single event per requestId instead of one duplicate per retry.\n */\n async #writeAudit(\n c: Context,\n scope: AutomationRunScope,\n action: AuditAction,\n requestId: string,\n targets: AuditTarget[],\n metadata: Record<string, unknown>,\n ): Promise<void> {\n await this.deps.audit.record({\n idempotencyKey: `${action}:${requestId}`,\n orgId: scope.orgId,\n actorId: 'factory-external-orchestrator',\n actorType: 'system',\n action,\n targets,\n metadata,\n factoryProjectId: scope.factoryProjectId,\n context: auditRequestContext(c),\n });\n }\n\n routes(): ApiRoute[] {\n const { workItems, configVersion } = this.deps;\n const contract = FACTORY_ROUTE_CONTRACTS.workItemAutomationRun;\n\n return [\n registerApiRoute(contract.path, {\n method: contract.method,\n handler: async c => {\n const context = loose(c);\n const resolved = await this.#resolveProject(context);\n if ('response' in resolved) return resolved.response;\n\n const parsedPath = contract.pathSchema.safeParse({\n id: c.req.param('id'),\n workItemId: c.req.param('workItemId'),\n });\n if (!parsedPath.success) return c.json({ error: 'Work item not found' }, 404);\n\n const body = await c.req.json().catch(() => undefined);\n if (body === undefined) return c.json({ error: 'Invalid JSON body' }, 400);\n const parsed = contract.bodySchema.safeParse(body);\n if (!parsed.success) return c.json({ error: 'invalid_automation_run_request' }, 400);\n const request = parsed.data as {\n requestId: string;\n expectedRevision: number;\n role: string;\n skillName: string;\n arguments?: string;\n };\n\n const item = await workItems.getForProject(\n resolved.orgId,\n resolved.factoryProjectId,\n (parsedPath.data as { workItemId: string }).workItemId,\n );\n if (!item) return c.json({ error: 'Work item not found' }, 404);\n\n const idempotencyKey = `external-orchestrator:${request.requestId}`;\n const decision = {\n type: 'invokeSkill' as const,\n idempotencyKey,\n role: request.role,\n skillName: request.skillName,\n ...(request.arguments !== undefined ? { arguments: request.arguments } : {}),\n };\n\n const now = new Date();\n const commit = await workItems.commitRuleEvaluation({\n orgId: resolved.orgId,\n factoryProjectId: resolved.factoryProjectId,\n workItemId: item.id,\n ingress: { identity: idempotencyKey, triggerType: 'external-orchestrator.invoke-skill' },\n configVersion,\n expectedRevision: request.expectedRevision,\n actor: { type: 'system', id: 'factory-external-orchestrator' },\n outcome: { status: 'accepted' },\n decisions: [decision],\n causalChain: [],\n now,\n });\n\n if (commit.status === 'missing') return c.json({ error: 'Work item not found' }, 404);\n\n // A stale commit persists nothing, so the caller can retry the same\n // requestId once it has re-read the work item's revision.\n const result = (commit.status === 'stale' ? { status: 'rejected', code: 'stale' } : commit.result) as {\n status?: string;\n code?: string;\n itemId?: string | null;\n decisions?: unknown[];\n };\n const resultStatus = result.status ?? 'accepted';\n const code = typeof result.code === 'string' ? result.code : undefined;\n const targets = [{ type: 'work_item' as const, id: item.id, name: item.title }];\n\n const auditMetadata = {\n requestId: request.requestId,\n role: request.role,\n skillName: request.skillName,\n commitStatus: commit.status,\n resultStatus,\n ...(code ? { code } : {}),\n };\n\n // A replay only means \"this request was already committed\" — it must\n // be the SAME operation. If the caller reused a requestId against a\n // different work item, role, skill, or arguments, returning\n // `replayed` would report durable success for work that was never\n // enqueued. Reject the collision instead of silently swallowing it.\n if (commit.status === 'replayed' && !replayMatchesRequest(result, item.id, decision)) {\n await this.#writeAudit(context, resolved, 'factory.run.rejected', request.requestId, targets, {\n ...auditMetadata,\n resultStatus: 'rejected',\n code: 'request_id_conflict',\n });\n return c.json(\n {\n status: 'rejected',\n code: 'request_id_conflict',\n requestId: request.requestId,\n },\n 409,\n );\n }\n\n if (resultStatus === 'accepted') {\n await this.#writeAudit(context, resolved, 'factory.run.queued', request.requestId, targets, auditMetadata);\n return c.json(\n { status: commit.status === 'replayed' ? 'replayed' : 'committed', requestId: request.requestId },\n commit.status === 'replayed' ? 200 : 202,\n );\n }\n\n await this.#writeAudit(context, resolved, 'factory.run.rejected', request.requestId, targets, auditMetadata);\n return c.json(\n { status: 'rejected', ...(code ? { code } : {}), requestId: request.requestId },\n code === 'stale' ? 409 : 422,\n );\n },\n }),\n ];\n }\n}\n\nexport function buildAutomationRunRoutes(deps: AutomationRunRoutesDeps): ApiRoute[] {\n return new AutomationRunRoutes(deps).routes();\n}\n"],"mappings":"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"}
|
package/dist/routes/config.d.ts
CHANGED
|
@@ -209,6 +209,12 @@ export interface ConfigRoutesDeps extends RouteDependencies {
|
|
|
209
209
|
* defaults. Defaults to the standard app-data location; injectable for tests.
|
|
210
210
|
*/
|
|
211
211
|
settingsPath?: string;
|
|
212
|
+
/**
|
|
213
|
+
* Organization this deployment serves (`MASTRACODE_DEPLOYMENT_ORGANIZATION_ID`).
|
|
214
|
+
* When auth is enabled, only admins of this organization may write
|
|
215
|
+
* deployment-wide settings; without it those writes stay blocked.
|
|
216
|
+
*/
|
|
217
|
+
deploymentOrganizationId?: string;
|
|
212
218
|
}
|
|
213
219
|
/**
|
|
214
220
|
* The web config routes as Mastra `apiRoutes`:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/routes/config.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/routes/config.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/config.js
CHANGED
|
@@ -346,6 +346,30 @@ var ConfigRoutes = class extends Route {
|
|
|
346
346
|
return;
|
|
347
347
|
}
|
|
348
348
|
};
|
|
349
|
+
const deploymentThinkingAccess = async (c) => {
|
|
350
|
+
if (!auth.enabled()) return { ok: true };
|
|
351
|
+
await auth.ensureUser(c);
|
|
352
|
+
const tenant = auth.tenant(c);
|
|
353
|
+
if (!tenant) return {
|
|
354
|
+
ok: false,
|
|
355
|
+
status: 401,
|
|
356
|
+
error: "unauthorized"
|
|
357
|
+
};
|
|
358
|
+
const orgId = tenantOrgId(tenant);
|
|
359
|
+
if (!options.deploymentOrganizationId || orgId !== options.deploymentOrganizationId) return {
|
|
360
|
+
ok: false,
|
|
361
|
+
status: 403,
|
|
362
|
+
error: "deployment_organization_required",
|
|
363
|
+
message: "Deployment thinking defaults are shared by the whole deployment. Set MASTRACODE_DEPLOYMENT_ORGANIZATION_ID to let that organization's admins change them while authentication is enabled"
|
|
364
|
+
};
|
|
365
|
+
if (!await auth.isOrganizationAdmin(c, orgId)) return {
|
|
366
|
+
ok: false,
|
|
367
|
+
status: 403,
|
|
368
|
+
error: "organization_admin_required",
|
|
369
|
+
message: "Only organization admins can change deployment thinking defaults while authentication is enabled"
|
|
370
|
+
};
|
|
371
|
+
return { ok: true };
|
|
372
|
+
};
|
|
349
373
|
return [
|
|
350
374
|
registerApiRoute("/web/config/features", {
|
|
351
375
|
method: "GET",
|
|
@@ -713,7 +737,7 @@ var ConfigRoutes = class extends Route {
|
|
|
713
737
|
globalDefault: settings.preferences.thinkingLevel,
|
|
714
738
|
modeDefaults: settings.models.modeThinkingDefaults,
|
|
715
739
|
modes,
|
|
716
|
-
editable:
|
|
740
|
+
editable: (await deploymentThinkingAccess(loose(c))).ok
|
|
717
741
|
});
|
|
718
742
|
} catch (error) {
|
|
719
743
|
return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
|
|
@@ -724,7 +748,11 @@ var ConfigRoutes = class extends Route {
|
|
|
724
748
|
method: "PUT",
|
|
725
749
|
requiresAuth: false,
|
|
726
750
|
handler: async (c) => {
|
|
727
|
-
|
|
751
|
+
const access = await deploymentThinkingAccess(loose(c));
|
|
752
|
+
if (!access.ok) return c.json({
|
|
753
|
+
error: access.error,
|
|
754
|
+
...access.message ? { message: access.message } : {}
|
|
755
|
+
}, access.status);
|
|
728
756
|
let body;
|
|
729
757
|
try {
|
|
730
758
|
const parsed = await c.req.json();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","names":[],"sources":["../../src/routes/config.ts"],"sourcesContent":["import { MastraCodeGateway } from '@mastra/code-sdk/agents/mastracode-gateway';\nimport type { AuthStorage } from '@mastra/code-sdk/auth/storage';\nimport { resolveAutoOMModelId } from '@mastra/code-sdk/onboarding/packs';\nimport type { ProviderAccess, ProviderAccessLevel } from '@mastra/code-sdk/onboarding/packs';\nimport {\n getCustomProviderId,\n isThinkingLevelSetting,\n loadSettings,\n MASTRA_GATEWAY_PROVIDER,\n saveSettings,\n THINKING_LEVEL_VALUES,\n} from '@mastra/code-sdk/onboarding/settings';\nimport type { CustomProviderSetting, ThinkingLevelSetting } from '@mastra/code-sdk/onboarding/settings';\nimport { AMAZON_BEDROCK_GATEWAY_ID } from '@mastra/code-sdk/providers/amazon-bedrock-gateway';\nimport { MASTRA_GATEWAY_PREFIX } from '@mastra/code-sdk/providers/model-ids';\nimport { getModelReasoningOptions } from '@mastra/core/llm';\nimport type { ApiRoute } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\n\nimport type { Context } from 'hono';\nimport { z } from 'zod';\nimport { DEFAULT_OBSERVATION_THRESHOLD, DEFAULT_REFLECTION_THRESHOLD } from '../session/memory-settings-hydration.js';\nimport type {\n CredentialRecord,\n LoginSessionKind,\n ModelCredentialsStorage,\n} from '../storage/domains/credentials/base.js';\nimport type { CustomProviderRecord, CustomProvidersStorage } from '../storage/domains/custom-providers/base.js';\nimport { factoryMemorySettingsUserId } from '../storage/domains/memory-settings/base.js';\nimport type {\n MemorySettingsPatch,\n MemorySettingsRecord,\n MemorySettingsStorage,\n} from '../storage/domains/memory-settings/base.js';\nimport type { ModelDefaultsStorage } from '../storage/domains/model-defaults/base.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type { SourceControlStorageHandle } from '../storage/domains/source-control/base.js';\nimport {\n getAuthProviderId,\n listTenantCredentialsForRequest,\n resolveCredentialContext,\n tenantOrgId,\n WEB_OAUTH_FLOW_KINDS,\n} from './provider-credentials.js';\nimport { Route } from './route.js';\nimport type { RouteAuth, RouteDependencies } from './route.js';\n\n/** Widen a route-local Hono context to the plain `Context` the auth helpers take. */\nfunction loose(c: unknown): Context {\n return c as Context;\n}\n\n/**\n * Server-side configuration routes for the web app.\n *\n * The browser has no access to the credential store or the model catalog, so\n * the web settings panel asks the server — which owns both — to list providers\n * and manage API keys. This mirrors the TUI's `/api-keys` command, exposing the\n * same `AuthStorage`-backed key management over HTTP.\n *\n * Keys are never returned to the client; only their presence and source.\n */\n\n/**\n * Where a provider's active credential comes from, as seen by the caller.\n * Local mode reports `oauth`/`stored` (server-global `auth.json`); tenant mode\n * reports the scoped variants (`oauth-user`/`stored-user`/`stored-org`).\n * `deployment` (tenant mode) marks a provider the operator opted in to run on\n * the server process's own credentials (e.g. Amazon Bedrock's AWS chain).\n */\nexport type ProviderCredentialSource =\n | 'deployment'\n | 'oauth'\n | 'stored'\n | 'env'\n | 'none'\n | 'oauth-user'\n | 'oauth-org'\n | 'stored-user'\n | 'stored-org';\n\n/** A model provider with the current source of its credentials. */\nexport interface ProviderInfo {\n provider: string;\n /** Env var the provider's key is read from, if any. */\n envVar?: string;\n /** Where the active credential comes from. */\n source: ProviderCredentialSource;\n /**\n * Tenant mode: whether an org-wide API key exists for this provider, even\n * when the caller's personal credential shadows it. Lets the UI tell\n * \"shared with the org\" apart from \"only works for me\".\n */\n orgKey?: boolean;\n /**\n * Tenant mode: the caller's personal credential for this provider, if any.\n * Reported independently of `source` so the UI can manage each scope even\n * when one shadows the other.\n */\n userCredential?: 'oauth' | 'api_key';\n /** Tenant mode: the shared org credential for this provider, if any. */\n orgCredential?: 'oauth' | 'api_key';\n /** Web OAuth sign-in capability, when the provider supports it. */\n oauth?: { supported: true; modes: LoginSessionKind[] };\n}\n\n/** Minimal session surface the config routes touch. */\nexport interface OMSession {\n /** `get()` returns '' when no model is selected, so callers fall back on falsy. */\n model: { get: () => string };\n}\n\n/** Minimal controller surface this module needs (model catalog + modes + sessions). */\ninterface ModelCatalog {\n listAvailableModels: () => Promise<\n Array<{ id?: string; modelName?: string; provider: string; hasApiKey: boolean; apiKeyEnvVar?: string }>\n >;\n listModes?: () => Array<{ id: string; defaultModelId?: string }>;\n getSessionByResource?: (resourceId: string, scope?: string) => Promise<OMSession | undefined>;\n}\n\n/**\n * Build a deduplicated, sorted list of providers from the model catalog,\n * annotated with where each provider's credential currently comes from.\n * Mirrors the TUI's `/api-keys` provider list.\n *\n * When `tenantCredentials` is given (deployed mode), sources reflect the\n * *caller's* tenant rows with user > org precedence and the server-global\n * `authStorage` is ignored; otherwise the local `auth.json` view is reported.\n */\nexport async function listProviders({\n controller,\n authStorage,\n tenantCredentials,\n deploymentProviders,\n}: {\n controller: ModelCatalog;\n authStorage?: AuthStorage;\n tenantCredentials?: CredentialRecord[];\n deploymentProviders?: ReadonlySet<string>;\n}): Promise<ProviderInfo[]> {\n const models = await controller.listAvailableModels();\n const seen = new Map<string, ProviderInfo>();\n\n for (const model of models) {\n if (seen.has(model.provider)) continue;\n\n if (tenantCredentials && isDeploymentModelProvider(model.provider)) {\n // Credentials for these providers live on the server process, never in\n // tenant rows, so no account can connect them. List them only when the\n // operator opted the deployment in and the server has credentials.\n const usable =\n deploymentProviders?.has(model.provider) && models.some(m => m.provider === model.provider && m.hasApiKey);\n if (usable) seen.set(model.provider, { provider: model.provider, source: 'deployment' });\n continue;\n }\n\n const authProviderId = getAuthProviderId(model.provider);\n let source: ProviderInfo['source'] = 'none';\n let orgKey: boolean | undefined;\n let userCredential: ProviderInfo['userCredential'];\n let orgCredential: ProviderInfo['orgCredential'];\n if (tenantCredentials) {\n const userRec = tenantCredentials.find(r => r.scope === 'user' && r.provider === authProviderId);\n const orgRec = tenantCredentials.find(r => r.scope === 'org' && r.provider === authProviderId);\n // Any shared org credential (API key or org-wide OAuth) counts.\n orgKey = orgRec !== undefined;\n userCredential = userRec?.credential.type;\n orgCredential = orgRec?.credential.type;\n if (userRec?.credential.type === 'oauth') {\n source = 'oauth-user';\n } else if (userRec?.credential.type === 'api_key') {\n source = 'stored-user';\n } else if (orgRec?.credential.type === 'oauth') {\n source = 'oauth-org';\n } else if (orgRec?.credential.type === 'api_key') {\n source = 'stored-org';\n }\n } else if (authStorage?.isLoggedIn(authProviderId)) {\n source = 'oauth';\n } else if (authStorage?.hasStoredApiKey(model.provider)) {\n source = 'stored';\n } else if (model.apiKeyEnvVar && process.env[model.apiKeyEnvVar]) {\n source = 'env';\n } else if (model.hasApiKey) {\n source = 'env';\n }\n\n const flowKind = WEB_OAUTH_FLOW_KINDS[model.provider];\n seen.set(model.provider, {\n provider: model.provider,\n envVar: model.apiKeyEnvVar,\n source,\n ...(orgKey !== undefined ? { orgKey } : {}),\n ...(userCredential ? { userCredential } : {}),\n ...(orgCredential ? { orgCredential } : {}),\n ...(flowKind ? { oauth: { supported: true as const, modes: [flowKind] } } : {}),\n });\n }\n\n return Array.from(seen.values()).sort((a, b) => a.provider.localeCompare(b.provider));\n}\n\n/** A user-defined OpenAI-compatible provider, with key presence (never the key). */\nexport interface CustomProviderInfo {\n id: string;\n name: string;\n url: string;\n hasApiKey: boolean;\n models: string[];\n}\n\n/** Redact a stored custom-provider row for the client (key presence only). */\nfunction toCustomProviderInfo(record: CustomProviderRecord): CustomProviderInfo {\n return {\n id: record.providerId,\n name: record.name,\n url: record.url,\n hasApiKey: Boolean(record.apiKey),\n models: record.models,\n };\n}\n\n/** The resolved custom-providers storage scope for a request. */\ninterface CustomProvidersContext {\n storage: CustomProvidersStorage;\n orgId: string;\n userId: string;\n}\n\n/**\n * Resolve the custom-providers context for a request, or a ready-to-return\n * error response. Same posture as memory settings: tenant rows in deployed\n * mode, a sentinel `local` org in no-auth mode — never settings.json.\n */\nasync function resolveCustomProvidersContext({\n c,\n auth,\n customProviders,\n}: {\n c: Context;\n auth: RouteAuth;\n customProviders?: CustomProvidersStorage;\n}): Promise<CustomProvidersContext | { response: Response }> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant && auth.enabled()) return { response: c.json({ error: 'unauthorized' }, 401) };\n if (customProviders) {\n try {\n await customProviders.ensureReady();\n return tenant\n ? { storage: customProviders, orgId: tenantOrgId(tenant), userId: tenant.userId }\n : { storage: customProviders, orgId: 'local', userId: 'local' };\n } catch {\n // fall through to the unavailable response\n }\n }\n return {\n response: c.json(\n {\n error: 'custom_providers_unavailable',\n message: 'Custom provider storage is unavailable — the app database is not configured or failed to start.',\n },\n 503,\n ),\n };\n}\n\n/** Validate + coerce a request body into a CustomProviderSetting. */\nfunction parseCustomProviderBody(body: unknown): CustomProviderSetting | { error: string } {\n if (!body || typeof body !== 'object') return { error: 'Invalid JSON body' };\n const b = body as Record<string, unknown>;\n const name = typeof b.name === 'string' ? b.name.trim() : '';\n if (!name) return { error: 'Missing required field: name' };\n const url = typeof b.url === 'string' ? b.url.trim() : '';\n if (!url) return { error: 'Missing required field: url' };\n try {\n const parsed = new URL(url);\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n return { error: 'url must be an http(s) URL' };\n }\n } catch {\n return { error: 'url must be a valid URL' };\n }\n const apiKey = typeof b.apiKey === 'string' && b.apiKey.trim() ? b.apiKey.trim() : undefined;\n const models = Array.isArray(b.models)\n ? b.models.filter((m): m is string => typeof m === 'string' && m.trim().length > 0).map(m => m.trim())\n : [];\n return { name, url, apiKey, models };\n}\n\n// ── Available models ───────────────────────────────────────────────────────\n\n/**\n * Providers whose credentials can only come from the server process (Amazon\n * Bedrock authenticates through the AWS credential chain). In tenant mode they\n * are usable only when the operator lists them in\n * `MastraFactoryConfig.deploymentModelProviders`.\n */\nexport const DEPLOYMENT_MODEL_PROVIDERS: readonly string[] = [AMAZON_BEDROCK_GATEWAY_ID];\n\nexport function isDeploymentModelProvider(provider: string): boolean {\n return DEPLOYMENT_MODEL_PROVIDERS.includes(provider);\n}\n\n/**\n * Normalize the operator's `deploymentModelProviders` list. Unsupported ids are\n * ignored with a warning rather than failing boot.\n */\nexport function resolveDeploymentModelProviders(providers: readonly string[] | undefined): ReadonlySet<string> {\n const resolved = new Set<string>();\n for (const raw of providers ?? []) {\n const provider = raw.trim();\n if (!provider) continue;\n if (isDeploymentModelProvider(provider)) {\n resolved.add(provider);\n } else {\n console.warn(\n `[factory] Ignoring deployment model provider \"${provider}\". Supported: ${DEPLOYMENT_MODEL_PROVIDERS.join(', ')}.`,\n );\n }\n }\n return resolved;\n}\n\n/**\n * Compute which providers the user can reach, mirroring the TUI's\n * `/models-pack` access derivation: OAuth/api-key from the credential store for\n * the named providers, plus any other provider that has a usable key.\n */\nexport async function buildProviderAccess({\n controller,\n authStorage,\n tenantCredentials,\n deploymentProviders,\n}: {\n controller: ModelCatalog;\n authStorage?: AuthStorage;\n tenantCredentials?: CredentialRecord[];\n deploymentProviders?: ReadonlySet<string>;\n}): Promise<ProviderAccess> {\n const models = await controller.listAvailableModels();\n const hasModelKey = (provider: string) => models.some(m => m.provider === provider && m.hasApiKey);\n const accessLevel = (provider: string): ProviderAccessLevel => {\n const authProviderId = getAuthProviderId(provider);\n if (tenantCredentials) {\n // Tenant rows never authenticate these providers; only an operator\n // opt-in plus credentials on the server process does.\n if (isDeploymentModelProvider(provider)) {\n return deploymentProviders?.has(provider) && hasModelKey(provider) ? 'apikey' : false;\n }\n const userRec = tenantCredentials.find(r => r.scope === 'user' && r.provider === authProviderId);\n const orgRec = tenantCredentials.find(r => r.scope === 'org' && r.provider === authProviderId);\n const credential = userRec?.credential ?? orgRec?.credential;\n if (credential?.type === 'oauth') return 'oauth';\n if (credential?.type === 'api_key' && credential.key.trim().length > 0) return 'apikey';\n return false;\n }\n\n const oauthCredential = authStorage?.get(authProviderId);\n if (oauthCredential?.type === 'oauth') return 'oauth';\n if (authStorage?.hasStoredApiKey(provider)) return 'apikey';\n const directCredential = authStorage?.get(provider);\n if (directCredential?.type === 'api_key' && directCredential.key.trim().length > 0) return 'apikey';\n return hasModelKey(provider) ? 'apikey' : false;\n };\n const access: ProviderAccess = {\n anthropic: accessLevel('anthropic'),\n openai: accessLevel('openai'),\n cerebras: accessLevel('cerebras'),\n google: accessLevel('google'),\n deepseek: accessLevel('deepseek'),\n 'github-copilot': accessLevel('github-copilot'),\n };\n const seen = new Set(Object.keys(access));\n for (const m of models) {\n if (!seen.has(m.provider)) {\n access[m.provider] = accessLevel(m.provider);\n seen.add(m.provider);\n }\n }\n return access;\n}\n\nfunction canUseModelProvider(access: ProviderAccess, provider: string): boolean {\n return Boolean(access[provider]);\n}\n\n// ── Default model ──────────────────────────────────────────────────────────\n\n/** Per-user default model context for the current request. */\nexport interface ModelDefaultsContext {\n storage: ModelDefaultsStorage;\n orgId: string;\n userId: string;\n}\n\n/** Resolve the default-model context for a request, or a ready-to-return error response. */\nasync function resolveModelDefaultsContext({\n c,\n auth,\n modelDefaults,\n}: {\n c: Context;\n auth: RouteAuth;\n modelDefaults?: ModelDefaultsStorage;\n}): Promise<ModelDefaultsContext | { response: Response }> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant && auth.enabled()) return { response: c.json({ error: 'unauthorized' }, 401) };\n if (modelDefaults) {\n try {\n await modelDefaults.ensureReady();\n return tenant\n ? { storage: modelDefaults, orgId: tenantOrgId(tenant), userId: tenant.userId }\n : { storage: modelDefaults, orgId: 'local', userId: 'local' };\n } catch {\n // fall through to the unavailable response\n }\n }\n return {\n response: c.json(\n {\n error: 'model_defaults_unavailable',\n message: 'Default model storage is unavailable — the app database is not configured or failed to start.',\n },\n 503,\n ),\n };\n}\n\n// ── Observational memory ────────────────────────────────────────────────────\n// Mirrors the TUI `/om` command. Settings are persisted per organization and\n// user in the Factory app database, then loaded into request context for each\n// invocation without copying them into mutable session state.\n\nexport interface OMRoleConfigInfo {\n model: 'auto' | string;\n effectiveModelId: string;\n effectiveModelSource: 'explicit' | 'live-session' | 'configured-default';\n providerStatus: 'available' | 'unavailable';\n}\n\n/** Persisted intent plus the concrete models the current Factory configuration resolves. */\nexport interface OMConfigInfo {\n observer: OMRoleConfigInfo;\n reflector: OMRoleConfigInfo;\n /** @deprecated Use `observer.effectiveModelId`. */\n observerModelId: string;\n /** @deprecated Use `reflector.effectiveModelId`. */\n reflectorModelId: string;\n observationThreshold: number;\n reflectionThreshold: number;\n observeAttachments: 'auto' | boolean;\n}\n\nexport interface ProviderOMDefaultsResponse {\n ok: true;\n config: OMConfigInfo;\n}\n\n/** `GET /web/config/thinking` — deployment-scoped reasoning-effort defaults. */\nexport interface ThinkingConfigInfo {\n /** All selectable levels, in escalation order. */\n levels: readonly ThinkingLevelSetting[];\n /** `preferences.thinkingLevel` — fallback when a mode has no default. */\n globalDefault: ThinkingLevelSetting;\n /** `models.modeThinkingDefaults` — per-mode overrides of the global default. */\n modeDefaults: Record<string, ThinkingLevelSetting>;\n /** Mode ids known to the controller (for rendering per-mode rows). */\n modes: string[];\n /** False when the deployment refuses writes, so the UI can render read-only rows. */\n editable: boolean;\n}\n\n/** `PUT /web/config/thinking` success payload. */\nexport interface UpdateThinkingConfigResponse {\n ok: true;\n globalDefault: ThinkingLevelSetting;\n modeDefaults: Record<string, ThinkingLevelSetting>;\n}\n\nfunction modelProvider(modelId: string): string {\n // Effective IDs keep their `mastra/` route; the provider segment after it is what\n // the SDK resolver falls back to when the gateway is not configured.\n const normalized = modelId.replace(/^mastracode\\//, '').replace(/^mastra\\//, '');\n return normalized.split('/', 1)[0] ?? '';\n}\n\nfunction roleConfig(\n model: OMRoleConfigInfo['model'],\n effectiveModelId: string,\n autoModelSource: 'live-session' | 'configured-default',\n availableProviders: ReadonlySet<string>,\n): OMRoleConfigInfo {\n return {\n model,\n effectiveModelId,\n effectiveModelSource: model === 'auto' ? autoModelSource : 'explicit',\n providerStatus:\n availableProviders.has(modelProvider(effectiveModelId)) ||\n (effectiveModelId.startsWith(MASTRA_GATEWAY_PREFIX) && availableProviders.has(MASTRA_GATEWAY_PROVIDER))\n ? 'available'\n : 'unavailable',\n };\n}\n\nfunction readStoredOMConfig(\n record: MemorySettingsRecord | null,\n currentModelId: string | undefined,\n autoModelSource: 'live-session' | 'configured-default',\n availableProviders: ReadonlySet<string>,\n): OMConfigInfo {\n const autoModelId = resolveAutoOMModelId(currentModelId);\n const observerModelId = record?.observerModelId ?? autoModelId;\n const reflectorModelId = record?.reflectorModelId ?? autoModelId;\n return {\n observer: roleConfig(record?.observerModelId ?? 'auto', observerModelId, autoModelSource, availableProviders),\n reflector: roleConfig(record?.reflectorModelId ?? 'auto', reflectorModelId, autoModelSource, availableProviders),\n observerModelId,\n reflectorModelId,\n observationThreshold: record?.observationThreshold ?? DEFAULT_OBSERVATION_THRESHOLD,\n reflectionThreshold: record?.reflectionThreshold ?? DEFAULT_REFLECTION_THRESHOLD,\n observeAttachments: record?.observeAttachments ?? 'auto',\n };\n}\n\n/**\n * Where a request's OM settings live: the `memory-settings` factory storage\n * domain, one row per (org, user). Without a tenant (auth disabled), settings\n * land on a sentinel `(local, local)` row in the same table — the web surface\n * never reads or writes `settings.json` for memory settings.\n */\ninterface MemorySettingsContext {\n storage: MemorySettingsStorage;\n orgId: string;\n userId: string;\n}\n\n/**\n * Resolve the memory-settings context for a request, or a ready-to-return\n * error response. When `factoryProjectId` is provided the row addressed is the\n * factory project's shared settings (a sentinel user id in the caller's org)\n * instead of the caller's personal row — this is what factory board runs and\n * channel sessions hydrate from.\n */\nasync function resolveMemorySettingsContext({\n c,\n auth,\n memorySettings,\n factoryProjectId,\n factoryProjects,\n}: {\n c: Context;\n auth: RouteAuth;\n memorySettings?: MemorySettingsStorage;\n factoryProjectId?: string;\n factoryProjects?: FactoryProjectsStorage;\n}): Promise<MemorySettingsContext | { response: Response }> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant && auth.enabled()) return { response: c.json({ error: 'unauthorized' }, 401) };\n // Factory-scoped rows are shared org state: the target project must exist in\n // the caller's org before its settings row can be read or written.\n if (factoryProjectId && tenant) {\n if (!factoryProjects) return { response: c.json({ error: 'factory_unavailable' }, 503) };\n try {\n await factoryProjects.ensureReady();\n const project = await factoryProjects.get({ orgId: tenantOrgId(tenant), id: factoryProjectId });\n if (!project) return { response: c.json({ error: 'factory_project_not_found' }, 404) };\n } catch {\n return { response: c.json({ error: 'factory_unavailable' }, 503) };\n }\n }\n if (memorySettings) {\n try {\n await memorySettings.ensureReady();\n const factoryUserId = factoryProjectId ? factoryMemorySettingsUserId(factoryProjectId) : undefined;\n return tenant\n ? { storage: memorySettings, orgId: tenantOrgId(tenant), userId: factoryUserId ?? tenant.userId }\n : { storage: memorySettings, orgId: 'local', userId: factoryUserId ?? 'local' };\n } catch {\n // fall through to the unavailable response\n }\n }\n return {\n response: c.json(\n {\n error: 'memory_settings_unavailable',\n message: 'Memory settings storage is unavailable — the app database is not configured or failed to start.',\n },\n 503,\n ),\n };\n}\n\n/** Persist an OM knob change to the caller's memory-settings row. */\nasync function persistMemorySettings(context: MemorySettingsContext, patch: MemorySettingsPatch): Promise<void> {\n await context.storage.patch({ orgId: context.orgId, userId: context.userId, patch });\n}\n\n/** Dependencies injected into {@link ConfigRoutes}. */\nexport interface ConfigRoutesDeps extends RouteDependencies {\n controller: ModelCatalog;\n features?: { knowledge: boolean };\n authStorage?: AuthStorage;\n /** Tenant credential domain handle; absent in local (no-DB) mode. */\n modelCredentials?: ModelCredentialsStorage;\n /** Tenant model-defaults domain handle; absent in local (no-DB) mode. */\n modelDefaults?: ModelDefaultsStorage;\n /** Source-control sessions available to config route integrations. */\n sourceControlSessions?: Pick<SourceControlStorageHandle['sessions'], 'getBySessionId'>;\n /** Tenant memory-settings domain handle; absent in local (no-DB) mode. */\n memorySettings?: MemorySettingsStorage;\n /** Factory projects domain, used to derive OM fallbacks from a factory's default model. */\n factoryProjects?: FactoryProjectsStorage;\n /** Custom-providers domain handle; absent when the app database is missing. */\n customProviders?: CustomProvidersStorage;\n /** Notifies the host after tenant credentials change so caches can be dropped. */\n onCredentialsChanged?: (tenant: { orgId: string; userId?: string }) => void;\n /** Notifies the host after custom providers change so model-router caches can be dropped. */\n onCustomProvidersChanged?: (tenant: { orgId: string }) => void;\n /**\n * Tenant mode: providers the operator opted in to run on the server process's\n * own credentials (see `DEPLOYMENT_MODEL_PROVIDERS`).\n */\n deploymentProviders?: ReadonlySet<string>;\n /**\n * Path of the server's settings.json backing the deployment-scoped thinking\n * defaults. Defaults to the standard app-data location; injectable for tests.\n */\n settingsPath?: string;\n}\n\n/**\n * The web config routes as Mastra `apiRoutes`:\n * - `GET /web/config/features` — list server-enabled product features\n * - `GET /web/config/providers` — list providers + key source\n * - `PUT /web/config/providers/:provider/key` — set/update a provider's API key\n * - `DELETE /web/config/providers/:provider/key` — remove a stored API key\n * - `GET /web/config/models` — list available models (credentialed providers)\n * - `GET /web/config/custom-providers` — list custom OpenAI-compatible providers\n * - `POST /web/config/custom-providers` — create/update a custom provider\n * - `DELETE /web/config/custom-providers/:id` — remove a custom provider\n * - `GET /web/config/thinking` — read thinking (reasoning-effort) defaults\n * - `PUT /web/config/thinking` — set global/per-mode thinking defaults\n * - `GET /web/config/om` — read OM models/thresholds/observe-attachments\n * - `PUT /web/config/om/:role/model` — switch observer/reflector model\n * - `PUT /web/config/om/thresholds` — set observation/reflection thresholds\n * - `PUT /web/config/om/observe-attachments` — set observe-attachments (auto/on/off)\n */\nexport class ConfigRoutes extends Route<ConfigRoutesDeps> {\n routes(): ApiRoute[] {\n const options = this.deps;\n const { controller, authStorage, auth, deploymentProviders } = options;\n const onCredentialsChanged = options.onCredentialsChanged ?? (() => {});\n const onCustomProvidersChanged = options.onCustomProvidersChanged ?? (() => {});\n\n const resolveOMResponseContext = async (c: Context) => {\n const tenantCredentials = await listTenantCredentialsForRequest({\n c: loose(c),\n auth,\n credentials: options.modelCredentials,\n });\n const access = await buildProviderAccess({\n controller,\n authStorage: tenantCredentials ? undefined : authStorage,\n tenantCredentials,\n deploymentProviders,\n });\n const availableProviders = new Set(\n Object.entries(access).flatMap(([providerId, configured]) => (configured ? [providerId] : [])),\n );\n // `mastra/` routes run through the Mastra gateway whenever its key is configured.\n if (MastraCodeGateway.getMastraGatewayApiKey()) availableProviders.add(MASTRA_GATEWAY_PROVIDER);\n if (options.customProviders) {\n const context = await resolveCustomProvidersContext({\n c: loose(c),\n auth,\n customProviders: options.customProviders,\n });\n if (!('response' in context)) {\n for (const provider of await context.storage.list({ orgId: context.orgId })) {\n availableProviders.add(provider.providerId);\n }\n }\n }\n return availableProviders;\n };\n\n // Factory-scoped OM reads without a stored row fall back to the low-cost\n // OM model of the factory default model's provider — not the global\n // built-in default, whose provider may have no credential here.\n const factoryOmFallback = async (factoryProjectId: string | undefined): Promise<string | undefined> => {\n try {\n const defaultModelId = factoryProjectId\n ? await options.factoryProjects\n ?.getById({ id: factoryProjectId })\n .then(project => project?.defaultModelId ?? undefined)\n : controller.listModes?.().find(mode => mode.defaultModelId)?.defaultModelId;\n return defaultModelId ? resolveAutoOMModelId(defaultModelId) : undefined;\n } catch {\n return undefined;\n }\n };\n\n return [\n registerApiRoute('/web/config/features', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => c.json({ knowledge: options.features?.knowledge ?? false }),\n }),\n\n registerApiRoute('/web/config/providers', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n try {\n // Tenant mode lists the caller's rows and never exposes the\n // server-global auth.json; local mode is unchanged.\n const tenantCredentials = await listTenantCredentialsForRequest({\n c: loose(c),\n auth,\n credentials: options.modelCredentials,\n });\n // Tenant mode also reports whether the caller may write org-wide\n // keys, so the settings UI can gate the \"Everyone in org\" option.\n const tenant = auth.tenant(loose(c));\n const orgKeyAdmin = tenant ? await auth.isOrganizationAdmin(loose(c), tenantOrgId(tenant)) : undefined;\n return c.json({\n providers: await listProviders({\n controller,\n authStorage: tenantCredentials ? undefined : authStorage,\n tenantCredentials,\n deploymentProviders,\n }),\n ...(orgKeyAdmin !== undefined ? { orgKeyAdmin } : {}),\n });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/providers/:provider/key', {\n method: 'PUT',\n requiresAuth: false,\n handler: async c => {\n const ctx = await resolveCredentialContext({ c: loose(c), auth, credentials: options.modelCredentials });\n if ('response' in ctx) return ctx.response;\n\n const provider = c.req.param('provider');\n let body: { key?: unknown; envVar?: unknown; scope?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const key = typeof body.key === 'string' ? body.key.trim() : '';\n if (!key) return c.json({ error: 'Missing required field: key' }, 400);\n const envVar = typeof body.envVar === 'string' ? body.envVar : undefined;\n const scope = body.scope === 'org' ? 'org' : 'user';\n try {\n if (ctx.mode === 'tenant') {\n // A stored key would never be read: these providers authenticate\n // with the server process's credentials only.\n if (isDeploymentModelProvider(provider)) {\n return c.json(\n {\n error: 'provider_configured_by_deployment',\n message: `${provider} is configured by the Factory deployment (credentials on the server), not per account.`,\n },\n 400,\n );\n }\n if (scope === 'org' && !(await auth.isOrganizationAdmin(loose(c), ctx.orgId))) {\n return c.json({ error: 'organization_admin_required' }, 403);\n }\n const tenant = scope === 'org' ? { orgId: ctx.orgId } : { orgId: ctx.orgId, userId: ctx.userId };\n // envVar is intentionally ignored: tenant credentials are resolved\n // per-request, never written into process.env.\n await ctx.storage.setCredential(tenant, getAuthProviderId(provider), { type: 'api_key', key });\n onCredentialsChanged(tenant);\n const records = await ctx.storage.listCredentials(ctx.orgId, ctx.userId);\n const providers = await listProviders({ controller, tenantCredentials: records, deploymentProviders });\n return c.json({ ok: true, provider: providers.find(p => p.provider === provider) });\n }\n if (!authStorage) return c.json({ error: 'Credential storage is not available' }, 503);\n // Local mode is single-user: scope is meaningless and ignored.\n authStorage.setStoredApiKey(provider, key, envVar);\n const providers = await listProviders({ controller, authStorage });\n return c.json({ ok: true, provider: providers.find(p => p.provider === provider) });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/providers/:provider/key', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async c => {\n const ctx = await resolveCredentialContext({ c: loose(c), auth, credentials: options.modelCredentials });\n if ('response' in ctx) return ctx.response;\n\n const provider = c.req.param('provider');\n const scope = c.req.query('scope') === 'org' ? 'org' : 'user';\n try {\n if (ctx.mode === 'tenant') {\n if (scope === 'org' && !(await auth.isOrganizationAdmin(loose(c), ctx.orgId))) {\n return c.json({ error: 'organization_admin_required' }, 403);\n }\n const tenant = scope === 'org' ? { orgId: ctx.orgId } : { orgId: ctx.orgId, userId: ctx.userId };\n await ctx.storage.removeCredential(tenant, getAuthProviderId(provider));\n onCredentialsChanged(tenant);\n const records = await ctx.storage.listCredentials(ctx.orgId, ctx.userId);\n const providers = await listProviders({ controller, tenantCredentials: records, deploymentProviders });\n return c.json({ ok: true, provider: providers.find(p => p.provider === provider) });\n }\n if (!authStorage) return c.json({ error: 'Credential storage is not available' }, 503);\n authStorage.remove(`apikey:${provider}`);\n const providers = await listProviders({ controller, authStorage });\n return c.json({ ok: true, provider: providers.find(p => p.provider === provider) });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n // ── Custom providers (OpenAI-compatible endpoints) ──────────────────────\n // Mirrors the TUI's /custom-providers command, but backed by the\n // `custom-providers` domain (org rows in tenant mode, a sentinel `local`\n // org in no-auth mode) — the server never reads settings.json for these.\n\n registerApiRoute('/web/config/custom-providers', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const ctx = await resolveCustomProvidersContext({\n c: loose(c),\n auth,\n customProviders: options.customProviders,\n });\n if ('response' in ctx) return ctx.response;\n try {\n const records = await ctx.storage.list({ orgId: ctx.orgId });\n return c.json({ providers: records.map(toCustomProviderInfo) });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/custom-providers', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const ctx = await resolveCustomProvidersContext({\n c: loose(c),\n auth,\n customProviders: options.customProviders,\n });\n if ('response' in ctx) return ctx.response;\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const parsed = parseCustomProviderBody(body);\n if ('error' in parsed) return c.json({ error: parsed.error }, 400);\n // `previousId` lets a rename remove the old entry as well as any name clash.\n const previousId =\n body && typeof body === 'object' && typeof (body as Record<string, unknown>).previousId === 'string'\n ? ((body as Record<string, unknown>).previousId as string)\n : undefined;\n try {\n const record = await ctx.storage.upsert({\n orgId: ctx.orgId,\n userId: ctx.userId,\n input: {\n providerId: getCustomProviderId(parsed.name),\n name: parsed.name,\n url: parsed.url,\n apiKey: parsed.apiKey,\n models: parsed.models,\n },\n previousProviderId: previousId,\n });\n onCustomProvidersChanged({ orgId: ctx.orgId });\n return c.json({ ok: true, provider: toCustomProviderInfo(record) });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/custom-providers/:id', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async c => {\n const ctx = await resolveCustomProvidersContext({\n c: loose(c),\n auth,\n customProviders: options.customProviders,\n });\n if ('response' in ctx) return ctx.response;\n const id = c.req.param('id');\n try {\n await ctx.storage.delete({ orgId: ctx.orgId, providerId: id });\n onCustomProvidersChanged({ orgId: ctx.orgId });\n return c.json({ ok: true });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n // ── Available models ────────────────────────────────────────────────────\n // Session-independent model catalog for settings pickers (Factory default\n // model, pack editors). Only models whose provider has a credential are\n // returned — the same filter the session-scoped hook applies client-side.\n\n registerApiRoute('/web/config/models', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n try {\n const tenantCredentials = await listTenantCredentialsForRequest({\n c: loose(c),\n auth,\n credentials: options.modelCredentials,\n });\n const [models, access] = await Promise.all([\n controller.listAvailableModels(),\n buildProviderAccess({\n controller,\n authStorage: tenantCredentials ? undefined : authStorage,\n tenantCredentials,\n deploymentProviders,\n }),\n ]);\n const catalog = models.flatMap(({ id, provider, modelName }) =>\n typeof id === 'string' && canUseModelProvider(access, provider)\n ? [{ id, provider, modelName, hasApiKey: true, reasoningOptions: getModelReasoningOptions(id) }]\n : [],\n );\n // Append the caller's custom provider models (DB-backed, org rows in\n // tenant mode / sentinel `local` org in no-auth mode). The boot-time\n // gateway catalog only carries the local list, so tenant callers get\n // theirs here. Dedupe against ids already present.\n if (options.customProviders) {\n try {\n const ctx = await resolveCustomProvidersContext({\n c: loose(c),\n auth,\n customProviders: options.customProviders,\n });\n if (!('response' in ctx)) {\n const known = new Set(catalog.map(m => m.id));\n for (const record of await ctx.storage.list({ orgId: ctx.orgId })) {\n for (const model of record.models) {\n const id = `${record.providerId}/${model}`;\n if (known.has(id)) continue;\n known.add(id);\n catalog.push({\n id,\n provider: record.providerId,\n modelName: model,\n hasApiKey: true,\n reasoningOptions: undefined,\n });\n }\n }\n }\n } catch {\n // Fail soft: the catalog still serves the built-in models.\n }\n }\n return c.json({\n models: catalog.sort((a, b) =>\n a.provider === b.provider ? a.id.localeCompare(b.id) : a.provider.localeCompare(b.provider),\n ),\n });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n // ── Default model ───────────────────────────────────────────────────────\n\n registerApiRoute('/web/config/default-model', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const context = await resolveModelDefaultsContext({\n c: loose(c),\n auth,\n modelDefaults: options.modelDefaults,\n });\n if ('response' in context) return context.response;\n try {\n const record = await context.storage.get({ orgId: context.orgId, userId: context.userId });\n return c.json({ modelId: record?.modelId ?? null });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/default-model', {\n method: 'PUT',\n requiresAuth: false,\n handler: async c => {\n const context = await resolveModelDefaultsContext({\n c: loose(c),\n auth,\n modelDefaults: options.modelDefaults,\n });\n if ('response' in context) return context.response;\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const parsed = z.object({ modelId: z.string().trim().min(1).max(256) }).safeParse(body);\n if (!parsed.success) return c.json({ error: 'Missing required field: modelId' }, 400);\n const { modelId } = parsed.data;\n try {\n await context.storage.set({ orgId: context.orgId, userId: context.userId, modelId });\n return c.json({ ok: true, modelId });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/default-model', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async c => {\n const context = await resolveModelDefaultsContext({\n c: loose(c),\n auth,\n modelDefaults: options.modelDefaults,\n });\n if ('response' in context) return context.response;\n try {\n await context.storage.clear({ orgId: context.orgId, userId: context.userId });\n return c.json({ ok: true, modelId: null });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n // ── Thinking (reasoning-effort) defaults ─────────────────────────────────\n // Deployment-scoped defaults stored in the server's settings.json: the\n // global `preferences.thinkingLevel` plus per-mode\n // `models.modeThinkingDefaults`. These are what request-time resolution\n // falls back to when a session carries no explicit override — including\n // automated (rule-driven) Factory runs nobody opens interactively. In\n // tenant mode, writes are disabled because the settings file is shared\n // deployment-wide rather than scoped to an organization.\n\n registerApiRoute('/web/config/thinking', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n try {\n const settings = loadSettings(options.settingsPath);\n const modes = controller.listModes?.().map(mode => mode.id) ?? [];\n return c.json({\n levels: THINKING_LEVEL_VALUES,\n globalDefault: settings.preferences.thinkingLevel,\n modeDefaults: settings.models.modeThinkingDefaults,\n modes,\n editable: !auth.enabled(),\n });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/thinking', {\n method: 'PUT',\n requiresAuth: false,\n handler: async c => {\n if (auth.enabled()) {\n return c.json(\n {\n error:\n 'Deployment thinking defaults are shared by the whole deployment, so they cannot be changed while authentication is enabled',\n },\n 403,\n );\n }\n let body: { globalDefault?: unknown; modeDefaults?: unknown };\n try {\n const parsed: unknown = await c.req.json();\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return c.json({ error: 'Request body must be a JSON object' }, 400);\n }\n body = parsed as { globalDefault?: unknown; modeDefaults?: unknown };\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (body.globalDefault === undefined && body.modeDefaults === undefined) {\n return c.json({ error: 'Provide globalDefault and/or modeDefaults' }, 400);\n }\n if (body.globalDefault !== undefined && !isThinkingLevelSetting(body.globalDefault)) {\n return c.json(\n { error: `Invalid globalDefault — expected one of: ${THINKING_LEVEL_VALUES.join(', ')}` },\n 400,\n );\n }\n // Per-mode patch semantics: a valid level sets the mode's default,\n // `null` clears it (back to the global default).\n const modePatch: Record<string, ThinkingLevelSetting | null> = {};\n if (body.modeDefaults !== undefined) {\n if (!body.modeDefaults || typeof body.modeDefaults !== 'object' || Array.isArray(body.modeDefaults)) {\n return c.json({ error: 'modeDefaults must be an object of mode → level (or null to clear)' }, 400);\n }\n const knownModes = new Set(controller.listModes?.().map(mode => mode.id) ?? []);\n for (const [mode, level] of Object.entries(body.modeDefaults as Record<string, unknown>)) {\n if (!knownModes.has(mode)) {\n return c.json({ error: `Unknown mode \"${mode}\"` }, 400);\n }\n if (level === null) {\n modePatch[mode] = null;\n } else if (isThinkingLevelSetting(level)) {\n modePatch[mode] = level;\n } else {\n return c.json(\n { error: `Invalid level for mode \"${mode}\" — expected one of: ${THINKING_LEVEL_VALUES.join(', ')}` },\n 400,\n );\n }\n }\n }\n try {\n const settings = loadSettings(options.settingsPath);\n if (body.globalDefault !== undefined && isThinkingLevelSetting(body.globalDefault)) {\n settings.preferences.thinkingLevel = body.globalDefault;\n }\n for (const [mode, level] of Object.entries(modePatch)) {\n if (level === null) delete settings.models.modeThinkingDefaults[mode];\n else settings.models.modeThinkingDefaults[mode] = level;\n }\n saveSettings(settings, options.settingsPath);\n return c.json({\n ok: true,\n globalDefault: settings.preferences.thinkingLevel,\n modeDefaults: settings.models.modeThinkingDefaults,\n });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n // ── Observational memory ──────────────────────────────────────────────────\n // Mirrors the TUI's /om command. All five knobs are durably stored in the\n // per-(org, user) `memory-settings` app table — never settings.json or\n // mutable session state.\n\n registerApiRoute('/web/config/om', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resourceId = c.req.query('resourceId');\n const scope = c.req.query('scope') || undefined;\n const factoryProjectId = c.req.query('factoryId') || undefined;\n const context = await resolveMemorySettingsContext({\n c: loose(c),\n auth,\n memorySettings: options.memorySettings,\n factoryProjectId,\n factoryProjects: options.factoryProjects,\n });\n if ('response' in context) return context.response;\n try {\n const record = await context.storage.get({ orgId: context.orgId, userId: context.userId });\n const fallback = await factoryOmFallback(factoryProjectId);\n const availableProviders = await resolveOMResponseContext(loose(c));\n const session = resourceId ? await controller.getSessionByResource?.(resourceId, scope) : undefined;\n const sessionModelId = session?.model.get();\n return c.json({\n config: readStoredOMConfig(\n record,\n sessionModelId || fallback,\n sessionModelId ? 'live-session' : 'configured-default',\n availableProviders,\n ),\n });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/om/:role/model', {\n method: 'PUT',\n requiresAuth: false,\n handler: async c => {\n const role = c.req.param('role');\n if (role !== 'observer' && role !== 'reflector') {\n return c.json({ error: `Unknown OM role \"${role}\"` }, 400);\n }\n let body: { resourceId?: unknown; modelId?: unknown; scope?: unknown; factoryId?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const resourceId = typeof body.resourceId === 'string' ? body.resourceId : '';\n const scope = typeof body.scope === 'string' && body.scope ? body.scope : undefined;\n const factoryProjectId = typeof body.factoryId === 'string' && body.factoryId ? body.factoryId : undefined;\n const model = typeof body.modelId === 'string' ? body.modelId.trim() : '';\n if (!model) {\n return c.json({ error: 'Missing required field: modelId' }, 400);\n }\n // `'auto'` is selection intent, not a model ID: store null so the role\n // follows the active main model instead of pinning a model named \"auto\".\n const wantsAuto = model === 'auto';\n const context = await resolveMemorySettingsContext({\n c: loose(c),\n auth,\n memorySettings: options.memorySettings,\n factoryProjectId,\n factoryProjects: options.factoryProjects,\n });\n if ('response' in context) return context.response;\n // Resolve the response context before persisting: a provider-enumeration\n // failure must not report 500 for a write that already succeeded.\n const availableProviders = await resolveOMResponseContext(loose(c));\n try {\n await persistMemorySettings(context, {\n [role === 'observer' ? 'observerModelId' : 'reflectorModelId']: wantsAuto ? null : model,\n });\n const record = await context.storage.get({ orgId: context.orgId, userId: context.userId });\n const session = resourceId ? await controller.getSessionByResource?.(resourceId, scope) : undefined;\n const sessionModelId = session?.model.get();\n const config = readStoredOMConfig(\n record,\n sessionModelId || (await factoryOmFallback(factoryProjectId)),\n sessionModelId ? 'live-session' : 'configured-default',\n availableProviders,\n );\n return c.json({ ok: true, config });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/om/thresholds', {\n method: 'PUT',\n requiresAuth: false,\n handler: async c => {\n let body: {\n resourceId?: unknown;\n observationThreshold?: unknown;\n reflectionThreshold?: unknown;\n scope?: unknown;\n factoryId?: unknown;\n };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const resourceId = typeof body.resourceId === 'string' ? body.resourceId : '';\n const scope = typeof body.scope === 'string' && body.scope ? body.scope : undefined;\n const factoryProjectId = typeof body.factoryId === 'string' && body.factoryId ? body.factoryId : undefined;\n const observation =\n typeof body.observationThreshold === 'number' && body.observationThreshold > 0\n ? Math.round(body.observationThreshold)\n : undefined;\n const reflection =\n typeof body.reflectionThreshold === 'number' && body.reflectionThreshold > 0\n ? Math.round(body.reflectionThreshold)\n : undefined;\n if (observation === undefined && reflection === undefined) {\n return c.json({ error: 'Provide observationThreshold and/or reflectionThreshold (positive numbers)' }, 400);\n }\n const context = await resolveMemorySettingsContext({\n c: loose(c),\n auth,\n memorySettings: options.memorySettings,\n factoryProjectId,\n factoryProjects: options.factoryProjects,\n });\n if ('response' in context) return context.response;\n const availableProviders = await resolveOMResponseContext(loose(c));\n try {\n await persistMemorySettings(context, {\n ...(observation !== undefined ? { observationThreshold: observation } : {}),\n ...(reflection !== undefined ? { reflectionThreshold: reflection } : {}),\n });\n const record = await context.storage.get({ orgId: context.orgId, userId: context.userId });\n const session = resourceId ? await controller.getSessionByResource?.(resourceId, scope) : undefined;\n const sessionModelId = session?.model.get();\n const config = readStoredOMConfig(\n record,\n sessionModelId || (await factoryOmFallback(factoryProjectId)),\n sessionModelId ? 'live-session' : 'configured-default',\n availableProviders,\n );\n return c.json({ ok: true, config });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/om/observe-attachments', {\n method: 'PUT',\n requiresAuth: false,\n handler: async c => {\n let body: { resourceId?: unknown; value?: unknown; scope?: unknown; factoryId?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const resourceId = typeof body.resourceId === 'string' ? body.resourceId : '';\n const scope = typeof body.scope === 'string' && body.scope ? body.scope : undefined;\n const factoryProjectId = typeof body.factoryId === 'string' && body.factoryId ? body.factoryId : undefined;\n const raw = body.value;\n const value: 'auto' | boolean = raw === 'auto' || raw === true || raw === false ? raw : 'auto';\n if (raw !== 'auto' && raw !== true && raw !== false) {\n return c.json({ error: \"value must be 'auto', true, or false\" }, 400);\n }\n const context = await resolveMemorySettingsContext({\n c: loose(c),\n auth,\n memorySettings: options.memorySettings,\n factoryProjectId,\n factoryProjects: options.factoryProjects,\n });\n if ('response' in context) return context.response;\n const availableProviders = await resolveOMResponseContext(loose(c));\n try {\n await persistMemorySettings(context, { observeAttachments: value });\n const record = await context.storage.get({ orgId: context.orgId, userId: context.userId });\n const session = resourceId ? await controller.getSessionByResource?.(resourceId, scope) : undefined;\n const sessionModelId = session?.model.get();\n const config = readStoredOMConfig(\n record,\n sessionModelId || (await factoryOmFallback(factoryProjectId)),\n sessionModelId ? 'live-session' : 'configured-default',\n availableProviders,\n );\n return c.json({ ok: true, config });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n ];\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.js","names":[],"sources":["../../src/routes/config.ts"],"sourcesContent":["import { MastraCodeGateway } from '@mastra/code-sdk/agents/mastracode-gateway';\nimport type { AuthStorage } from '@mastra/code-sdk/auth/storage';\nimport { resolveAutoOMModelId } from '@mastra/code-sdk/onboarding/packs';\nimport type { ProviderAccess, ProviderAccessLevel } from '@mastra/code-sdk/onboarding/packs';\nimport {\n getCustomProviderId,\n isThinkingLevelSetting,\n loadSettings,\n MASTRA_GATEWAY_PROVIDER,\n saveSettings,\n THINKING_LEVEL_VALUES,\n} from '@mastra/code-sdk/onboarding/settings';\nimport type { CustomProviderSetting, ThinkingLevelSetting } from '@mastra/code-sdk/onboarding/settings';\nimport { AMAZON_BEDROCK_GATEWAY_ID } from '@mastra/code-sdk/providers/amazon-bedrock-gateway';\nimport { MASTRA_GATEWAY_PREFIX } from '@mastra/code-sdk/providers/model-ids';\nimport { getModelReasoningOptions } from '@mastra/core/llm';\nimport type { ApiRoute } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\n\nimport type { Context } from 'hono';\nimport { z } from 'zod';\nimport { DEFAULT_OBSERVATION_THRESHOLD, DEFAULT_REFLECTION_THRESHOLD } from '../session/memory-settings-hydration.js';\nimport type {\n CredentialRecord,\n LoginSessionKind,\n ModelCredentialsStorage,\n} from '../storage/domains/credentials/base.js';\nimport type { CustomProviderRecord, CustomProvidersStorage } from '../storage/domains/custom-providers/base.js';\nimport { factoryMemorySettingsUserId } from '../storage/domains/memory-settings/base.js';\nimport type {\n MemorySettingsPatch,\n MemorySettingsRecord,\n MemorySettingsStorage,\n} from '../storage/domains/memory-settings/base.js';\nimport type { ModelDefaultsStorage } from '../storage/domains/model-defaults/base.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type { SourceControlStorageHandle } from '../storage/domains/source-control/base.js';\nimport {\n getAuthProviderId,\n listTenantCredentialsForRequest,\n resolveCredentialContext,\n tenantOrgId,\n WEB_OAUTH_FLOW_KINDS,\n} from './provider-credentials.js';\nimport { Route } from './route.js';\nimport type { RouteAuth, RouteDependencies } from './route.js';\n\n/** Widen a route-local Hono context to the plain `Context` the auth helpers take. */\nfunction loose(c: unknown): Context {\n return c as Context;\n}\n\n/**\n * Server-side configuration routes for the web app.\n *\n * The browser has no access to the credential store or the model catalog, so\n * the web settings panel asks the server — which owns both — to list providers\n * and manage API keys. This mirrors the TUI's `/api-keys` command, exposing the\n * same `AuthStorage`-backed key management over HTTP.\n *\n * Keys are never returned to the client; only their presence and source.\n */\n\n/**\n * Where a provider's active credential comes from, as seen by the caller.\n * Local mode reports `oauth`/`stored` (server-global `auth.json`); tenant mode\n * reports the scoped variants (`oauth-user`/`stored-user`/`stored-org`).\n * `deployment` (tenant mode) marks a provider the operator opted in to run on\n * the server process's own credentials (e.g. Amazon Bedrock's AWS chain).\n */\nexport type ProviderCredentialSource =\n | 'deployment'\n | 'oauth'\n | 'stored'\n | 'env'\n | 'none'\n | 'oauth-user'\n | 'oauth-org'\n | 'stored-user'\n | 'stored-org';\n\n/** A model provider with the current source of its credentials. */\nexport interface ProviderInfo {\n provider: string;\n /** Env var the provider's key is read from, if any. */\n envVar?: string;\n /** Where the active credential comes from. */\n source: ProviderCredentialSource;\n /**\n * Tenant mode: whether an org-wide API key exists for this provider, even\n * when the caller's personal credential shadows it. Lets the UI tell\n * \"shared with the org\" apart from \"only works for me\".\n */\n orgKey?: boolean;\n /**\n * Tenant mode: the caller's personal credential for this provider, if any.\n * Reported independently of `source` so the UI can manage each scope even\n * when one shadows the other.\n */\n userCredential?: 'oauth' | 'api_key';\n /** Tenant mode: the shared org credential for this provider, if any. */\n orgCredential?: 'oauth' | 'api_key';\n /** Web OAuth sign-in capability, when the provider supports it. */\n oauth?: { supported: true; modes: LoginSessionKind[] };\n}\n\n/** Minimal session surface the config routes touch. */\nexport interface OMSession {\n /** `get()` returns '' when no model is selected, so callers fall back on falsy. */\n model: { get: () => string };\n}\n\n/** Minimal controller surface this module needs (model catalog + modes + sessions). */\ninterface ModelCatalog {\n listAvailableModels: () => Promise<\n Array<{ id?: string; modelName?: string; provider: string; hasApiKey: boolean; apiKeyEnvVar?: string }>\n >;\n listModes?: () => Array<{ id: string; defaultModelId?: string }>;\n getSessionByResource?: (resourceId: string, scope?: string) => Promise<OMSession | undefined>;\n}\n\n/**\n * Build a deduplicated, sorted list of providers from the model catalog,\n * annotated with where each provider's credential currently comes from.\n * Mirrors the TUI's `/api-keys` provider list.\n *\n * When `tenantCredentials` is given (deployed mode), sources reflect the\n * *caller's* tenant rows with user > org precedence and the server-global\n * `authStorage` is ignored; otherwise the local `auth.json` view is reported.\n */\nexport async function listProviders({\n controller,\n authStorage,\n tenantCredentials,\n deploymentProviders,\n}: {\n controller: ModelCatalog;\n authStorage?: AuthStorage;\n tenantCredentials?: CredentialRecord[];\n deploymentProviders?: ReadonlySet<string>;\n}): Promise<ProviderInfo[]> {\n const models = await controller.listAvailableModels();\n const seen = new Map<string, ProviderInfo>();\n\n for (const model of models) {\n if (seen.has(model.provider)) continue;\n\n if (tenantCredentials && isDeploymentModelProvider(model.provider)) {\n // Credentials for these providers live on the server process, never in\n // tenant rows, so no account can connect them. List them only when the\n // operator opted the deployment in and the server has credentials.\n const usable =\n deploymentProviders?.has(model.provider) && models.some(m => m.provider === model.provider && m.hasApiKey);\n if (usable) seen.set(model.provider, { provider: model.provider, source: 'deployment' });\n continue;\n }\n\n const authProviderId = getAuthProviderId(model.provider);\n let source: ProviderInfo['source'] = 'none';\n let orgKey: boolean | undefined;\n let userCredential: ProviderInfo['userCredential'];\n let orgCredential: ProviderInfo['orgCredential'];\n if (tenantCredentials) {\n const userRec = tenantCredentials.find(r => r.scope === 'user' && r.provider === authProviderId);\n const orgRec = tenantCredentials.find(r => r.scope === 'org' && r.provider === authProviderId);\n // Any shared org credential (API key or org-wide OAuth) counts.\n orgKey = orgRec !== undefined;\n userCredential = userRec?.credential.type;\n orgCredential = orgRec?.credential.type;\n if (userRec?.credential.type === 'oauth') {\n source = 'oauth-user';\n } else if (userRec?.credential.type === 'api_key') {\n source = 'stored-user';\n } else if (orgRec?.credential.type === 'oauth') {\n source = 'oauth-org';\n } else if (orgRec?.credential.type === 'api_key') {\n source = 'stored-org';\n }\n } else if (authStorage?.isLoggedIn(authProviderId)) {\n source = 'oauth';\n } else if (authStorage?.hasStoredApiKey(model.provider)) {\n source = 'stored';\n } else if (model.apiKeyEnvVar && process.env[model.apiKeyEnvVar]) {\n source = 'env';\n } else if (model.hasApiKey) {\n source = 'env';\n }\n\n const flowKind = WEB_OAUTH_FLOW_KINDS[model.provider];\n seen.set(model.provider, {\n provider: model.provider,\n envVar: model.apiKeyEnvVar,\n source,\n ...(orgKey !== undefined ? { orgKey } : {}),\n ...(userCredential ? { userCredential } : {}),\n ...(orgCredential ? { orgCredential } : {}),\n ...(flowKind ? { oauth: { supported: true as const, modes: [flowKind] } } : {}),\n });\n }\n\n return Array.from(seen.values()).sort((a, b) => a.provider.localeCompare(b.provider));\n}\n\n/** A user-defined OpenAI-compatible provider, with key presence (never the key). */\nexport interface CustomProviderInfo {\n id: string;\n name: string;\n url: string;\n hasApiKey: boolean;\n models: string[];\n}\n\n/** Redact a stored custom-provider row for the client (key presence only). */\nfunction toCustomProviderInfo(record: CustomProviderRecord): CustomProviderInfo {\n return {\n id: record.providerId,\n name: record.name,\n url: record.url,\n hasApiKey: Boolean(record.apiKey),\n models: record.models,\n };\n}\n\n/** The resolved custom-providers storage scope for a request. */\ninterface CustomProvidersContext {\n storage: CustomProvidersStorage;\n orgId: string;\n userId: string;\n}\n\n/**\n * Resolve the custom-providers context for a request, or a ready-to-return\n * error response. Same posture as memory settings: tenant rows in deployed\n * mode, a sentinel `local` org in no-auth mode — never settings.json.\n */\nasync function resolveCustomProvidersContext({\n c,\n auth,\n customProviders,\n}: {\n c: Context;\n auth: RouteAuth;\n customProviders?: CustomProvidersStorage;\n}): Promise<CustomProvidersContext | { response: Response }> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant && auth.enabled()) return { response: c.json({ error: 'unauthorized' }, 401) };\n if (customProviders) {\n try {\n await customProviders.ensureReady();\n return tenant\n ? { storage: customProviders, orgId: tenantOrgId(tenant), userId: tenant.userId }\n : { storage: customProviders, orgId: 'local', userId: 'local' };\n } catch {\n // fall through to the unavailable response\n }\n }\n return {\n response: c.json(\n {\n error: 'custom_providers_unavailable',\n message: 'Custom provider storage is unavailable — the app database is not configured or failed to start.',\n },\n 503,\n ),\n };\n}\n\n/** Validate + coerce a request body into a CustomProviderSetting. */\nfunction parseCustomProviderBody(body: unknown): CustomProviderSetting | { error: string } {\n if (!body || typeof body !== 'object') return { error: 'Invalid JSON body' };\n const b = body as Record<string, unknown>;\n const name = typeof b.name === 'string' ? b.name.trim() : '';\n if (!name) return { error: 'Missing required field: name' };\n const url = typeof b.url === 'string' ? b.url.trim() : '';\n if (!url) return { error: 'Missing required field: url' };\n try {\n const parsed = new URL(url);\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n return { error: 'url must be an http(s) URL' };\n }\n } catch {\n return { error: 'url must be a valid URL' };\n }\n const apiKey = typeof b.apiKey === 'string' && b.apiKey.trim() ? b.apiKey.trim() : undefined;\n const models = Array.isArray(b.models)\n ? b.models.filter((m): m is string => typeof m === 'string' && m.trim().length > 0).map(m => m.trim())\n : [];\n return { name, url, apiKey, models };\n}\n\n// ── Available models ───────────────────────────────────────────────────────\n\n/**\n * Providers whose credentials can only come from the server process (Amazon\n * Bedrock authenticates through the AWS credential chain). In tenant mode they\n * are usable only when the operator lists them in\n * `MastraFactoryConfig.deploymentModelProviders`.\n */\nexport const DEPLOYMENT_MODEL_PROVIDERS: readonly string[] = [AMAZON_BEDROCK_GATEWAY_ID];\n\nexport function isDeploymentModelProvider(provider: string): boolean {\n return DEPLOYMENT_MODEL_PROVIDERS.includes(provider);\n}\n\n/**\n * Normalize the operator's `deploymentModelProviders` list. Unsupported ids are\n * ignored with a warning rather than failing boot.\n */\nexport function resolveDeploymentModelProviders(providers: readonly string[] | undefined): ReadonlySet<string> {\n const resolved = new Set<string>();\n for (const raw of providers ?? []) {\n const provider = raw.trim();\n if (!provider) continue;\n if (isDeploymentModelProvider(provider)) {\n resolved.add(provider);\n } else {\n console.warn(\n `[factory] Ignoring deployment model provider \"${provider}\". Supported: ${DEPLOYMENT_MODEL_PROVIDERS.join(', ')}.`,\n );\n }\n }\n return resolved;\n}\n\n/**\n * Compute which providers the user can reach, mirroring the TUI's\n * `/models-pack` access derivation: OAuth/api-key from the credential store for\n * the named providers, plus any other provider that has a usable key.\n */\nexport async function buildProviderAccess({\n controller,\n authStorage,\n tenantCredentials,\n deploymentProviders,\n}: {\n controller: ModelCatalog;\n authStorage?: AuthStorage;\n tenantCredentials?: CredentialRecord[];\n deploymentProviders?: ReadonlySet<string>;\n}): Promise<ProviderAccess> {\n const models = await controller.listAvailableModels();\n const hasModelKey = (provider: string) => models.some(m => m.provider === provider && m.hasApiKey);\n const accessLevel = (provider: string): ProviderAccessLevel => {\n const authProviderId = getAuthProviderId(provider);\n if (tenantCredentials) {\n // Tenant rows never authenticate these providers; only an operator\n // opt-in plus credentials on the server process does.\n if (isDeploymentModelProvider(provider)) {\n return deploymentProviders?.has(provider) && hasModelKey(provider) ? 'apikey' : false;\n }\n const userRec = tenantCredentials.find(r => r.scope === 'user' && r.provider === authProviderId);\n const orgRec = tenantCredentials.find(r => r.scope === 'org' && r.provider === authProviderId);\n const credential = userRec?.credential ?? orgRec?.credential;\n if (credential?.type === 'oauth') return 'oauth';\n if (credential?.type === 'api_key' && credential.key.trim().length > 0) return 'apikey';\n return false;\n }\n\n const oauthCredential = authStorage?.get(authProviderId);\n if (oauthCredential?.type === 'oauth') return 'oauth';\n if (authStorage?.hasStoredApiKey(provider)) return 'apikey';\n const directCredential = authStorage?.get(provider);\n if (directCredential?.type === 'api_key' && directCredential.key.trim().length > 0) return 'apikey';\n return hasModelKey(provider) ? 'apikey' : false;\n };\n const access: ProviderAccess = {\n anthropic: accessLevel('anthropic'),\n openai: accessLevel('openai'),\n cerebras: accessLevel('cerebras'),\n google: accessLevel('google'),\n deepseek: accessLevel('deepseek'),\n 'github-copilot': accessLevel('github-copilot'),\n };\n const seen = new Set(Object.keys(access));\n for (const m of models) {\n if (!seen.has(m.provider)) {\n access[m.provider] = accessLevel(m.provider);\n seen.add(m.provider);\n }\n }\n return access;\n}\n\nfunction canUseModelProvider(access: ProviderAccess, provider: string): boolean {\n return Boolean(access[provider]);\n}\n\n// ── Default model ──────────────────────────────────────────────────────────\n\n/** Per-user default model context for the current request. */\nexport interface ModelDefaultsContext {\n storage: ModelDefaultsStorage;\n orgId: string;\n userId: string;\n}\n\n/** Resolve the default-model context for a request, or a ready-to-return error response. */\nasync function resolveModelDefaultsContext({\n c,\n auth,\n modelDefaults,\n}: {\n c: Context;\n auth: RouteAuth;\n modelDefaults?: ModelDefaultsStorage;\n}): Promise<ModelDefaultsContext | { response: Response }> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant && auth.enabled()) return { response: c.json({ error: 'unauthorized' }, 401) };\n if (modelDefaults) {\n try {\n await modelDefaults.ensureReady();\n return tenant\n ? { storage: modelDefaults, orgId: tenantOrgId(tenant), userId: tenant.userId }\n : { storage: modelDefaults, orgId: 'local', userId: 'local' };\n } catch {\n // fall through to the unavailable response\n }\n }\n return {\n response: c.json(\n {\n error: 'model_defaults_unavailable',\n message: 'Default model storage is unavailable — the app database is not configured or failed to start.',\n },\n 503,\n ),\n };\n}\n\n// ── Observational memory ────────────────────────────────────────────────────\n// Mirrors the TUI `/om` command. Settings are persisted per organization and\n// user in the Factory app database, then loaded into request context for each\n// invocation without copying them into mutable session state.\n\nexport interface OMRoleConfigInfo {\n model: 'auto' | string;\n effectiveModelId: string;\n effectiveModelSource: 'explicit' | 'live-session' | 'configured-default';\n providerStatus: 'available' | 'unavailable';\n}\n\n/** Persisted intent plus the concrete models the current Factory configuration resolves. */\nexport interface OMConfigInfo {\n observer: OMRoleConfigInfo;\n reflector: OMRoleConfigInfo;\n /** @deprecated Use `observer.effectiveModelId`. */\n observerModelId: string;\n /** @deprecated Use `reflector.effectiveModelId`. */\n reflectorModelId: string;\n observationThreshold: number;\n reflectionThreshold: number;\n observeAttachments: 'auto' | boolean;\n}\n\nexport interface ProviderOMDefaultsResponse {\n ok: true;\n config: OMConfigInfo;\n}\n\n/** `GET /web/config/thinking` — deployment-scoped reasoning-effort defaults. */\nexport interface ThinkingConfigInfo {\n /** All selectable levels, in escalation order. */\n levels: readonly ThinkingLevelSetting[];\n /** `preferences.thinkingLevel` — fallback when a mode has no default. */\n globalDefault: ThinkingLevelSetting;\n /** `models.modeThinkingDefaults` — per-mode overrides of the global default. */\n modeDefaults: Record<string, ThinkingLevelSetting>;\n /** Mode ids known to the controller (for rendering per-mode rows). */\n modes: string[];\n /** False when the deployment refuses writes, so the UI can render read-only rows. */\n editable: boolean;\n}\n\n/** `PUT /web/config/thinking` success payload. */\nexport interface UpdateThinkingConfigResponse {\n ok: true;\n globalDefault: ThinkingLevelSetting;\n modeDefaults: Record<string, ThinkingLevelSetting>;\n}\n\nfunction modelProvider(modelId: string): string {\n // Effective IDs keep their `mastra/` route; the provider segment after it is what\n // the SDK resolver falls back to when the gateway is not configured.\n const normalized = modelId.replace(/^mastracode\\//, '').replace(/^mastra\\//, '');\n return normalized.split('/', 1)[0] ?? '';\n}\n\nfunction roleConfig(\n model: OMRoleConfigInfo['model'],\n effectiveModelId: string,\n autoModelSource: 'live-session' | 'configured-default',\n availableProviders: ReadonlySet<string>,\n): OMRoleConfigInfo {\n return {\n model,\n effectiveModelId,\n effectiveModelSource: model === 'auto' ? autoModelSource : 'explicit',\n providerStatus:\n availableProviders.has(modelProvider(effectiveModelId)) ||\n (effectiveModelId.startsWith(MASTRA_GATEWAY_PREFIX) && availableProviders.has(MASTRA_GATEWAY_PROVIDER))\n ? 'available'\n : 'unavailable',\n };\n}\n\nfunction readStoredOMConfig(\n record: MemorySettingsRecord | null,\n currentModelId: string | undefined,\n autoModelSource: 'live-session' | 'configured-default',\n availableProviders: ReadonlySet<string>,\n): OMConfigInfo {\n const autoModelId = resolveAutoOMModelId(currentModelId);\n const observerModelId = record?.observerModelId ?? autoModelId;\n const reflectorModelId = record?.reflectorModelId ?? autoModelId;\n return {\n observer: roleConfig(record?.observerModelId ?? 'auto', observerModelId, autoModelSource, availableProviders),\n reflector: roleConfig(record?.reflectorModelId ?? 'auto', reflectorModelId, autoModelSource, availableProviders),\n observerModelId,\n reflectorModelId,\n observationThreshold: record?.observationThreshold ?? DEFAULT_OBSERVATION_THRESHOLD,\n reflectionThreshold: record?.reflectionThreshold ?? DEFAULT_REFLECTION_THRESHOLD,\n observeAttachments: record?.observeAttachments ?? 'auto',\n };\n}\n\n/**\n * Where a request's OM settings live: the `memory-settings` factory storage\n * domain, one row per (org, user). Without a tenant (auth disabled), settings\n * land on a sentinel `(local, local)` row in the same table — the web surface\n * never reads or writes `settings.json` for memory settings.\n */\ninterface MemorySettingsContext {\n storage: MemorySettingsStorage;\n orgId: string;\n userId: string;\n}\n\n/**\n * Resolve the memory-settings context for a request, or a ready-to-return\n * error response. When `factoryProjectId` is provided the row addressed is the\n * factory project's shared settings (a sentinel user id in the caller's org)\n * instead of the caller's personal row — this is what factory board runs and\n * channel sessions hydrate from.\n */\nasync function resolveMemorySettingsContext({\n c,\n auth,\n memorySettings,\n factoryProjectId,\n factoryProjects,\n}: {\n c: Context;\n auth: RouteAuth;\n memorySettings?: MemorySettingsStorage;\n factoryProjectId?: string;\n factoryProjects?: FactoryProjectsStorage;\n}): Promise<MemorySettingsContext | { response: Response }> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant && auth.enabled()) return { response: c.json({ error: 'unauthorized' }, 401) };\n // Factory-scoped rows are shared org state: the target project must exist in\n // the caller's org before its settings row can be read or written.\n if (factoryProjectId && tenant) {\n if (!factoryProjects) return { response: c.json({ error: 'factory_unavailable' }, 503) };\n try {\n await factoryProjects.ensureReady();\n const project = await factoryProjects.get({ orgId: tenantOrgId(tenant), id: factoryProjectId });\n if (!project) return { response: c.json({ error: 'factory_project_not_found' }, 404) };\n } catch {\n return { response: c.json({ error: 'factory_unavailable' }, 503) };\n }\n }\n if (memorySettings) {\n try {\n await memorySettings.ensureReady();\n const factoryUserId = factoryProjectId ? factoryMemorySettingsUserId(factoryProjectId) : undefined;\n return tenant\n ? { storage: memorySettings, orgId: tenantOrgId(tenant), userId: factoryUserId ?? tenant.userId }\n : { storage: memorySettings, orgId: 'local', userId: factoryUserId ?? 'local' };\n } catch {\n // fall through to the unavailable response\n }\n }\n return {\n response: c.json(\n {\n error: 'memory_settings_unavailable',\n message: 'Memory settings storage is unavailable — the app database is not configured or failed to start.',\n },\n 503,\n ),\n };\n}\n\n/** Persist an OM knob change to the caller's memory-settings row. */\nasync function persistMemorySettings(context: MemorySettingsContext, patch: MemorySettingsPatch): Promise<void> {\n await context.storage.patch({ orgId: context.orgId, userId: context.userId, patch });\n}\n\n/** Dependencies injected into {@link ConfigRoutes}. */\nexport interface ConfigRoutesDeps extends RouteDependencies {\n controller: ModelCatalog;\n features?: { knowledge: boolean };\n authStorage?: AuthStorage;\n /** Tenant credential domain handle; absent in local (no-DB) mode. */\n modelCredentials?: ModelCredentialsStorage;\n /** Tenant model-defaults domain handle; absent in local (no-DB) mode. */\n modelDefaults?: ModelDefaultsStorage;\n /** Source-control sessions available to config route integrations. */\n sourceControlSessions?: Pick<SourceControlStorageHandle['sessions'], 'getBySessionId'>;\n /** Tenant memory-settings domain handle; absent in local (no-DB) mode. */\n memorySettings?: MemorySettingsStorage;\n /** Factory projects domain, used to derive OM fallbacks from a factory's default model. */\n factoryProjects?: FactoryProjectsStorage;\n /** Custom-providers domain handle; absent when the app database is missing. */\n customProviders?: CustomProvidersStorage;\n /** Notifies the host after tenant credentials change so caches can be dropped. */\n onCredentialsChanged?: (tenant: { orgId: string; userId?: string }) => void;\n /** Notifies the host after custom providers change so model-router caches can be dropped. */\n onCustomProvidersChanged?: (tenant: { orgId: string }) => void;\n /**\n * Tenant mode: providers the operator opted in to run on the server process's\n * own credentials (see `DEPLOYMENT_MODEL_PROVIDERS`).\n */\n deploymentProviders?: ReadonlySet<string>;\n /**\n * Path of the server's settings.json backing the deployment-scoped thinking\n * defaults. Defaults to the standard app-data location; injectable for tests.\n */\n settingsPath?: string;\n /**\n * Organization this deployment serves (`MASTRACODE_DEPLOYMENT_ORGANIZATION_ID`).\n * When auth is enabled, only admins of this organization may write\n * deployment-wide settings; without it those writes stay blocked.\n */\n deploymentOrganizationId?: string;\n}\n\n/**\n * The web config routes as Mastra `apiRoutes`:\n * - `GET /web/config/features` — list server-enabled product features\n * - `GET /web/config/providers` — list providers + key source\n * - `PUT /web/config/providers/:provider/key` — set/update a provider's API key\n * - `DELETE /web/config/providers/:provider/key` — remove a stored API key\n * - `GET /web/config/models` — list available models (credentialed providers)\n * - `GET /web/config/custom-providers` — list custom OpenAI-compatible providers\n * - `POST /web/config/custom-providers` — create/update a custom provider\n * - `DELETE /web/config/custom-providers/:id` — remove a custom provider\n * - `GET /web/config/thinking` — read thinking (reasoning-effort) defaults\n * - `PUT /web/config/thinking` — set global/per-mode thinking defaults\n * - `GET /web/config/om` — read OM models/thresholds/observe-attachments\n * - `PUT /web/config/om/:role/model` — switch observer/reflector model\n * - `PUT /web/config/om/thresholds` — set observation/reflection thresholds\n * - `PUT /web/config/om/observe-attachments` — set observe-attachments (auto/on/off)\n */\nexport class ConfigRoutes extends Route<ConfigRoutesDeps> {\n routes(): ApiRoute[] {\n const options = this.deps;\n const { controller, authStorage, auth, deploymentProviders } = options;\n const onCredentialsChanged = options.onCredentialsChanged ?? (() => {});\n const onCustomProvidersChanged = options.onCustomProvidersChanged ?? (() => {});\n\n const resolveOMResponseContext = async (c: Context) => {\n const tenantCredentials = await listTenantCredentialsForRequest({\n c: loose(c),\n auth,\n credentials: options.modelCredentials,\n });\n const access = await buildProviderAccess({\n controller,\n authStorage: tenantCredentials ? undefined : authStorage,\n tenantCredentials,\n deploymentProviders,\n });\n const availableProviders = new Set(\n Object.entries(access).flatMap(([providerId, configured]) => (configured ? [providerId] : [])),\n );\n // `mastra/` routes run through the Mastra gateway whenever its key is configured.\n if (MastraCodeGateway.getMastraGatewayApiKey()) availableProviders.add(MASTRA_GATEWAY_PROVIDER);\n if (options.customProviders) {\n const context = await resolveCustomProvidersContext({\n c: loose(c),\n auth,\n customProviders: options.customProviders,\n });\n if (!('response' in context)) {\n for (const provider of await context.storage.list({ orgId: context.orgId })) {\n availableProviders.add(provider.providerId);\n }\n }\n }\n return availableProviders;\n };\n\n // Factory-scoped OM reads without a stored row fall back to the low-cost\n // OM model of the factory default model's provider — not the global\n // built-in default, whose provider may have no credential here.\n const factoryOmFallback = async (factoryProjectId: string | undefined): Promise<string | undefined> => {\n try {\n const defaultModelId = factoryProjectId\n ? await options.factoryProjects\n ?.getById({ id: factoryProjectId })\n .then(project => project?.defaultModelId ?? undefined)\n : controller.listModes?.().find(mode => mode.defaultModelId)?.defaultModelId;\n return defaultModelId ? resolveAutoOMModelId(defaultModelId) : undefined;\n } catch {\n return undefined;\n }\n };\n\n const deploymentThinkingAccess = async (\n c: Context,\n ): Promise<{ ok: true } | { ok: false; status: 401 | 403; error: string; message?: string }> => {\n if (!auth.enabled()) return { ok: true };\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant) return { ok: false, status: 401, error: 'unauthorized' };\n const orgId = tenantOrgId(tenant);\n if (!options.deploymentOrganizationId || orgId !== options.deploymentOrganizationId) {\n return {\n ok: false,\n status: 403,\n error: 'deployment_organization_required',\n message:\n \"Deployment thinking defaults are shared by the whole deployment. Set MASTRACODE_DEPLOYMENT_ORGANIZATION_ID to let that organization's admins change them while authentication is enabled\",\n };\n }\n if (!(await auth.isOrganizationAdmin(c, orgId))) {\n return {\n ok: false,\n status: 403,\n error: 'organization_admin_required',\n message: 'Only organization admins can change deployment thinking defaults while authentication is enabled',\n };\n }\n return { ok: true };\n };\n\n return [\n registerApiRoute('/web/config/features', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => c.json({ knowledge: options.features?.knowledge ?? false }),\n }),\n\n registerApiRoute('/web/config/providers', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n try {\n // Tenant mode lists the caller's rows and never exposes the\n // server-global auth.json; local mode is unchanged.\n const tenantCredentials = await listTenantCredentialsForRequest({\n c: loose(c),\n auth,\n credentials: options.modelCredentials,\n });\n // Tenant mode also reports whether the caller may write org-wide\n // keys, so the settings UI can gate the \"Everyone in org\" option.\n const tenant = auth.tenant(loose(c));\n const orgKeyAdmin = tenant ? await auth.isOrganizationAdmin(loose(c), tenantOrgId(tenant)) : undefined;\n return c.json({\n providers: await listProviders({\n controller,\n authStorage: tenantCredentials ? undefined : authStorage,\n tenantCredentials,\n deploymentProviders,\n }),\n ...(orgKeyAdmin !== undefined ? { orgKeyAdmin } : {}),\n });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/providers/:provider/key', {\n method: 'PUT',\n requiresAuth: false,\n handler: async c => {\n const ctx = await resolveCredentialContext({ c: loose(c), auth, credentials: options.modelCredentials });\n if ('response' in ctx) return ctx.response;\n\n const provider = c.req.param('provider');\n let body: { key?: unknown; envVar?: unknown; scope?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const key = typeof body.key === 'string' ? body.key.trim() : '';\n if (!key) return c.json({ error: 'Missing required field: key' }, 400);\n const envVar = typeof body.envVar === 'string' ? body.envVar : undefined;\n const scope = body.scope === 'org' ? 'org' : 'user';\n try {\n if (ctx.mode === 'tenant') {\n // A stored key would never be read: these providers authenticate\n // with the server process's credentials only.\n if (isDeploymentModelProvider(provider)) {\n return c.json(\n {\n error: 'provider_configured_by_deployment',\n message: `${provider} is configured by the Factory deployment (credentials on the server), not per account.`,\n },\n 400,\n );\n }\n if (scope === 'org' && !(await auth.isOrganizationAdmin(loose(c), ctx.orgId))) {\n return c.json({ error: 'organization_admin_required' }, 403);\n }\n const tenant = scope === 'org' ? { orgId: ctx.orgId } : { orgId: ctx.orgId, userId: ctx.userId };\n // envVar is intentionally ignored: tenant credentials are resolved\n // per-request, never written into process.env.\n await ctx.storage.setCredential(tenant, getAuthProviderId(provider), { type: 'api_key', key });\n onCredentialsChanged(tenant);\n const records = await ctx.storage.listCredentials(ctx.orgId, ctx.userId);\n const providers = await listProviders({ controller, tenantCredentials: records, deploymentProviders });\n return c.json({ ok: true, provider: providers.find(p => p.provider === provider) });\n }\n if (!authStorage) return c.json({ error: 'Credential storage is not available' }, 503);\n // Local mode is single-user: scope is meaningless and ignored.\n authStorage.setStoredApiKey(provider, key, envVar);\n const providers = await listProviders({ controller, authStorage });\n return c.json({ ok: true, provider: providers.find(p => p.provider === provider) });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/providers/:provider/key', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async c => {\n const ctx = await resolveCredentialContext({ c: loose(c), auth, credentials: options.modelCredentials });\n if ('response' in ctx) return ctx.response;\n\n const provider = c.req.param('provider');\n const scope = c.req.query('scope') === 'org' ? 'org' : 'user';\n try {\n if (ctx.mode === 'tenant') {\n if (scope === 'org' && !(await auth.isOrganizationAdmin(loose(c), ctx.orgId))) {\n return c.json({ error: 'organization_admin_required' }, 403);\n }\n const tenant = scope === 'org' ? { orgId: ctx.orgId } : { orgId: ctx.orgId, userId: ctx.userId };\n await ctx.storage.removeCredential(tenant, getAuthProviderId(provider));\n onCredentialsChanged(tenant);\n const records = await ctx.storage.listCredentials(ctx.orgId, ctx.userId);\n const providers = await listProviders({ controller, tenantCredentials: records, deploymentProviders });\n return c.json({ ok: true, provider: providers.find(p => p.provider === provider) });\n }\n if (!authStorage) return c.json({ error: 'Credential storage is not available' }, 503);\n authStorage.remove(`apikey:${provider}`);\n const providers = await listProviders({ controller, authStorage });\n return c.json({ ok: true, provider: providers.find(p => p.provider === provider) });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n // ── Custom providers (OpenAI-compatible endpoints) ──────────────────────\n // Mirrors the TUI's /custom-providers command, but backed by the\n // `custom-providers` domain (org rows in tenant mode, a sentinel `local`\n // org in no-auth mode) — the server never reads settings.json for these.\n\n registerApiRoute('/web/config/custom-providers', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const ctx = await resolveCustomProvidersContext({\n c: loose(c),\n auth,\n customProviders: options.customProviders,\n });\n if ('response' in ctx) return ctx.response;\n try {\n const records = await ctx.storage.list({ orgId: ctx.orgId });\n return c.json({ providers: records.map(toCustomProviderInfo) });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/custom-providers', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const ctx = await resolveCustomProvidersContext({\n c: loose(c),\n auth,\n customProviders: options.customProviders,\n });\n if ('response' in ctx) return ctx.response;\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const parsed = parseCustomProviderBody(body);\n if ('error' in parsed) return c.json({ error: parsed.error }, 400);\n // `previousId` lets a rename remove the old entry as well as any name clash.\n const previousId =\n body && typeof body === 'object' && typeof (body as Record<string, unknown>).previousId === 'string'\n ? ((body as Record<string, unknown>).previousId as string)\n : undefined;\n try {\n const record = await ctx.storage.upsert({\n orgId: ctx.orgId,\n userId: ctx.userId,\n input: {\n providerId: getCustomProviderId(parsed.name),\n name: parsed.name,\n url: parsed.url,\n apiKey: parsed.apiKey,\n models: parsed.models,\n },\n previousProviderId: previousId,\n });\n onCustomProvidersChanged({ orgId: ctx.orgId });\n return c.json({ ok: true, provider: toCustomProviderInfo(record) });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/custom-providers/:id', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async c => {\n const ctx = await resolveCustomProvidersContext({\n c: loose(c),\n auth,\n customProviders: options.customProviders,\n });\n if ('response' in ctx) return ctx.response;\n const id = c.req.param('id');\n try {\n await ctx.storage.delete({ orgId: ctx.orgId, providerId: id });\n onCustomProvidersChanged({ orgId: ctx.orgId });\n return c.json({ ok: true });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n // ── Available models ────────────────────────────────────────────────────\n // Session-independent model catalog for settings pickers (Factory default\n // model, pack editors). Only models whose provider has a credential are\n // returned — the same filter the session-scoped hook applies client-side.\n\n registerApiRoute('/web/config/models', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n try {\n const tenantCredentials = await listTenantCredentialsForRequest({\n c: loose(c),\n auth,\n credentials: options.modelCredentials,\n });\n const [models, access] = await Promise.all([\n controller.listAvailableModels(),\n buildProviderAccess({\n controller,\n authStorage: tenantCredentials ? undefined : authStorage,\n tenantCredentials,\n deploymentProviders,\n }),\n ]);\n const catalog = models.flatMap(({ id, provider, modelName }) =>\n typeof id === 'string' && canUseModelProvider(access, provider)\n ? [{ id, provider, modelName, hasApiKey: true, reasoningOptions: getModelReasoningOptions(id) }]\n : [],\n );\n // Append the caller's custom provider models (DB-backed, org rows in\n // tenant mode / sentinel `local` org in no-auth mode). The boot-time\n // gateway catalog only carries the local list, so tenant callers get\n // theirs here. Dedupe against ids already present.\n if (options.customProviders) {\n try {\n const ctx = await resolveCustomProvidersContext({\n c: loose(c),\n auth,\n customProviders: options.customProviders,\n });\n if (!('response' in ctx)) {\n const known = new Set(catalog.map(m => m.id));\n for (const record of await ctx.storage.list({ orgId: ctx.orgId })) {\n for (const model of record.models) {\n const id = `${record.providerId}/${model}`;\n if (known.has(id)) continue;\n known.add(id);\n catalog.push({\n id,\n provider: record.providerId,\n modelName: model,\n hasApiKey: true,\n reasoningOptions: undefined,\n });\n }\n }\n }\n } catch {\n // Fail soft: the catalog still serves the built-in models.\n }\n }\n return c.json({\n models: catalog.sort((a, b) =>\n a.provider === b.provider ? a.id.localeCompare(b.id) : a.provider.localeCompare(b.provider),\n ),\n });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n // ── Default model ───────────────────────────────────────────────────────\n\n registerApiRoute('/web/config/default-model', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const context = await resolveModelDefaultsContext({\n c: loose(c),\n auth,\n modelDefaults: options.modelDefaults,\n });\n if ('response' in context) return context.response;\n try {\n const record = await context.storage.get({ orgId: context.orgId, userId: context.userId });\n return c.json({ modelId: record?.modelId ?? null });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/default-model', {\n method: 'PUT',\n requiresAuth: false,\n handler: async c => {\n const context = await resolveModelDefaultsContext({\n c: loose(c),\n auth,\n modelDefaults: options.modelDefaults,\n });\n if ('response' in context) return context.response;\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const parsed = z.object({ modelId: z.string().trim().min(1).max(256) }).safeParse(body);\n if (!parsed.success) return c.json({ error: 'Missing required field: modelId' }, 400);\n const { modelId } = parsed.data;\n try {\n await context.storage.set({ orgId: context.orgId, userId: context.userId, modelId });\n return c.json({ ok: true, modelId });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/default-model', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async c => {\n const context = await resolveModelDefaultsContext({\n c: loose(c),\n auth,\n modelDefaults: options.modelDefaults,\n });\n if ('response' in context) return context.response;\n try {\n await context.storage.clear({ orgId: context.orgId, userId: context.userId });\n return c.json({ ok: true, modelId: null });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n // ── Thinking (reasoning-effort) defaults ─────────────────────────────────\n // Deployment-scoped defaults stored in the server's settings.json: the\n // global `preferences.thinkingLevel` plus per-mode\n // `models.modeThinkingDefaults`. These are what request-time resolution\n // falls back to when a session carries no explicit override — including\n // automated (rule-driven) Factory runs nobody opens interactively. When\n // auth is enabled, only signed-in admins of the configured deployment\n // organization may write them, because the settings file is shared by\n // the whole deployment.\n\n registerApiRoute('/web/config/thinking', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n try {\n const settings = loadSettings(options.settingsPath);\n const modes = controller.listModes?.().map(mode => mode.id) ?? [];\n return c.json({\n levels: THINKING_LEVEL_VALUES,\n globalDefault: settings.preferences.thinkingLevel,\n modeDefaults: settings.models.modeThinkingDefaults,\n modes,\n editable: (await deploymentThinkingAccess(loose(c))).ok,\n });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/thinking', {\n method: 'PUT',\n requiresAuth: false,\n handler: async c => {\n const access = await deploymentThinkingAccess(loose(c));\n if (!access.ok) {\n return c.json(\n { error: access.error, ...(access.message ? { message: access.message } : {}) },\n access.status,\n );\n }\n let body: { globalDefault?: unknown; modeDefaults?: unknown };\n try {\n const parsed: unknown = await c.req.json();\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return c.json({ error: 'Request body must be a JSON object' }, 400);\n }\n body = parsed as { globalDefault?: unknown; modeDefaults?: unknown };\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (body.globalDefault === undefined && body.modeDefaults === undefined) {\n return c.json({ error: 'Provide globalDefault and/or modeDefaults' }, 400);\n }\n if (body.globalDefault !== undefined && !isThinkingLevelSetting(body.globalDefault)) {\n return c.json(\n { error: `Invalid globalDefault — expected one of: ${THINKING_LEVEL_VALUES.join(', ')}` },\n 400,\n );\n }\n // Per-mode patch semantics: a valid level sets the mode's default,\n // `null` clears it (back to the global default).\n const modePatch: Record<string, ThinkingLevelSetting | null> = {};\n if (body.modeDefaults !== undefined) {\n if (!body.modeDefaults || typeof body.modeDefaults !== 'object' || Array.isArray(body.modeDefaults)) {\n return c.json({ error: 'modeDefaults must be an object of mode → level (or null to clear)' }, 400);\n }\n const knownModes = new Set(controller.listModes?.().map(mode => mode.id) ?? []);\n for (const [mode, level] of Object.entries(body.modeDefaults as Record<string, unknown>)) {\n if (!knownModes.has(mode)) {\n return c.json({ error: `Unknown mode \"${mode}\"` }, 400);\n }\n if (level === null) {\n modePatch[mode] = null;\n } else if (isThinkingLevelSetting(level)) {\n modePatch[mode] = level;\n } else {\n return c.json(\n { error: `Invalid level for mode \"${mode}\" — expected one of: ${THINKING_LEVEL_VALUES.join(', ')}` },\n 400,\n );\n }\n }\n }\n try {\n const settings = loadSettings(options.settingsPath);\n if (body.globalDefault !== undefined && isThinkingLevelSetting(body.globalDefault)) {\n settings.preferences.thinkingLevel = body.globalDefault;\n }\n for (const [mode, level] of Object.entries(modePatch)) {\n if (level === null) delete settings.models.modeThinkingDefaults[mode];\n else settings.models.modeThinkingDefaults[mode] = level;\n }\n saveSettings(settings, options.settingsPath);\n return c.json({\n ok: true,\n globalDefault: settings.preferences.thinkingLevel,\n modeDefaults: settings.models.modeThinkingDefaults,\n });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n // ── Observational memory ──────────────────────────────────────────────────\n // Mirrors the TUI's /om command. All five knobs are durably stored in the\n // per-(org, user) `memory-settings` app table — never settings.json or\n // mutable session state.\n\n registerApiRoute('/web/config/om', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resourceId = c.req.query('resourceId');\n const scope = c.req.query('scope') || undefined;\n const factoryProjectId = c.req.query('factoryId') || undefined;\n const context = await resolveMemorySettingsContext({\n c: loose(c),\n auth,\n memorySettings: options.memorySettings,\n factoryProjectId,\n factoryProjects: options.factoryProjects,\n });\n if ('response' in context) return context.response;\n try {\n const record = await context.storage.get({ orgId: context.orgId, userId: context.userId });\n const fallback = await factoryOmFallback(factoryProjectId);\n const availableProviders = await resolveOMResponseContext(loose(c));\n const session = resourceId ? await controller.getSessionByResource?.(resourceId, scope) : undefined;\n const sessionModelId = session?.model.get();\n return c.json({\n config: readStoredOMConfig(\n record,\n sessionModelId || fallback,\n sessionModelId ? 'live-session' : 'configured-default',\n availableProviders,\n ),\n });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/om/:role/model', {\n method: 'PUT',\n requiresAuth: false,\n handler: async c => {\n const role = c.req.param('role');\n if (role !== 'observer' && role !== 'reflector') {\n return c.json({ error: `Unknown OM role \"${role}\"` }, 400);\n }\n let body: { resourceId?: unknown; modelId?: unknown; scope?: unknown; factoryId?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const resourceId = typeof body.resourceId === 'string' ? body.resourceId : '';\n const scope = typeof body.scope === 'string' && body.scope ? body.scope : undefined;\n const factoryProjectId = typeof body.factoryId === 'string' && body.factoryId ? body.factoryId : undefined;\n const model = typeof body.modelId === 'string' ? body.modelId.trim() : '';\n if (!model) {\n return c.json({ error: 'Missing required field: modelId' }, 400);\n }\n // `'auto'` is selection intent, not a model ID: store null so the role\n // follows the active main model instead of pinning a model named \"auto\".\n const wantsAuto = model === 'auto';\n const context = await resolveMemorySettingsContext({\n c: loose(c),\n auth,\n memorySettings: options.memorySettings,\n factoryProjectId,\n factoryProjects: options.factoryProjects,\n });\n if ('response' in context) return context.response;\n // Resolve the response context before persisting: a provider-enumeration\n // failure must not report 500 for a write that already succeeded.\n const availableProviders = await resolveOMResponseContext(loose(c));\n try {\n await persistMemorySettings(context, {\n [role === 'observer' ? 'observerModelId' : 'reflectorModelId']: wantsAuto ? null : model,\n });\n const record = await context.storage.get({ orgId: context.orgId, userId: context.userId });\n const session = resourceId ? await controller.getSessionByResource?.(resourceId, scope) : undefined;\n const sessionModelId = session?.model.get();\n const config = readStoredOMConfig(\n record,\n sessionModelId || (await factoryOmFallback(factoryProjectId)),\n sessionModelId ? 'live-session' : 'configured-default',\n availableProviders,\n );\n return c.json({ ok: true, config });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/om/thresholds', {\n method: 'PUT',\n requiresAuth: false,\n handler: async c => {\n let body: {\n resourceId?: unknown;\n observationThreshold?: unknown;\n reflectionThreshold?: unknown;\n scope?: unknown;\n factoryId?: unknown;\n };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const resourceId = typeof body.resourceId === 'string' ? body.resourceId : '';\n const scope = typeof body.scope === 'string' && body.scope ? body.scope : undefined;\n const factoryProjectId = typeof body.factoryId === 'string' && body.factoryId ? body.factoryId : undefined;\n const observation =\n typeof body.observationThreshold === 'number' && body.observationThreshold > 0\n ? Math.round(body.observationThreshold)\n : undefined;\n const reflection =\n typeof body.reflectionThreshold === 'number' && body.reflectionThreshold > 0\n ? Math.round(body.reflectionThreshold)\n : undefined;\n if (observation === undefined && reflection === undefined) {\n return c.json({ error: 'Provide observationThreshold and/or reflectionThreshold (positive numbers)' }, 400);\n }\n const context = await resolveMemorySettingsContext({\n c: loose(c),\n auth,\n memorySettings: options.memorySettings,\n factoryProjectId,\n factoryProjects: options.factoryProjects,\n });\n if ('response' in context) return context.response;\n const availableProviders = await resolveOMResponseContext(loose(c));\n try {\n await persistMemorySettings(context, {\n ...(observation !== undefined ? { observationThreshold: observation } : {}),\n ...(reflection !== undefined ? { reflectionThreshold: reflection } : {}),\n });\n const record = await context.storage.get({ orgId: context.orgId, userId: context.userId });\n const session = resourceId ? await controller.getSessionByResource?.(resourceId, scope) : undefined;\n const sessionModelId = session?.model.get();\n const config = readStoredOMConfig(\n record,\n sessionModelId || (await factoryOmFallback(factoryProjectId)),\n sessionModelId ? 'live-session' : 'configured-default',\n availableProviders,\n );\n return c.json({ ok: true, config });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n\n registerApiRoute('/web/config/om/observe-attachments', {\n method: 'PUT',\n requiresAuth: false,\n handler: async c => {\n let body: { resourceId?: unknown; value?: unknown; scope?: unknown; factoryId?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const resourceId = typeof body.resourceId === 'string' ? body.resourceId : '';\n const scope = typeof body.scope === 'string' && body.scope ? body.scope : undefined;\n const factoryProjectId = typeof body.factoryId === 'string' && body.factoryId ? body.factoryId : undefined;\n const raw = body.value;\n const value: 'auto' | boolean = raw === 'auto' || raw === true || raw === false ? raw : 'auto';\n if (raw !== 'auto' && raw !== true && raw !== false) {\n return c.json({ error: \"value must be 'auto', true, or false\" }, 400);\n }\n const context = await resolveMemorySettingsContext({\n c: loose(c),\n auth,\n memorySettings: options.memorySettings,\n factoryProjectId,\n factoryProjects: options.factoryProjects,\n });\n if ('response' in context) return context.response;\n const availableProviders = await resolveOMResponseContext(loose(c));\n try {\n await persistMemorySettings(context, { observeAttachments: value });\n const record = await context.storage.get({ orgId: context.orgId, userId: context.userId });\n const session = resourceId ? await controller.getSessionByResource?.(resourceId, scope) : undefined;\n const sessionModelId = session?.model.get();\n const config = readStoredOMConfig(\n record,\n sessionModelId || (await factoryOmFallback(factoryProjectId)),\n sessionModelId ? 'live-session' : 'configured-default',\n availableProviders,\n );\n return c.json({ ok: true, config });\n } catch (error) {\n return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n }),\n ];\n }\n}\n"],"mappings":"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"}
|
package/dist/routes/surface.d.ts
CHANGED
|
@@ -71,6 +71,8 @@ export interface FactoryApiRoutesDeps {
|
|
|
71
71
|
intakeReady: boolean;
|
|
72
72
|
factoryReady: boolean;
|
|
73
73
|
knowledgeEnabled: boolean;
|
|
74
|
+
/** Organization this deployment serves; its admins may edit deployment-wide settings. */
|
|
75
|
+
deploymentOrganizationId?: string;
|
|
74
76
|
/** Providers the operator opted in to run on the server process's own credentials. */
|
|
75
77
|
deploymentModelProviders?: ReadonlySet<string>;
|
|
76
78
|
knowledgeKey?: string;
|