@massa-ai/mcp-client 1.66.1 → 1.67.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.
@@ -2182,6 +2182,15 @@ function estimateTokens(text, type = "code") {
2182
2182
  const charsPerToken = type === "code" ? 4 : 5;
2183
2183
  return Math.ceil(text.length / charsPerToken);
2184
2184
  }
2185
+ function truncateToTokenLimit(text, limit, type = "code") {
2186
+ const charsPerToken = type === "code" ? 4 : 5;
2187
+ const maxChars = limit * charsPerToken;
2188
+ if (text.length <= maxChars) {
2189
+ return text;
2190
+ }
2191
+ return text.slice(0, maxChars) + `
2192
+ ... (truncated)`;
2193
+ }
2185
2194
  // ../../packages/shared/dist/utils/metrics.js
2186
2195
  var FALLBACK_PRICING, MetricsCollector;
2187
2196
  var init_metrics = __esm(() => {
@@ -53035,12 +53044,55 @@ function _isAbortOrTimeoutError(err) {
53035
53044
  }
53036
53045
  return false;
53037
53046
  }
53047
+ function _isConnectionError(err) {
53048
+ let cur = err;
53049
+ for (let hops = 0;cur && hops < 5; hops++, cur = cur.lastError ?? cur.cause) {
53050
+ const code = typeof cur.code === "string" ? cur.code : "";
53051
+ if (/^(ECONNREFUSED|ECONNRESET|ENOTFOUND|EHOSTUNREACH|ConnectionRefused|ConnectionClosed|FailedToOpenSocket)$/.test(code)) {
53052
+ return true;
53053
+ }
53054
+ const message = typeof cur.message === "string" ? cur.message : "";
53055
+ if (message.startsWith("Cannot connect to API"))
53056
+ return true;
53057
+ }
53058
+ return false;
53059
+ }
53038
53060
  function summarizeZodIssues(error51, maxIssues = 5) {
53039
53061
  return error51.issues.slice(0, maxIssues).map((issue2) => `${issue2.path.join(".") || "(root)"}: ${issue2.message}`).join("; ");
53040
53062
  }
53063
+ function isEndpointCircuitOpen(baseUrl) {
53064
+ const circuit = endpointCircuits.get(baseUrl);
53065
+ if (!circuit || circuit.failures < ENDPOINT_FAILURE_THRESHOLD)
53066
+ return false;
53067
+ const now2 = Date.now();
53068
+ if (now2 < circuit.openUntil)
53069
+ return true;
53070
+ circuit.openUntil = now2 + ENDPOINT_COOLDOWN_MS;
53071
+ return false;
53072
+ }
53073
+ function recordEndpointOutcome(baseUrl, err) {
53074
+ if (!err || !_isConnectionError(err)) {
53075
+ endpointCircuits.delete(baseUrl);
53076
+ return;
53077
+ }
53078
+ const circuit = endpointCircuits.get(baseUrl) ?? { failures: 0, openUntil: 0 };
53079
+ circuit.failures++;
53080
+ if (circuit.failures >= ENDPOINT_FAILURE_THRESHOLD) {
53081
+ circuit.openUntil = Date.now() + ENDPOINT_COOLDOWN_MS;
53082
+ }
53083
+ if (circuit.failures === ENDPOINT_FAILURE_THRESHOLD) {
53084
+ logger.warn("LLM endpoint unreachable \u2014 pausing LLM calls", {
53085
+ provider: resolveProviderIdForLogging(baseUrl),
53086
+ consecutiveConnectionFailures: circuit.failures,
53087
+ cooldownMs: ENDPOINT_COOLDOWN_MS
53088
+ });
53089
+ }
53090
+ endpointCircuits.set(baseUrl, circuit);
53091
+ }
53041
53092
  function recordLlmFailure(label, role, model, baseUrl, timeoutMs, elapsedMs, err) {
53042
53093
  const consecutiveFailures = (llmFailureStreaks.get(label) ?? 0) + 1;
53043
53094
  llmFailureStreaks.set(label, consecutiveFailures);
53095
+ recordEndpointOutcome(baseUrl, err);
53044
53096
  logger.warn("LLM call failed \u2014 using non-LLM fallback", {
53045
53097
  label,
53046
53098
  role,
@@ -53054,7 +53106,8 @@ function recordLlmFailure(label, role, model, baseUrl, timeoutMs, elapsedMs, err
53054
53106
  });
53055
53107
  return consecutiveFailures;
53056
53108
  }
53057
- function recordLlmSuccess(label, model) {
53109
+ function recordLlmSuccess(label, model, baseUrl) {
53110
+ recordEndpointOutcome(baseUrl, null);
53058
53111
  const priorFailures = llmFailureStreaks.get(label) ?? 0;
53059
53112
  if (priorFailures > 0) {
53060
53113
  logger.info("LLM call recovered", { label, model, afterFailures: priorFailures });
@@ -53066,6 +53119,9 @@ async function llmComplete(prompt, opts) {
53066
53119
  return { ok: false, error: "llm disabled" };
53067
53120
  }
53068
53121
  const llm = getLlmConfig({ modelRole: opts.modelRole });
53122
+ if (isEndpointCircuitOpen(llm.baseUrl)) {
53123
+ return { ok: false, error: "llm endpoint unreachable (circuit open)" };
53124
+ }
53069
53125
  const role = opts.modelRole ?? "instruct";
53070
53126
  const timeoutMs = opts.timeoutMs ?? llm.timeoutMs;
53071
53127
  const startedAt = Date.now();
@@ -53080,7 +53136,7 @@ async function llmComplete(prompt, opts) {
53080
53136
  });
53081
53137
  const text2 = result.text ?? "";
53082
53138
  if (text2.length > 0) {
53083
- recordLlmSuccess(opts.label, llm.model);
53139
+ recordLlmSuccess(opts.label, llm.model, llm.baseUrl);
53084
53140
  return { ok: true, value: text2 };
53085
53141
  }
53086
53142
  if (llm.disableThink) {
@@ -53089,7 +53145,7 @@ async function llmComplete(prompt, opts) {
53089
53145
  logger.warn("llmComplete: empty content \u2014 recovered from reasoning channel", {
53090
53146
  reasoningLen: reasoning.length
53091
53147
  });
53092
- recordLlmSuccess(opts.label, llm.model);
53148
+ recordLlmSuccess(opts.label, llm.model, llm.baseUrl);
53093
53149
  return { ok: true, value: reasoning };
53094
53150
  }
53095
53151
  logger.warn("llm reasoning-recovery empty", {
@@ -53110,6 +53166,9 @@ async function llmObject(prompt, schema, opts) {
53110
53166
  return { ok: false, error: "llm disabled" };
53111
53167
  }
53112
53168
  const llm = getLlmConfig({ modelRole: opts.modelRole });
53169
+ if (isEndpointCircuitOpen(llm.baseUrl)) {
53170
+ return { ok: false, error: "llm endpoint unreachable (circuit open)" };
53171
+ }
53113
53172
  const role = opts.modelRole ?? "instruct";
53114
53173
  const timeoutMs = opts.timeoutMs ?? llm.timeoutMs;
53115
53174
  const startedAt = Date.now();
@@ -53128,7 +53187,7 @@ async function llmObject(prompt, schema, opts) {
53128
53187
  abortSignal: timeoutSignal(timeoutMs)
53129
53188
  });
53130
53189
  logger.debug("json_schema: constrained decoding used", { label: opts.label, model: llm.model });
53131
- recordLlmSuccess(opts.label, llm.model);
53190
+ recordLlmSuccess(opts.label, llm.model, llm.baseUrl);
53132
53191
  return { ok: true, value: result.object };
53133
53192
  }
53134
53193
  result = await generateObject({
@@ -53143,7 +53202,7 @@ async function llmObject(prompt, schema, opts) {
53143
53202
  const validated = schema.safeParse(result.object);
53144
53203
  if (validated.success) {
53145
53204
  logger.debug("json_schema: fallback to json_object \u2014 validated", { label: opts.label, model: llm.model });
53146
- recordLlmSuccess(opts.label, llm.model);
53205
+ recordLlmSuccess(opts.label, llm.model, llm.baseUrl);
53147
53206
  return { ok: true, value: validated.data };
53148
53207
  }
53149
53208
  if (llm.disableThink) {
@@ -53156,7 +53215,7 @@ async function llmObject(prompt, schema, opts) {
53156
53215
  logger.warn("llmObject: recovered object from reasoning channel (fallback path)", {
53157
53216
  reasoningLen: reasoning.length
53158
53217
  });
53159
- recordLlmSuccess(opts.label, llm.model);
53218
+ recordLlmSuccess(opts.label, llm.model, llm.baseUrl);
53160
53219
  return { ok: true, value: recovered.data };
53161
53220
  }
53162
53221
  }
@@ -53168,7 +53227,7 @@ async function llmObject(prompt, schema, opts) {
53168
53227
  recordLlmFailure(opts.label, role, llm.model, llm.baseUrl, timeoutMs, Date.now() - startedAt, validationErr);
53169
53228
  return { ok: false, error: validationErr.message };
53170
53229
  } catch (e) {
53171
- if (llm.disableThink && !_isAbortOrTimeoutError(e)) {
53230
+ if (llm.disableThink && !_isAbortOrTimeoutError(e) && !_isConnectionError(e)) {
53172
53231
  const reasoning = _reasoningToText(result).length > 0 ? _reasoningToText(result) : _reasoningToText(e);
53173
53232
  if (reasoning.length > 0) {
53174
53233
  const parsed = _extractJsonObject(reasoning);
@@ -53178,7 +53237,7 @@ async function llmObject(prompt, schema, opts) {
53178
53237
  logger.warn("llmObject: recovered object from reasoning channel", {
53179
53238
  reasoningLen: reasoning.length
53180
53239
  });
53181
- recordLlmSuccess(opts.label, llm.model);
53240
+ recordLlmSuccess(opts.label, llm.model, llm.baseUrl);
53182
53241
  return { ok: true, value: validated.data };
53183
53242
  }
53184
53243
  }
@@ -53192,7 +53251,7 @@ async function llmObject(prompt, schema, opts) {
53192
53251
  return { ok: false, error: e.message };
53193
53252
  }
53194
53253
  }
53195
- var _jsonSchemaSupported = null, testEnabledOverride = null, testBaseUrlOverride = null, llmFailureStreaks, llm;
53254
+ var _jsonSchemaSupported = null, testEnabledOverride = null, testBaseUrlOverride = null, llmFailureStreaks, ENDPOINT_FAILURE_THRESHOLD = 3, ENDPOINT_COOLDOWN_MS = 60000, endpointCircuits, llm;
53196
53255
  var init_llm_client = __esm(() => {
53197
53256
  init_dist6();
53198
53257
  init_dist7();
@@ -53200,6 +53259,7 @@ var init_llm_client = __esm(() => {
53200
53259
  init_config();
53201
53260
  init_inference_providers();
53202
53261
  llmFailureStreaks = new Map;
53262
+ endpointCircuits = new Map;
53203
53263
  llm = {
53204
53264
  complete: llmComplete,
53205
53265
  object: llmObject,
@@ -129938,6 +129998,7 @@ var init_auto_improve_job = __esm(() => {
129938
129998
  var exports_observation_consolidation_job = {};
129939
129999
  __export(exports_observation_consolidation_job, {
129940
130000
  observationConsolidationJob: () => observationConsolidationJob,
130001
+ buildObservationPrompt: () => buildObservationPrompt,
129941
130002
  ObservationConsolidationJob: () => ObservationConsolidationJob
129942
130003
  });
129943
130004
  import { randomUUID as randomUUID8 } from "crypto";
@@ -129965,6 +130026,7 @@ class ObservationConsolidationJob {
129965
130026
  maxWindow;
129966
130027
  lastRunAt = 0;
129967
130028
  newSinceRun = 0;
130029
+ running = false;
129968
130030
  runCalls = 0;
129969
130031
  get store() {
129970
130032
  return this.injectedStore ?? getObservationStore();
@@ -130008,6 +130070,18 @@ class ObservationConsolidationJob {
130008
130070
  }
130009
130071
  async runOnce(projectId) {
130010
130072
  this.runCalls++;
130073
+ if (this.running) {
130074
+ logger.debug("observation consolidation: skipped, a run is in flight", { projectId });
130075
+ return { consolidated: false, batchesCreated: 0 };
130076
+ }
130077
+ this.running = true;
130078
+ try {
130079
+ return await this.consolidateWindow(projectId);
130080
+ } finally {
130081
+ this.running = false;
130082
+ }
130083
+ }
130084
+ async consolidateWindow(projectId) {
130011
130085
  const noop2 = {
130012
130086
  consolidated: false,
130013
130087
  batchesCreated: 0
@@ -130097,8 +130171,9 @@ class ObservationConsolidationJob {
130097
130171
  }
130098
130172
  }
130099
130173
  function buildObservationPrompt(window2) {
130174
+ const observationTokens = Math.min(MAX_OBSERVATION_TOKENS, Math.floor(MAX_WINDOW_TOKENS / Math.max(window2.length, 1)));
130100
130175
  const items = window2.map((o, i) => `[${i}] id=${o.id} source=${o.source} importance=${o.importance.toFixed(2)}
130101
- ${o.payloadJson}`).join(`
130176
+ ${digestPayload(o.payloadJson, observationTokens)}`).join(`
130102
130177
  `);
130103
130178
  return [
130104
130179
  "You are consolidating a window of passive lifecycle observations (agent telemetry)",
@@ -130113,7 +130188,20 @@ ${o.payloadJson}`).join(`
130113
130188
  ].join(`
130114
130189
  `);
130115
130190
  }
130116
- var FALLBACK_BRIDGE, observationConsolidationJob;
130191
+ function digestPayload(payloadJson, maxTokens) {
130192
+ let payload;
130193
+ try {
130194
+ payload = JSON.parse(payloadJson);
130195
+ } catch {
130196
+ return truncateToTokenLimit(payloadJson, maxTokens);
130197
+ }
130198
+ if (payload && typeof payload === "object" && !Array.isArray(payload)) {
130199
+ payload = Object.fromEntries(Object.entries(payload).filter(([key]) => !PROMPT_BOOKKEEPING_KEYS.has(key)));
130200
+ }
130201
+ const compact = JSON.stringify(payload, (_key, value) => typeof value === "string" && value.length > MAX_PROMPT_FIELD_CHARS ? `${value.slice(0, MAX_PROMPT_FIELD_CHARS)}\u2026` : value);
130202
+ return truncateToTokenLimit(compact ?? "", maxTokens);
130203
+ }
130204
+ var FALLBACK_BRIDGE, observationConsolidationJob, PROMPT_BOOKKEEPING_KEYS, MAX_PROMPT_FIELD_CHARS = 400, MAX_OBSERVATION_TOKENS = 300, MAX_WINDOW_TOKENS = 2400;
130117
130205
  var init_observation_consolidation_job = __esm(() => {
130118
130206
  init_dist();
130119
130207
  init_dist();
@@ -130129,6 +130217,18 @@ var init_observation_consolidation_job = __esm(() => {
130129
130217
  maxWindow: 8
130130
130218
  };
130131
130219
  observationConsolidationJob = new ObservationConsolidationJob;
130220
+ PROMPT_BOOKKEEPING_KEYS = new Set([
130221
+ "session_id",
130222
+ "transcript_path",
130223
+ "cwd",
130224
+ "prompt_id",
130225
+ "tool_use_id",
130226
+ "agent_id",
130227
+ "hook_event_name",
130228
+ "permission_mode",
130229
+ "effort",
130230
+ "duration_ms"
130231
+ ]);
130132
130232
  });
130133
130233
 
130134
130234
  // ../../packages/core/dist/services/checkpoint/checkpoint-store-pg.js
package/dist/index.js CHANGED
@@ -27179,6 +27179,15 @@ function estimateTokens(text, type = "code") {
27179
27179
  const charsPerToken = type === "code" ? 4 : 5;
27180
27180
  return Math.ceil(text.length / charsPerToken);
27181
27181
  }
27182
+ function truncateToTokenLimit(text, limit, type = "code") {
27183
+ const charsPerToken = type === "code" ? 4 : 5;
27184
+ const maxChars = limit * charsPerToken;
27185
+ if (text.length <= maxChars) {
27186
+ return text;
27187
+ }
27188
+ return text.slice(0, maxChars) + `
27189
+ ... (truncated)`;
27190
+ }
27182
27191
  // ../../packages/shared/dist/utils/metrics.js
27183
27192
  var FALLBACK_PRICING, MetricsCollector;
27184
27193
  var init_metrics = __esm(() => {
@@ -59594,12 +59603,55 @@ function _isAbortOrTimeoutError(err) {
59594
59603
  }
59595
59604
  return false;
59596
59605
  }
59606
+ function _isConnectionError(err) {
59607
+ let cur = err;
59608
+ for (let hops = 0;cur && hops < 5; hops++, cur = cur.lastError ?? cur.cause) {
59609
+ const code = typeof cur.code === "string" ? cur.code : "";
59610
+ if (/^(ECONNREFUSED|ECONNRESET|ENOTFOUND|EHOSTUNREACH|ConnectionRefused|ConnectionClosed|FailedToOpenSocket)$/.test(code)) {
59611
+ return true;
59612
+ }
59613
+ const message = typeof cur.message === "string" ? cur.message : "";
59614
+ if (message.startsWith("Cannot connect to API"))
59615
+ return true;
59616
+ }
59617
+ return false;
59618
+ }
59597
59619
  function summarizeZodIssues(error51, maxIssues = 5) {
59598
59620
  return error51.issues.slice(0, maxIssues).map((issue2) => `${issue2.path.join(".") || "(root)"}: ${issue2.message}`).join("; ");
59599
59621
  }
59622
+ function isEndpointCircuitOpen(baseUrl) {
59623
+ const circuit = endpointCircuits.get(baseUrl);
59624
+ if (!circuit || circuit.failures < ENDPOINT_FAILURE_THRESHOLD)
59625
+ return false;
59626
+ const now2 = Date.now();
59627
+ if (now2 < circuit.openUntil)
59628
+ return true;
59629
+ circuit.openUntil = now2 + ENDPOINT_COOLDOWN_MS;
59630
+ return false;
59631
+ }
59632
+ function recordEndpointOutcome(baseUrl, err) {
59633
+ if (!err || !_isConnectionError(err)) {
59634
+ endpointCircuits.delete(baseUrl);
59635
+ return;
59636
+ }
59637
+ const circuit = endpointCircuits.get(baseUrl) ?? { failures: 0, openUntil: 0 };
59638
+ circuit.failures++;
59639
+ if (circuit.failures >= ENDPOINT_FAILURE_THRESHOLD) {
59640
+ circuit.openUntil = Date.now() + ENDPOINT_COOLDOWN_MS;
59641
+ }
59642
+ if (circuit.failures === ENDPOINT_FAILURE_THRESHOLD) {
59643
+ logger.warn("LLM endpoint unreachable \u2014 pausing LLM calls", {
59644
+ provider: resolveProviderIdForLogging(baseUrl),
59645
+ consecutiveConnectionFailures: circuit.failures,
59646
+ cooldownMs: ENDPOINT_COOLDOWN_MS
59647
+ });
59648
+ }
59649
+ endpointCircuits.set(baseUrl, circuit);
59650
+ }
59600
59651
  function recordLlmFailure(label, role, model, baseUrl, timeoutMs, elapsedMs, err) {
59601
59652
  const consecutiveFailures = (llmFailureStreaks.get(label) ?? 0) + 1;
59602
59653
  llmFailureStreaks.set(label, consecutiveFailures);
59654
+ recordEndpointOutcome(baseUrl, err);
59603
59655
  logger.warn("LLM call failed \u2014 using non-LLM fallback", {
59604
59656
  label,
59605
59657
  role,
@@ -59613,7 +59665,8 @@ function recordLlmFailure(label, role, model, baseUrl, timeoutMs, elapsedMs, err
59613
59665
  });
59614
59666
  return consecutiveFailures;
59615
59667
  }
59616
- function recordLlmSuccess(label, model) {
59668
+ function recordLlmSuccess(label, model, baseUrl) {
59669
+ recordEndpointOutcome(baseUrl, null);
59617
59670
  const priorFailures = llmFailureStreaks.get(label) ?? 0;
59618
59671
  if (priorFailures > 0) {
59619
59672
  logger.info("LLM call recovered", { label, model, afterFailures: priorFailures });
@@ -59625,6 +59678,9 @@ async function llmComplete(prompt, opts) {
59625
59678
  return { ok: false, error: "llm disabled" };
59626
59679
  }
59627
59680
  const llm = getLlmConfig({ modelRole: opts.modelRole });
59681
+ if (isEndpointCircuitOpen(llm.baseUrl)) {
59682
+ return { ok: false, error: "llm endpoint unreachable (circuit open)" };
59683
+ }
59628
59684
  const role = opts.modelRole ?? "instruct";
59629
59685
  const timeoutMs = opts.timeoutMs ?? llm.timeoutMs;
59630
59686
  const startedAt = Date.now();
@@ -59639,7 +59695,7 @@ async function llmComplete(prompt, opts) {
59639
59695
  });
59640
59696
  const text2 = result.text ?? "";
59641
59697
  if (text2.length > 0) {
59642
- recordLlmSuccess(opts.label, llm.model);
59698
+ recordLlmSuccess(opts.label, llm.model, llm.baseUrl);
59643
59699
  return { ok: true, value: text2 };
59644
59700
  }
59645
59701
  if (llm.disableThink) {
@@ -59648,7 +59704,7 @@ async function llmComplete(prompt, opts) {
59648
59704
  logger.warn("llmComplete: empty content \u2014 recovered from reasoning channel", {
59649
59705
  reasoningLen: reasoning.length
59650
59706
  });
59651
- recordLlmSuccess(opts.label, llm.model);
59707
+ recordLlmSuccess(opts.label, llm.model, llm.baseUrl);
59652
59708
  return { ok: true, value: reasoning };
59653
59709
  }
59654
59710
  logger.warn("llm reasoning-recovery empty", {
@@ -59669,6 +59725,9 @@ async function llmObject(prompt, schema, opts) {
59669
59725
  return { ok: false, error: "llm disabled" };
59670
59726
  }
59671
59727
  const llm = getLlmConfig({ modelRole: opts.modelRole });
59728
+ if (isEndpointCircuitOpen(llm.baseUrl)) {
59729
+ return { ok: false, error: "llm endpoint unreachable (circuit open)" };
59730
+ }
59672
59731
  const role = opts.modelRole ?? "instruct";
59673
59732
  const timeoutMs = opts.timeoutMs ?? llm.timeoutMs;
59674
59733
  const startedAt = Date.now();
@@ -59687,7 +59746,7 @@ async function llmObject(prompt, schema, opts) {
59687
59746
  abortSignal: timeoutSignal(timeoutMs)
59688
59747
  });
59689
59748
  logger.debug("json_schema: constrained decoding used", { label: opts.label, model: llm.model });
59690
- recordLlmSuccess(opts.label, llm.model);
59749
+ recordLlmSuccess(opts.label, llm.model, llm.baseUrl);
59691
59750
  return { ok: true, value: result.object };
59692
59751
  }
59693
59752
  result = await generateObject({
@@ -59702,7 +59761,7 @@ async function llmObject(prompt, schema, opts) {
59702
59761
  const validated = schema.safeParse(result.object);
59703
59762
  if (validated.success) {
59704
59763
  logger.debug("json_schema: fallback to json_object \u2014 validated", { label: opts.label, model: llm.model });
59705
- recordLlmSuccess(opts.label, llm.model);
59764
+ recordLlmSuccess(opts.label, llm.model, llm.baseUrl);
59706
59765
  return { ok: true, value: validated.data };
59707
59766
  }
59708
59767
  if (llm.disableThink) {
@@ -59715,7 +59774,7 @@ async function llmObject(prompt, schema, opts) {
59715
59774
  logger.warn("llmObject: recovered object from reasoning channel (fallback path)", {
59716
59775
  reasoningLen: reasoning.length
59717
59776
  });
59718
- recordLlmSuccess(opts.label, llm.model);
59777
+ recordLlmSuccess(opts.label, llm.model, llm.baseUrl);
59719
59778
  return { ok: true, value: recovered.data };
59720
59779
  }
59721
59780
  }
@@ -59727,7 +59786,7 @@ async function llmObject(prompt, schema, opts) {
59727
59786
  recordLlmFailure(opts.label, role, llm.model, llm.baseUrl, timeoutMs, Date.now() - startedAt, validationErr);
59728
59787
  return { ok: false, error: validationErr.message };
59729
59788
  } catch (e) {
59730
- if (llm.disableThink && !_isAbortOrTimeoutError(e)) {
59789
+ if (llm.disableThink && !_isAbortOrTimeoutError(e) && !_isConnectionError(e)) {
59731
59790
  const reasoning = _reasoningToText(result).length > 0 ? _reasoningToText(result) : _reasoningToText(e);
59732
59791
  if (reasoning.length > 0) {
59733
59792
  const parsed = _extractJsonObject(reasoning);
@@ -59737,7 +59796,7 @@ async function llmObject(prompt, schema, opts) {
59737
59796
  logger.warn("llmObject: recovered object from reasoning channel", {
59738
59797
  reasoningLen: reasoning.length
59739
59798
  });
59740
- recordLlmSuccess(opts.label, llm.model);
59799
+ recordLlmSuccess(opts.label, llm.model, llm.baseUrl);
59741
59800
  return { ok: true, value: validated.data };
59742
59801
  }
59743
59802
  }
@@ -59751,7 +59810,7 @@ async function llmObject(prompt, schema, opts) {
59751
59810
  return { ok: false, error: e.message };
59752
59811
  }
59753
59812
  }
59754
- var _jsonSchemaSupported = null, testEnabledOverride = null, testBaseUrlOverride = null, llmFailureStreaks, llm;
59813
+ var _jsonSchemaSupported = null, testEnabledOverride = null, testBaseUrlOverride = null, llmFailureStreaks, ENDPOINT_FAILURE_THRESHOLD = 3, ENDPOINT_COOLDOWN_MS = 60000, endpointCircuits, llm;
59755
59814
  var init_llm_client = __esm(() => {
59756
59815
  init_dist6();
59757
59816
  init_dist7();
@@ -59759,6 +59818,7 @@ var init_llm_client = __esm(() => {
59759
59818
  init_config();
59760
59819
  init_inference_providers();
59761
59820
  llmFailureStreaks = new Map;
59821
+ endpointCircuits = new Map;
59762
59822
  llm = {
59763
59823
  complete: llmComplete,
59764
59824
  object: llmObject,
@@ -146745,6 +146805,7 @@ var init_auto_improve_job = __esm(() => {
146745
146805
  var exports_observation_consolidation_job = {};
146746
146806
  __export(exports_observation_consolidation_job, {
146747
146807
  observationConsolidationJob: () => observationConsolidationJob,
146808
+ buildObservationPrompt: () => buildObservationPrompt,
146748
146809
  ObservationConsolidationJob: () => ObservationConsolidationJob
146749
146810
  });
146750
146811
  import { randomUUID as randomUUID9 } from "crypto";
@@ -146772,6 +146833,7 @@ class ObservationConsolidationJob {
146772
146833
  maxWindow;
146773
146834
  lastRunAt = 0;
146774
146835
  newSinceRun = 0;
146836
+ running = false;
146775
146837
  runCalls = 0;
146776
146838
  get store() {
146777
146839
  return this.injectedStore ?? getObservationStore();
@@ -146815,6 +146877,18 @@ class ObservationConsolidationJob {
146815
146877
  }
146816
146878
  async runOnce(projectId) {
146817
146879
  this.runCalls++;
146880
+ if (this.running) {
146881
+ logger.debug("observation consolidation: skipped, a run is in flight", { projectId });
146882
+ return { consolidated: false, batchesCreated: 0 };
146883
+ }
146884
+ this.running = true;
146885
+ try {
146886
+ return await this.consolidateWindow(projectId);
146887
+ } finally {
146888
+ this.running = false;
146889
+ }
146890
+ }
146891
+ async consolidateWindow(projectId) {
146818
146892
  const noop2 = {
146819
146893
  consolidated: false,
146820
146894
  batchesCreated: 0
@@ -146904,8 +146978,9 @@ class ObservationConsolidationJob {
146904
146978
  }
146905
146979
  }
146906
146980
  function buildObservationPrompt(window2) {
146981
+ const observationTokens = Math.min(MAX_OBSERVATION_TOKENS, Math.floor(MAX_WINDOW_TOKENS / Math.max(window2.length, 1)));
146907
146982
  const items = window2.map((o, i) => `[${i}] id=${o.id} source=${o.source} importance=${o.importance.toFixed(2)}
146908
- ${o.payloadJson}`).join(`
146983
+ ${digestPayload(o.payloadJson, observationTokens)}`).join(`
146909
146984
  `);
146910
146985
  return [
146911
146986
  "You are consolidating a window of passive lifecycle observations (agent telemetry)",
@@ -146920,7 +146995,20 @@ ${o.payloadJson}`).join(`
146920
146995
  ].join(`
146921
146996
  `);
146922
146997
  }
146923
- var FALLBACK_BRIDGE, observationConsolidationJob;
146998
+ function digestPayload(payloadJson, maxTokens) {
146999
+ let payload;
147000
+ try {
147001
+ payload = JSON.parse(payloadJson);
147002
+ } catch {
147003
+ return truncateToTokenLimit(payloadJson, maxTokens);
147004
+ }
147005
+ if (payload && typeof payload === "object" && !Array.isArray(payload)) {
147006
+ payload = Object.fromEntries(Object.entries(payload).filter(([key]) => !PROMPT_BOOKKEEPING_KEYS.has(key)));
147007
+ }
147008
+ const compact = JSON.stringify(payload, (_key, value) => typeof value === "string" && value.length > MAX_PROMPT_FIELD_CHARS ? `${value.slice(0, MAX_PROMPT_FIELD_CHARS)}\u2026` : value);
147009
+ return truncateToTokenLimit(compact ?? "", maxTokens);
147010
+ }
147011
+ var FALLBACK_BRIDGE, observationConsolidationJob, PROMPT_BOOKKEEPING_KEYS, MAX_PROMPT_FIELD_CHARS = 400, MAX_OBSERVATION_TOKENS = 300, MAX_WINDOW_TOKENS = 2400;
146924
147012
  var init_observation_consolidation_job = __esm(() => {
146925
147013
  init_dist();
146926
147014
  init_dist();
@@ -146936,6 +147024,18 @@ var init_observation_consolidation_job = __esm(() => {
146936
147024
  maxWindow: 8
146937
147025
  };
146938
147026
  observationConsolidationJob = new ObservationConsolidationJob;
147027
+ PROMPT_BOOKKEEPING_KEYS = new Set([
147028
+ "session_id",
147029
+ "transcript_path",
147030
+ "cwd",
147031
+ "prompt_id",
147032
+ "tool_use_id",
147033
+ "agent_id",
147034
+ "hook_event_name",
147035
+ "permission_mode",
147036
+ "effort",
147037
+ "duration_ms"
147038
+ ]);
146939
147039
  });
146940
147040
 
146941
147041
  // ../../packages/core/dist/services/scheduler/scheduler-defaults.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massa-ai/mcp-client",
3
- "version": "1.66.1",
3
+ "version": "1.67.0",
4
4
  "description": "massa-ai MCP server - Semantic code search, memory, and context compression via Model Context Protocol",
5
5
  "author": "luizgmassa",
6
6
  "type": "module",
@@ -20,8 +20,8 @@
20
20
  "type-check": "tsc --noEmit"
21
21
  },
22
22
  "dependencies": {
23
- "@massa-ai/core": "^1.66.1",
24
- "@massa-ai/shared": "^1.66.1",
23
+ "@massa-ai/core": "^1.67.0",
24
+ "@massa-ai/shared": "^1.67.0",
25
25
  "@modelcontextprotocol/sdk": "^1.0.0"
26
26
  },
27
27
  "devDependencies": {