@axiom-lattice/core 8.0.2 → 8.1.0

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/index.js CHANGED
@@ -1616,6 +1616,7 @@ __export(index_exports, {
1616
1616
  BUILTIN_PLUGINS: () => BUILTIN_PLUGINS,
1617
1617
  BUILTIN_SKILLS: () => BUILTIN_SKILLS,
1618
1618
  CAPABILITY_TOOL_NAME_CONFLICT: () => CAPABILITY_TOOL_NAME_CONFLICT,
1619
+ COLLECTION_CHANGED_TOPIC: () => COLLECTION_CHANGED_TOPIC,
1619
1620
  CapabilityBundleMergeError: () => CapabilityBundleMergeError,
1620
1621
  CapabilityBundleMerger: () => CapabilityBundleMerger,
1621
1622
  CapabilityBundleValidationError: () => CapabilityBundleValidationError,
@@ -1635,6 +1636,7 @@ __export(index_exports, {
1635
1636
  DEFAULT_DELAY_MS: () => DEFAULT_DELAY_MS,
1636
1637
  DEFAULT_HANDLER_TIMEOUT_MS: () => DEFAULT_HANDLER_TIMEOUT_MS,
1637
1638
  DEFAULT_MAX_ATTEMPTS: () => DEFAULT_MAX_ATTEMPTS,
1639
+ DEFAULT_MODEL_EXTRA: () => DEFAULT_MODEL_EXTRA,
1638
1640
  DEFAULT_RESIDENT_INVOKE_TIMEOUT_MS: () => DEFAULT_RESIDENT_INVOKE_TIMEOUT_MS,
1639
1641
  DaytonaInstance: () => DaytonaInstance,
1640
1642
  DaytonaProvider: () => DaytonaProvider,
@@ -1790,7 +1792,10 @@ __export(index_exports, {
1790
1792
  buildGrepResultsDict: () => buildGrepResultsDict,
1791
1793
  buildHandlerCommand: () => buildHandlerCommand,
1792
1794
  buildInput: () => buildInput,
1795
+ buildModelConfig: () => buildModelConfig,
1796
+ buildModelEmbeddingsConfig: () => buildModelEmbeddingsConfig,
1793
1797
  buildModelLlmConfig: () => buildModelLlmConfig,
1798
+ buildModelSttConfig: () => buildModelSttConfig,
1794
1799
  buildNamedVolumeName: () => buildNamedVolumeName,
1795
1800
  buildRemotePackDirectoryCommand: () => buildRemotePackDirectoryCommand,
1796
1801
  buildSandboxMetadataEnv: () => buildSandboxMetadataEnv,
@@ -1811,6 +1816,7 @@ __export(index_exports, {
1811
1816
  compileSandboxPlugin: () => compileSandboxPlugin,
1812
1817
  compileWorkflow: () => compileWorkflow,
1813
1818
  computeSandboxName: () => computeSandboxName,
1819
+ configureCollectionSync: () => configureCollectionSync,
1814
1820
  configureCoordinationLeaseStore: () => configureCoordinationLeaseStore,
1815
1821
  configurePluginCatalogSync: () => configurePluginCatalogSync,
1816
1822
  configureStores: () => configureStores,
@@ -1988,6 +1994,7 @@ __export(index_exports, {
1988
1994
  projectRoomPlugin: () => projectRoomPlugin,
1989
1995
  projectTaskAdmissionNotifier: () => projectTaskAdmissionNotifier,
1990
1996
  provisionSandboxOpenClient: () => provisionSandboxOpenClient,
1997
+ publishCollectionChanged: () => publishCollectionChanged,
1991
1998
  publishPluginCatalogChanged: () => publishPluginCatalogChanged,
1992
1999
  queueLatticeManager: () => queueLatticeManager,
1993
2000
  readLoopBreakerConfig: () => readLoopBreakerConfig,
@@ -2281,9 +2288,6 @@ var ModelLattice = class extends import_chat_models.BaseChatModel {
2281
2288
  }
2282
2289
  };
2283
2290
 
2284
- // src/model_lattice/ModelLatticeManager.ts
2285
- var import_protocols10 = require("@axiom-lattice/protocols");
2286
-
2287
2291
  // src/store_lattice/StoreLatticeManager.ts
2288
2292
  init_BaseLatticeManager();
2289
2293
 
@@ -3883,6 +3887,9 @@ var InMemoryModelProviderStore = class {
3883
3887
  // explicit flag marks one.
3884
3888
  stale: model.stale ?? false,
3885
3889
  extra: carried && Object.keys(carried).length > 0 ? carried : void 0,
3890
+ // Same rule as `extra`: an omitted kind keeps the stored one, and a new
3891
+ // row — which discovery creates without a kind — starts as chat.
3892
+ kind: model.kind ?? existing?.kind ?? "chat",
3886
3893
  isDefault: model.isDefault ?? (namesDefault ? false : existing?.isDefault) ?? false,
3887
3894
  discoveredAt: now
3888
3895
  };
@@ -7941,7 +7948,136 @@ var SimpleMemoryVectorStore = class extends import_vectorstores.VectorStore {
7941
7948
  };
7942
7949
 
7943
7950
  // src/embeddings_lattice/EmbeddingsLatticeManager.ts
7951
+ var import_openai2 = require("@langchain/openai");
7944
7952
  init_BaseLatticeManager();
7953
+
7954
+ // src/model_lattice/buildModelLlmConfig.ts
7955
+ var ALLOWED_LLM_PROVIDERS = /* @__PURE__ */ new Set(["openai"]);
7956
+ var UnsupportedModelProviderError = class extends Error {
7957
+ constructor(llmProvider) {
7958
+ super(`Unsupported LLM provider: ${llmProvider}`);
7959
+ this.llmProvider = llmProvider;
7960
+ this.code = "UNSUPPORTED_PROTOCOL";
7961
+ this.name = "UnsupportedModelProviderError";
7962
+ }
7963
+ };
7964
+ var DEFAULT_MODEL_EXTRA = {
7965
+ disableThinking: true
7966
+ };
7967
+ function buildModelLlmConfig(provider2, model) {
7968
+ if (!ALLOWED_LLM_PROVIDERS.has(provider2.llmProvider)) {
7969
+ throw new UnsupportedModelProviderError(provider2.llmProvider);
7970
+ }
7971
+ const extra = { ...model.extra ?? {} };
7972
+ delete extra.apiKeyEnvName;
7973
+ const disableThinking = extra.disableThinking === true;
7974
+ delete extra.disableThinking;
7975
+ if (disableThinking) {
7976
+ extra.modelKwargs = {
7977
+ enable_thinking: false,
7978
+ thinking: { type: "disabled" },
7979
+ ...extra.modelKwargs ?? {}
7980
+ };
7981
+ }
7982
+ return {
7983
+ ...extra,
7984
+ provider: provider2.llmProvider,
7985
+ model: model.modelId,
7986
+ displayName: model.displayName ?? model.modelId,
7987
+ streaming: true,
7988
+ apiKey: provider2.apiKey,
7989
+ // A provider without a key talks to an upstream that needs no
7990
+ // credentials. Saying so explicitly keeps `initChatModel` from falling
7991
+ // back to `process.env[...]` and handing the gateway's own deployment key
7992
+ // to the tenant's host.
7993
+ noAuth: !provider2.apiKey,
7994
+ baseURL: provider2.baseURL,
7995
+ // Chat Completions and the Responses API are different routes with
7996
+ // different request fields; without this the gateway would post
7997
+ // `messages` to an endpoint expecting `input`.
7998
+ ...provider2.apiStyle === "responses" ? { useResponsesApi: true } : {}
7999
+ };
8000
+ }
8001
+
8002
+ // src/model_lattice/buildModelConfig.ts
8003
+ function numberOrUndefined(value) {
8004
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
8005
+ }
8006
+ function buildModelEmbeddingsConfig(provider2, model) {
8007
+ const extra = { ...model.extra ?? {} };
8008
+ delete extra.apiKeyEnvName;
8009
+ const encodingFormat = extra.encodingFormat === "float" || extra.encodingFormat === "base64" ? extra.encodingFormat : void 0;
8010
+ return {
8011
+ ...extra,
8012
+ model: model.modelId,
8013
+ baseURL: provider2.baseURL,
8014
+ apiKey: provider2.apiKey || "EMPTY",
8015
+ dimensions: numberOrUndefined(extra.dimensions),
8016
+ timeout: numberOrUndefined(extra.timeout),
8017
+ batchSize: numberOrUndefined(extra.batchSize),
8018
+ encodingFormat
8019
+ };
8020
+ }
8021
+ function buildModelSttConfig(provider2, model) {
8022
+ const extra = { ...model.extra ?? {} };
8023
+ delete extra.apiKeyEnvName;
8024
+ return {
8025
+ ...extra,
8026
+ apiMode: extra.apiMode === "chat" ? "chat" : "whisper",
8027
+ model: model.modelId,
8028
+ // Placeholder for the same reason as embeddings: `STTModelLattice` falls
8029
+ // back to `process.env.OPENAI_API_KEY` when this is empty.
8030
+ apiKey: provider2.apiKey || "EMPTY",
8031
+ baseURL: provider2.baseURL
8032
+ };
8033
+ }
8034
+ function buildModelConfig(provider2, model) {
8035
+ switch (model.kind) {
8036
+ case "embedding":
8037
+ return {
8038
+ kind: "embedding",
8039
+ config: buildModelEmbeddingsConfig(provider2, model)
8040
+ };
8041
+ case "asr":
8042
+ return { kind: "asr", config: buildModelSttConfig(provider2, model) };
8043
+ case "chat":
8044
+ default:
8045
+ return { kind: "chat", config: buildModelLlmConfig(provider2, model) };
8046
+ }
8047
+ }
8048
+
8049
+ // src/model_lattice/loadTenantModelRow.ts
8050
+ var import_protocols10 = require("@axiom-lattice/protocols");
8051
+ async function loadTenantModelRow(tenantId2, key5) {
8052
+ try {
8053
+ const { store } = getStoreLattice("default", "modelProvider");
8054
+ const parsed = (0, import_protocols10.parseModelKey)(key5);
8055
+ if (!parsed) {
8056
+ return void 0;
8057
+ }
8058
+ const provider2 = await store.getProviderById(tenantId2, parsed.providerId);
8059
+ if (!provider2 || !provider2.enabled) {
8060
+ return void 0;
8061
+ }
8062
+ const model = await store.getModel(
8063
+ tenantId2,
8064
+ parsed.providerId,
8065
+ parsed.modelId
8066
+ );
8067
+ if (!model || !model.enabled) {
8068
+ return void 0;
8069
+ }
8070
+ return { provider: provider2, model };
8071
+ } catch (error) {
8072
+ console.error(
8073
+ `[model_lattice] Failed to load model "${key5}" for tenant "${tenantId2}":`,
8074
+ error
8075
+ );
8076
+ return void 0;
8077
+ }
8078
+ }
8079
+
8080
+ // src/embeddings_lattice/EmbeddingsLatticeManager.ts
7945
8081
  var EmbeddingsLatticeManager = class _EmbeddingsLatticeManager extends BaseLatticeManager {
7946
8082
  /**
7947
8083
  * Get EmbeddingsLatticeManager singleton instance
@@ -7973,6 +8109,37 @@ var EmbeddingsLatticeManager = class _EmbeddingsLatticeManager extends BaseLatti
7973
8109
  };
7974
8110
  this.register(key5, embeddingsLattice);
7975
8111
  }
8112
+ /**
8113
+ * Materialise a tenant embedding model that this process has never seen.
8114
+ *
8115
+ * Called by `BaseLatticeManager` on a registry miss. Only `kind: "embedding"`
8116
+ * rows are accepted: a chat or ASR model key must resolve to nothing here, so
8117
+ * a caller asking for an embedding client can never silently get the wrong
8118
+ * kind of model.
8119
+ *
8120
+ * @param tenantId Tenant scope
8121
+ * @param key `${providerId}/${modelId}`
8122
+ */
8123
+ async loadItemFromStore(tenantId2, key5) {
8124
+ const row = await loadTenantModelRow(tenantId2, key5);
8125
+ if (!row || row.model.kind !== "embedding") {
8126
+ return void 0;
8127
+ }
8128
+ const config = buildModelEmbeddingsConfig(row.provider, row.model);
8129
+ return {
8130
+ key: key5,
8131
+ client: new import_openai2.OpenAIEmbeddings({
8132
+ model: config.model,
8133
+ apiKey: config.apiKey,
8134
+ dimensions: config.dimensions,
8135
+ timeout: config.timeout,
8136
+ batchSize: config.batchSize,
8137
+ encodingFormat: config.encodingFormat,
8138
+ configuration: { baseURL: config.baseURL }
8139
+ }),
8140
+ label: row.model.displayName ?? row.model.modelId
8141
+ };
8142
+ }
7976
8143
  /**
7977
8144
  * Get all registered embeddings as { key, label } info list
7978
8145
  */
@@ -7990,6 +8157,53 @@ var EmbeddingsLatticeManager = class _EmbeddingsLatticeManager extends BaseLatti
7990
8157
  }
7991
8158
  return embeddingsLattice;
7992
8159
  }
8160
+ /**
8161
+ * Drop this replica's cached embedding clients for one provider.
8162
+ *
8163
+ * The provider's config (apiKey, baseURL, model `extra`) is baked into the
8164
+ * client at construction, and a resolved entry never re-reads the store. So a
8165
+ * model-provider change reaches this replica only if the entry is evicted
8166
+ * first — the same rule `ModelLatticeManager.evictProviderCache` applies to
8167
+ * chat models, and the same keys the model-provider outbox event covers.
8168
+ *
8169
+ * Unlike the chat manager this deliberately leaves the `"default"` key alone:
8170
+ * here it is a *deployment registration*, not a tenant resolution, so evicting
8171
+ * it would remove the global fallback every tenant relies on.
8172
+ *
8173
+ * @param tenantId Tenant scope
8174
+ * @param providerId Provider whose `${providerId}/` keys are stale
8175
+ */
8176
+ evictProviderCache(tenantId2, providerId) {
8177
+ if (!providerId) {
8178
+ return;
8179
+ }
8180
+ const prefix = `${providerId}/`;
8181
+ for (const key5 of this.keysByTenant(tenantId2)) {
8182
+ if (key5.startsWith(prefix)) {
8183
+ this.removeWithTenant(tenantId2, key5);
8184
+ }
8185
+ }
8186
+ }
8187
+ /**
8188
+ * Resolve an embeddings client for a tenant, loading a miss from the store.
8189
+ *
8190
+ * Mirrors `resolveModelLatticeForTenant`: the tenant's own model first, then
8191
+ * the deployment namespace, which is where boot-time registrations live.
8192
+ * Returns `undefined` rather than throwing, so a caller can fall back.
8193
+ *
8194
+ * @param tenantId Tenant scope
8195
+ * @param key `${providerId}/${modelId}` or a bare deployment key
8196
+ */
8197
+ async getEmbeddingsClientWithTenant(tenantId2, key5) {
8198
+ const own = await this.getOrLoadWithTenant(tenantId2, key5);
8199
+ if (own) {
8200
+ return own.client;
8201
+ }
8202
+ if (tenantId2 !== "default") {
8203
+ return (await this.getOrLoadWithTenant("default", key5))?.client;
8204
+ }
8205
+ return void 0;
8206
+ }
7993
8207
  /**
7994
8208
  * Get all Lattices
7995
8209
  */
@@ -8045,20 +8259,18 @@ var getEmbeddingsClient = (key5) => embeddingsLatticeManager.getEmbeddingsClient
8045
8259
  // src/vectorstore_lattice/VectorStoreProviderManager.ts
8046
8260
  var MemoryVectorStoreProvider = class {
8047
8261
  async create(params) {
8048
- let embeddings;
8049
- try {
8050
- embeddings = embeddingsLatticeManager.getEmbeddingsClient(params.embeddingKey);
8051
- } catch {
8052
- try {
8053
- embeddings = embeddingsLatticeManager.getEmbeddingsClient("default");
8054
- } catch {
8055
- throw new Error(
8056
- `No embedding model registered. Register one first, e.g.:
8057
- import { registerEmbeddingsLattice } from "@axiom-lattice/core";
8058
- import { OpenAIEmbeddings } from "@langchain/openai";
8059
- registerEmbeddingsLattice("default", new OpenAIEmbeddings({ modelName: "text-embedding-3-small" }));`
8060
- );
8061
- }
8262
+ const tenantId2 = params.tenantId ?? "default";
8263
+ const embeddings = await embeddingsLatticeManager.getEmbeddingsClientWithTenant(
8264
+ tenantId2,
8265
+ params.embeddingKey
8266
+ ) ?? await embeddingsLatticeManager.getEmbeddingsClientWithTenant(
8267
+ tenantId2,
8268
+ "default"
8269
+ );
8270
+ if (!embeddings) {
8271
+ throw new Error(
8272
+ `No embedding model "${params.embeddingKey}" registered for tenant "${tenantId2}", and no deployment default. Configure one in the model provider panel.`
8273
+ );
8062
8274
  }
8063
8275
  return new SimpleMemoryVectorStore(embeddings);
8064
8276
  }
@@ -12418,42 +12630,6 @@ var InMemoryMenuStore = class {
12418
12630
  }
12419
12631
  };
12420
12632
 
12421
- // src/model_lattice/buildModelLlmConfig.ts
12422
- var ALLOWED_LLM_PROVIDERS = /* @__PURE__ */ new Set(["openai"]);
12423
- var UnsupportedModelProviderError = class extends Error {
12424
- constructor(llmProvider) {
12425
- super(`Unsupported LLM provider: ${llmProvider}`);
12426
- this.llmProvider = llmProvider;
12427
- this.code = "UNSUPPORTED_PROTOCOL";
12428
- this.name = "UnsupportedModelProviderError";
12429
- }
12430
- };
12431
- function buildModelLlmConfig(provider2, model) {
12432
- if (!ALLOWED_LLM_PROVIDERS.has(provider2.llmProvider)) {
12433
- throw new UnsupportedModelProviderError(provider2.llmProvider);
12434
- }
12435
- const extra = { ...model.extra ?? {} };
12436
- delete extra.apiKeyEnvName;
12437
- return {
12438
- ...extra,
12439
- provider: provider2.llmProvider,
12440
- model: model.modelId,
12441
- displayName: model.displayName ?? model.modelId,
12442
- streaming: true,
12443
- apiKey: provider2.apiKey,
12444
- // A provider without a key talks to an upstream that needs no
12445
- // credentials. Saying so explicitly keeps `initChatModel` from falling
12446
- // back to `process.env[...]` and handing the gateway's own deployment key
12447
- // to the tenant's host.
12448
- noAuth: !provider2.apiKey,
12449
- baseURL: provider2.baseURL,
12450
- // Chat Completions and the Responses API are different routes with
12451
- // different request fields; without this the gateway would post
12452
- // `messages` to an endpoint expecting `input`.
12453
- ...provider2.apiStyle === "responses" ? { useResponsesApi: true } : {}
12454
- };
12455
- }
12456
-
12457
12633
  // src/model_lattice/ModelLatticeManager.ts
12458
12634
  var DEFAULT_MODEL_KEY = "default";
12459
12635
  var TENANT_DEFAULT_MISS_TTL_MS = 3e4;
@@ -12626,38 +12802,26 @@ var ModelLatticeManager = class _ModelLatticeManager extends BaseLatticeManager
12626
12802
  * @param key Lattice键名(`${providerId}/${modelId}`)
12627
12803
  */
12628
12804
  async loadItemFromStore(tenantId2, key5) {
12629
- try {
12630
- const { store } = getStoreLattice("default", "modelProvider");
12631
- if (key5 === DEFAULT_MODEL_KEY) {
12805
+ if (key5 === DEFAULT_MODEL_KEY) {
12806
+ try {
12807
+ const { store } = getStoreLattice("default", "modelProvider");
12632
12808
  return await this.loadTenantDefault(store, tenantId2);
12633
- }
12634
- const parsed = (0, import_protocols10.parseModelKey)(key5);
12635
- if (!parsed) {
12636
- return void 0;
12637
- }
12638
- const provider2 = await store.getProviderById(tenantId2, parsed.providerId);
12639
- if (!provider2 || !provider2.enabled) {
12640
- return void 0;
12641
- }
12642
- const model = await store.getModel(
12643
- tenantId2,
12644
- parsed.providerId,
12645
- parsed.modelId
12646
- );
12647
- if (!model || !model.enabled) {
12809
+ } catch (error) {
12810
+ console.error(
12811
+ `[ModelLatticeManager] Failed to load model "${key5}" for tenant "${tenantId2}":`,
12812
+ error
12813
+ );
12648
12814
  return void 0;
12649
12815
  }
12650
- return {
12651
- key: key5,
12652
- client: new ModelLattice(buildModelLlmConfig(provider2, model))
12653
- };
12654
- } catch (error) {
12655
- console.error(
12656
- `[ModelLatticeManager] Failed to load model "${key5}" for tenant "${tenantId2}":`,
12657
- error
12658
- );
12816
+ }
12817
+ const row = await loadTenantModelRow(tenantId2, key5);
12818
+ if (!row || row.model.kind !== "chat") {
12659
12819
  return void 0;
12660
12820
  }
12821
+ return {
12822
+ key: key5,
12823
+ client: new ModelLattice(buildModelLlmConfig(row.provider, row.model))
12824
+ };
12661
12825
  }
12662
12826
  /**
12663
12827
  * Forget that a tenant had no default model.
@@ -12689,7 +12853,9 @@ var ModelLatticeManager = class _ModelLatticeManager extends BaseLatticeManager
12689
12853
  return void 0;
12690
12854
  }
12691
12855
  const models = await store.listModels(tenantId2);
12692
- const marked = models.find((model) => model.isDefault === true);
12856
+ const marked = models.find(
12857
+ (model) => model.isDefault === true && model.kind === "chat"
12858
+ );
12693
12859
  if (!marked || !marked.enabled) {
12694
12860
  this.tenantDefaultMissAt.set(tenantId2, Date.now());
12695
12861
  return void 0;
@@ -12730,6 +12896,37 @@ var ModelLatticeManager = class _ModelLatticeManager extends BaseLatticeManager
12730
12896
  removeLatticeWithTenant(tenantId2, key5) {
12731
12897
  return this.removeWithTenant(tenantId2, key5);
12732
12898
  }
12899
+ /**
12900
+ * 驱逐一个 provider 贡献的缓存,外加本租户已解析的 `default` 哨兵。
12901
+ *
12902
+ * 改了配置(apiKey / baseURL / extra)却还在走旧客户端,根因就是
12903
+ * `BaseLatticeManager.registry` 的**正向条目没有 TTL**:命中一次之后
12904
+ * `loadItemFromStore` 再也不会被调用。驱逐之后,下一次解析会从**共享的**
12905
+ * store 重新物化 —— 这正是多副本「正确性不靠副本之间同步、靠共享库」那条不变式。
12906
+ *
12907
+ * 只驱逐、不重注册:`loadItemFromStore` 已经知道怎么按 key 物化,删掉就够,
12908
+ * 而且这里不需要读库。
12909
+ *
12910
+ * 为什么连哨兵一起删:`default` 是本租户默认模型的**解析结果**,同样被永久缓存。
12911
+ * 不删它,租户换了默认模型就得重启才生效(单副本也一样)。删掉只让下一次解析
12912
+ * 多读一次库。
12913
+ *
12914
+ * @param tenantId 租户ID
12915
+ * @param providerId 该 provider 的 `${providerId}/` 前缀会被清掉;省略则只清
12916
+ * 哨兵(例如只换了默认模型)
12917
+ */
12918
+ evictProviderCache(tenantId2, providerId) {
12919
+ if (providerId) {
12920
+ const prefix = `${providerId}/`;
12921
+ for (const key5 of this.keysByTenant(tenantId2)) {
12922
+ if (key5.startsWith(prefix)) {
12923
+ this.removeWithTenant(tenantId2, key5);
12924
+ }
12925
+ }
12926
+ }
12927
+ this.removeWithTenant(tenantId2, DEFAULT_MODEL_KEY);
12928
+ this.forgetTenantDefaultMiss(tenantId2);
12929
+ }
12733
12930
  };
12734
12931
  var modelLatticeManager = ModelLatticeManager.getInstance();
12735
12932
  var registerModelLattice = (key5, config) => modelLatticeManager.registerLattice(key5, config);
@@ -17732,7 +17929,7 @@ async function describeImage(options) {
17732
17929
  init_BaseLatticeManager();
17733
17930
 
17734
17931
  // src/stt_model_lattice/STTModelLattice.ts
17735
- var import_openai2 = require("@langchain/openai");
17932
+ var import_openai3 = require("@langchain/openai");
17736
17933
  var STTModelLattice = class {
17737
17934
  constructor(key5, config) {
17738
17935
  this.key = key5;
@@ -17742,7 +17939,7 @@ var STTModelLattice = class {
17742
17939
  if (!apiKey) {
17743
17940
  throw new Error("No API key configured for STT. Set apiKey, apiKeyEnvName, or OPENAI_API_KEY.");
17744
17941
  }
17745
- this.openaiClient = new import_openai2.OpenAIClient({
17942
+ this.openaiClient = new import_openai3.OpenAIClient({
17746
17943
  apiKey,
17747
17944
  baseURL: config.baseURL,
17748
17945
  timeout: config.timeout || 3e4
@@ -17764,7 +17961,7 @@ var STTModelLattice = class {
17764
17961
  */
17765
17962
  async transcribeViaWhisper(audio, format) {
17766
17963
  const mimeType = formatToMimeType(format);
17767
- const file = typeof File !== "undefined" ? new File([audio], `audio.${format}`, { type: mimeType }) : await (0, import_openai2.toFile)(audio, `audio.${format}`, { type: mimeType });
17964
+ const file = typeof File !== "undefined" ? new File([audio], `audio.${format}`, { type: mimeType }) : await (0, import_openai3.toFile)(audio, `audio.${format}`, { type: mimeType });
17768
17965
  const extra = this.config.extra || {};
17769
17966
  const response = await this.openaiClient.audio.transcriptions.create({
17770
17967
  file,
@@ -17858,6 +18055,26 @@ var STTModelLatticeManager = class _STTModelLatticeManager extends BaseLatticeMa
17858
18055
  };
17859
18056
  this.register(key5, sttLattice);
17860
18057
  }
18058
+ /**
18059
+ * Materialise a tenant ASR model that this process has never seen.
18060
+ *
18061
+ * Only `kind: "asr"` rows are accepted, mirroring the embedding loader: a
18062
+ * chat key must never resolve to a speech client.
18063
+ */
18064
+ async loadItemFromStore(tenantId2, key5) {
18065
+ const row = await loadTenantModelRow(tenantId2, key5);
18066
+ if (!row || row.model.kind !== "asr") {
18067
+ return void 0;
18068
+ }
18069
+ const config = buildModelSttConfig(row.provider, row.model);
18070
+ const client = new STTModelLattice(key5, config);
18071
+ return {
18072
+ key: key5,
18073
+ client,
18074
+ config,
18075
+ label: row.model.displayName ?? row.model.modelId
18076
+ };
18077
+ }
17861
18078
  /**
17862
18079
  * Get an STT model lattice by key.
17863
18080
  */
@@ -17889,6 +18106,49 @@ var STTModelLatticeManager = class _STTModelLatticeManager extends BaseLatticeMa
17889
18106
  }
17890
18107
  return lattice.client;
17891
18108
  }
18109
+ /**
18110
+ * Resolve an STT client for a tenant, loading a miss from the store.
18111
+ *
18112
+ * The synchronous `getSTTClientWithTenant` stays as it is for
18113
+ * deployment-registered models; this one is for the tenant catalog, where the
18114
+ * model may exist only in the shared store. Same order as every other
18115
+ * resolver: tenant first, then the deployment namespace.
18116
+ *
18117
+ * @param tenantId Tenant scope
18118
+ * @param key `${providerId}/${modelId}` or a bare deployment key
18119
+ */
18120
+ async getSTTClientWithTenantAsync(tenantId2, key5) {
18121
+ const own = await this.getOrLoadWithTenant(tenantId2, key5);
18122
+ if (own) {
18123
+ return own.client;
18124
+ }
18125
+ if (tenantId2 !== "default") {
18126
+ return (await this.getOrLoadWithTenant("default", key5))?.client;
18127
+ }
18128
+ return void 0;
18129
+ }
18130
+ /**
18131
+ * Drop this replica's cached STT clients for one provider.
18132
+ *
18133
+ * Same rule as the chat and embeddings managers: the provider's key and
18134
+ * address are baked into the client at construction, so a model-provider
18135
+ * change only reaches this replica if the cached entry is evicted first. The
18136
+ * deployment's `"default"` registration is left alone.
18137
+ *
18138
+ * @param tenantId Tenant scope
18139
+ * @param providerId Provider whose `${providerId}/` keys are stale
18140
+ */
18141
+ evictProviderCache(tenantId2, providerId) {
18142
+ if (!providerId) {
18143
+ return;
18144
+ }
18145
+ const prefix = `${providerId}/`;
18146
+ for (const key5 of this.keysByTenant(tenantId2)) {
18147
+ if (key5.startsWith(prefix)) {
18148
+ this.removeWithTenant(tenantId2, key5);
18149
+ }
18150
+ }
18151
+ }
17892
18152
  /**
17893
18153
  * Get all registered STT models as info list.
17894
18154
  */
@@ -17927,13 +18187,16 @@ var getSTTClientWithTenant = (tenantId2, key5) => sttModelLatticeManager.getSTTC
17927
18187
 
17928
18188
  // src/deep_agent_new/backends/transcribeAudio.ts
17929
18189
  async function transcribeAudio(options) {
17930
- const { audioBuffer, format } = options;
17931
- if (!sttModelLatticeManager.hasLattice("default")) {
18190
+ const { audioBuffer, format, tenantId: tenantId2 = "default", modelKey = "default" } = options;
18191
+ const client = await sttModelLatticeManager.getSTTClientWithTenantAsync(
18192
+ tenantId2,
18193
+ modelKey
18194
+ );
18195
+ if (!client) {
17932
18196
  throw new Error(
17933
- "No default STT model registered. Use registerSTTModelLattice('default', { ... }) first."
18197
+ `No STT model "${modelKey}" registered for tenant "${tenantId2}". Configure one in the model provider panel, or register a deployment default.`
17934
18198
  );
17935
18199
  }
17936
- const client = sttModelLatticeManager.getSTTClient("default");
17937
18200
  return await client.transcribe(audioBuffer, format);
17938
18201
  }
17939
18202
 
@@ -18108,7 +18371,13 @@ The current backend does not support binary reading, unable to process audio.`;
18108
18371
  ${sizeWarning}`;
18109
18372
  }
18110
18373
  const format = detectAudioFormat(file_path);
18111
- const result = await transcribeAudio({ audioBuffer: buffer2, format });
18374
+ const result = await transcribeAudio({
18375
+ audioBuffer: buffer2,
18376
+ format,
18377
+ // Tenant first; the deployment's `"default"` registration is the
18378
+ // fallback, so existing deployments keep working unchanged.
18379
+ tenantId: runConfig?.tenantId || "default"
18380
+ });
18112
18381
  let output = `[Audio] ${file_path} (${format}, ${(buffer2.length / 1024).toFixed(1)}KB)`;
18113
18382
  if (result.confidence !== void 0) {
18114
18383
  output += `
@@ -33992,6 +34261,28 @@ var VectorStoreLatticeManager = class _VectorStoreLatticeManager extends BaseLat
33992
34261
  const vectorStoreLattice = this.getVectorStoreLattice(key5);
33993
34262
  return vectorStoreLattice.client;
33994
34263
  }
34264
+ /**
34265
+ * Drop every cached vector store belonging to a tenant.
34266
+ *
34267
+ * Stores are registered through the legacy key-only API with a
34268
+ * `${tenantId}:${collection}` key name, so they all live under the `default`
34269
+ * namespace. Matching has to be on the key name, not on the lattice's tenant
34270
+ * prefix — `clearByTenant` would find nothing here.
34271
+ *
34272
+ * The stores are rebuilt lazily on next use. Evicting is required whenever the
34273
+ * embedding client they were built with may have changed: a collection's
34274
+ * `embeddingKey`, or the model provider behind that key.
34275
+ *
34276
+ * @param tenantId Tenant whose vector stores to drop
34277
+ */
34278
+ clearTenantVectorStores(tenantId2) {
34279
+ const prefix = `${tenantId2}:`;
34280
+ for (const lattice of this.getAllLattices()) {
34281
+ if (lattice.key.startsWith(prefix)) {
34282
+ this.removeLattice(lattice.key);
34283
+ }
34284
+ }
34285
+ }
33995
34286
  };
33996
34287
  var vectorStoreLatticeManager = VectorStoreLatticeManager.getInstance();
33997
34288
  var registerVectorStoreLattice = (key5, vectorStore) => vectorStoreLatticeManager.registerLattice(key5, vectorStore);
@@ -34685,6 +34976,26 @@ var SkillLatticeManager = class _SkillLatticeManager extends BaseLatticeManager
34685
34976
  };
34686
34977
  var skillLatticeManager = SkillLatticeManager.getInstance();
34687
34978
 
34979
+ // src/services/collectionSync.ts
34980
+ var COLLECTION_CHANGED_TOPIC = "collection-changed";
34981
+ var outbox;
34982
+ var owner = "unknown";
34983
+ function configureCollectionSync(next) {
34984
+ outbox = next?.outbox;
34985
+ owner = next?.owner ?? "unknown";
34986
+ }
34987
+ async function publishCollectionChanged(tenantId2) {
34988
+ if (!outbox || !tenantId2) return;
34989
+ try {
34990
+ await outbox.append({
34991
+ topic: COLLECTION_CHANGED_TOPIC,
34992
+ payload: { tenantId: tenantId2 },
34993
+ originReplicaId: owner
34994
+ });
34995
+ } catch {
34996
+ }
34997
+ }
34998
+
34688
34999
  // src/collection_lattice/CollectionLatticeManager.ts
34689
35000
  var CollectionLatticeManager = class _CollectionLatticeManager {
34690
35001
  static getInstance() {
@@ -34697,8 +35008,25 @@ var CollectionLatticeManager = class _CollectionLatticeManager {
34697
35008
  const lattice = storeLatticeManager.getStoreLattice("default", "collection");
34698
35009
  return lattice.store;
34699
35010
  }
35011
+ /**
35012
+ * Drop this replica's cached vector stores for the tenant, and tell peers.
35013
+ *
35014
+ * A vector store is constructed with one embedding client, so any collection
35015
+ * write can invalidate it — creating, renaming, changing `embeddingKey` or
35016
+ * deleting. Clearing the whole tenant is deliberate: the cache is small, and
35017
+ * a per-store match would still miss two collections sharing one client.
35018
+ *
35019
+ * Locally this must happen here because the outbox poller skips events this
35020
+ * replica published itself.
35021
+ */
35022
+ invalidateVectorStores(tenantId2) {
35023
+ vectorStoreLatticeManager.clearTenantVectorStores(tenantId2);
35024
+ void publishCollectionChanged(tenantId2);
35025
+ }
34700
35026
  async registerCollection(tenantId2, data) {
34701
- return this.getStore().createCollection(tenantId2, data);
35027
+ const collection = await this.getStore().createCollection(tenantId2, data);
35028
+ this.invalidateVectorStores(tenantId2);
35029
+ return collection;
34702
35030
  }
34703
35031
  async getCollection(tenantId2, name) {
34704
35032
  return this.getStore().getCollectionByName(tenantId2, name);
@@ -34707,10 +35035,18 @@ var CollectionLatticeManager = class _CollectionLatticeManager {
34707
35035
  return this.getStore().getAllCollections(tenantId2);
34708
35036
  }
34709
35037
  async removeCollection(tenantId2, name) {
34710
- return this.getStore().deleteCollection(tenantId2, name);
35038
+ const removed = await this.getStore().deleteCollection(tenantId2, name);
35039
+ if (removed) {
35040
+ this.invalidateVectorStores(tenantId2);
35041
+ }
35042
+ return removed;
34711
35043
  }
34712
35044
  async updateCollection(tenantId2, name, updates) {
34713
- return this.getStore().updateCollection(tenantId2, name, updates);
35045
+ const updated = await this.getStore().updateCollection(tenantId2, name, updates);
35046
+ if (updated) {
35047
+ this.invalidateVectorStores(tenantId2);
35048
+ }
35049
+ return updated;
34714
35050
  }
34715
35051
  };
34716
35052
  var collectionLatticeManager = CollectionLatticeManager.getInstance();
@@ -34734,7 +35070,11 @@ async function getOrCreateCollectionVectorStore(name, embeddingKey, tenantId2, p
34734
35070
  const initialization = (async () => {
34735
35071
  const provider2 = vectorStoreProviderManager.getProvider(providerKey);
34736
35072
  const tableName = buildTableName(tenantId2, name);
34737
- const vectorStore = await provider2.create({ tableName, embeddingKey });
35073
+ const vectorStore = await provider2.create({
35074
+ tableName,
35075
+ embeddingKey,
35076
+ tenantId: tenantId2
35077
+ });
34738
35078
  vectorStoreLatticeManager.registerLattice(storeKey, vectorStore);
34739
35079
  return vectorStore;
34740
35080
  })();
@@ -39136,8 +39476,8 @@ var TaskLifecycleNotifier = class {
39136
39476
  this.tails = /* @__PURE__ */ new Map();
39137
39477
  }
39138
39478
  /** Installs (or clears) the durable outbox used to fan notifications to other replicas. */
39139
- setOutbox(outbox2) {
39140
- this.outbox = outbox2;
39479
+ setOutbox(outbox3) {
39480
+ this.outbox = outbox3;
39141
39481
  }
39142
39482
  /**
39143
39483
  * Registers an async lifecycle listener.
@@ -39243,8 +39583,8 @@ var ProjectTaskAdmissionNotifier = class {
39243
39583
  this.listenerTimeoutMs = timeout;
39244
39584
  }
39245
39585
  /** Installs (or clears) the durable outbox used to fan notifications to other replicas. */
39246
- setOutbox(outbox2) {
39247
- this.outbox = outbox2;
39586
+ setOutbox(outbox3) {
39587
+ this.outbox = outbox3;
39248
39588
  }
39249
39589
  /**
39250
39590
  * Registers a Project task admission listener.
@@ -40091,9 +40431,9 @@ var BELIEF_OWNER_WRITE_ATTEMPTS = 3;
40091
40431
  function isWellFormedImpact(impact) {
40092
40432
  return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(impact.key) && Number.isInteger(impact.after) && impact.after >= 0 && impact.after <= 100 && impact.basis.trim().length > 0 && impact.basis.length <= 1e3 && !/[\r\n]/.test(impact.basis);
40093
40433
  }
40094
- async function applyBeliefImpacts(taskStore, owner2, impacts) {
40095
- if (impacts.length === 0) return { description: owner2.description ?? "" };
40096
- let current = owner2;
40434
+ async function applyBeliefImpacts(taskStore, owner3, impacts) {
40435
+ if (impacts.length === 0) return { description: owner3.description ?? "" };
40436
+ let current = owner3;
40097
40437
  for (let attempt = 0; attempt < BELIEF_OWNER_WRITE_ATTEMPTS; attempt += 1) {
40098
40438
  const parsed = (0, import_protocols32.parseTaskBeliefState)(current.description ?? "");
40099
40439
  const existingTable = parsed.success;
@@ -40222,14 +40562,14 @@ function sameBeliefOwner(left, right) {
40222
40562
  function sameBeliefOwnerIdentity(left, right) {
40223
40563
  return canonicalJson({ ...left, beliefState: void 0 }) === canonicalJson({ ...right, beliefState: void 0 });
40224
40564
  }
40225
- function canonicalBeliefOwner(owner2) {
40565
+ function canonicalBeliefOwner(owner3) {
40226
40566
  const beliefState = {
40227
- entries: owner2.beliefState.entries.map((entry) => ({
40567
+ entries: owner3.beliefState.entries.map((entry) => ({
40228
40568
  ...entry,
40229
40569
  basis: entry.basis.trim().replace(/\s+/g, " ")
40230
40570
  })).sort((left, right) => left.key < right.key ? -1 : left.key > right.key ? 1 : 0)
40231
40571
  };
40232
- return { ...owner2, beliefState };
40572
+ return { ...owner3, beliefState };
40233
40573
  }
40234
40574
  function eventKeyFor(taskId, result, impacts, beliefOwner) {
40235
40575
  const base = `belief-impact:${taskId}:${buildBeliefCompletionEventKey(taskId, result, impacts)}`;
@@ -41600,8 +41940,8 @@ var TaskLifecycleService = class {
41600
41940
  return { task: existing, parent: parentResult, eventKey, evidence, result, impacts };
41601
41941
  }
41602
41942
  beliefOwnerSnapshot(task, parent) {
41603
- const owner2 = parent?.ownerType === "agent" ? parent : task;
41604
- const parsed = (0, import_protocols32.parseTaskBeliefState)(owner2.description ?? "");
41943
+ const owner3 = parent?.ownerType === "agent" ? parent : task;
41944
+ const parsed = (0, import_protocols32.parseTaskBeliefState)(owner3.description ?? "");
41605
41945
  const beliefState = parsed.success ? parsed.state : { entries: [] };
41606
41946
  if (parent?.ownerType === "agent") {
41607
41947
  return {
@@ -43387,8 +43727,8 @@ function createTaskExecutionService(deps) {
43387
43727
  var import_node_crypto14 = require("crypto");
43388
43728
  async function runAsLeader(store, name, fn, options = {}) {
43389
43729
  const key5 = `leader:${name}`;
43390
- const owner2 = options.owner ?? getReplicaId();
43391
- const holder = `${owner2}#${(0, import_node_crypto14.randomUUID)()}`;
43730
+ const owner3 = options.owner ?? getReplicaId();
43731
+ const holder = `${owner3}#${(0, import_node_crypto14.randomUUID)()}`;
43392
43732
  const ttlMs = options.ttlMs ?? 6e4;
43393
43733
  if (!await store.tryAcquire(key5, holder, ttlMs)) return { ran: false };
43394
43734
  const heartbeat = setInterval(() => {
@@ -43406,16 +43746,16 @@ async function runAsLeader(store, name, fn, options = {}) {
43406
43746
 
43407
43747
  // src/services/pluginCatalogSync.ts
43408
43748
  var PLUGIN_CATALOG_CHANGED_TOPIC = "plugin-catalog-changed";
43409
- var outbox;
43410
- var owner = "unknown";
43749
+ var outbox2;
43750
+ var owner2 = "unknown";
43411
43751
  function configurePluginCatalogSync(next) {
43412
- outbox = next?.outbox;
43413
- owner = next?.owner ?? "unknown";
43752
+ outbox2 = next?.outbox;
43753
+ owner2 = next?.owner ?? "unknown";
43414
43754
  }
43415
43755
  async function publishPluginCatalogChanged(tenantId2) {
43416
- if (!outbox || !tenantId2) return;
43756
+ if (!outbox2 || !tenantId2) return;
43417
43757
  try {
43418
- await outbox.append({ topic: PLUGIN_CATALOG_CHANGED_TOPIC, payload: { tenantId: tenantId2 }, originReplicaId: owner });
43758
+ await outbox2.append({ topic: PLUGIN_CATALOG_CHANGED_TOPIC, payload: { tenantId: tenantId2 }, originReplicaId: owner2 });
43419
43759
  } catch {
43420
43760
  }
43421
43761
  }
@@ -43601,9 +43941,9 @@ var createLoadSkillsTool = ({ skills, readAll, pluginSkills, pluginSkillOwners }
43601
43941
  if (!skillName) continue;
43602
43942
  if (await isPluginSkillManagedInSandbox(sandbox, skillName)) {
43603
43943
  const enabledDefinition = pluginSkills?.[skillName];
43604
- const owner2 = pluginSkillOwners?.[skillName];
43605
- const registered = owner2 && enabledDefinition ? PluginRegistry.getSkillForPlugin(owner2, skillName) : void 0;
43606
- if (!registered || registered.definition !== enabledDefinition || !owner2 || !await isPluginSkillAuthorizedInSandbox(sandbox, skillName, owner2) || await getPluginSkillManifestVersion(sandbox, skillName) !== enabledDefinition.version) {
43944
+ const owner3 = pluginSkillOwners?.[skillName];
43945
+ const registered = owner3 && enabledDefinition ? PluginRegistry.getSkillForPlugin(owner3, skillName) : void 0;
43946
+ if (!registered || registered.definition !== enabledDefinition || !owner3 || !await isPluginSkillAuthorizedInSandbox(sandbox, skillName, owner3) || await getPluginSkillManifestVersion(sandbox, skillName) !== enabledDefinition.version) {
43607
43947
  continue;
43608
43948
  }
43609
43949
  }
@@ -43629,8 +43969,8 @@ var createLoadSkillsTool = ({ skills, readAll, pluginSkills, pluginSkillOwners }
43629
43969
  const seenNames = new Set(filteredSkills.map((skill) => skill.name));
43630
43970
  try {
43631
43971
  for (const [name, definition] of Object.entries(pluginSkills ?? {})) {
43632
- const owner2 = pluginSkillOwners?.[name];
43633
- const registered = owner2 ? PluginRegistry.getSkillForPlugin(owner2, name) : void 0;
43972
+ const owner3 = pluginSkillOwners?.[name];
43973
+ const registered = owner3 ? PluginRegistry.getSkillForPlugin(owner3, name) : void 0;
43634
43974
  if (!registered || registered.definition !== definition) continue;
43635
43975
  const { meta } = parseSkillFrontmatter(definition.content);
43636
43976
  if (!meta.name || !meta.description || seenNames.has(meta.name)) continue;
@@ -43667,24 +44007,24 @@ var import_zod52 = __toESM(require("zod"));
43667
44007
  var import_langchain63 = require("langchain");
43668
44008
 
43669
44009
  // src/sandbox_plugin/pluginSkillResolution.ts
43670
- async function resolveTenantPluginSkill(tenantId2, owner2, skillName) {
44010
+ async function resolveTenantPluginSkill(tenantId2, owner3, skillName) {
43671
44011
  try {
43672
44012
  const { plugins } = await getSandboxPluginCatalog().ensureLoaded(tenantId2);
43673
- const plugin = plugins.find((candidate) => candidate.meta.type === owner2);
44013
+ const plugin = plugins.find((candidate) => candidate.meta.type === owner3);
43674
44014
  return plugin?.skills?.[skillName];
43675
44015
  } catch {
43676
44016
  return void 0;
43677
44017
  }
43678
44018
  }
43679
- async function resolveEnabledPluginSkill(owner2, skillName, enabledDefinition, tenantId2) {
43680
- if (!owner2 || !enabledDefinition) return void 0;
43681
- const registered = PluginRegistry.getSkillForPlugin(owner2, skillName);
43682
- if (registered && registered.pluginType === owner2 && registered.definition === enabledDefinition) {
43683
- return { pluginType: owner2, definition: enabledDefinition };
44019
+ async function resolveEnabledPluginSkill(owner3, skillName, enabledDefinition, tenantId2) {
44020
+ if (!owner3 || !enabledDefinition) return void 0;
44021
+ const registered = PluginRegistry.getSkillForPlugin(owner3, skillName);
44022
+ if (registered && registered.pluginType === owner3 && registered.definition === enabledDefinition) {
44023
+ return { pluginType: owner3, definition: enabledDefinition };
43684
44024
  }
43685
44025
  if (!tenantId2) return void 0;
43686
- const tenantDefinition = await resolveTenantPluginSkill(tenantId2, owner2, skillName);
43687
- return tenantDefinition ? { pluginType: owner2, definition: tenantDefinition } : void 0;
44026
+ const tenantDefinition = await resolveTenantPluginSkill(tenantId2, owner3, skillName);
44027
+ return tenantDefinition ? { pluginType: owner3, definition: tenantDefinition } : void 0;
43688
44028
  }
43689
44029
 
43690
44030
  // src/tool_lattice/skill/load_skill_content.ts
@@ -43746,10 +44086,10 @@ var createLoadSkillContentTool = (pluginSkills, pluginSkillOwnersOrStaticSelecti
43746
44086
  return result2;
43747
44087
  }
43748
44088
  const enabledDefinition = pluginSkills?.[input.skill_name];
43749
- const owner2 = pluginSkillOwners?.[input.skill_name];
44089
+ const owner3 = pluginSkillOwners?.[input.skill_name];
43750
44090
  const runConfig = _exe_config?.configurable?.runConfig || {};
43751
44091
  const pluginSkill = await resolveEnabledPluginSkill(
43752
- owner2,
44092
+ owner3,
43753
44093
  input.skill_name,
43754
44094
  enabledDefinition,
43755
44095
  runConfig.tenantId
@@ -43856,9 +44196,9 @@ var createLoadSkillResourceTool = (pluginSkills, pluginSkillOwners) => {
43856
44196
  validateRelativePath(input.resource_path, "resource");
43857
44197
  const sandbox = await getSandboxFromExeConfig3(_exe_config);
43858
44198
  const definition = pluginSkills?.[input.skill_name];
43859
- const owner2 = pluginSkillOwners?.[input.skill_name];
44199
+ const owner3 = pluginSkillOwners?.[input.skill_name];
43860
44200
  const tenantId2 = _exe_config?.configurable?.runConfig?.tenantId;
43861
- const resolved = await resolveEnabledPluginSkill(owner2, input.skill_name, definition, tenantId2);
44201
+ const resolved = await resolveEnabledPluginSkill(owner3, input.skill_name, definition, tenantId2);
43862
44202
  if (definition) {
43863
44203
  if (!resolved || !resolved.definition.resources?.[input.resource_path]) {
43864
44204
  return `Resource "${input.resource_path}" not found for skill "${input.skill_name}".`;
@@ -44222,11 +44562,15 @@ var createSearchCollectionTool = (scope = { collectionKeys: [], connectAll: true
44222
44562
  tenantId2
44223
44563
  );
44224
44564
  }
44225
- let embeddingsClient;
44226
- try {
44227
- embeddingsClient = embeddingsLatticeManager.getEmbeddingsClient(embeddingKey);
44228
- } catch {
44229
- embeddingsClient = embeddingsLatticeManager.getEmbeddingsClient("default");
44565
+ const embeddingsClient = await embeddingsLatticeManager.getEmbeddingsClientWithTenant(
44566
+ tenantId2,
44567
+ embeddingKey
44568
+ ) ?? await embeddingsLatticeManager.getEmbeddingsClientWithTenant(
44569
+ tenantId2,
44570
+ "default"
44571
+ );
44572
+ if (!embeddingsClient) {
44573
+ return `No embedding model "${embeddingKey}" is available for this tenant.`;
44230
44574
  }
44231
44575
  const queryVector = await embeddingsClient.embedQuery(query);
44232
44576
  const results = await vectorStore.similaritySearchVectorWithScore(
@@ -52326,6 +52670,7 @@ registerBuiltinPlugins();
52326
52670
  BUILTIN_PLUGINS,
52327
52671
  BUILTIN_SKILLS,
52328
52672
  CAPABILITY_TOOL_NAME_CONFLICT,
52673
+ COLLECTION_CHANGED_TOPIC,
52329
52674
  CapabilityBundleMergeError,
52330
52675
  CapabilityBundleMerger,
52331
52676
  CapabilityBundleValidationError,
@@ -52345,6 +52690,7 @@ registerBuiltinPlugins();
52345
52690
  DEFAULT_DELAY_MS,
52346
52691
  DEFAULT_HANDLER_TIMEOUT_MS,
52347
52692
  DEFAULT_MAX_ATTEMPTS,
52693
+ DEFAULT_MODEL_EXTRA,
52348
52694
  DEFAULT_RESIDENT_INVOKE_TIMEOUT_MS,
52349
52695
  DaytonaInstance,
52350
52696
  DaytonaProvider,
@@ -52500,7 +52846,10 @@ registerBuiltinPlugins();
52500
52846
  buildGrepResultsDict,
52501
52847
  buildHandlerCommand,
52502
52848
  buildInput,
52849
+ buildModelConfig,
52850
+ buildModelEmbeddingsConfig,
52503
52851
  buildModelLlmConfig,
52852
+ buildModelSttConfig,
52504
52853
  buildNamedVolumeName,
52505
52854
  buildRemotePackDirectoryCommand,
52506
52855
  buildSandboxMetadataEnv,
@@ -52521,6 +52870,7 @@ registerBuiltinPlugins();
52521
52870
  compileSandboxPlugin,
52522
52871
  compileWorkflow,
52523
52872
  computeSandboxName,
52873
+ configureCollectionSync,
52524
52874
  configureCoordinationLeaseStore,
52525
52875
  configurePluginCatalogSync,
52526
52876
  configureStores,
@@ -52698,6 +53048,7 @@ registerBuiltinPlugins();
52698
53048
  projectRoomPlugin,
52699
53049
  projectTaskAdmissionNotifier,
52700
53050
  provisionSandboxOpenClient,
53051
+ publishCollectionChanged,
52701
53052
  publishPluginCatalogChanged,
52702
53053
  queueLatticeManager,
52703
53054
  readLoopBreakerConfig,