orchestrator-client 5.7.2 → 5.7.4

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
@@ -15,8 +15,8 @@ var OrchestratorConnectionError = class extends OrchestratorError {
15
15
  }
16
16
  };
17
17
  var OrchestratorAuthError = class extends OrchestratorError {
18
- constructor(message, statusCode = 401) {
19
- super(message, { statusCode });
18
+ constructor(message, statusCode = 401, errorCode) {
19
+ super(message, { statusCode, errorCode });
20
20
  this.name = "OrchestratorAuthError";
21
21
  }
22
22
  };
@@ -43,6 +43,28 @@ var OrchestratorConfigError = class extends OrchestratorError {
43
43
  }
44
44
  };
45
45
 
46
+ // src/utils.ts
47
+ function snakeToCamel(str) {
48
+ return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
49
+ }
50
+ function camelToSnake(str) {
51
+ return str.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
52
+ }
53
+ function deepCamelCase(obj) {
54
+ if (Array.isArray(obj)) {
55
+ return obj.map(deepCamelCase);
56
+ }
57
+ if (typeof obj === "object" && obj !== null) {
58
+ return Object.fromEntries(
59
+ Object.entries(obj).map(([key, value]) => [
60
+ snakeToCamel(key),
61
+ deepCamelCase(value)
62
+ ])
63
+ );
64
+ }
65
+ return obj;
66
+ }
67
+
46
68
  // src/client.ts
47
69
  var RETRY_BACKOFF_BASE = 500;
48
70
  var DEFAULT_TIMEOUT_MS = 3e4;
@@ -62,22 +84,66 @@ function buildTaskSummary(t) {
62
84
  return {
63
85
  id: t.id ?? "",
64
86
  status: t.status ?? "",
65
- workflowId: t.workflowId ?? t.workflow_id ?? "",
87
+ workflowId: t.workflowId ?? "",
66
88
  iteration: t.iteration ?? 0,
67
- maxIterations: t.maxIterations ?? t.max_iterations ?? 0,
68
- goalPrompt: t.goalPrompt ?? t.goal_prompt ?? "",
89
+ maxIterations: t.maxIterations ?? 0,
90
+ goalPrompt: t.goalPrompt ?? "",
69
91
  result: t.result ?? "",
70
- resultLocalized: t.resultLocalized ?? t.result_localized ?? null,
71
- approvalReason: t.approvalReason ?? t.approval_reason ?? "",
72
- ticketId: t.ticketId ?? t.ticket_id ?? null,
73
- availableTools: t.availableTools ?? t.available_tools ?? null,
92
+ resultLocalized: t.resultLocalized ?? null,
93
+ approvalReason: t.approvalReason ?? "",
94
+ ticketId: t.ticketId ?? null,
95
+ availableTools: t.availableTools ?? null,
74
96
  insight: t.insight ?? null,
75
- insightLocalized: t.insightLocalized ?? t.insight_localized ?? null,
76
- createdAt: t.createdAt ?? t.created_at ?? "",
77
- updatedAt: t.updatedAt ?? t.updated_at ?? "",
78
- pendingTranslationsForLocales: t.pendingTranslationsForLocales ?? t.pending_translations_for_locales ?? null
97
+ insightLocalized: t.insightLocalized ?? null,
98
+ createdAt: t.createdAt ?? "",
99
+ updatedAt: t.updatedAt ?? "",
100
+ pendingTranslationsForLocales: t.pendingTranslationsForLocales ?? null
79
101
  };
80
102
  }
103
+ function parseApiErrorBody(body, fallbackMessage) {
104
+ let errorCode = body.error_code ?? null;
105
+ if (!errorCode && body.error && typeof body.error === "object") {
106
+ const nested = body.error;
107
+ errorCode = nested.code ?? null;
108
+ }
109
+ let message = null;
110
+ if (typeof body.error === "string") {
111
+ message = body.error;
112
+ } else if (typeof body.message === "string") {
113
+ message = body.message;
114
+ }
115
+ let details = body.details ?? null;
116
+ const detail = body.detail;
117
+ if (typeof detail === "string") {
118
+ message = detail;
119
+ } else if (detail && typeof detail === "object" && !Array.isArray(detail)) {
120
+ const detailObj = detail;
121
+ if (!errorCode) {
122
+ errorCode = detailObj.error_code ?? null;
123
+ }
124
+ if (typeof detailObj.error === "string") {
125
+ message = detailObj.error;
126
+ } else if (typeof detailObj.message === "string") {
127
+ message = detailObj.message;
128
+ }
129
+ if (!details) {
130
+ details = detailObj;
131
+ }
132
+ }
133
+ if (!message) {
134
+ message = fallbackMessage;
135
+ }
136
+ const missingFields = body.missing_fields;
137
+ if (Array.isArray(missingFields) && missingFields.length > 0) {
138
+ const fields = missingFields.filter(
139
+ (f) => typeof f === "string"
140
+ );
141
+ if (fields.length > 0) {
142
+ message = `${message} (missing: ${fields.join(", ")})`;
143
+ }
144
+ }
145
+ return { message, errorCode, details };
146
+ }
81
147
  var OrchestratorAsync = class {
82
148
  constructor(opts = {}) {
83
149
  this._abortController = null;
@@ -91,7 +157,7 @@ var OrchestratorAsync = class {
91
157
  this._timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
92
158
  this._maxRetries = opts.maxRetries ?? DEFAULT_MAX_RETRIES;
93
159
  this._locale = opts.locale;
94
- this._fetch = opts.fetch ?? globalThis.fetch;
160
+ this._fetch = opts.fetch ?? globalThis.fetch.bind(globalThis);
95
161
  if (opts.insecure && !opts.fetch && typeof process !== "undefined" && process.versions?.node) {
96
162
  this._insecure = true;
97
163
  }
@@ -149,16 +215,21 @@ var OrchestratorAsync = class {
149
215
  signal
150
216
  });
151
217
  clearTimeout(timeoutId);
152
- if (response.status === 401) {
153
- throw new OrchestratorAuthError(
154
- `Authentication failed for ${method} ${path}`,
155
- 401
156
- );
157
- }
158
- if (response.status === 403) {
218
+ if (response.status === 401 || response.status === 403) {
219
+ const defaultAuthMsg = response.status === 401 ? `Authentication failed for ${method} ${path}` : `Access denied for ${method} ${path}`;
220
+ let authErrorCode = null;
221
+ let authErrorMsg = defaultAuthMsg;
222
+ try {
223
+ const body = await response.clone().json();
224
+ const parsed = parseApiErrorBody(body, defaultAuthMsg);
225
+ authErrorMsg = parsed.message;
226
+ authErrorCode = parsed.errorCode;
227
+ } catch {
228
+ }
159
229
  throw new OrchestratorAuthError(
160
- `Access denied for ${method} ${path}`,
161
- 403
230
+ authErrorMsg,
231
+ response.status,
232
+ authErrorCode
162
233
  );
163
234
  }
164
235
  if (response.status === 404) {
@@ -185,21 +256,27 @@ var OrchestratorAsync = class {
185
256
  if (response.ok) {
186
257
  const contentType = response.headers.get("content-type") ?? "";
187
258
  if (contentType.includes("application/json")) {
188
- return response.json();
259
+ return deepCamelCase(await response.json());
189
260
  }
190
261
  return { _text: await response.text() };
191
262
  }
192
- let errorMessage;
263
+ const defaultMessage = `API Error with status ${response.status}`;
264
+ let errorMessage = defaultMessage;
193
265
  let errorCode = null;
194
266
  let errorDetails = null;
195
267
  try {
196
- const body = await response.json();
197
- const error = body.error ?? body;
198
- errorCode = error.code ?? null;
199
- errorMessage = error.message ?? await response.text();
200
- errorDetails = error.details ?? null;
268
+ const clonedResponse = response.clone();
269
+ const body = await clonedResponse.json();
270
+ const parsed = parseApiErrorBody(body, JSON.stringify(body));
271
+ errorMessage = parsed.message;
272
+ errorCode = parsed.errorCode;
273
+ errorDetails = parsed.details;
201
274
  } catch {
202
- errorMessage = await response.text();
275
+ try {
276
+ errorMessage = await response.text();
277
+ } catch {
278
+ errorMessage = defaultMessage;
279
+ }
203
280
  }
204
281
  throw new OrchestratorAPIError(
205
282
  errorMessage,
@@ -269,7 +346,7 @@ var OrchestratorAsync = class {
269
346
  params: {
270
347
  page: params?.page,
271
348
  limit: params?.limit,
272
- order_by: params?.orderBy,
349
+ order_by: params?.orderBy ? camelToSnake(params.orderBy) : void 0,
273
350
  order_direction: params?.orderDirection,
274
351
  workflow_id: params?.workflowId
275
352
  },
@@ -342,10 +419,10 @@ var OrchestratorAsync = class {
342
419
  };
343
420
  }
344
421
  async getArchivedMessageContent(taskId, messageId) {
345
- return this._get(
346
- "/task/message/archived-content",
347
- { task_id: taskId, message_id: messageId }
348
- );
422
+ return this._get("/task/message/archived-content", {
423
+ task_id: taskId,
424
+ message_id: messageId
425
+ });
349
426
  }
350
427
  async getTaskCompactions(taskId) {
351
428
  return this._get("/task/compactions", {
@@ -404,19 +481,39 @@ var OrchestratorAsync = class {
404
481
  // ------------------------------------------------------------------
405
482
  // Attachments
406
483
  // ------------------------------------------------------------------
407
- async uploadAttachment(file, filename) {
484
+ async uploadAttachment(file, filename, options) {
408
485
  const formData = new FormData();
409
486
  formData.append("file", file, filename);
410
487
  const headers = await this._resolveHeaders();
411
488
  const response = await this._fetch(this._makeUrl("/attachment"), {
412
489
  method: "POST",
413
490
  headers: { ...headers },
414
- body: formData
491
+ body: formData,
492
+ signal: options?.signal
415
493
  });
416
494
  if (!response.ok) {
495
+ const defaultMessage = `Attachment upload failed: ${response.statusText}`;
496
+ let errorMessage = defaultMessage;
497
+ let errorCode = null;
498
+ let errorDetails = null;
499
+ try {
500
+ const body = await response.clone().json();
501
+ const parsed = parseApiErrorBody(body, defaultMessage);
502
+ errorMessage = parsed.message;
503
+ errorCode = parsed.errorCode;
504
+ errorDetails = parsed.details;
505
+ } catch {
506
+ try {
507
+ errorMessage = await response.text() || defaultMessage;
508
+ } catch {
509
+ errorMessage = defaultMessage;
510
+ }
511
+ }
417
512
  throw new OrchestratorAPIError(
418
- `Attachment upload failed: ${response.statusText}`,
419
- response.status
513
+ errorMessage,
514
+ response.status,
515
+ errorCode,
516
+ errorDetails ?? void 0
420
517
  );
421
518
  }
422
519
  const data = await response.json();
@@ -934,10 +1031,24 @@ var OrchestratorAsync = class {
934
1031
  if (since) params.since = since;
935
1032
  return this._get("/errors/stats", params);
936
1033
  }
937
- async countErrors(since) {
938
- const params = {};
939
- if (since) params.since = since;
940
- return this._get("/errors/count", params);
1034
+ async countErrors(since, severity) {
1035
+ const authHeaders = await this._resolveHeaders();
1036
+ const url = new URL(this._makeUrl("/errors/count"));
1037
+ if (since) url.searchParams.set("since", since);
1038
+ for (const s of severity ?? []) {
1039
+ url.searchParams.append("severity", s);
1040
+ }
1041
+ const response = await this._fetch(url.toString(), {
1042
+ method: "GET",
1043
+ headers: { ...authHeaders }
1044
+ });
1045
+ if (!response.ok) {
1046
+ throw new OrchestratorAPIError(
1047
+ `countErrors failed: ${response.statusText}`,
1048
+ response.status
1049
+ );
1050
+ }
1051
+ return deepCamelCase(await response.json());
941
1052
  }
942
1053
  async purgeErrors() {
943
1054
  return this._delete("/errors");
@@ -969,7 +1080,35 @@ var OrchestratorAsync = class {
969
1080
  return this._get("/configuration/system/status");
970
1081
  }
971
1082
  async updateSettings(settings) {
972
- return this._post("/configuration/system/settings", settings);
1083
+ const body = {};
1084
+ if (settings.agentModelId !== void 0) {
1085
+ body.agent_model_id = settings.agentModelId;
1086
+ }
1087
+ if (settings.orchestratorModelId !== void 0) {
1088
+ body.orchestrator_model_id = settings.orchestratorModelId;
1089
+ }
1090
+ if (settings.compactorModelId !== void 0) {
1091
+ body.compactor_model_id = settings.compactorModelId;
1092
+ }
1093
+ if (settings.journalModelId !== void 0) {
1094
+ body.journal_model_id = settings.journalModelId;
1095
+ }
1096
+ if (settings.summaryModelId !== void 0) {
1097
+ body.summary_model_id = settings.summaryModelId;
1098
+ }
1099
+ if (settings.translateModelId !== void 0) {
1100
+ body.translate_model_id = settings.translateModelId;
1101
+ }
1102
+ if (settings.maxConcurrentTasksPerReplica !== void 0) {
1103
+ body.max_concurrent_tasks_per_replica = settings.maxConcurrentTasksPerReplica;
1104
+ }
1105
+ if (settings.subagentsEnabled !== void 0) {
1106
+ body.subagents_enabled = settings.subagentsEnabled;
1107
+ }
1108
+ if (settings.localizationTargets !== void 0) {
1109
+ body.localization_targets = settings.localizationTargets;
1110
+ }
1111
+ return this._post("/configuration/system/settings", body);
973
1112
  }
974
1113
  async getConfigurationStatus() {
975
1114
  return this._get("/configuration/status");
@@ -989,9 +1128,7 @@ var OrchestratorAsync = class {
989
1128
  return { message: data.message ?? "" };
990
1129
  }
991
1130
  async getLLMBackendStatus() {
992
- return this._get(
993
- "/configuration/llmbackend/status"
994
- );
1131
+ return this._get("/configuration/llmbackend/status");
995
1132
  }
996
1133
  async addLLMBackend(host, apiKey) {
997
1134
  const data = await this._post(
@@ -1008,9 +1145,7 @@ var OrchestratorAsync = class {
1008
1145
  return { message: data.message ?? "" };
1009
1146
  }
1010
1147
  async getMCPServerStatus() {
1011
- return this._get(
1012
- "/configuration/mcpserver/status"
1013
- );
1148
+ return this._get("/configuration/mcpserver/status");
1014
1149
  }
1015
1150
  async addMCPServer(host, apiKey) {
1016
1151
  const data = await this._post(
@@ -1199,8 +1334,8 @@ var Orchestrator = class {
1199
1334
  // ------------------------------------------------------------------
1200
1335
  // Attachments
1201
1336
  // ------------------------------------------------------------------
1202
- uploadAttachment(file, filename) {
1203
- return runSync(this._async.uploadAttachment(file, filename));
1337
+ uploadAttachment(file, filename, options) {
1338
+ return runSync(this._async.uploadAttachment(file, filename, options));
1204
1339
  }
1205
1340
  downloadAttachment(attachmentId) {
1206
1341
  return runSync(this._async.downloadAttachment(attachmentId));
@@ -1401,8 +1536,8 @@ var Orchestrator = class {
1401
1536
  getErrorStats(since) {
1402
1537
  return runSync(this._async.getErrorStats(since));
1403
1538
  }
1404
- countErrors(since) {
1405
- return runSync(this._async.countErrors(since));
1539
+ countErrors(since, severity) {
1540
+ return runSync(this._async.countErrors(since, severity));
1406
1541
  }
1407
1542
  purgeErrors() {
1408
1543
  return runSync(this._async.purgeErrors());
@@ -1705,12 +1840,18 @@ var RealtimeClient = class {
1705
1840
  /**
1706
1841
  * Dispatch a message envelope to registered handlers and subscribers.
1707
1842
  * The server sends: socket.emit("message", {type: "message", event: {..., event_type: "...", ...}})
1843
+ *
1844
+ * All event payloads are deep-converted from snake_case to camelCase so
1845
+ * consumers receive consistent camelCase objects (same convention as the
1846
+ * REST responses from _request). The raw event_type string is extracted
1847
+ * before conversion so the handler-map lookup still works.
1708
1848
  */
1709
1849
  _dispatch(payload) {
1710
1850
  const envelope = payload;
1711
- const event = envelope.event ?? envelope;
1712
- const eventType = event.event_type;
1851
+ const rawEvent = envelope.event ?? envelope;
1852
+ const eventType = rawEvent.event_type;
1713
1853
  if (!eventType) return;
1854
+ const event = deepCamelCase(rawEvent);
1714
1855
  const handlers = this._handlers.get(eventType);
1715
1856
  if (handlers) {
1716
1857
  for (const h of handlers) {
@@ -1943,7 +2084,10 @@ export {
1943
2084
  OrchestratorNotFoundError,
1944
2085
  RealtimeClient,
1945
2086
  VERSION,
2087
+ camelToSnake,
1946
2088
  createInsecureFetch,
1947
- loadConfig
2089
+ deepCamelCase,
2090
+ loadConfig,
2091
+ snakeToCamel
1948
2092
  };
1949
2093
  //# sourceMappingURL=index.js.map