@massa-ai/tools-api 1.58.0 → 1.60.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.
Files changed (2) hide show
  1. package/dist/index.js +202 -67
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -444,10 +444,15 @@ function parseLmStudioModelList(body) {
444
444
  function inferenceProviderList() {
445
445
  return LOCAL_INFERENCE_IDS.map((id) => INFERENCE_PROVIDERS[id]);
446
446
  }
447
- var LOCAL_INFERENCE_IDS, INFERENCE_PROVIDERS;
447
+ var LOCAL_INFERENCE_IDS, INFERENCE_ROLE_DEFAULTS, INFERENCE_PROVIDERS;
448
448
  var init_inference_providers = __esm(() => {
449
449
  init_embedding_dimensions();
450
450
  LOCAL_INFERENCE_IDS = ["ollama", "lmstudio"];
451
+ INFERENCE_ROLE_DEFAULTS = {
452
+ embedding: { contextWindow: 8192 },
453
+ instruct: { contextWindow: 16384, temperature: 0.2 },
454
+ coding: { contextWindow: 32768, temperature: 0 }
455
+ };
451
456
  INFERENCE_PROVIDERS = {
452
457
  ollama: {
453
458
  id: "ollama",
@@ -459,6 +464,13 @@ var init_inference_providers = __esm(() => {
459
464
  dimensions: "OLLAMA_EMBEDDING_DIMENSIONS"
460
465
  },
461
466
  knownDimensions: KNOWN_EMBEDDING_DIMENSIONS,
467
+ defaultModels: {
468
+ embedding: "qwen3-embedding:0.6b",
469
+ instruct: "qwen3-vl:8b",
470
+ coding: "qwen2.5-coder:7b"
471
+ },
472
+ appliesContextPerRequest: true,
473
+ embedBatchSize: 64,
462
474
  supportsOllamaVersionProbe: true,
463
475
  injectsDisableThink: true,
464
476
  requiresChatCompletionsApi: false,
@@ -474,8 +486,36 @@ var init_inference_providers = __esm(() => {
474
486
  dimensions: "LMSTUDIO_EMBEDDING_DIMENSIONS"
475
487
  },
476
488
  knownDimensions: {
477
- "text-embedding-nomic-embed-text-v1.5": 768
489
+ "text-embedding-nomic-embed-text-v1.5": 768,
490
+ "text-embedding-qwen3-embedding-0.6b": 1024,
491
+ "qwen3-embedding-0.6b-dwq": 1024
492
+ },
493
+ defaultModels: {
494
+ embedding: "text-embedding-qwen3-embedding-0.6b",
495
+ instruct: "qwen3-vl-8b-instruct",
496
+ coding: "qwen2.5-coder-7b-instruct"
497
+ },
498
+ mlxModels: {
499
+ embedding: {
500
+ repo: "mlx-community/Qwen3-Embedding-0.6B-4bit-DWQ",
501
+ model: "qwen3-embedding-0.6b-dwq"
502
+ },
503
+ instruct: {
504
+ repo: "mlx-community/Qwen3-VL-8B-Instruct-4bit",
505
+ model: "qwen3-vl-8b-instruct"
506
+ },
507
+ coding: {
508
+ repo: "mlx-community/Qwen2.5-Coder-7B-Instruct-4bit",
509
+ model: "qwen2.5-coder-7b-instruct"
510
+ }
478
511
  },
512
+ ggufRepos: {
513
+ embedding: "Qwen/Qwen3-Embedding-0.6B-GGUF",
514
+ instruct: "lmstudio-community/Qwen3-VL-8B-Instruct-GGUF",
515
+ coding: "lmstudio-community/Qwen2.5-Coder-7B-Instruct-GGUF"
516
+ },
517
+ appliesContextPerRequest: false,
518
+ embedBatchSize: 64,
479
519
  supportsOllamaVersionProbe: false,
480
520
  injectsDisableThink: false,
481
521
  requiresChatCompletionsApi: true,
@@ -490,6 +530,7 @@ var API_PROVIDER_IDS, EMBEDDING_PROVIDER_IDS, SCHEDULER_JOB_KINDS, MAX_MATCH_WOR
490
530
  var init_massa_ai_config = __esm(() => {
491
531
  init_xdg();
492
532
  init_inference_providers();
533
+ init_embedding_dimensions();
493
534
  API_PROVIDER_IDS = ["mistral", "openai", "google", "cohere"];
494
535
  EMBEDDING_PROVIDER_IDS = [
495
536
  ...LOCAL_INFERENCE_IDS,
@@ -556,9 +597,9 @@ var init_massa_ai_config = __esm(() => {
556
597
  },
557
598
  embedding: {
558
599
  provider: "ollama",
559
- model: "qwen3-embedding:4b",
600
+ model: INFERENCE_PROVIDERS.ollama.defaultModels.embedding,
560
601
  baseURL: "http://localhost:11434",
561
- dimensions: 2560
602
+ dimensions: knownEmbeddingDimensions(INFERENCE_PROVIDERS.ollama.defaultModels.embedding) ?? 768
562
603
  },
563
604
  compression: {
564
605
  defaultStrategy: "code_structure",
@@ -597,12 +638,15 @@ var init_massa_ai_config = __esm(() => {
597
638
  enabled: false,
598
639
  baseUrl: "http://localhost:11434/v1",
599
640
  apiKey: "ollama",
600
- model: "qwen2.5:7b-instruct",
601
- codeModel: "qwen2.5-coder:7b",
641
+ model: INFERENCE_PROVIDERS.ollama.defaultModels.instruct,
642
+ codeModel: INFERENCE_PROVIDERS.ollama.defaultModels.coding,
602
643
  temperature: 0.2,
603
644
  maxOutputTokens: 8000,
604
645
  timeoutMs: 90000,
605
- disableThink: true
646
+ disableThink: true,
647
+ contextWindow: INFERENCE_ROLE_DEFAULTS.instruct.contextWindow,
648
+ codeContextWindow: INFERENCE_ROLE_DEFAULTS.coding.contextWindow,
649
+ codeTemperature: INFERENCE_ROLE_DEFAULTS.coding.temperature
606
650
  },
607
651
  memory: {
608
652
  decay: {
@@ -1098,6 +1142,10 @@ function validatePartial(partial) {
1098
1142
  details.push("embedding.apiKey must be a string");
1099
1143
  if (e.dimensions !== undefined && !checkNumber(e.dimensions, 1))
1100
1144
  details.push("embedding.dimensions must be a positive number");
1145
+ if (e.contextWindow !== undefined && !checkNumber(e.contextWindow, 1))
1146
+ details.push("embedding.contextWindow must be a positive number");
1147
+ if (e.batchSize !== undefined && !checkNumber(e.batchSize, 1))
1148
+ details.push("embedding.batchSize must be a positive number");
1101
1149
  }
1102
1150
  if (partial.compression !== undefined) {
1103
1151
  const c = partial.compression;
@@ -1181,6 +1229,12 @@ function validatePartial(partial) {
1181
1229
  details.push("llm.timeoutMs must be a positive number");
1182
1230
  if (!checkBoolean(l.disableThink))
1183
1231
  details.push("llm.disableThink must be a boolean");
1232
+ if (!checkNumber(l.contextWindow, 1))
1233
+ details.push("llm.contextWindow must be a positive number");
1234
+ if (!checkNumber(l.codeContextWindow, 1))
1235
+ details.push("llm.codeContextWindow must be a positive number");
1236
+ if (!checkNumber(l.codeTemperature))
1237
+ details.push("llm.codeTemperature must be a number");
1184
1238
  }
1185
1239
  if (partial.memory !== undefined) {
1186
1240
  const m = partial.memory;
@@ -1619,6 +1673,13 @@ function getGlobalDataDir() {
1619
1673
  return fileConfig.dataDir;
1620
1674
  return path6.join(getConfigDir(), "data");
1621
1675
  }
1676
+ function activeInferenceProviderId() {
1677
+ const providerId = fileConfig.embedding?.provider;
1678
+ if (providerId && LOCAL_INFERENCE_IDS.includes(providerId)) {
1679
+ return providerId;
1680
+ }
1681
+ return "ollama";
1682
+ }
1622
1683
 
1623
1684
  class Config {
1624
1685
  config;
@@ -1755,11 +1816,12 @@ class Config {
1755
1816
  this.config[key] = value;
1756
1817
  }
1757
1818
  }
1758
- var DEFAULT_LLM_MODEL = "qwen2.5:7b-instruct", DEFAULT_LLM_CODE_MODEL = "qwen2.5-coder:7b", SCHEDULER_JOB_ENV, DEFAULT_ALLOWED_EXTENSIONS, fileConfig, fileCacheL1Bytes, fileCacheL2Bytes, resolvedDataDir, defaultConfig, config;
1819
+ var SCHEDULER_JOB_ENV, DEFAULT_ALLOWED_EXTENSIONS, fileConfig, DEFAULT_LLM_MODEL, DEFAULT_LLM_CODE_MODEL, fileCacheL1Bytes, fileCacheL2Bytes, resolvedDataDir, defaultConfig, config;
1759
1820
  var init_config = __esm(() => {
1760
1821
  init_env();
1761
1822
  init_config_loader();
1762
1823
  init_massa_ai_config();
1824
+ init_inference_providers();
1763
1825
  init_massa_ai_config();
1764
1826
  init_massa_ai_config();
1765
1827
  init_config_loader();
@@ -1830,6 +1892,8 @@ var init_config = __esm(() => {
1830
1892
  ".hs"
1831
1893
  ];
1832
1894
  fileConfig = loadConfigSafe();
1895
+ DEFAULT_LLM_MODEL = INFERENCE_PROVIDERS[activeInferenceProviderId()].defaultModels.instruct;
1896
+ DEFAULT_LLM_CODE_MODEL = INFERENCE_PROVIDERS[activeInferenceProviderId()].defaultModels.coding;
1833
1897
  fileCacheL1Bytes = fileConfig.cache?.l1MaxSizeMB ? fileConfig.cache.l1MaxSizeMB * 1024 * 1024 : undefined;
1834
1898
  fileCacheL2Bytes = fileConfig.cache?.l2MaxSizeMB ? fileConfig.cache.l2MaxSizeMB * 1024 * 1024 : undefined;
1835
1899
  resolvedDataDir = getGlobalDataDir();
@@ -1872,7 +1936,10 @@ var init_config = __esm(() => {
1872
1936
  temperature: envNum("MASSA_AI_LLM_TEMPERATURE", fileConfig.llm?.temperature ?? 0.2),
1873
1937
  maxOutputTokens: envNum("MASSA_AI_LLM_MAX_OUTPUT_TOKENS", fileConfig.llm?.maxOutputTokens ?? 8000),
1874
1938
  timeoutMs: envNum("MASSA_AI_LLM_TIMEOUT_MS", fileConfig.llm?.timeoutMs ?? 90000),
1875
- disableThink: envBool("MASSA_AI_LLM_DISABLE_THINK", fileConfig.llm?.disableThink ?? true)
1939
+ disableThink: envBool("MASSA_AI_LLM_DISABLE_THINK", fileConfig.llm?.disableThink ?? true),
1940
+ contextWindow: fileConfig.llm?.contextWindow ?? INFERENCE_ROLE_DEFAULTS.instruct.contextWindow,
1941
+ codeContextWindow: fileConfig.llm?.codeContextWindow ?? INFERENCE_ROLE_DEFAULTS.coding.contextWindow,
1942
+ codeTemperature: envNum("MASSA_AI_LLM_CODE_TEMPERATURE", fileConfig.llm?.codeTemperature ?? INFERENCE_ROLE_DEFAULTS.coding.temperature)
1876
1943
  },
1877
1944
  memory: {
1878
1945
  decay: {
@@ -52615,20 +52682,26 @@ function isLlmEnabled() {
52615
52682
  function _setLlmEnabledForTesting(flag) {
52616
52683
  testEnabledOverride = flag;
52617
52684
  }
52618
- function getLlmConfig(opts) {
52619
- const cfg = config.get("llm");
52620
- const role = opts?.modelRole ?? "instruct";
52621
- const model = role === "code" ? cfg?.codeModel ?? cfg?.model ?? DEFAULT_LLM_MODEL : cfg?.model ?? DEFAULT_LLM_MODEL;
52685
+ function _resolveLlmConfig(cfg, role, baseUrlOverride) {
52686
+ const baseUrl = baseUrlOverride ?? cfg?.baseUrl ?? INFERENCE_PROVIDERS.ollama.defaultLlmBaseUrl;
52687
+ const spec = resolveInferenceSpec(baseUrl);
52688
+ const model = role === "code" ? cfg?.codeModel ?? spec.defaultModels.coding : cfg?.model ?? spec.defaultModels.instruct;
52689
+ const temperature = role === "code" ? cfg?.codeTemperature ?? INFERENCE_ROLE_DEFAULTS.coding.temperature : cfg?.temperature ?? INFERENCE_ROLE_DEFAULTS.instruct.temperature;
52690
+ const contextWindow = role === "code" ? cfg?.codeContextWindow ?? INFERENCE_ROLE_DEFAULTS.coding.contextWindow : cfg?.contextWindow ?? INFERENCE_ROLE_DEFAULTS.instruct.contextWindow;
52622
52691
  return {
52623
- baseUrl: testBaseUrlOverride ?? cfg?.baseUrl ?? "http://localhost:11434/v1",
52624
- apiKey: cfg?.apiKey ?? "ollama",
52692
+ baseUrl,
52693
+ apiKey: cfg?.apiKey ?? spec.id,
52625
52694
  model,
52626
- temperature: cfg?.temperature ?? 0.2,
52695
+ temperature,
52696
+ contextWindow,
52627
52697
  maxOutputTokens: cfg?.maxOutputTokens ?? 8000,
52628
52698
  timeoutMs: cfg?.timeoutMs ?? 90000,
52629
- disableThink: cfg?.disableThink ?? true
52699
+ disableThink: cfg?.disableThink ?? spec.injectsDisableThink
52630
52700
  };
52631
52701
  }
52702
+ function getLlmConfig(opts) {
52703
+ return _resolveLlmConfig(config.get("llm"), opts?.modelRole ?? "instruct", testBaseUrlOverride);
52704
+ }
52632
52705
  function hostPort(url2) {
52633
52706
  try {
52634
52707
  const u = new URL(url2);
@@ -52672,12 +52745,34 @@ function _wrapFetchDisableThink(baseFetch) {
52672
52745
  };
52673
52746
  return wrapped;
52674
52747
  }
52748
+ function _wrapFetchContextWindow(baseFetch, contextWindow) {
52749
+ const wrapped = async (input, init) => {
52750
+ try {
52751
+ if (init?.body && typeof init.body === "string") {
52752
+ const parsed = JSON.parse(init.body);
52753
+ if (parsed && typeof parsed === "object") {
52754
+ parsed.options = { ...parsed.options, num_ctx: contextWindow };
52755
+ init = { ...init, body: JSON.stringify(parsed) };
52756
+ }
52757
+ }
52758
+ } catch {}
52759
+ return baseFetch(input, init);
52760
+ };
52761
+ return wrapped;
52762
+ }
52675
52763
  function buildProvider(llm) {
52676
52764
  const spec = resolveInferenceSpec(llm.baseUrl);
52765
+ let fetchImpl;
52766
+ if (spec.appliesContextPerRequest) {
52767
+ fetchImpl = _wrapFetchContextWindow(fetchImpl ?? globalThis.fetch, llm.contextWindow);
52768
+ }
52769
+ if (llm.disableThink && spec.injectsDisableThink) {
52770
+ fetchImpl = _wrapFetchDisableThink(fetchImpl ?? globalThis.fetch);
52771
+ }
52677
52772
  const openai2 = createOpenAI({
52678
52773
  baseURL: llm.baseUrl,
52679
52774
  apiKey: llm.apiKey,
52680
- ...llm.disableThink && spec.injectsDisableThink ? { fetch: _wrapFetchDisableThink(globalThis.fetch) } : {}
52775
+ ...fetchImpl ? { fetch: fetchImpl } : {}
52681
52776
  });
52682
52777
  return spec.requiresChatCompletionsApi ? openai2.chat(llm.model) : openai2(llm.model);
52683
52778
  }
@@ -95425,6 +95520,9 @@ var init_local_transformers = __esm(() => {
95425
95520
  });
95426
95521
 
95427
95522
  // ../../packages/core/dist/services/embeddings/provider.js
95523
+ function _resolveEmbedContextWindow(embeddingConfig) {
95524
+ return parsePositiveIntEnv(process.env.OLLAMA_EMBEDDING_NUM_CTX, embeddingConfig?.contextWindow ?? INFERENCE_ROLE_DEFAULTS.embedding.contextWindow);
95525
+ }
95428
95526
  function sleep(ms) {
95429
95527
  return new Promise((resolve4) => setTimeout(resolve4, ms));
95430
95528
  }
@@ -95467,7 +95565,7 @@ function createProvider(config3, providerId) {
95467
95565
  }
95468
95566
  return new AISDKEmbeddingProvider(config3, providerId);
95469
95567
  }
95470
- var OLLAMA_EMBED_NUM_CTX, DimensionMismatchError, AISDKEmbeddingProvider;
95568
+ var DimensionMismatchError, AISDKEmbeddingProvider;
95471
95569
  var init_provider = __esm(() => {
95472
95570
  init_dist6();
95473
95571
  init_dist7();
@@ -95479,8 +95577,8 @@ var init_provider = __esm(() => {
95479
95577
  init_rate_limiter2();
95480
95578
  init_dist();
95481
95579
  init_config();
95580
+ init_inference_providers();
95482
95581
  init_local_transformers();
95483
- OLLAMA_EMBED_NUM_CTX = parsePositiveIntEnv(process.env.OLLAMA_EMBEDDING_NUM_CTX, 8192);
95484
95582
  DimensionMismatchError = class DimensionMismatchError extends Error {
95485
95583
  providerId;
95486
95584
  expected;
@@ -95642,7 +95740,7 @@ var init_provider = __esm(() => {
95642
95740
  const response = await this.ollamaFetch("/api/embed", {
95643
95741
  model: this.model,
95644
95742
  input: inputText,
95645
- options: { num_ctx: OLLAMA_EMBED_NUM_CTX }
95743
+ options: { num_ctx: _resolveEmbedContextWindow(loadConfigSafe().embedding) }
95646
95744
  });
95647
95745
  if (!response.ok) {
95648
95746
  throw new Error(`Ollama API error: ${response.status} ${response.statusText}`);
@@ -95733,7 +95831,7 @@ var init_provider = __esm(() => {
95733
95831
  const response = await this.ollamaFetch("/api/embed", {
95734
95832
  model: this.model,
95735
95833
  input: texts.map((t2) => this.sanitizeText(this.truncateText(t2))),
95736
- options: { num_ctx: OLLAMA_EMBED_NUM_CTX }
95834
+ options: { num_ctx: _resolveEmbedContextWindow(loadConfigSafe().embedding) }
95737
95835
  });
95738
95836
  if (!response.ok) {
95739
95837
  throw new Error(`Ollama batch API error: ${response.status} ${response.statusText}`);
@@ -107020,7 +107118,7 @@ var init_config2 = __esm(() => {
107020
107118
  })(),
107021
107119
  ollama: (() => {
107022
107120
  const file3 = fileFor("ollama");
107023
- const model = process.env.OLLAMA_EMBEDDING_MODEL || file3?.model || "qwen3-embedding:4b";
107121
+ const model = process.env.OLLAMA_EMBEDDING_MODEL || file3?.model || INFERENCE_PROVIDERS.ollama.defaultModels.embedding;
107024
107122
  const rawEnvDimensions = Number(process.env.OLLAMA_EMBEDDING_DIMENSIONS);
107025
107123
  const envDimensions = Number.isInteger(rawEnvDimensions) && rawEnvDimensions > 0 ? rawEnvDimensions : undefined;
107026
107124
  const resolvedDimensions = resolveEmbeddingDimensions(model, file3?.dimensions, envDimensions);
@@ -107126,7 +107224,7 @@ var init_config2 = __esm(() => {
107126
107224
  })(),
107127
107225
  lmstudio: (() => {
107128
107226
  const file3 = fileFor("lmstudio");
107129
- const model = process.env.LMSTUDIO_EMBEDDING_MODEL || file3?.model || "text-embedding-nomic-embed-text-v1.5";
107227
+ const model = process.env.LMSTUDIO_EMBEDDING_MODEL || file3?.model || INFERENCE_PROVIDERS.lmstudio.defaultModels.embedding;
107130
107228
  return {
107131
107229
  provider: "custom",
107132
107230
  model,
@@ -109478,6 +109576,12 @@ var init_base_vector_store = __esm(() => {
109478
109576
  });
109479
109577
 
109480
109578
  // ../../packages/core/dist/data/vector/postgres-vector-store.js
109579
+ function _resolveEmbedBatchSize(embeddingConfig) {
109580
+ const providerId = embeddingConfig?.provider;
109581
+ const spec = providerId && LOCAL_INFERENCE_IDS.includes(providerId) ? INFERENCE_PROVIDERS[providerId] : INFERENCE_PROVIDERS.ollama;
109582
+ return embeddingConfig?.batchSize ?? spec.embedBatchSize;
109583
+ }
109584
+
109481
109585
  class PostgresVectorCollection {
109482
109586
  pool;
109483
109587
  name;
@@ -109590,6 +109694,8 @@ var init_postgres_vector_store = __esm(() => {
109590
109694
  init_base_vector_store();
109591
109695
  init_dist();
109592
109696
  init_dist();
109697
+ init_config();
109698
+ init_inference_providers();
109593
109699
  init_identity_guard_installer();
109594
109700
  PostgresVectorStore = class PostgresVectorStore extends BaseVectorStore {
109595
109701
  pool = null;
@@ -109815,7 +109921,7 @@ var init_postgres_vector_store = __esm(() => {
109815
109921
  if (documents.length === 0)
109816
109922
  return;
109817
109923
  const pool = await this.ensureInitialized();
109818
- const EMBED_SUB_BATCH_SIZE = 8;
109924
+ const EMBED_SUB_BATCH_SIZE = _resolveEmbedBatchSize(loadConfigSafe().embedding);
109819
109925
  let totalInserted = 0;
109820
109926
  let totalFailed = 0;
109821
109927
  for (let i = 0;i < documents.length; i += EMBED_SUB_BATCH_SIZE) {
@@ -128125,6 +128231,7 @@ class PgObservationStore {
128125
128231
  mirror = new Map;
128126
128232
  hydrated = false;
128127
128233
  hydrating = null;
128234
+ inflight = new Map;
128128
128235
  hydrateFailedAt = 0;
128129
128236
  static HYDRATE_RETRY_MS = 30000;
128130
128237
  getClient() {
@@ -128176,46 +128283,53 @@ class PgObservationStore {
128176
128283
  const cachedCanonical = getProjectIdentityAliasResolver().resolveCached(obs.projectId);
128177
128284
  this.mirror.set(obs.id, cachedCanonical && cachedCanonical !== obs.projectId ? { ...obs, projectId: cachedCanonical } : obs);
128178
128285
  this.ensureHydrated();
128179
- (async () => {
128180
- try {
128181
- const prisma2 = this.getClient();
128182
- const canonicalProjectId = await getProjectIdentityAliasResolver().resolve(obs.projectId);
128183
- if (canonicalProjectId !== obs.projectId) {
128184
- this.mirror.set(obs.id, { ...obs, projectId: canonicalProjectId });
128185
- }
128186
- await prisma2.$executeRaw`
128187
- INSERT INTO observations (
128188
- id, project_id, session_id, source, category, payload_json, importance, created_at, agent_id, attribution_source
128189
- ) VALUES (
128190
- ${obs.id},
128191
- ${canonicalProjectId},
128192
- ${obs.sessionId},
128193
- ${obs.source},
128194
- ${obs.category ?? null},
128195
- ${obs.payloadJson},
128196
- ${obs.importance},
128197
- ${obs.createdAt}::bigint,
128198
- ${obs.agentId ?? null},
128199
- ${obs.attributionSource ?? null}
128200
- )
128201
- ON CONFLICT (id) DO UPDATE SET
128202
- project_id = EXCLUDED.project_id,
128203
- session_id = EXCLUDED.session_id,
128204
- source = EXCLUDED.source,
128205
- category = EXCLUDED.category,
128206
- payload_json = EXCLUDED.payload_json,
128207
- importance = EXCLUDED.importance,
128208
- created_at = EXCLUDED.created_at,
128209
- agent_id = EXCLUDED.agent_id,
128210
- attribution_source = EXCLUDED.attribution_source
128211
- `;
128212
- } catch (e) {
128213
- logger.warn("PgObservationStore.insert failed (best-effort)", {
128214
- id: obs.id,
128215
- error: e.message
128216
- });
128286
+ this.chainWrite(obs.id, async () => {
128287
+ const prisma2 = this.getClient();
128288
+ const canonicalProjectId = await getProjectIdentityAliasResolver().resolve(obs.projectId);
128289
+ if (canonicalProjectId !== obs.projectId) {
128290
+ this.mirror.set(obs.id, { ...obs, projectId: canonicalProjectId });
128217
128291
  }
128218
- })();
128292
+ await prisma2.$executeRaw`
128293
+ INSERT INTO observations (
128294
+ id, project_id, session_id, source, category, payload_json, importance, created_at, agent_id, attribution_source
128295
+ ) VALUES (
128296
+ ${obs.id},
128297
+ ${canonicalProjectId},
128298
+ ${obs.sessionId},
128299
+ ${obs.source},
128300
+ ${obs.category ?? null},
128301
+ ${obs.payloadJson},
128302
+ ${obs.importance},
128303
+ ${obs.createdAt}::bigint,
128304
+ ${obs.agentId ?? null},
128305
+ ${obs.attributionSource ?? null}
128306
+ )
128307
+ ON CONFLICT (id) DO UPDATE SET
128308
+ project_id = EXCLUDED.project_id,
128309
+ session_id = EXCLUDED.session_id,
128310
+ source = EXCLUDED.source,
128311
+ category = EXCLUDED.category,
128312
+ payload_json = EXCLUDED.payload_json,
128313
+ importance = EXCLUDED.importance,
128314
+ created_at = EXCLUDED.created_at,
128315
+ agent_id = EXCLUDED.agent_id,
128316
+ attribution_source = EXCLUDED.attribution_source
128317
+ `;
128318
+ });
128319
+ }
128320
+ chainWrite(key, fn) {
128321
+ const prev = this.inflight.get(key) ?? Promise.resolve();
128322
+ const next = prev.then(fn).catch((e) => {
128323
+ logger.warn("PgObservationStore.insert failed (best-effort)", {
128324
+ id: key,
128325
+ error: e.message
128326
+ });
128327
+ });
128328
+ this.inflight.set(key, next);
128329
+ next.then(() => {
128330
+ if (this.inflight.get(key) === next)
128331
+ this.inflight.delete(key);
128332
+ });
128219
128333
  }
128220
128334
  listRecent(projectId, limit) {
128221
128335
  this.ensureHydrated();
@@ -128242,6 +128356,9 @@ class PgObservationStore {
128242
128356
  await this.ensureHydrated();
128243
128357
  }
128244
128358
  async __drain() {
128359
+ const pending = Array.from(this.inflight.values());
128360
+ if (pending.length > 0)
128361
+ await Promise.allSettled(pending);
128245
128362
  await new Promise((r2) => setTimeout(r2, 10));
128246
128363
  }
128247
128364
  }
@@ -181069,9 +181186,14 @@ var analyticsRoutes = new Elysia({ prefix: "/api/v1/analytics" }).post("/", asyn
181069
181186
 
181070
181187
  // src/routes/system.ts
181071
181188
  init_dist();
181189
+ init_config();
181190
+ init_inference_providers();
181072
181191
  import path37 from "path";
181073
181192
  import fs24 from "fs";
181074
181193
  import os9 from "os";
181194
+ function resolveConfiguredOllamaEmbeddingModel() {
181195
+ return process.env.OLLAMA_EMBEDDING_MODEL || loadRawUserConfig().embedding?.model || INFERENCE_PROVIDERS.ollama.defaultModels.embedding;
181196
+ }
181075
181197
  function databaseUrlParts() {
181076
181198
  const url2 = new URL(process.env.DATABASE_URL);
181077
181199
  return {
@@ -181185,7 +181307,7 @@ var systemRoutes = new Elysia({ prefix: "/api/v1/system" }).get("/info", async (
181185
181307
  return {
181186
181308
  ...ollamaStatus,
181187
181309
  models,
181188
- configuredModel: process.env.OLLAMA_EMBEDDING_MODEL || "qwen3-embedding:4b",
181310
+ configuredModel: resolveConfiguredOllamaEmbeddingModel(),
181189
181311
  baseUrl: process.env.OLLAMA_BASE_URL || "http://localhost:11434"
181190
181312
  };
181191
181313
  }, {
@@ -183779,9 +183901,14 @@ var profileRoutes = new Elysia({ prefix: "/api/v1/profiles" }).get("/", ({ query
183779
183901
 
183780
183902
  // src/routes/config.ts
183781
183903
  init_dist();
183904
+ init_inference_providers();
183782
183905
  var CONFIG_DETAIL = {
183783
183906
  tags: ["config"]
183784
183907
  };
183908
+ function defaultEmbedBatchSize(provider) {
183909
+ const spec = typeof provider === "string" && LOCAL_INFERENCE_IDS.includes(provider) ? INFERENCE_PROVIDERS[provider] : INFERENCE_PROVIDERS.ollama;
183910
+ return spec.embedBatchSize;
183911
+ }
183785
183912
  var SENSITIVE_FIELDS = {
183786
183913
  database: ["url"],
183787
183914
  embedding: ["apiKey"],
@@ -183806,7 +183933,15 @@ var configRoutes = new Elysia({ prefix: "/api/v1/config" }).get("/", ({ set: set
183806
183933
  const config3 = loadConfig();
183807
183934
  const masked = maskSensitive(config3);
183808
183935
  const restart = restartNeededSections(config3);
183809
- const defaults2 = maskSensitive(defaultMassaAiConfig);
183936
+ const shipped = maskSensitive(defaultMassaAiConfig);
183937
+ const defaults2 = {
183938
+ ...shipped,
183939
+ embedding: {
183940
+ ...shipped.embedding,
183941
+ contextWindow: INFERENCE_ROLE_DEFAULTS.embedding.contextWindow,
183942
+ batchSize: defaultEmbedBatchSize(config3.embedding?.provider)
183943
+ }
183944
+ };
183810
183945
  set3.status = 200;
183811
183946
  return {
183812
183947
  success: true,
@@ -183816,7 +183951,7 @@ var configRoutes = new Elysia({ prefix: "/api/v1/config" }).get("/", ({ set: set
183816
183951
  detail: {
183817
183952
  ...CONFIG_DETAIL,
183818
183953
  summary: "Get current config with sensitive fields masked",
183819
- description: "Returns the current config.json with security.apiKey, llm.apiKey, embedding.apiKey, and database.url masked to '***'. Includes restartNeededSections \u2014 the subset of [database, embedding, llm, security] present in the config \u2014 and defaults, the shipped default config (also masked) the Config tab falls back to for any field the persisted file omits."
183954
+ description: "Returns the current config.json with security.apiKey, llm.apiKey, embedding.apiKey, and database.url masked to '***'. Includes restartNeededSections \u2014 the subset of [database, embedding, llm, security] present in the config \u2014 and defaults, the shipped default config (also masked) the Config tab falls back to for any field the persisted file omits. defaults.embedding.contextWindow and defaults.embedding.batchSize are derived rather than shipped: they come from the role table and the resolved provider's seam entry, because defaultMassaAiConfig deliberately leaves both unset (PDM-12)."
183820
183955
  }
183821
183956
  }).get("/reveal", ({ query, set: set3 }) => {
183822
183957
  const section = query.section;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massa-ai/tools-api",
3
- "version": "1.58.0",
3
+ "version": "1.60.0",
4
4
  "author": "luizgmassa",
5
5
  "description": "massa-ai REST API server - Semantic code search, memory, and context compression",
6
6
  "type": "module",
@@ -21,8 +21,8 @@
21
21
  "test": "bun scripts/run-tests-isolated.ts"
22
22
  },
23
23
  "dependencies": {
24
- "@massa-ai/core": "^1.58.0",
25
- "@massa-ai/shared": "^1.58.0",
24
+ "@massa-ai/core": "^1.60.0",
25
+ "@massa-ai/shared": "^1.60.0",
26
26
  "elysia": "^1.2.25",
27
27
  "@elysiajs/swagger": "^1.2.0",
28
28
  "@elysiajs/cors": "^1.2.0",