@mastra/factory 0.1.0-alpha.3 → 0.1.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/capabilities/intake.d.ts +2 -0
  3. package/dist/capabilities/intake.d.ts.map +1 -1
  4. package/dist/capabilities/version-control.d.ts +6 -0
  5. package/dist/capabilities/version-control.d.ts.map +1 -1
  6. package/dist/factory.d.ts.map +1 -1
  7. package/dist/factory.js +912 -242
  8. package/dist/factory.js.map +1 -1
  9. package/dist/index.js +912 -242
  10. package/dist/index.js.map +1 -1
  11. package/dist/integrations/github/integration.d.ts +2 -2
  12. package/dist/integrations/github/integration.js +45 -12
  13. package/dist/integrations/github/integration.js.map +1 -1
  14. package/dist/integrations/github/provenance.js.map +1 -1
  15. package/dist/integrations/github/routes.js +12 -10
  16. package/dist/integrations/github/routes.js.map +1 -1
  17. package/dist/integrations/github/sandbox.d.ts +1 -0
  18. package/dist/integrations/github/sandbox.d.ts.map +1 -1
  19. package/dist/integrations/github/sandbox.js +2 -2
  20. package/dist/integrations/github/sandbox.js.map +1 -1
  21. package/dist/integrations/github/session-subscriptions.d.ts +3 -0
  22. package/dist/integrations/github/session-subscriptions.d.ts.map +1 -1
  23. package/dist/integrations/github/session-subscriptions.js +30 -0
  24. package/dist/integrations/github/session-subscriptions.js.map +1 -1
  25. package/dist/integrations/github/token-refresh.d.ts +6 -0
  26. package/dist/integrations/github/token-refresh.d.ts.map +1 -0
  27. package/dist/integrations/github/token-refresh.js +17 -0
  28. package/dist/integrations/github/token-refresh.js.map +1 -0
  29. package/dist/integrations/platform/api-client.d.ts +2 -0
  30. package/dist/integrations/platform/api-client.d.ts.map +1 -1
  31. package/dist/integrations/platform/api-client.js +7 -0
  32. package/dist/integrations/platform/api-client.js.map +1 -1
  33. package/dist/integrations/platform/github/event-worker.js.map +1 -1
  34. package/dist/integrations/platform/github/integration.d.ts.map +1 -1
  35. package/dist/integrations/platform/github/integration.js +173 -45
  36. package/dist/integrations/platform/github/integration.js.map +1 -1
  37. package/dist/integrations/platform/linear/integration.js +3 -0
  38. package/dist/integrations/platform/linear/integration.js.map +1 -1
  39. package/dist/routes/config.d.ts +16 -11
  40. package/dist/routes/config.d.ts.map +1 -1
  41. package/dist/routes/config.js +222 -109
  42. package/dist/routes/config.js.map +1 -1
  43. package/dist/routes/custom-provider-source.d.ts +52 -0
  44. package/dist/routes/custom-provider-source.d.ts.map +1 -0
  45. package/dist/routes/custom-provider-source.js +107 -0
  46. package/dist/routes/custom-provider-source.js.map +1 -0
  47. package/dist/routes/oauth.js +33 -1
  48. package/dist/routes/oauth.js.map +1 -1
  49. package/dist/routes/surface.d.ts +4 -0
  50. package/dist/routes/surface.d.ts.map +1 -1
  51. package/dist/routes/surface.js +266 -110
  52. package/dist/routes/surface.js.map +1 -1
  53. package/dist/sandbox/fleet.d.ts +3 -0
  54. package/dist/sandbox/fleet.d.ts.map +1 -1
  55. package/dist/sandbox/fleet.js +10 -3
  56. package/dist/sandbox/fleet.js.map +1 -1
  57. package/dist/spa-static.d.ts +4 -5
  58. package/dist/spa-static.d.ts.map +1 -1
  59. package/dist/spa-static.js +5 -2
  60. package/dist/spa-static.js.map +1 -1
  61. package/dist/storage/domains/custom-providers/base.d.ts +57 -0
  62. package/dist/storage/domains/custom-providers/base.d.ts.map +1 -0
  63. package/dist/storage/domains/custom-providers/base.js +150 -0
  64. package/dist/storage/domains/custom-providers/base.js.map +1 -0
  65. package/dist/storage/domains/memory-settings/base.d.ts +62 -0
  66. package/dist/storage/domains/memory-settings/base.d.ts.map +1 -0
  67. package/dist/storage/domains/memory-settings/base.js +111 -0
  68. package/dist/storage/domains/memory-settings/base.js.map +1 -0
  69. package/dist/workspace.d.ts.map +1 -1
  70. package/dist/workspace.js +17 -0
  71. package/dist/workspace.js.map +1 -1
  72. package/package.json +8 -7
@@ -11,8 +11,10 @@ import type { SandboxFleet } from '../sandbox/fleet.js';
11
11
  import type { StateSigner } from '../state-signing.js';
12
12
  import type { AuditEmitter } from '../storage/domains/audit/domain.js';
13
13
  import type { ModelCredentialsStorage } from '../storage/domains/credentials/base.js';
14
+ import type { CustomProvidersStorage } from '../storage/domains/custom-providers/base.js';
14
15
  import type { IntakeStorage } from '../storage/domains/intake/base.js';
15
16
  import type { IntegrationStorage } from '../storage/domains/integrations/base.js';
17
+ import type { MemorySettingsStorage } from '../storage/domains/memory-settings/base.js';
16
18
  import type { ModelPacksStorage } from '../storage/domains/model-packs/base.js';
17
19
  import type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';
18
20
  import type { QueueHealthStorage } from '../storage/domains/queue-health/base.js';
@@ -44,6 +46,8 @@ export interface FactoryApiRoutesDeps {
44
46
  domains: {
45
47
  intake: IntakeStorage;
46
48
  modelCredentials: ModelCredentialsStorage;
49
+ memorySettings: MemorySettingsStorage;
50
+ customProviders: CustomProvidersStorage;
47
51
  modelPacks: ModelPacksStorage;
48
52
  projects: FactoryProjectsStorage;
49
53
  queueHealth: QueueHealthStorage;
@@ -1 +1 @@
1
- {"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../src/routes/surface.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../src/routes/surface.ts"],"names":[],"mappings":"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"}
@@ -11163,8 +11163,10 @@ function assertIdentifier(kind, name) {
11163
11163
  }
11164
11164
  }
11165
11165
  function isUniqueViolation(error) {
11166
+ const code = typeof error === "object" && error !== null ? error.code : void 0;
11167
+ if (code === "SQLITE_CONSTRAINT_UNIQUE" || code === "SQLITE_CONSTRAINT_PRIMARYKEY") return true;
11166
11168
  const message = error instanceof Error ? error.message : String(error);
11167
- return message.includes("UNIQUE constraint failed") || message.includes("SQLITE_CONSTRAINT");
11169
+ return message.includes("UNIQUE constraint failed") || message.includes("SQLITE_CONSTRAINT_UNIQUE") || message.includes("SQLITE_CONSTRAINT_PRIMARYKEY");
11168
11170
  }
11169
11171
  function primaryKeyOf(schema) {
11170
11172
  const pks = Object.entries(schema.columns).filter(([, spec]) => spec.type === "uuid-pk" || spec.primaryKey);
@@ -24103,6 +24105,35 @@ ${unreflectedContent}` : bufferedReflection;
24103
24105
  if (spec.default !== void 0) ddl += ` DEFAULT ${serializeDefault(spec.default)}`;
24104
24106
  return ddl;
24105
24107
  }
24108
+ /**
24109
+ * A table created by an older schema may still say NOT NULL on a column the
24110
+ * current schema declares nullable — inserts of null then fail on databases
24111
+ * that predate the change. SQLite has no `ALTER COLUMN DROP NOT NULL`, so
24112
+ * relaxation swaps in a table rebuilt from the current schema (create shadow
24113
+ * → copy → drop → rename) atomically.
24114
+ */
24115
+ async #relaxDriftedNotNulls(schema) {
24116
+ const info = await this.#client.execute(`PRAGMA table_info("${schema.name}")`);
24117
+ const hasDrift = info.rows.some((row) => {
24118
+ const spec = schema.columns[String(row.name)];
24119
+ if (!spec || spec.type === "uuid-pk" || spec.primaryKey) return false;
24120
+ return spec.nullable === true && Number(row.notnull) === 1;
24121
+ });
24122
+ if (!hasDrift) return;
24123
+ const ddl = Object.entries(schema.columns).map(([name, spec]) => this.#columnDdl(name, spec));
24124
+ const shadow = `${schema.name}__nullable_rebuild`;
24125
+ const cols = Object.keys(schema.columns).map((name) => `"${name}"`).join(", ");
24126
+ await this.#client.batch(
24127
+ [
24128
+ `DROP TABLE IF EXISTS "${shadow}"`,
24129
+ `CREATE TABLE "${shadow}" (${ddl.join(", ")})`,
24130
+ `INSERT INTO "${shadow}" (${cols}) SELECT ${cols} FROM "${schema.name}"`,
24131
+ `DROP TABLE "${schema.name}"`,
24132
+ `ALTER TABLE "${shadow}" RENAME TO "${schema.name}"`
24133
+ ],
24134
+ "write"
24135
+ );
24136
+ }
24106
24137
  async #ensureCollection(schema) {
24107
24138
  assertIdentifier("collection", schema.name);
24108
24139
  primaryKeyOf(schema);
@@ -24114,6 +24145,7 @@ ${unreflectedContent}` : bufferedReflection;
24114
24145
  if (existing.has(name)) continue;
24115
24146
  await this.#client.execute(`ALTER TABLE "${schema.name}" ADD COLUMN ${this.#columnDdl(name, spec)}`);
24116
24147
  }
24148
+ await this.#relaxDriftedNotNulls(schema);
24117
24149
  for (const index of schema.uniqueIndexes ?? []) {
24118
24150
  assertIdentifier("index", index.name);
24119
24151
  index.columns.forEach((column) => assertIdentifier("column", column));
@@ -25410,19 +25442,9 @@ var FactoryTransitionService = class {
25410
25442
  };
25411
25443
 
25412
25444
  // src/routes/config.ts
25413
- import { removeCustomPackFromSettings } from "@mastra/code-sdk/onboarding/custom-packs";
25414
- import {
25415
- removeCustomProviderFromSettings,
25416
- upsertCustomProviderInSettings
25417
- } from "@mastra/code-sdk/onboarding/custom-providers";
25418
- import { applyOmRoleOverride, persistOmObserveAttachments } from "@mastra/code-sdk/onboarding/om-settings";
25445
+ import { DEFAULT_OM_MODEL_ID } from "@mastra/code-sdk/constants";
25419
25446
  import { getAvailableModePacks } from "@mastra/code-sdk/onboarding/packs";
25420
- import {
25421
- getCustomProviderId,
25422
- loadSettings,
25423
- saveSettings,
25424
- THREAD_ACTIVE_MODEL_PACK_ID_KEY
25425
- } from "@mastra/code-sdk/onboarding/settings";
25447
+ import { getCustomProviderId, THREAD_ACTIVE_MODEL_PACK_ID_KEY } from "@mastra/code-sdk/onboarding/settings";
25426
25448
  import { registerApiRoute } from "@mastra/core/server";
25427
25449
 
25428
25450
  // src/routes/provider-credentials.ts
@@ -25537,15 +25559,39 @@ async function listProviders({
25537
25559
  }
25538
25560
  return Array.from(seen.values()).sort((a, b) => a.provider.localeCompare(b.provider));
25539
25561
  }
25540
- function listCustomProviders() {
25541
- const settings = loadSettings();
25542
- return settings.customProviders.map((p) => ({
25543
- id: getCustomProviderId(p.name),
25544
- name: p.name,
25545
- url: p.url,
25546
- hasApiKey: Boolean(p.apiKey),
25547
- models: p.models
25548
- }));
25562
+ function toCustomProviderInfo(record) {
25563
+ return {
25564
+ id: record.providerId,
25565
+ name: record.name,
25566
+ url: record.url,
25567
+ hasApiKey: Boolean(record.apiKey),
25568
+ models: record.models
25569
+ };
25570
+ }
25571
+ async function resolveCustomProvidersContext({
25572
+ c,
25573
+ auth,
25574
+ customProviders
25575
+ }) {
25576
+ await auth.ensureUser(c);
25577
+ const tenant = auth.tenant(c);
25578
+ if (!tenant && auth.enabled()) return { response: c.json({ error: "unauthorized" }, 401) };
25579
+ if (customProviders) {
25580
+ try {
25581
+ await customProviders.ensureReady();
25582
+ return tenant ? { storage: customProviders, orgId: tenantOrgId(tenant), userId: tenant.userId } : { storage: customProviders, orgId: "local", userId: "local" };
25583
+ } catch {
25584
+ }
25585
+ }
25586
+ return {
25587
+ response: c.json(
25588
+ {
25589
+ error: "custom_providers_unavailable",
25590
+ message: "Custom provider storage is unavailable \u2014 the app database is not configured or failed to start."
25591
+ },
25592
+ 503
25593
+ )
25594
+ };
25549
25595
  }
25550
25596
  function parseCustomProviderBody(body) {
25551
25597
  if (!body || typeof body !== "object") return { error: "Invalid JSON body" };
@@ -25610,15 +25656,6 @@ async function buildProviderAccess({
25610
25656
  function canUseModelProvider(access, provider) {
25611
25657
  return Boolean(access[provider]);
25612
25658
  }
25613
- async function getTenantModelPacksStorage(modelPacks) {
25614
- if (!modelPacks) return void 0;
25615
- try {
25616
- await modelPacks.ensureReady();
25617
- } catch {
25618
- return void 0;
25619
- }
25620
- return modelPacks;
25621
- }
25622
25659
  async function resolvePackContext({
25623
25660
  c,
25624
25661
  auth,
@@ -25626,23 +25663,23 @@ async function resolvePackContext({
25626
25663
  }) {
25627
25664
  await auth.ensureUser(c);
25628
25665
  const tenant = auth.tenant(c);
25629
- if (!tenant) {
25630
- if (auth.enabled()) return { response: c.json({ error: "unauthorized" }, 401) };
25631
- return { mode: "local" };
25632
- }
25633
- const storage = await getTenantModelPacksStorage(modelPacks);
25634
- if (!storage) {
25635
- return {
25636
- response: c.json(
25637
- {
25638
- error: "model_packs_unavailable",
25639
- message: "Model pack storage is unavailable \u2014 the app database is not configured or failed to start."
25640
- },
25641
- 503
25642
- )
25643
- };
25666
+ if (!tenant && auth.enabled()) return { response: c.json({ error: "unauthorized" }, 401) };
25667
+ if (modelPacks) {
25668
+ try {
25669
+ await modelPacks.ensureReady();
25670
+ return tenant ? { storage: modelPacks, orgId: tenantOrgId(tenant), userId: tenant.userId } : { storage: modelPacks, orgId: "local", userId: "local" };
25671
+ } catch {
25672
+ }
25644
25673
  }
25645
- return { mode: "tenant", storage, orgId: tenantOrgId(tenant), userId: tenant.userId };
25674
+ return {
25675
+ response: c.json(
25676
+ {
25677
+ error: "model_packs_unavailable",
25678
+ message: "Model pack storage is unavailable \u2014 the app database is not configured or failed to start."
25679
+ },
25680
+ 503
25681
+ )
25682
+ };
25646
25683
  }
25647
25684
  function recordToModePack(record) {
25648
25685
  return { id: `custom:${record.id}`, name: record.name, description: "Saved custom pack", models: record.models };
@@ -25655,7 +25692,7 @@ async function listModelPacks({
25655
25692
  activePackId
25656
25693
  }) {
25657
25694
  const access = await buildProviderAccess({ controller, authStorage, tenantCredentials });
25658
- const packs = packContext.mode === "local" ? getAvailableModePacks(access, loadSettings().customModelPacks) : [
25695
+ const packs = [
25659
25696
  ...getAvailableModePacks(access),
25660
25697
  ...(await packContext.storage.list({ orgId: packContext.orgId })).map(recordToModePack)
25661
25698
  ];
@@ -25713,20 +25750,57 @@ function readOMConfig(session) {
25713
25750
  observeAttachments: observeAttachments === true || observeAttachments === false ? observeAttachments : "auto"
25714
25751
  };
25715
25752
  }
25716
- function persistOmThreshold({ role, value }) {
25717
- const settings = loadSettings();
25718
- if (role === "observation") settings.models.omObservationThreshold = value;
25719
- else settings.models.omReflectionThreshold = value;
25720
- saveSettings(settings);
25721
- }
25722
- function persistOmRoleOverride({
25723
- role,
25724
- modelId,
25725
- otherRoleCurrentModelId
25753
+ async function resolveMemorySettingsContext({
25754
+ c,
25755
+ auth,
25756
+ memorySettings
25726
25757
  }) {
25727
- const settings = loadSettings();
25728
- applyOmRoleOverride(settings, role, modelId, otherRoleCurrentModelId);
25729
- saveSettings(settings);
25758
+ await auth.ensureUser(c);
25759
+ const tenant = auth.tenant(c);
25760
+ if (!tenant && auth.enabled()) return { response: c.json({ error: "unauthorized" }, 401) };
25761
+ if (memorySettings) {
25762
+ try {
25763
+ await memorySettings.ensureReady();
25764
+ return tenant ? { storage: memorySettings, orgId: tenantOrgId(tenant), userId: tenant.userId } : { storage: memorySettings, orgId: "local", userId: "local" };
25765
+ } catch {
25766
+ }
25767
+ }
25768
+ return {
25769
+ response: c.json(
25770
+ {
25771
+ error: "memory_settings_unavailable",
25772
+ message: "Memory settings storage is unavailable \u2014 the app database is not configured or failed to start."
25773
+ },
25774
+ 503
25775
+ )
25776
+ };
25777
+ }
25778
+ async function persistMemorySettings(context, patch, fillIfUnset) {
25779
+ await context.storage.patch({ orgId: context.orgId, userId: context.userId, patch, fillIfUnset });
25780
+ }
25781
+ async function hydrateSessionMemorySettings(session, record) {
25782
+ for (const role of ["observer", "reflector"]) {
25783
+ const stored = role === "observer" ? record?.observerModelId : record?.reflectorModelId;
25784
+ const target = stored ?? DEFAULT_OM_MODEL_ID;
25785
+ if (session.om[role].modelId() !== target) {
25786
+ await session.om[role].switchModel({ modelId: target });
25787
+ }
25788
+ }
25789
+ const state = session.state.get() ?? {};
25790
+ const updates = {};
25791
+ const observationThreshold = record?.observationThreshold ?? DEFAULT_OBSERVATION_THRESHOLD;
25792
+ if (state.observationThreshold !== observationThreshold) {
25793
+ updates.observationThreshold = observationThreshold;
25794
+ }
25795
+ const reflectionThreshold = record?.reflectionThreshold ?? DEFAULT_REFLECTION_THRESHOLD;
25796
+ if (state.reflectionThreshold !== reflectionThreshold) {
25797
+ updates.reflectionThreshold = reflectionThreshold;
25798
+ }
25799
+ const observeAttachments = record?.observeAttachments ?? "auto";
25800
+ if ((state.observeAttachments ?? "auto") !== observeAttachments) {
25801
+ updates.observeAttachments = observeAttachments;
25802
+ }
25803
+ if (Object.keys(updates).length > 0) await session.state.set(updates);
25730
25804
  }
25731
25805
  var ConfigRoutes = class extends Route {
25732
25806
  routes() {
@@ -25734,6 +25808,8 @@ var ConfigRoutes = class extends Route {
25734
25808
  const { controller, authStorage, auth } = options;
25735
25809
  const onCredentialsChanged = options.onCredentialsChanged ?? (() => {
25736
25810
  });
25811
+ const onCustomProvidersChanged = options.onCustomProvidersChanged ?? (() => {
25812
+ });
25737
25813
  return [
25738
25814
  registerApiRoute("/web/config/providers", {
25739
25815
  method: "GET",
@@ -25825,14 +25901,22 @@ var ConfigRoutes = class extends Route {
25825
25901
  }
25826
25902
  }),
25827
25903
  // ── Custom providers (OpenAI-compatible endpoints) ──────────────────────
25828
- // Mirrors the TUI's /custom-providers command. Backed by GlobalSettings
25829
- // (settings.json), not session state these are user-global definitions.
25904
+ // Mirrors the TUI's /custom-providers command, but backed by the
25905
+ // `custom-providers` domain (org rows in tenant mode, a sentinel `local`
25906
+ // org in no-auth mode) — the server never reads settings.json for these.
25830
25907
  registerApiRoute("/web/config/custom-providers", {
25831
25908
  method: "GET",
25832
25909
  requiresAuth: false,
25833
- handler: (c) => {
25910
+ handler: async (c) => {
25911
+ const ctx = await resolveCustomProvidersContext({
25912
+ c: loose(c),
25913
+ auth,
25914
+ customProviders: options.customProviders
25915
+ });
25916
+ if ("response" in ctx) return ctx.response;
25834
25917
  try {
25835
- return c.json({ providers: listCustomProviders() });
25918
+ const records = await ctx.storage.list({ orgId: ctx.orgId });
25919
+ return c.json({ providers: records.map(toCustomProviderInfo) });
25836
25920
  } catch (error) {
25837
25921
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
25838
25922
  }
@@ -25842,6 +25926,12 @@ var ConfigRoutes = class extends Route {
25842
25926
  method: "POST",
25843
25927
  requiresAuth: false,
25844
25928
  handler: async (c) => {
25929
+ const ctx = await resolveCustomProvidersContext({
25930
+ c: loose(c),
25931
+ auth,
25932
+ customProviders: options.customProviders
25933
+ });
25934
+ if ("response" in ctx) return ctx.response;
25845
25935
  let body;
25846
25936
  try {
25847
25937
  body = await c.req.json();
@@ -25852,11 +25942,20 @@ var ConfigRoutes = class extends Route {
25852
25942
  if ("error" in parsed) return c.json({ error: parsed.error }, 400);
25853
25943
  const previousId = body && typeof body === "object" && typeof body.previousId === "string" ? body.previousId : void 0;
25854
25944
  try {
25855
- const settings = loadSettings();
25856
- upsertCustomProviderInSettings(settings, parsed, previousId);
25857
- saveSettings(settings);
25858
- const id = getCustomProviderId(parsed.name);
25859
- return c.json({ ok: true, provider: listCustomProviders().find((p) => p.id === id) });
25945
+ const record = await ctx.storage.upsert({
25946
+ orgId: ctx.orgId,
25947
+ userId: ctx.userId,
25948
+ input: {
25949
+ providerId: getCustomProviderId(parsed.name),
25950
+ name: parsed.name,
25951
+ url: parsed.url,
25952
+ apiKey: parsed.apiKey,
25953
+ models: parsed.models
25954
+ },
25955
+ previousProviderId: previousId
25956
+ });
25957
+ onCustomProvidersChanged({ orgId: ctx.orgId });
25958
+ return c.json({ ok: true, provider: toCustomProviderInfo(record) });
25860
25959
  } catch (error) {
25861
25960
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
25862
25961
  }
@@ -25865,12 +25964,17 @@ var ConfigRoutes = class extends Route {
25865
25964
  registerApiRoute("/web/config/custom-providers/:id", {
25866
25965
  method: "DELETE",
25867
25966
  requiresAuth: false,
25868
- handler: (c) => {
25967
+ handler: async (c) => {
25968
+ const ctx = await resolveCustomProvidersContext({
25969
+ c: loose(c),
25970
+ auth,
25971
+ customProviders: options.customProviders
25972
+ });
25973
+ if ("response" in ctx) return ctx.response;
25869
25974
  const id = c.req.param("id");
25870
25975
  try {
25871
- const settings = loadSettings();
25872
- removeCustomProviderFromSettings(settings, id);
25873
- saveSettings(settings);
25976
+ await ctx.storage.delete({ orgId: ctx.orgId, providerId: id });
25977
+ onCustomProvidersChanged({ orgId: ctx.orgId });
25874
25978
  return c.json({ ok: true });
25875
25979
  } catch (error) {
25876
25980
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
@@ -25899,8 +26003,30 @@ var ConfigRoutes = class extends Route {
25899
26003
  tenantCredentials
25900
26004
  })
25901
26005
  ]);
26006
+ const catalog = models.filter((m) => canUseModelProvider(access, m.provider) && typeof m.id === "string").map((m) => ({ id: m.id, provider: m.provider, modelName: m.modelName, hasApiKey: true }));
26007
+ if (options.customProviders) {
26008
+ try {
26009
+ const ctx = await resolveCustomProvidersContext({
26010
+ c: loose(c),
26011
+ auth,
26012
+ customProviders: options.customProviders
26013
+ });
26014
+ if (!("response" in ctx)) {
26015
+ const known = new Set(catalog.map((m) => m.id));
26016
+ for (const record of await ctx.storage.list({ orgId: ctx.orgId })) {
26017
+ for (const model of record.models) {
26018
+ const id = `${record.providerId}/${model}`;
26019
+ if (known.has(id)) continue;
26020
+ known.add(id);
26021
+ catalog.push({ id, provider: record.providerId, modelName: model, hasApiKey: true });
26022
+ }
26023
+ }
26024
+ }
26025
+ } catch {
26026
+ }
26027
+ }
25902
26028
  return c.json({
25903
- models: models.filter((m) => canUseModelProvider(access, m.provider) && typeof m.id === "string").map((m) => ({ id: m.id, provider: m.provider, modelName: m.modelName, hasApiKey: true })).sort(
26029
+ models: catalog.sort(
25904
26030
  (a, b) => a.provider === b.provider ? a.id.localeCompare(b.id) : a.provider.localeCompare(b.provider)
25905
26031
  )
25906
26032
  });
@@ -25910,10 +26036,10 @@ var ConfigRoutes = class extends Route {
25910
26036
  }
25911
26037
  }),
25912
26038
  // ── Model packs ─────────────────────────────────────────────────────────
25913
- // Mirrors the TUI's /models-pack command. Custom-pack CRUD is DB-backed in
25914
- // tenant mode (model-packs storage domain, org-scoped) and settings.json in
25915
- // local mode; activation is session-scoped and resolves the session from
25916
- // the controller registry by resourceId.
26039
+ // Mirrors the TUI's /models-pack command. Custom-pack CRUD lives in the
26040
+ // model-packs storage domain (org-scoped, sentinel `local` org in no-auth
26041
+ // mode — never settings.json); activation is session-scoped and resolves
26042
+ // the session from the controller registry by resourceId.
25917
26043
  registerApiRoute("/web/config/model-packs", {
25918
26044
  method: "GET",
25919
26045
  requiresAuth: false,
@@ -25967,21 +26093,12 @@ var ConfigRoutes = class extends Route {
25967
26093
  return c.json({ error: "models.build, models.plan and models.fast are required" }, 400);
25968
26094
  }
25969
26095
  try {
25970
- if (packContext.mode === "tenant") {
25971
- const record = await packContext.storage.upsert({
25972
- orgId: packContext.orgId,
25973
- userId: packContext.userId,
25974
- input: { name, models: { build, plan, fast } }
25975
- });
25976
- return c.json({ ok: true, pack: recordToModePack(record) });
25977
- }
25978
- const settings = loadSettings();
25979
- const entry = { name, models: { build, plan, fast }, createdAt: (/* @__PURE__ */ new Date()).toISOString() };
25980
- const idx = settings.customModelPacks.findIndex((p) => p.name === name);
25981
- if (idx >= 0) settings.customModelPacks[idx] = entry;
25982
- else settings.customModelPacks.push(entry);
25983
- saveSettings(settings);
25984
- return c.json({ ok: true, pack: { id: `custom:${name}`, name, models: { build, plan, fast } } });
26096
+ const record = await packContext.storage.upsert({
26097
+ orgId: packContext.orgId,
26098
+ userId: packContext.userId,
26099
+ input: { name, models: { build, plan, fast } }
26100
+ });
26101
+ return c.json({ ok: true, pack: recordToModePack(record) });
25985
26102
  } catch (error) {
25986
26103
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
25987
26104
  }
@@ -25995,15 +26112,9 @@ var ConfigRoutes = class extends Route {
25995
26112
  if ("response" in packContext) return packContext.response;
25996
26113
  const id = decodeURIComponent(c.req.param("id"));
25997
26114
  try {
25998
- if (packContext.mode === "tenant") {
25999
- const recordId = id.startsWith("custom:") ? id.slice("custom:".length) : id;
26000
- const deleted = await packContext.storage.delete({ orgId: packContext.orgId, id: recordId });
26001
- return deleted ? c.json({ ok: true }) : c.json({ error: `Unknown pack "${id}"` }, 404);
26002
- }
26003
- const settings = loadSettings();
26004
- removeCustomPackFromSettings(settings, id);
26005
- saveSettings(settings);
26006
- return c.json({ ok: true });
26115
+ const recordId = id.startsWith("custom:") ? id.slice("custom:".length) : id;
26116
+ const deleted = await packContext.storage.delete({ orgId: packContext.orgId, id: recordId });
26117
+ return deleted ? c.json({ ok: true }) : c.json({ error: `Unknown pack "${id}"` }, 404);
26007
26118
  } catch (error) {
26008
26119
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
26009
26120
  }
@@ -26050,8 +26161,10 @@ var ConfigRoutes = class extends Route {
26050
26161
  }),
26051
26162
  // ── Observational memory ──────────────────────────────────────────────────
26052
26163
  // Mirrors the TUI's /om command. All five knobs are session-scoped (resolved
26053
- // from the session, persisted to its state + thread setting) plus written to
26054
- // GlobalSettings so the choice survives restarts and stays in sync with the TUI.
26164
+ // from the session, persisted to its state + thread setting) and durably
26165
+ // stored in the per-(org, user) `memory-settings` app table never
26166
+ // settings.json. GET hydrates the session from the stored row first so the
26167
+ // DB, not the SDK's boot-time seed, is the source of truth.
26055
26168
  registerApiRoute("/web/config/om", {
26056
26169
  method: "GET",
26057
26170
  requiresAuth: false,
@@ -26059,9 +26172,17 @@ var ConfigRoutes = class extends Route {
26059
26172
  const resourceId = c.req.query("resourceId");
26060
26173
  const scope = c.req.query("scope") || void 0;
26061
26174
  if (!resourceId) return c.json({ error: "Missing required query param: resourceId" }, 400);
26175
+ const context = await resolveMemorySettingsContext({
26176
+ c: loose(c),
26177
+ auth,
26178
+ memorySettings: options.memorySettings
26179
+ });
26180
+ if ("response" in context) return context.response;
26062
26181
  try {
26063
26182
  const session = await controller.getSessionByResource?.(resourceId, scope);
26064
26183
  if (!session) return c.json({ error: `No session for resourceId "${resourceId}"` }, 404);
26184
+ const record = await context.storage.get({ orgId: context.orgId, userId: context.userId });
26185
+ await hydrateSessionMemorySettings(session, record);
26065
26186
  return c.json({ config: readOMConfig(session) });
26066
26187
  } catch (error) {
26067
26188
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
@@ -26087,13 +26208,24 @@ var ConfigRoutes = class extends Route {
26087
26208
  const modelId = typeof body.modelId === "string" ? body.modelId.trim() : "";
26088
26209
  if (!resourceId) return c.json({ error: "Missing required field: resourceId" }, 400);
26089
26210
  if (!modelId) return c.json({ error: "Missing required field: modelId" }, 400);
26211
+ const context = await resolveMemorySettingsContext({
26212
+ c: loose(c),
26213
+ auth,
26214
+ memorySettings: options.memorySettings
26215
+ });
26216
+ if ("response" in context) return context.response;
26090
26217
  try {
26091
26218
  const session = await controller.getSessionByResource?.(resourceId, scope);
26092
26219
  if (!session) return c.json({ error: `No session for resourceId "${resourceId}"` }, 404);
26093
26220
  const otherRole = role === "observer" ? session.om.reflector : session.om.observer;
26094
26221
  const otherRoleCurrentModelId = otherRole.modelId() ?? null;
26095
26222
  await session.om[role].switchModel({ modelId });
26096
- persistOmRoleOverride({ role, modelId, otherRoleCurrentModelId });
26223
+ const otherKey = role === "observer" ? "reflectorModelId" : "observerModelId";
26224
+ await persistMemorySettings(
26225
+ context,
26226
+ { [role === "observer" ? "observerModelId" : "reflectorModelId"]: modelId },
26227
+ otherRoleCurrentModelId ? { [otherKey]: otherRoleCurrentModelId } : void 0
26228
+ );
26097
26229
  return c.json({ ok: true, config: readOMConfig(session) });
26098
26230
  } catch (error) {
26099
26231
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
@@ -26118,19 +26250,27 @@ var ConfigRoutes = class extends Route {
26118
26250
  if (observation === void 0 && reflection === void 0) {
26119
26251
  return c.json({ error: "Provide observationThreshold and/or reflectionThreshold (positive numbers)" }, 400);
26120
26252
  }
26253
+ const context = await resolveMemorySettingsContext({
26254
+ c: loose(c),
26255
+ auth,
26256
+ memorySettings: options.memorySettings
26257
+ });
26258
+ if ("response" in context) return context.response;
26121
26259
  try {
26122
26260
  const session = await controller.getSessionByResource?.(resourceId, scope);
26123
26261
  if (!session) return c.json({ error: `No session for resourceId "${resourceId}"` }, 404);
26124
26262
  if (observation !== void 0) {
26125
26263
  await session.state.set({ observationThreshold: observation });
26126
26264
  await session.thread.setSetting({ key: "observationThreshold", value: observation });
26127
- persistOmThreshold({ role: "observation", value: observation });
26128
26265
  }
26129
26266
  if (reflection !== void 0) {
26130
26267
  await session.state.set({ reflectionThreshold: reflection });
26131
26268
  await session.thread.setSetting({ key: "reflectionThreshold", value: reflection });
26132
- persistOmThreshold({ role: "reflection", value: reflection });
26133
26269
  }
26270
+ await persistMemorySettings(context, {
26271
+ ...observation !== void 0 ? { observationThreshold: observation } : {},
26272
+ ...reflection !== void 0 ? { reflectionThreshold: reflection } : {}
26273
+ });
26134
26274
  return c.json({ ok: true, config: readOMConfig(session) });
26135
26275
  } catch (error) {
26136
26276
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
@@ -26155,12 +26295,18 @@ var ConfigRoutes = class extends Route {
26155
26295
  if (raw !== "auto" && raw !== true && raw !== false) {
26156
26296
  return c.json({ error: "value must be 'auto', true, or false" }, 400);
26157
26297
  }
26298
+ const context = await resolveMemorySettingsContext({
26299
+ c: loose(c),
26300
+ auth,
26301
+ memorySettings: options.memorySettings
26302
+ });
26303
+ if ("response" in context) return context.response;
26158
26304
  try {
26159
26305
  const session = await controller.getSessionByResource?.(resourceId, scope);
26160
26306
  if (!session) return c.json({ error: `No session for resourceId "${resourceId}"` }, 404);
26161
26307
  await session.state.set({ observeAttachments: value });
26162
26308
  await session.thread.setSetting({ key: "observeAttachments", value });
26163
- persistOmObserveAttachments(value);
26309
+ await persistMemorySettings(context, { observeAttachments: value });
26164
26310
  return c.json({ ok: true, config: readOMConfig(session) });
26165
26311
  } catch (error) {
26166
26312
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
@@ -26171,6 +26317,13 @@ var ConfigRoutes = class extends Route {
26171
26317
  }
26172
26318
  };
26173
26319
 
26320
+ // src/routes/custom-provider-source.ts
26321
+ import { setCustomProvidersSource } from "@mastra/code-sdk/agents/custom-provider-source";
26322
+ var orgSnapshots = /* @__PURE__ */ new Map();
26323
+ function invalidateCustomProvidersSnapshots(tenant) {
26324
+ orgSnapshots.delete(tenant.orgId);
26325
+ }
26326
+
26174
26327
  // src/routes/fs.ts
26175
26328
  import { lstat, open, readdir, realpath, stat } from "fs/promises";
26176
26329
  import { homedir } from "os";
@@ -28475,7 +28628,10 @@ function assembleFactoryApiRoutes(deps) {
28475
28628
  authStorage: deps.authStorage,
28476
28629
  modelCredentials: deps.domains.modelCredentials,
28477
28630
  modelPacks: deps.domains.modelPacks,
28478
- onCredentialsChanged: invalidateTenantCredentialSnapshots
28631
+ memorySettings: deps.domains.memorySettings,
28632
+ customProviders: deps.domains.customProviders,
28633
+ onCredentialsChanged: invalidateTenantCredentialSnapshots,
28634
+ onCustomProvidersChanged: invalidateCustomProvidersSnapshots
28479
28635
  }).routes(),
28480
28636
  ...new OAuthRoutes({
28481
28637
  auth: deps.auth,