@mitralab.io/functions-sdk 0.1.0 → 0.2.0-beta.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
@@ -1,8 +1,15 @@
1
1
  // src/client.ts
2
2
  import {
3
+ createAgentTaskSessionManager,
3
4
  createSdkCore,
4
- encodePathSegment,
5
- expectObject
5
+ encodePathSegment as encodePathSegment2,
6
+ expectObject,
7
+ withAgentTaskSessions
8
+ } from "@mitralab.io/sdk-core";
9
+
10
+ // src/agent-task-sse.ts
11
+ import {
12
+ encodePathSegment
6
13
  } from "@mitralab.io/sdk-core";
7
14
 
8
15
  // src/errors.ts
@@ -29,69 +36,11 @@ var MitraApiError = class extends Error {
29
36
  }
30
37
  };
31
38
 
32
- // src/config.ts
33
- var DEFAULT_TIMEOUT_MS = 1e4;
34
- function readDefaultEnvironment() {
35
- return typeof process === "undefined" ? {} : process.env;
36
- }
37
- function requiredValue(value, name) {
38
- if (!value?.trim()) {
39
- throw new MitraConfigurationError(`${name} is required`);
40
- }
41
- return value.trim();
42
- }
43
- function normalizeApiUrl(value) {
44
- let parsed;
45
- try {
46
- parsed = new URL(value);
47
- } catch {
48
- throw new MitraConfigurationError("apiUrl must be a valid HTTP or HTTPS URL");
49
- }
50
- if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
51
- throw new MitraConfigurationError("apiUrl must be a valid HTTP or HTTPS URL");
52
- }
53
- if (parsed.username || parsed.password || parsed.search || parsed.hash || value.includes("?") || value.includes("#")) {
54
- throw new MitraConfigurationError(
55
- "apiUrl must not include credentials, query parameters, or a fragment"
56
- );
57
- }
58
- return parsed.toString().replace(/\/+$/, "");
59
- }
60
- function resolveConfig(config = {}, environment = readDefaultEnvironment()) {
61
- const apiUrl = normalizeApiUrl(
62
- requiredValue(config.apiUrl ?? environment.MITRA_API_URL, "apiUrl")
63
- );
64
- const accessToken = requiredValue(
65
- config.accessToken ?? environment.MITRA_PLATFORM_ACCESS_TOKEN,
66
- "accessToken"
67
- );
68
- const appId = requiredValue(config.appId ?? environment.MITRA_APP_ID, "appId");
69
- const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
70
- const fetchImplementation = config.fetch ?? globalThis.fetch;
71
- if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
72
- throw new MitraConfigurationError("timeoutMs must be a positive number");
73
- }
74
- if (typeof fetchImplementation !== "function") {
75
- throw new MitraConfigurationError("A fetch implementation is required");
76
- }
77
- const dataSourceId = config.dataSourceId ?? environment.MITRA_DATA_SOURCE_ID;
78
- if (dataSourceId !== void 0 && !dataSourceId.trim()) {
79
- throw new MitraConfigurationError("dataSourceId must not be empty when provided");
80
- }
81
- return {
82
- apiUrl,
83
- accessToken,
84
- appId,
85
- ...dataSourceId === void 0 ? {} : { dataSourceId: dataSourceId.trim() },
86
- timeoutMs,
87
- fetch: fetchImplementation
88
- };
89
- }
90
-
91
39
  // src/http-client.ts
92
40
  var bearerCredentialPattern = /(\bBearer\s+)\S+/gi;
93
41
  function redactText(value, accessToken) {
94
- return value.replace(bearerCredentialPattern, "$1[REDACTED]").split(accessToken).join("[REDACTED]");
42
+ const bearerRedacted = value.replace(bearerCredentialPattern, "$1[REDACTED]");
43
+ return accessToken ? bearerRedacted.split(accessToken).join("[REDACTED]") : bearerRedacted;
95
44
  }
96
45
  function redactDetails(value, accessToken) {
97
46
  if (typeof value === "string") return redactText(value, accessToken);
@@ -112,7 +61,67 @@ function redactDetails(value, accessToken) {
112
61
  function optionalString(value) {
113
62
  return typeof value === "string" ? value : void 0;
114
63
  }
64
+ function appendQueryParameters(url, params) {
65
+ for (const [key, value] of Object.entries(params)) {
66
+ if (value === void 0) continue;
67
+ const values = Array.isArray(value) ? value : [value];
68
+ for (const item of values) {
69
+ url.searchParams.append(key, typeof item === "string" ? item : item.toString());
70
+ }
71
+ }
72
+ }
73
+ function createRequestHeaders(hasBody, customHeaders, authentication) {
74
+ const safeCustomHeaders = Object.fromEntries(
75
+ Object.entries(customHeaders ?? {}).filter(
76
+ ([name]) => !["authorization", "x-app-id"].includes(name.toLowerCase())
77
+ )
78
+ );
79
+ return {
80
+ Accept: "application/json",
81
+ ...hasBody ? { "Content-Type": "application/json" } : {},
82
+ ...safeCustomHeaders,
83
+ ...authentication.type === "bearer" ? {
84
+ Authorization: `Bearer ${authentication.accessToken}`,
85
+ "X-App-Id": authentication.appId
86
+ } : {}
87
+ };
88
+ }
89
+ async function parsePayload(response) {
90
+ const text = await response.text();
91
+ if (response.ok && !text.trim()) return void 0;
92
+ try {
93
+ return JSON.parse(text);
94
+ } catch {
95
+ if (response.ok) {
96
+ throw new MitraApiError("The Mitra API returned invalid JSON", response.status, {
97
+ code: "INVALID_RESPONSE",
98
+ retryable: false
99
+ });
100
+ }
101
+ return {};
102
+ }
103
+ }
104
+ function createApiError(response, payload, accessToken) {
105
+ const errorPayload = payload && typeof payload === "object" ? payload : {};
106
+ const rawMessage = optionalString(errorPayload.message);
107
+ const message = redactText(
108
+ rawMessage ?? `Request failed with status ${response.status}`,
109
+ accessToken
110
+ );
111
+ const rawRequestId = optionalString(errorPayload.request_id) ?? optionalString(errorPayload.requestId) ?? response.headers.get("X-Request-Id") ?? void 0;
112
+ const rawCode = optionalString(errorPayload.error_code) ?? optionalString(errorPayload.code);
113
+ const requestId = rawRequestId === void 0 ? void 0 : redactText(rawRequestId, accessToken);
114
+ const code = rawCode === void 0 ? void 0 : redactText(rawCode, accessToken);
115
+ const retryable = typeof errorPayload.retryable === "boolean" ? errorPayload.retryable : response.status >= 500;
116
+ return new MitraApiError(message, response.status, {
117
+ ...code === void 0 ? {} : { code },
118
+ ...errorPayload.details === void 0 ? {} : { details: redactDetails(errorPayload.details, accessToken) },
119
+ ...requestId === void 0 ? {} : { requestId },
120
+ ...retryable === void 0 ? {} : { retryable }
121
+ });
122
+ }
115
123
  var HttpClient = class {
124
+ #authentication;
116
125
  #accessToken;
117
126
  baseUrl;
118
127
  appId;
@@ -120,70 +129,38 @@ var HttpClient = class {
120
129
  fetchImplementation;
121
130
  constructor(config) {
122
131
  this.baseUrl = config.baseUrl;
123
- this.#accessToken = config.accessToken;
124
- this.appId = config.appId;
132
+ this.#authentication = config.authentication;
133
+ this.#accessToken = config.authentication === "bearer" ? config.accessToken : void 0;
134
+ this.appId = config.authentication === "bearer" ? config.appId : void 0;
125
135
  this.timeoutMs = config.timeoutMs;
126
136
  this.fetchImplementation = config.fetch;
127
137
  }
128
138
  async request(path, options = {}) {
129
139
  const url = new URL(`${this.baseUrl}${path}`);
130
- for (const [key, value] of Object.entries(options.params ?? {})) {
131
- if (value !== void 0) url.searchParams.append(key, String(value));
132
- }
133
- const controller = new AbortController();
134
- const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
140
+ appendQueryParameters(url, options.params ?? {});
141
+ const controller = this.timeoutMs === void 0 ? void 0 : new AbortController();
142
+ const timeout = controller === void 0 ? void 0 : setTimeout(() => controller.abort(), this.timeoutMs);
135
143
  const hasBody = options.body !== void 0;
144
+ const authentication = this.#authentication === "bearer" ? {
145
+ type: "bearer",
146
+ accessToken: this.#accessToken,
147
+ appId: this.appId
148
+ } : { type: "anonymous" };
136
149
  try {
137
150
  const response = await this.fetchImplementation(url, {
138
151
  method: options.method ?? "GET",
139
- headers: {
140
- Accept: "application/json",
141
- ...hasBody ? { "Content-Type": "application/json" } : {},
142
- Authorization: `Bearer ${this.#accessToken}`,
143
- "X-App-Id": this.appId,
144
- ...options.headers
145
- },
152
+ headers: createRequestHeaders(hasBody, options.headers, authentication),
146
153
  ...hasBody ? { body: JSON.stringify(options.body) } : {},
147
154
  redirect: "manual",
148
- signal: controller.signal
155
+ ...controller === void 0 ? {} : { signal: controller.signal }
149
156
  });
150
157
  if (response.status === 204) return void 0;
151
- const text = await response.text();
152
- let payload;
153
- try {
154
- payload = JSON.parse(text);
155
- } catch {
156
- if (response.ok) {
157
- throw new MitraApiError("The Mitra API returned invalid JSON", response.status, {
158
- code: "INVALID_RESPONSE",
159
- retryable: false
160
- });
161
- }
162
- payload = {};
163
- }
164
- if (!response.ok) {
165
- const errorPayload = payload && typeof payload === "object" ? payload : {};
166
- const rawMessage = optionalString(errorPayload.message);
167
- const message = redactText(
168
- rawMessage ?? `Request failed with status ${response.status}`,
169
- this.#accessToken
170
- );
171
- const rawRequestId = optionalString(errorPayload.request_id) ?? optionalString(errorPayload.requestId) ?? response.headers.get("X-Request-Id") ?? void 0;
172
- const rawCode = optionalString(errorPayload.error_code) ?? optionalString(errorPayload.code);
173
- const requestId = rawRequestId === void 0 ? void 0 : redactText(rawRequestId, this.#accessToken);
174
- const code = rawCode === void 0 ? void 0 : redactText(rawCode, this.#accessToken);
175
- const retryable = typeof errorPayload.retryable === "boolean" ? errorPayload.retryable : response.status >= 500;
176
- throw new MitraApiError(message, response.status, {
177
- ...code === void 0 ? {} : { code },
178
- ...errorPayload.details === void 0 ? {} : { details: redactDetails(errorPayload.details, this.#accessToken) },
179
- ...requestId === void 0 ? {} : { requestId },
180
- ...retryable === void 0 ? {} : { retryable }
181
- });
182
- }
158
+ const payload = await parsePayload(response);
159
+ if (!response.ok) throw createApiError(response, payload, this.#accessToken);
183
160
  return payload;
184
161
  } catch (error) {
185
162
  if (error instanceof MitraApiError) throw error;
186
- if (controller.signal.aborted) {
163
+ if (controller?.signal.aborted) {
187
164
  throw new MitraApiError("Mitra request timed out", 0, {
188
165
  code: "REQUEST_TIMEOUT",
189
166
  retryable: true
@@ -194,7 +171,7 @@ var HttpClient = class {
194
171
  retryable: true
195
172
  });
196
173
  } finally {
197
- clearTimeout(timeout);
174
+ if (timeout !== void 0) clearTimeout(timeout);
198
175
  }
199
176
  }
200
177
  get(path, params) {
@@ -218,17 +195,385 @@ var HttpClient = class {
218
195
  }
219
196
  };
220
197
 
198
+ // src/agent-task-sse.ts
199
+ function invalidResponse(message) {
200
+ return new MitraApiError(message, 200, {
201
+ code: "INVALID_RESPONSE",
202
+ retryable: false
203
+ });
204
+ }
205
+ function parseAgentTaskEvent(data) {
206
+ let value;
207
+ try {
208
+ value = JSON.parse(data);
209
+ } catch {
210
+ throw invalidResponse("The Agent event stream returned invalid JSON");
211
+ }
212
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
213
+ throw invalidResponse("The Agent event stream returned an invalid event");
214
+ }
215
+ const event = value;
216
+ if (typeof event.type !== "string" || typeof event.timestamp !== "number") {
217
+ throw invalidResponse("The Agent event stream returned an invalid event");
218
+ }
219
+ if (event.sequence !== void 0 && typeof event.sequence !== "number") {
220
+ throw invalidResponse("The Agent event stream returned an invalid event sequence");
221
+ }
222
+ return value;
223
+ }
224
+ function consumeEventBlock(block, observer) {
225
+ let eventName = "message";
226
+ const data = [];
227
+ for (const rawLine of block.split(/\r?\n/)) {
228
+ const line = rawLine.replace(/^\uFEFF/, "");
229
+ if (!line || line.startsWith(":")) continue;
230
+ const separator = line.indexOf(":");
231
+ const field = separator === -1 ? line : line.slice(0, separator);
232
+ let value = separator === -1 ? "" : line.slice(separator + 1);
233
+ if (value.startsWith(" ")) value = value.slice(1);
234
+ if (field === "event") eventName = value;
235
+ if (field === "data") data.push(value);
236
+ }
237
+ if (eventName === "hello" || eventName === "ping") return;
238
+ if (eventName !== "message" || data.length === 0) return;
239
+ observer.onEvent(parseAgentTaskEvent(data.join("\n")));
240
+ }
241
+ async function readErrorPayload(response) {
242
+ const text = await response.text();
243
+ try {
244
+ return JSON.parse(text);
245
+ } catch {
246
+ return {};
247
+ }
248
+ }
249
+ var AgentTaskSseEventSource = class {
250
+ constructor(config) {
251
+ this.config = config;
252
+ }
253
+ async open(taskId, observer, signal, transport) {
254
+ if (transport === "websocket") {
255
+ throw new MitraConfigurationError(
256
+ "WebSocket Agent sessions are not available in the Functions runtime"
257
+ );
258
+ }
259
+ if (signal?.aborted) throw signal.reason ?? new Error("Agent event stream was aborted");
260
+ const controller = new AbortController();
261
+ let handshakeTimedOut = false;
262
+ let intentionallyClosed = false;
263
+ let disconnected = false;
264
+ const abortFromCaller = () => controller.abort(signal?.reason);
265
+ signal?.addEventListener("abort", abortFromCaller, { once: true });
266
+ const handshakeTimeout = this.config.timeoutMs === void 0 ? void 0 : setTimeout(() => {
267
+ handshakeTimedOut = true;
268
+ controller.abort();
269
+ }, this.config.timeoutMs);
270
+ const disconnect = (error) => {
271
+ if (disconnected || intentionallyClosed) return;
272
+ disconnected = true;
273
+ observer.onDisconnect(error);
274
+ };
275
+ const cleanup = () => signal?.removeEventListener("abort", abortFromCaller);
276
+ let response;
277
+ try {
278
+ const path = encodePathSegment(taskId, "taskId", this.config.errors);
279
+ response = await this.config.fetch(`${this.config.baseUrl}/api/v1/tasks/${path}/events`, {
280
+ method: "GET",
281
+ headers: {
282
+ Accept: "text/event-stream",
283
+ Authorization: `Bearer ${this.config.accessToken}`,
284
+ "X-App-Id": this.config.appId
285
+ },
286
+ redirect: "manual",
287
+ signal: controller.signal
288
+ });
289
+ } catch {
290
+ if (handshakeTimeout !== void 0) clearTimeout(handshakeTimeout);
291
+ cleanup();
292
+ if (handshakeTimedOut) {
293
+ throw new MitraApiError("Mitra Agent event stream handshake timed out", 0, {
294
+ code: "REQUEST_TIMEOUT",
295
+ retryable: true
296
+ });
297
+ }
298
+ if (signal?.aborted) throw signal.reason ?? new Error("Agent event stream was aborted");
299
+ throw new MitraApiError("The Mitra Agent event stream request failed", 0, {
300
+ code: "NETWORK_ERROR",
301
+ retryable: true
302
+ });
303
+ }
304
+ if (handshakeTimeout !== void 0) clearTimeout(handshakeTimeout);
305
+ if (!response.ok) {
306
+ cleanup();
307
+ throw createApiError(response, await readErrorPayload(response), this.config.accessToken);
308
+ }
309
+ if (!response.body) {
310
+ cleanup();
311
+ throw invalidResponse("The Agent event stream response has no body");
312
+ }
313
+ const contentType = response.headers.get("Content-Type") ?? "";
314
+ if (!contentType.toLowerCase().includes("text/event-stream")) {
315
+ controller.abort();
316
+ cleanup();
317
+ throw invalidResponse("The Agent event stream returned an invalid content type");
318
+ }
319
+ const reader = response.body.getReader();
320
+ const decoder = new TextDecoder();
321
+ let buffer = "";
322
+ void (async () => {
323
+ try {
324
+ while (true) {
325
+ const { done, value } = await reader.read();
326
+ if (done) break;
327
+ buffer += decoder.decode(value, { stream: true });
328
+ let boundary = /\r?\n\r?\n/.exec(buffer);
329
+ while (boundary?.index !== void 0) {
330
+ consumeEventBlock(buffer.slice(0, boundary.index), observer);
331
+ buffer = buffer.slice(boundary.index + boundary[0].length);
332
+ boundary = /\r?\n\r?\n/.exec(buffer);
333
+ }
334
+ }
335
+ buffer += decoder.decode();
336
+ if (buffer.trim()) consumeEventBlock(buffer, observer);
337
+ disconnect();
338
+ } catch (error) {
339
+ if (!controller.signal.aborted) {
340
+ controller.abort();
341
+ await reader.cancel().catch(() => void 0);
342
+ disconnect(error);
343
+ }
344
+ } finally {
345
+ cleanup();
346
+ reader.releaseLock();
347
+ }
348
+ })();
349
+ return {
350
+ close() {
351
+ if (intentionallyClosed) return;
352
+ intentionallyClosed = true;
353
+ cleanup();
354
+ controller.abort();
355
+ void reader.cancel().catch(() => void 0);
356
+ }
357
+ };
358
+ }
359
+ };
360
+
361
+ // src/app-scoped-apps.ts
362
+ function unavailable(operation) {
363
+ throw new MitraConfigurationError(
364
+ `apps.${operation} is not available in an app-scoped Functions runtime`
365
+ );
366
+ }
367
+ function assertCurrentApp(configuredAppId, requestedAppId) {
368
+ if (requestedAppId !== configuredAppId) {
369
+ throw new MitraConfigurationError(
370
+ `Code Studio access is fixed to app ${configuredAppId}; received ${requestedAppId}`
371
+ );
372
+ }
373
+ }
374
+ function createAppScopedAppsModule(apps, appId) {
375
+ const scoped = {
376
+ async list() {
377
+ return unavailable("list");
378
+ },
379
+ async get(requestedAppId, options) {
380
+ assertCurrentApp(appId, requestedAppId);
381
+ return apps.get(appId, options);
382
+ },
383
+ async create() {
384
+ return unavailable("create");
385
+ },
386
+ async delete(requestedAppId) {
387
+ assertCurrentApp(appId, requestedAppId);
388
+ return apps.delete(appId);
389
+ },
390
+ async update(requestedAppId, input) {
391
+ assertCurrentApp(appId, requestedAppId);
392
+ return apps.update(appId, input);
393
+ },
394
+ async getFiles(requestedAppId) {
395
+ assertCurrentApp(appId, requestedAppId);
396
+ return apps.getFiles(appId);
397
+ },
398
+ async replaceFiles(requestedAppId, files) {
399
+ assertCurrentApp(appId, requestedAppId);
400
+ return apps.replaceFiles(appId, files);
401
+ },
402
+ async mergeFiles(requestedAppId, files) {
403
+ assertCurrentApp(appId, requestedAppId);
404
+ return apps.mergeFiles(appId, files);
405
+ },
406
+ async build(requestedAppId) {
407
+ assertCurrentApp(appId, requestedAppId);
408
+ return apps.build(appId);
409
+ },
410
+ async publish(requestedAppId, options) {
411
+ assertCurrentApp(appId, requestedAppId);
412
+ return apps.publish(appId, options);
413
+ },
414
+ async getDeploy(requestedAppId, deployId) {
415
+ assertCurrentApp(appId, requestedAppId);
416
+ return apps.getDeploy(appId, deployId);
417
+ },
418
+ async getCurrentDeploy(requestedAppId) {
419
+ assertCurrentApp(appId, requestedAppId);
420
+ return apps.getCurrentDeploy(appId);
421
+ },
422
+ async cancelBuild(requestedAppId, deployId) {
423
+ assertCurrentApp(appId, requestedAppId);
424
+ return apps.cancelBuild(appId, deployId);
425
+ },
426
+ async rollback(requestedAppId, targetVersionId) {
427
+ assertCurrentApp(appId, requestedAppId);
428
+ return apps.rollback(appId, targetVersionId);
429
+ },
430
+ async listDeploys(requestedAppId, options) {
431
+ assertCurrentApp(appId, requestedAppId);
432
+ return apps.listDeploys(appId, options);
433
+ },
434
+ async listVersions(requestedAppId, options) {
435
+ assertCurrentApp(appId, requestedAppId);
436
+ return apps.listVersions(appId, options);
437
+ }
438
+ };
439
+ return {
440
+ apps: scoped,
441
+ currentApp: {
442
+ get: (options) => scoped.get(appId, options),
443
+ delete: () => scoped.delete(appId),
444
+ update: (input) => scoped.update(appId, input),
445
+ getFiles: () => scoped.getFiles(appId),
446
+ replaceFiles: (files) => scoped.replaceFiles(appId, files),
447
+ mergeFiles: (files) => scoped.mergeFiles(appId, files),
448
+ build: () => scoped.build(appId),
449
+ publish: (options) => scoped.publish(appId, options),
450
+ getDeploy: (deployId) => scoped.getDeploy(appId, deployId),
451
+ getCurrentDeploy: () => scoped.getCurrentDeploy(appId),
452
+ cancelBuild: (deployId) => scoped.cancelBuild(appId, deployId),
453
+ rollback: (targetVersionId) => scoped.rollback(appId, targetVersionId),
454
+ listDeploys: (options) => scoped.listDeploys(appId, options),
455
+ listVersions: (options) => scoped.listVersions(appId, options)
456
+ }
457
+ };
458
+ }
459
+
460
+ // src/config.ts
461
+ function readDefaultEnvironment() {
462
+ return typeof process === "undefined" ? {} : process.env;
463
+ }
464
+ function requiredValue(value, name) {
465
+ if (!value?.trim()) {
466
+ throw new MitraConfigurationError(`${name} is required`);
467
+ }
468
+ return value.trim();
469
+ }
470
+ function removeTrailingSlashes(value) {
471
+ let end = value.length;
472
+ while (end > 0 && value.charCodeAt(end - 1) === 47) end -= 1;
473
+ return value.slice(0, end);
474
+ }
475
+ function normalizeApiUrl(value) {
476
+ let parsed;
477
+ try {
478
+ parsed = new URL(value);
479
+ } catch {
480
+ throw new MitraConfigurationError("apiUrl must be a valid HTTP or HTTPS URL");
481
+ }
482
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
483
+ throw new MitraConfigurationError("apiUrl must be a valid HTTP or HTTPS URL");
484
+ }
485
+ if (parsed.username || parsed.password || parsed.search || parsed.hash || value.includes("?") || value.includes("#")) {
486
+ throw new MitraConfigurationError(
487
+ "apiUrl must not include credentials, query parameters, or a fragment"
488
+ );
489
+ }
490
+ return removeTrailingSlashes(parsed.toString());
491
+ }
492
+ function deriveNativeApiUrl(legacyBaseUrl) {
493
+ if (legacyBaseUrl === void 0) return void 0;
494
+ const parsed = new URL(normalizeApiUrl(legacyBaseUrl));
495
+ parsed.pathname = parsed.pathname.replace(/\/legacy\/?$/, "") || "/";
496
+ return removeTrailingSlashes(parsed.toString());
497
+ }
498
+ function resolveConfig(config = {}, environment = readDefaultEnvironment()) {
499
+ const apiUrl = normalizeApiUrl(
500
+ requiredValue(
501
+ config.apiUrl ?? environment.MITRA_API_URL ?? deriveNativeApiUrl(environment.MITRA_BASE_URL),
502
+ "apiUrl"
503
+ )
504
+ );
505
+ const accessToken = requiredValue(
506
+ config.accessToken ?? environment.MITRA_PLATFORM_ACCESS_TOKEN ?? environment.MITRA_TOKEN,
507
+ "accessToken"
508
+ );
509
+ const appId = requiredValue(
510
+ config.appId ?? environment.MITRA_APP_ID ?? environment.MITRA_PROJECT_ID,
511
+ "appId"
512
+ );
513
+ const timeoutMs = config.timeoutMs;
514
+ const fetchImplementation = config.fetch ?? globalThis.fetch;
515
+ if (timeoutMs !== void 0 && (!Number.isFinite(timeoutMs) || timeoutMs <= 0)) {
516
+ throw new MitraConfigurationError("timeoutMs must be a positive number");
517
+ }
518
+ if (typeof fetchImplementation !== "function") {
519
+ throw new MitraConfigurationError("A fetch implementation is required");
520
+ }
521
+ const dataSourceId = config.dataSourceId ?? environment.MITRA_DATA_SOURCE_ID;
522
+ if (dataSourceId !== void 0 && !dataSourceId.trim()) {
523
+ throw new MitraConfigurationError("dataSourceId must not be empty when provided");
524
+ }
525
+ return {
526
+ apiUrl,
527
+ legacyBaseUrl: normalizeApiUrl(config.legacyBaseUrl ?? environment.MITRA_BASE_URL ?? apiUrl),
528
+ accessToken,
529
+ appId,
530
+ ...dataSourceId === void 0 ? {} : { dataSourceId: dataSourceId.trim() },
531
+ ...timeoutMs === void 0 ? {} : { timeoutMs },
532
+ fetch: fetchImplementation
533
+ };
534
+ }
535
+
536
+ // src/legacy/configure.ts
537
+ import { configureSdkMitra } from "mitra-sdk";
538
+ function configureLegacySdk(config) {
539
+ configureSdkMitra({
540
+ baseURL: config.legacyBaseUrl,
541
+ token: config.accessToken,
542
+ projectId: config.appId
543
+ });
544
+ }
545
+
221
546
  // src/client.ts
222
547
  var coreErrors = {
223
548
  configuration: (message) => new MitraConfigurationError(message),
224
549
  invalidResponse: (message) => new MitraApiError(message, 200, { code: "INVALID_RESPONSE", retryable: false })
225
550
  };
226
551
  var DefaultMitraClient = class {
552
+ agentConnections;
553
+ agentCredentials;
554
+ agents;
555
+ agentTasks;
556
+ apps;
227
557
  auth;
558
+ context;
559
+ currentApp;
560
+ customQueries;
561
+ dataSources;
228
562
  entities;
229
563
  functions;
564
+ functionsAdmin;
565
+ imports;
230
566
  integration;
567
+ integrationAdmin;
568
+ integrationResources;
569
+ integrationTemplates;
570
+ members;
571
+ messenger;
572
+ publicFunctions;
231
573
  queries;
574
+ schema;
575
+ sql;
576
+ workflows;
232
577
  #dataSourceId;
233
578
  #initPromise;
234
579
  #appId;
@@ -238,27 +583,78 @@ var DefaultMitraClient = class {
238
583
  this.#dataSourceId = config.dataSourceId;
239
584
  const httpClient = (service) => new HttpClient({
240
585
  baseUrl: `${config.apiUrl}/${service}`,
586
+ authentication: "bearer",
241
587
  accessToken: config.accessToken,
242
588
  appId: config.appId,
243
- timeoutMs: config.timeoutMs,
589
+ ...config.timeoutMs === void 0 ? {} : { timeoutMs: config.timeoutMs },
244
590
  fetch: config.fetch
245
591
  });
246
592
  const core = createSdkCore({
247
593
  transports: {
248
594
  auth: httpClient("iam"),
595
+ codeStudio: httpClient("code-studio"),
596
+ copilot: httpClient("copilot"),
249
597
  dataManager: httpClient("data-manager"),
250
598
  functions: httpClient("functions"),
251
- integration: httpClient("integration")
599
+ integration: httpClient("integration"),
600
+ messenger: httpClient("messenger"),
601
+ publicFunctions: new HttpClient({
602
+ baseUrl: `${config.apiUrl}/functions`,
603
+ authentication: "anonymous",
604
+ ...config.timeoutMs === void 0 ? {} : { timeoutMs: config.timeoutMs },
605
+ fetch: config.fetch
606
+ })
252
607
  },
253
- getDataSourceId: () => this.#dataSourceId,
608
+ getAppId: () => this.#appId,
254
609
  functions: { executeInvocationType: "sync", emptyInput: "empty-object" },
255
610
  errors: coreErrors
256
611
  });
612
+ const appModules = createAppScopedAppsModule(core.apps, this.#appId);
613
+ this.agentConnections = core.agentConnections;
614
+ this.agentCredentials = core.agentCredentials;
615
+ this.agents = core.agents;
616
+ const agentSessionManager = createAgentTaskSessionManager({
617
+ tasks: core.agentTasks,
618
+ eventSource: new AgentTaskSseEventSource({
619
+ baseUrl: `${config.apiUrl}/copilot`,
620
+ accessToken: config.accessToken,
621
+ appId: config.appId,
622
+ ...config.timeoutMs === void 0 ? {} : { timeoutMs: config.timeoutMs },
623
+ fetch: config.fetch,
624
+ errors: coreErrors
625
+ })
626
+ });
627
+ this.agentTasks = withAgentTaskSessions(core.agentTasks, {
628
+ session: (options) => {
629
+ if (options.transport === "websocket") {
630
+ throw new MitraConfigurationError(
631
+ "WebSocket Agent sessions are not available in the Functions runtime; use http or auto"
632
+ );
633
+ }
634
+ return agentSessionManager.session(options);
635
+ }
636
+ });
637
+ this.apps = appModules.apps;
257
638
  this.auth = core.auth;
639
+ this.context = core.context;
640
+ this.currentApp = appModules.currentApp;
641
+ this.customQueries = core.customQueries;
642
+ this.dataSources = core.dataSources;
258
643
  this.entities = core.entities;
259
644
  this.functions = core.functions;
645
+ this.functionsAdmin = core.functionsAdmin;
646
+ this.imports = core.imports;
260
647
  this.integration = core.integration;
648
+ this.integrationAdmin = core.integrationAdmin;
649
+ this.integrationResources = core.integrationResources;
650
+ this.integrationTemplates = core.integrationTemplates;
651
+ this.members = core.members;
652
+ this.messenger = core.messenger;
653
+ this.publicFunctions = core.publicFunctions;
261
654
  this.queries = core.queries;
655
+ this.schema = core.schema;
656
+ this.sql = core.sql;
657
+ this.workflows = core.workflows;
262
658
  this.#codeStudioHttpClient = httpClient("code-studio");
263
659
  }
264
660
  init() {
@@ -274,12 +670,13 @@ var DefaultMitraClient = class {
274
670
  async resolveDataSourceId() {
275
671
  const appInfo = expectObject(
276
672
  await this.#codeStudioHttpClient.get(
277
- `/api/v1/apps/${encodePathSegment(this.#appId, "appId", coreErrors)}/info`
673
+ `/api/v1/apps/${encodePathSegment2(this.#appId, "appId", coreErrors)}/info`
278
674
  ),
279
675
  "App info response",
280
676
  coreErrors
281
677
  );
282
- if (!appInfo.dataSourceId?.trim()) {
678
+ if (appInfo.dataSourceId === null) return;
679
+ if (typeof appInfo.dataSourceId !== "string" || !appInfo.dataSourceId.trim()) {
283
680
  throw new MitraApiError("The app info response does not include a dataSourceId", 200, {
284
681
  code: "INVALID_RESPONSE",
285
682
  retryable: false
@@ -288,15 +685,148 @@ var DefaultMitraClient = class {
288
685
  this.#dataSourceId = appInfo.dataSourceId;
289
686
  }
290
687
  };
688
+ function createConfiguredClient(config) {
689
+ configureLegacySdk(config);
690
+ return new DefaultMitraClient(config);
691
+ }
291
692
  function createClient(config = {}) {
292
- return new DefaultMitraClient(resolveConfig(config));
693
+ return createConfiguredClient(resolveConfig(config));
293
694
  }
294
695
  function createClientFromEnvironment(environment) {
295
- return new DefaultMitraClient(resolveConfig({}, environment));
696
+ return createConfiguredClient(resolveConfig({}, environment));
296
697
  }
698
+
699
+ // src/index.ts
700
+ import { AgentTaskTurnError } from "@mitralab.io/sdk-core";
701
+
702
+ // src/legacy/index.ts
703
+ import * as legacy from "mitra-sdk";
704
+ var configureSdkMitra3 = legacy.configureSdkMitra;
705
+ var createMitraSdkInstance2 = legacy.createMitraSdkInstance;
706
+ var resolveProjectId2 = legacy.resolveProjectId;
707
+ var createRecordMitra2 = legacy.createRecordMitra;
708
+ var createRecordsBatchMitra2 = legacy.createRecordsBatchMitra;
709
+ var getRecordMitra2 = legacy.getRecordMitra;
710
+ var listRecordsMitra2 = legacy.listRecordsMitra;
711
+ var updateRecordMitra2 = legacy.updateRecordMitra;
712
+ var patchRecordMitra2 = legacy.patchRecordMitra;
713
+ var deleteRecordMitra2 = legacy.deleteRecordMitra;
714
+ var executeServerFunctionMitra2 = legacy.executeServerFunctionMitra;
715
+ var executeServerFunctionAsyncMitra2 = legacy.executeServerFunctionAsyncMitra;
716
+ var getServerFunctionExecutionMitra2 = legacy.getServerFunctionExecutionMitra;
717
+ var stopServerFunctionExecutionMitra2 = legacy.stopServerFunctionExecutionMitra;
718
+ var executePublicServerFunctionAsyncMitra2 = legacy.executePublicServerFunctionAsyncMitra;
719
+ var callIntegrationMitra2 = legacy.callIntegrationMitra;
720
+ var listIntegrationsMitra2 = legacy.listIntegrationsMitra;
721
+ var getProjectsMitra2 = legacy.getProjectsMitra;
722
+ var getProjectContextMitra2 = legacy.getProjectContextMitra;
723
+ var listProjectsMitra2 = legacy.listProjectsMitra;
724
+ var createProjectMitra2 = legacy.createProjectMitra;
725
+ var updateProjectSettingsMitra2 = legacy.updateProjectSettingsMitra;
726
+ var getGitConfigMitra2 = legacy.getGitConfigMitra;
727
+ var createJdbcConnectionMitra2 = legacy.createJdbcConnectionMitra;
728
+ var listJdbcConnectionsMitra2 = legacy.listJdbcConnectionsMitra;
729
+ var updateJdbcConnectionMitra2 = legacy.updateJdbcConnectionMitra;
730
+ var deleteJdbcConnectionMitra2 = legacy.deleteJdbcConnectionMitra;
731
+ var runQueryMitra2 = legacy.runQueryMitra;
732
+ var runDdlMitra2 = legacy.runDdlMitra;
733
+ var runDmlMitra2 = legacy.runDmlMitra;
734
+ var listTablesMitra2 = legacy.listTablesMitra;
735
+ var createOnlineTableMitra2 = legacy.createOnlineTableMitra;
736
+ var listOnlineTablesMitra2 = legacy.listOnlineTablesMitra;
737
+ var updateOnlineTableMitra2 = legacy.updateOnlineTableMitra;
738
+ var deleteOnlineTableMitra2 = legacy.deleteOnlineTableMitra;
739
+ var createServerFunctionMitra2 = legacy.createServerFunctionMitra;
740
+ var readServerFunctionMitra2 = legacy.readServerFunctionMitra;
741
+ var listServerFunctionsMitra2 = legacy.listServerFunctionsMitra;
742
+ var updateServerFunctionMitra2 = legacy.updateServerFunctionMitra;
743
+ var deleteServerFunctionMitra2 = legacy.deleteServerFunctionMitra;
744
+ var togglePublicExecutionMitra2 = legacy.togglePublicExecutionMitra;
745
+ var createIntegrationMitra2 = legacy.createIntegrationMitra;
746
+ var updateIntegrationMitra2 = legacy.updateIntegrationMitra;
747
+ var deleteIntegrationMitra2 = legacy.deleteIntegrationMitra;
748
+ var testIntegrationMitra2 = legacy.testIntegrationMitra;
749
+ var testIntegrationByIdMitra2 = legacy.testIntegrationByIdMitra;
750
+ var listIntegrationTemplatesMitra2 = legacy.listIntegrationTemplatesMitra;
751
+ var getIntegrationTemplateMitra2 = legacy.getIntegrationTemplateMitra;
752
+ var createAgentMitra2 = legacy.createAgentMitra;
753
+ var readAgentMitra2 = legacy.readAgentMitra;
754
+ var listAgentsMitra2 = legacy.listAgentsMitra;
755
+ var updateAgentMitra2 = legacy.updateAgentMitra;
756
+ var deleteAgentMitra2 = legacy.deleteAgentMitra;
757
+ var getAgentTaskMitra2 = legacy.getAgentTaskMitra;
758
+ var manageAgentChatMitra2 = legacy.manageAgentChatMitra;
759
+ var manageAgentCredentialMitra2 = legacy.manageAgentCredentialMitra;
760
+ var manageAgentConnectionMitra2 = legacy.manageAgentConnectionMitra;
761
+ var inviteUserMitra2 = legacy.inviteUserMitra;
762
+ var unsubscribeUserMitra2 = legacy.unsubscribeUserMitra;
763
+ var deployToS3Mitra2 = legacy.deployToS3Mitra;
764
+ var getDeployStatusMitra2 = legacy.getDeployStatusMitra;
297
765
  export {
766
+ AgentTaskTurnError,
298
767
  MitraApiError,
299
768
  MitraConfigurationError,
769
+ callIntegrationMitra2 as callIntegrationMitra,
770
+ configureSdkMitra3 as configureSdkMitra,
771
+ createAgentMitra2 as createAgentMitra,
300
772
  createClient,
301
- createClientFromEnvironment
773
+ createClientFromEnvironment,
774
+ createIntegrationMitra2 as createIntegrationMitra,
775
+ createJdbcConnectionMitra2 as createJdbcConnectionMitra,
776
+ createMitraSdkInstance2 as createMitraSdkInstance,
777
+ createOnlineTableMitra2 as createOnlineTableMitra,
778
+ createProjectMitra2 as createProjectMitra,
779
+ createRecordMitra2 as createRecordMitra,
780
+ createRecordsBatchMitra2 as createRecordsBatchMitra,
781
+ createServerFunctionMitra2 as createServerFunctionMitra,
782
+ deleteAgentMitra2 as deleteAgentMitra,
783
+ deleteIntegrationMitra2 as deleteIntegrationMitra,
784
+ deleteJdbcConnectionMitra2 as deleteJdbcConnectionMitra,
785
+ deleteOnlineTableMitra2 as deleteOnlineTableMitra,
786
+ deleteRecordMitra2 as deleteRecordMitra,
787
+ deleteServerFunctionMitra2 as deleteServerFunctionMitra,
788
+ deployToS3Mitra2 as deployToS3Mitra,
789
+ executePublicServerFunctionAsyncMitra2 as executePublicServerFunctionAsyncMitra,
790
+ executeServerFunctionAsyncMitra2 as executeServerFunctionAsyncMitra,
791
+ executeServerFunctionMitra2 as executeServerFunctionMitra,
792
+ getAgentTaskMitra2 as getAgentTaskMitra,
793
+ getDeployStatusMitra2 as getDeployStatusMitra,
794
+ getGitConfigMitra2 as getGitConfigMitra,
795
+ getIntegrationTemplateMitra2 as getIntegrationTemplateMitra,
796
+ getProjectContextMitra2 as getProjectContextMitra,
797
+ getProjectsMitra2 as getProjectsMitra,
798
+ getRecordMitra2 as getRecordMitra,
799
+ getServerFunctionExecutionMitra2 as getServerFunctionExecutionMitra,
800
+ inviteUserMitra2 as inviteUserMitra,
801
+ listAgentsMitra2 as listAgentsMitra,
802
+ listIntegrationTemplatesMitra2 as listIntegrationTemplatesMitra,
803
+ listIntegrationsMitra2 as listIntegrationsMitra,
804
+ listJdbcConnectionsMitra2 as listJdbcConnectionsMitra,
805
+ listOnlineTablesMitra2 as listOnlineTablesMitra,
806
+ listProjectsMitra2 as listProjectsMitra,
807
+ listRecordsMitra2 as listRecordsMitra,
808
+ listServerFunctionsMitra2 as listServerFunctionsMitra,
809
+ listTablesMitra2 as listTablesMitra,
810
+ manageAgentChatMitra2 as manageAgentChatMitra,
811
+ manageAgentConnectionMitra2 as manageAgentConnectionMitra,
812
+ manageAgentCredentialMitra2 as manageAgentCredentialMitra,
813
+ patchRecordMitra2 as patchRecordMitra,
814
+ readAgentMitra2 as readAgentMitra,
815
+ readServerFunctionMitra2 as readServerFunctionMitra,
816
+ resolveProjectId2 as resolveProjectId,
817
+ runDdlMitra2 as runDdlMitra,
818
+ runDmlMitra2 as runDmlMitra,
819
+ runQueryMitra2 as runQueryMitra,
820
+ stopServerFunctionExecutionMitra2 as stopServerFunctionExecutionMitra,
821
+ testIntegrationByIdMitra2 as testIntegrationByIdMitra,
822
+ testIntegrationMitra2 as testIntegrationMitra,
823
+ togglePublicExecutionMitra2 as togglePublicExecutionMitra,
824
+ unsubscribeUserMitra2 as unsubscribeUserMitra,
825
+ updateAgentMitra2 as updateAgentMitra,
826
+ updateIntegrationMitra2 as updateIntegrationMitra,
827
+ updateJdbcConnectionMitra2 as updateJdbcConnectionMitra,
828
+ updateOnlineTableMitra2 as updateOnlineTableMitra,
829
+ updateProjectSettingsMitra2 as updateProjectSettingsMitra,
830
+ updateRecordMitra2 as updateRecordMitra,
831
+ updateServerFunctionMitra2 as updateServerFunctionMitra
302
832
  };