orquesta-cli 0.2.88 → 0.2.89

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.
@@ -96,7 +96,9 @@ export declare class LLMClient {
96
96
  healthy: boolean;
97
97
  latency?: number;
98
98
  error?: string;
99
+ switchedToBatuta?: boolean;
99
100
  }>;
101
+ private static probeEndpoint;
100
102
  static testConnection(baseUrl: string, apiKey: string, model: string): Promise<{
101
103
  success: boolean;
102
104
  latency?: number;
@@ -6,6 +6,22 @@ import { LLMError, TokenLimitError, RateLimitError, ContextLengthError, } from '
6
6
  import { logger, isLLMLogEnabled } from '../../utils/logger.js';
7
7
  import { usageTracker } from '../usage-tracker.js';
8
8
  import { getForcedTier, getBatutaSessionId, setLastBatutaRoute } from '../routing-state.js';
9
+ function safeStringify(value, space) {
10
+ const seen = new WeakSet();
11
+ try {
12
+ return JSON.stringify(value, (_key, val) => {
13
+ if (typeof val === 'object' && val !== null) {
14
+ if (seen.has(val))
15
+ return '[Circular]';
16
+ seen.add(val);
17
+ }
18
+ return val;
19
+ }, space);
20
+ }
21
+ catch {
22
+ return String(value);
23
+ }
24
+ }
9
25
  function extractTopLevelJsonObjects(s) {
10
26
  const objects = [];
11
27
  let depth = 0;
@@ -972,11 +988,11 @@ export class LLMClient {
972
988
  errorMessage,
973
989
  errorType,
974
990
  errorCode,
975
- responseBody: JSON.stringify(data, null, 2),
991
+ responseBody: safeStringify(data, 2),
976
992
  requestMethod: requestContext?.method,
977
993
  requestUrl: requestContext?.url,
978
994
  requestBody: requestContext?.body
979
- ? JSON.stringify(requestContext.body, null, 2).substring(0, 5000)
995
+ ? safeStringify(requestContext.body, 2).substring(0, 5000)
980
996
  : undefined,
981
997
  responseHeaders: axiosError.response.headers,
982
998
  });
@@ -1033,6 +1049,16 @@ export class LLMClient {
1033
1049
  },
1034
1050
  });
1035
1051
  }
1052
+ if (status === 402) {
1053
+ logger.error('Batuta not available (402)', { errorMessage });
1054
+ return new APIError(errorMessage || 'Payment required', 402, this.baseUrl, {
1055
+ isRecoverable: false,
1056
+ cause: axiosError,
1057
+ userMessage: `Batuta isn't available for this account (402): ${errorMessage || 'add-on required'}.\n` +
1058
+ `Enable the Batuta add-on for your organization in the Orquesta dashboard, or point the CLI at a local LLM provider.`,
1059
+ details: { endpoint: this.baseUrl, fullError: data },
1060
+ });
1061
+ }
1036
1062
  if (status === 401) {
1037
1063
  logger.error('Authentication Failed', {
1038
1064
  endpoint: this.baseUrl,
@@ -1276,6 +1302,22 @@ export class LLMClient {
1276
1302
  if (!endpoint || !model) {
1277
1303
  return { healthy: false, error: 'No endpoint/model configured' };
1278
1304
  }
1305
+ const first = await LLMClient.probeEndpoint(endpoint, model.id);
1306
+ if (first.healthy)
1307
+ return first;
1308
+ const batuta = configManager.getAllEndpoints().find((e) => e.id === 'batuta-proxy' || e.provider === 'batuta');
1309
+ if (batuta && batuta.apiKey && batuta.id !== endpoint.id) {
1310
+ const m = batuta.models.find((x) => x.enabled) || batuta.models[0];
1311
+ if (m) {
1312
+ await configManager.setCurrentEndpoint(batuta.id);
1313
+ await configManager.setCurrentModel(m.id);
1314
+ const second = await LLMClient.probeEndpoint(batuta, m.id);
1315
+ return { ...second, switchedToBatuta: true };
1316
+ }
1317
+ }
1318
+ return first;
1319
+ }
1320
+ static async probeEndpoint(endpoint, modelId) {
1279
1321
  const startTime = Date.now();
1280
1322
  try {
1281
1323
  const axiosInstance = axios.create({
@@ -1287,7 +1329,7 @@ export class LLMClient {
1287
1329
  timeout: 10000,
1288
1330
  });
1289
1331
  const response = await axiosInstance.post('/chat/completions', {
1290
- model: model.id,
1332
+ model: modelId,
1291
1333
  messages: [{ role: 'user', content: 'ping' }],
1292
1334
  max_tokens: 1,
1293
1335
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orquesta-cli",
3
- "version": "0.2.88",
3
+ "version": "0.2.89",
4
4
  "description": "Orquesta CLI - AI-powered coding assistant with team collaboration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",