@choiceopen/atomemo-plugin-sdk-js 0.3.4 → 0.4.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.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import "dotenv/config";
2
2
  import { CredentialDefinitionSchema, ModelDefinitionSchema, ToolDefinitionSchema } from "@choiceopen/atomemo-plugin-schema/schemas";
3
- import { z } from "zod";
3
+ import { z as z$1 } from "zod";
4
4
  import { Socket, SocketConnectOption } from "phoenix";
5
5
  import { PluginDefinition } from "@choiceopen/atomemo-plugin-schema/types";
6
6
 
@@ -13,9 +13,9 @@ interface TransporterOptions extends Partial<Pick<SocketConnectOption, "heartbea
13
13
  }
14
14
  //#endregion
15
15
  //#region src/plugin.d.ts
16
- type CredentialDefinition = z.infer<typeof CredentialDefinitionSchema>;
17
- type ToolDefinition = z.infer<typeof ToolDefinitionSchema>;
18
- type ModelDefinition = z.infer<typeof ModelDefinitionSchema>;
16
+ type CredentialDefinition = z$1.infer<typeof CredentialDefinitionSchema>;
17
+ type ToolDefinition = z$1.infer<typeof ToolDefinitionSchema>;
18
+ type ModelDefinition = z$1.infer<typeof ModelDefinitionSchema>;
19
19
  /**
20
20
  * Creates a new plugin instance with the specified options.
21
21
  *
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import "dotenv/config";
2
- import { CredentialDefinitionSchema, ModelDefinitionSchema, ToolDefinitionSchema } from "@choiceopen/atomemo-plugin-schema/schemas";
3
- import z$1, { z } from "zod";
2
+ import { CredentialDefinitionSchema, FileRefSchema, ModelDefinitionSchema, ToolDefinitionSchema } from "@choiceopen/atomemo-plugin-schema/schemas";
3
+ import z, { ZodError, z as z$1 } from "zod";
4
4
  import { readFileSync } from "node:fs";
5
5
  import { homedir } from "node:os";
6
6
  import { join } from "node:path";
@@ -32,22 +32,83 @@ function invariant(condition, message) {
32
32
  throw message;
33
33
  }
34
34
 
35
+ //#endregion
36
+ //#region src/context.ts
37
+ function inferMimeType(extension) {
38
+ return Bun.file(`file${extension ?? ""}`).type.split(";")[0] || "application/octet-stream";
39
+ }
40
+ function createPluginContext(hubCaller) {
41
+ const attachRemoteUrl = async (fileRef) => {
42
+ if (fileRef.remote_url) return {
43
+ ...fileRef,
44
+ remote_url: fileRef.remote_url
45
+ };
46
+ const response = await hubCaller.call("get_file_url", { res_key: fileRef.res_key });
47
+ return {
48
+ ...fileRef,
49
+ remote_url: response.url
50
+ };
51
+ };
52
+ const download = async (fileRef) => {
53
+ if (fileRef.source === "mem") return fileRef;
54
+ const fileRefWithRemoteUrl = await attachRemoteUrl(fileRef);
55
+ const response = await fetch(fileRefWithRemoteUrl.remote_url);
56
+ const content = Buffer.from(await response.arrayBuffer()).toString("base64");
57
+ return {
58
+ ...fileRefWithRemoteUrl,
59
+ content
60
+ };
61
+ };
62
+ const upload = async (input, options) => {
63
+ const fileRef = FileRefSchema.parse(input);
64
+ if (fileRef.source === "oss") return fileRef;
65
+ const content = fileRef.content ?? "";
66
+ const mimeType = fileRef.mime_type || inferMimeType(fileRef.extension);
67
+ const payload = {
68
+ extension: fileRef.extension,
69
+ prefixKey: options?.prefixKey
70
+ };
71
+ const { presigned_url, res_key } = await hubCaller.call("get_upload_url", payload);
72
+ const response = await fetch(presigned_url, {
73
+ method: "PUT",
74
+ body: Buffer.from(content, "base64"),
75
+ headers: { "content-type": mimeType }
76
+ });
77
+ if (!response.ok) throw new Error(`Failed to upload file: ${response.status} ${response.statusText}`.trim());
78
+ return {
79
+ ...fileRef,
80
+ source: "oss",
81
+ content: void 0,
82
+ size: Buffer.from(content, "base64").byteLength,
83
+ res_key,
84
+ remote_url: void 0
85
+ };
86
+ };
87
+ return { files: {
88
+ parseFileRef(input) {
89
+ return FileRefSchema.parse(input);
90
+ },
91
+ attachRemoteUrl,
92
+ download,
93
+ upload
94
+ } };
95
+ }
96
+
35
97
  //#endregion
36
98
  //#region src/env.ts
37
- const EnvSchema = z$1.object({
38
- HUB_MODE: z$1.enum(["debug", "release"]).default("debug").meta({ description: `The Hub Server runtime mode. This will be "debug" by default.` }),
39
- HUB_WS_URL: z$1.url({
99
+ const EnvSchema = z.object({
100
+ HUB_MODE: z.enum(["debug", "release"]).default("debug").meta({ description: `The Hub Server runtime mode. This will be "debug" by default.` }),
101
+ HUB_WS_URL: z.url({
40
102
  protocol: /wss?/,
41
103
  error: "HUB_WS_URL must be a valid WebSocket URL."
42
104
  }),
43
- HUB_DEBUG_API_KEY: z$1.string({ error: "HUB_DEBUG_API_KEY must be a string." }).optional().refine((value) => {
105
+ HUB_DEBUG_API_KEY: z.string({ error: "HUB_DEBUG_API_KEY must be a string." }).optional().refine((value) => {
44
106
  return Bun.env.NODE_ENV === "production" || isString(value) && value.length > 0;
45
107
  }).meta({ description: `The API key for the Hub Server` }),
46
- HUB_ORGANIZATION_ID: z$1.string().optional().meta({ description: `The organization ID for the plugin.` }),
47
- DEBUG: z$1.string().optional().transform((value) => {
108
+ DEBUG: z.string().optional().transform((value) => {
48
109
  return isNil(value) ? process.env.NODE_ENV !== "production" : value.toLowerCase() === "true";
49
110
  }).meta({ description: `Whether to enable debug mode. This will be enabled automatically when NODE_ENV is not "production". The value must be "true" (case-insensitive) to enable debug mode, otherwise it will be treated as false.` }),
50
- NODE_ENV: z$1.enum([
111
+ NODE_ENV: z.enum([
51
112
  "development",
52
113
  "production",
53
114
  "test"
@@ -58,7 +119,7 @@ function getEnv() {
58
119
  if (isNil(env)) {
59
120
  const result = EnvSchema.safeParse(process.env);
60
121
  if (!result.success) {
61
- console.error(z$1.prettifyError(result.error));
122
+ console.error(z.prettifyError(result.error));
62
123
  process.exit(1);
63
124
  }
64
125
  env = result.data;
@@ -66,14 +127,88 @@ function getEnv() {
66
127
  return env;
67
128
  }
68
129
 
130
+ //#endregion
131
+ //#region src/hub.ts
132
+ var HubCallError = class extends Error {
133
+ code;
134
+ constructor(code, message) {
135
+ super(message);
136
+ this.name = "HubCallError";
137
+ this.code = code;
138
+ }
139
+ };
140
+ var HubCallTimeoutError = class extends Error {
141
+ constructor(event, timeoutMs) {
142
+ super(`Hub call "${event}" timed out after ${timeoutMs}ms`);
143
+ this.name = "HubCallTimeoutError";
144
+ }
145
+ };
146
+ function createHubCaller(channel, options) {
147
+ const timeoutMs = options?.timeoutMs ?? 3e4;
148
+ const pending = /* @__PURE__ */ new Map();
149
+ let disposed = false;
150
+ function settlePending(requestId) {
151
+ const entry = pending.get(requestId);
152
+ if (!entry) return void 0;
153
+ clearTimeout(entry.timer);
154
+ pending.delete(requestId);
155
+ return entry;
156
+ }
157
+ const responseRef = channel.on("hub_call_response", (payload) => {
158
+ const entry = settlePending(payload.request_id);
159
+ if (entry) entry.resolve(payload.data);
160
+ });
161
+ const errorRef = channel.on("hub_call_error", (payload) => {
162
+ const entry = settlePending(payload.request_id);
163
+ if (entry) entry.reject(new HubCallError(payload.error.code, payload.error.message));
164
+ });
165
+ return {
166
+ call(event, data) {
167
+ if (disposed) return Promise.reject(/* @__PURE__ */ new Error("Hub caller is disposed"));
168
+ return new Promise((resolve, reject) => {
169
+ const requestId = crypto.randomUUID();
170
+ const timer = setTimeout(() => {
171
+ pending.delete(requestId);
172
+ reject(new HubCallTimeoutError(event, timeoutMs));
173
+ }, timeoutMs);
174
+ pending.set(requestId, {
175
+ resolve,
176
+ reject,
177
+ timer
178
+ });
179
+ channel.push(`hub_call:${event}`, {
180
+ request_id: requestId,
181
+ data
182
+ }).receive("error", (resp) => {
183
+ const entry = settlePending(requestId);
184
+ if (entry) entry.reject(new HubCallError("PUSH_FAILED", `Push rejected: ${JSON.stringify(resp)}`));
185
+ }).receive("timeout", () => {
186
+ const entry = settlePending(requestId);
187
+ if (entry) entry.reject(new HubCallTimeoutError(event, timeoutMs));
188
+ });
189
+ });
190
+ },
191
+ dispose() {
192
+ disposed = true;
193
+ for (const [, entry] of pending) {
194
+ clearTimeout(entry.timer);
195
+ entry.reject(/* @__PURE__ */ new Error("Hub caller disposed"));
196
+ }
197
+ pending.clear();
198
+ channel.off("hub_call_response", responseRef);
199
+ channel.off("hub_call_error", errorRef);
200
+ }
201
+ };
202
+ }
203
+
69
204
  //#endregion
70
205
  //#region src/config.ts
71
- const ConfigSchema = z.object({
72
- auth: z.object({
73
- endpoint: z.url().optional(),
74
- access_token: z.string().optional()
75
- }).optional(),
76
- hub: z.object({ endpoint: z.url().optional() }).optional()
206
+ const ConfigSchema = z$1.object({
207
+ auth: z$1.record(z$1.enum(["staging", "production"]), z$1.object({
208
+ endpoint: z$1.url().optional(),
209
+ access_token: z$1.string().optional()
210
+ })).optional(),
211
+ hub: z$1.record(z$1.enum(["staging", "production"]), z$1.object({ endpoint: z$1.url().optional() })).optional()
77
212
  });
78
213
  const CONFIG_PATH = join(homedir(), ".choiceform", "atomemo.json");
79
214
  /**
@@ -95,57 +230,59 @@ function readConfig() {
95
230
 
96
231
  //#endregion
97
232
  //#region src/oneauth.ts
98
- const SessionSchema = z.object({
99
- id: z.string().optional(),
100
- expiresAt: z.string(),
101
- token: z.string(),
102
- createdAt: z.string(),
103
- updatedAt: z.string(),
104
- ipAddress: z.string().optional(),
105
- userAgent: z.string().optional(),
106
- userId: z.string(),
107
- impersonatedBy: z.string().nullish(),
108
- activeOrganizationId: z.string().nullish(),
109
- activeTeamId: z.string().nullish()
233
+ const SessionSchema = z$1.object({
234
+ id: z$1.string(),
235
+ expiresAt: z$1.string(),
236
+ token: z$1.string(),
237
+ createdAt: z$1.string(),
238
+ updatedAt: z$1.string(),
239
+ ipAddress: z$1.string().nullish(),
240
+ userAgent: z$1.string().nullish(),
241
+ userId: z$1.string(),
242
+ impersonatedBy: z$1.string().nullish(),
243
+ activeOrganizationId: z$1.string().nullish(),
244
+ activeTeamId: z$1.string().nullish()
110
245
  });
111
- const UserSchema = z.object({
112
- id: z.string().optional(),
113
- name: z.string(),
114
- email: z.string(),
115
- emailVerified: z.boolean().optional(),
116
- image: z.string().optional(),
117
- createdAt: z.string(),
118
- updatedAt: z.string(),
119
- role: z.string().optional(),
120
- banned: z.boolean().optional(),
121
- banReason: z.string().nullish(),
122
- banExpires: z.string().nullish(),
123
- lastLoginMethod: z.string().optional(),
124
- inherentOrganizationId: z.string(),
125
- inherentTeamId: z.string(),
126
- metadata: z.unknown().optional(),
127
- stripeCustomerId: z.string().nullish()
246
+ const UserSchema = z$1.object({
247
+ id: z$1.string(),
248
+ name: z$1.string(),
249
+ email: z$1.string(),
250
+ emailVerified: z$1.boolean().optional(),
251
+ image: z$1.string().nullish(),
252
+ createdAt: z$1.string(),
253
+ updatedAt: z$1.string(),
254
+ role: z$1.string(),
255
+ banned: z$1.boolean().optional(),
256
+ banReason: z$1.string().nullish(),
257
+ banExpires: z$1.string().nullish(),
258
+ lastLoginMethod: z$1.string().optional(),
259
+ inherentOrganizationId: z$1.string(),
260
+ inherentTeamId: z$1.string(),
261
+ referralCode: z$1.string(),
262
+ referredBy: z$1.string().nullish(),
263
+ metadata: z$1.record(z$1.string(), z$1.any()),
264
+ stripeCustomerId: z$1.string().nullish()
128
265
  });
129
- const GetSessionResponseSchema = z.object({
266
+ const GetSessionResponseSchema = z$1.object({
130
267
  session: SessionSchema,
131
268
  user: UserSchema
132
269
  });
133
- const DEFAULT_ENDPOINT = "https://oneauth.choiceform.io";
270
+ const DEFAULT_ENDPOINT = "https://oneauth.atomemo.ai";
134
271
  /**
135
272
  * Fetches the current session and user information from the OneAuth API.
136
273
  *
137
274
  * @returns The session and user information.
138
275
  * @throws If the config file is missing, access token is missing, or the API request fails.
139
276
  */
140
- async function getSession() {
277
+ async function getSession(deployment) {
141
278
  const config = readConfig();
142
- if (!config?.auth?.access_token) throw new Error("Access token not found. Please ensure ~/.choiceform/atomemo.json contains auth.access_token");
143
- const endpoint = config.auth.endpoint || DEFAULT_ENDPOINT;
279
+ if (!config?.auth?.[deployment]?.access_token) throw new Error("Access token not found. Please ensure ~/.choiceform/atomemo.json contains auth.access_token");
280
+ const endpoint = config.auth?.[deployment]?.endpoint || DEFAULT_ENDPOINT;
144
281
  const url = new URL("/v1/auth/get-session", endpoint).toString();
145
282
  const response = await fetch(url, {
146
283
  method: "GET",
147
284
  headers: {
148
- Authorization: `Bearer ${config.auth.access_token}`,
285
+ Authorization: `Bearer ${config.auth?.[deployment]?.access_token}`,
149
286
  "Content-Type": "application/json"
150
287
  }
151
288
  });
@@ -272,19 +409,98 @@ function createTransporter(options = {}) {
272
409
  } };
273
410
  }
274
411
 
412
+ //#endregion
413
+ //#region src/utils/parse-file-refs.ts
414
+ function parseFileRefsInner(value, seen) {
415
+ if (value === null || value === void 0) return value;
416
+ if (Array.isArray(value)) {
417
+ if (seen.has(value)) return value;
418
+ seen.add(value);
419
+ return value.map((item) => parseFileRefsInner(item, seen));
420
+ }
421
+ if (typeof value === "object") {
422
+ if (seen.has(value)) return value;
423
+ seen.add(value);
424
+ const obj = value;
425
+ if (obj.__type__ === "file_ref") return FileRefSchema.parse(obj);
426
+ return Object.fromEntries(Object.entries(obj).map(([key, val]) => [key, parseFileRefsInner(val, seen)]));
427
+ }
428
+ return value;
429
+ }
430
+ /**
431
+ * Recursively traverses a value and parses any plain objects with
432
+ * `__type__: "file_ref"` into validated FileRef structures.
433
+ *
434
+ * This mirrors the behavior of Elixir SDK's recursive file_ref parsing
435
+ * in invoke_tool parameter handling.
436
+ */
437
+ function parseFileRefs(value) {
438
+ return parseFileRefsInner(value, /* @__PURE__ */ new WeakSet());
439
+ }
440
+
441
+ //#endregion
442
+ //#region src/utils/serialize-error.ts
443
+ const toJsonValue = (value, seen) => {
444
+ if (value === null) return null;
445
+ const type = typeof value;
446
+ if (type === "string" || type === "number" || type === "boolean") return value;
447
+ if (type === "undefined" || type === "symbol" || type === "bigint" || isFunction(value)) return;
448
+ if (Array.isArray(value)) {
449
+ const result = [];
450
+ for (const item of value) {
451
+ const serialized = toJsonValue(item, seen);
452
+ result.push(serialized === void 0 ? null : serialized);
453
+ }
454
+ return result;
455
+ }
456
+ if (type === "object" && value !== null) {
457
+ if (seen.has(value)) return;
458
+ seen.add(value);
459
+ if (value instanceof Date) return value.toISOString();
460
+ if (value instanceof Error) return serializeError(value);
461
+ const result = {};
462
+ for (const [key, v] of Object.entries(value)) {
463
+ const serialized = toJsonValue(v, seen);
464
+ if (serialized !== void 0) result[key] = serialized;
465
+ }
466
+ return result;
467
+ }
468
+ };
469
+ const serializeError = (error) => {
470
+ const base = {
471
+ name: error.name,
472
+ message: error.message,
473
+ stack: error.stack
474
+ };
475
+ const anyError = error;
476
+ if ("cause" in anyError && anyError.cause !== void 0) base.cause = anyError.cause;
477
+ for (const [key, value] of Object.entries(error)) {
478
+ if (key in base) continue;
479
+ base[key] = value;
480
+ }
481
+ const serialized = toJsonValue(base, new WeakSet([error]));
482
+ if (!serialized || Array.isArray(serialized) || typeof serialized !== "object") return {
483
+ name: error.name,
484
+ message: error.message,
485
+ stack: error.stack ?? null
486
+ };
487
+ return serialized;
488
+ };
489
+
275
490
  //#endregion
276
491
  //#region src/plugin.ts
277
- const CredentialAuthenticateMessage = z.object({
278
- request_id: z.string(),
279
- credential: z.record(z.string(), z.any()),
280
- credential_name: z.string(),
281
- extra: z.record(z.string(), z.any())
492
+ const CredentialAuthenticateMessage = z$1.object({
493
+ request_id: z$1.string(),
494
+ credential: z$1.record(z$1.string(), z$1.any()),
495
+ credential_name: z$1.string(),
496
+ extra: z$1.record(z$1.string(), z$1.any()).optional()
282
497
  });
283
- const ToolInvokeMessage = z.object({
284
- request_id: z.string(),
285
- tool_name: z.string(),
286
- parameters: z.record(z.string(), z.any()),
287
- credentials: z.record(z.string(), z.any()).optional()
498
+ const ToolInvokeMessage = z$1.object({
499
+ request_id: z$1.string(),
500
+ plugin_identifier: z$1.string().optional(),
501
+ tool_name: z$1.string(),
502
+ parameters: z$1.record(z$1.string(), z$1.any()),
503
+ credentials: z$1.record(z$1.string(), z$1.any()).optional()
288
504
  });
289
505
  /**
290
506
  * Creates a new plugin instance with the specified options.
@@ -295,36 +511,36 @@ const ToolInvokeMessage = z.object({
295
511
  async function createPlugin(options) {
296
512
  const env = getEnv();
297
513
  const isDebugMode = env.HUB_MODE === "debug";
298
- if (isDebugMode && !env.HUB_ORGANIZATION_ID) {
299
- console.error("DEBUG API Key is invalid. Please run `atomemo plugin refresh-key`");
300
- process.exit(1);
301
- }
302
514
  let user;
303
515
  if (isDebugMode) try {
304
- user = (await getSession()).user;
305
- if (user.inherentOrganizationId !== env.HUB_ORGANIZATION_ID) {
306
- console.info("Atomemo does not currently support developing plugins for other organizations. Please wait for official support.");
307
- process.exit(0);
308
- }
516
+ const session = await getSession(env.HUB_WS_URL.includes("atomemo.ai") ? "production" : "staging");
517
+ user = {
518
+ name: session.user.name,
519
+ email: session.user.email
520
+ };
309
521
  } catch (error) {
310
- console.error("Failed to fetch session:", error instanceof Error ? error.message : error);
522
+ console.error("Error fetching user session:", error);
311
523
  process.exit(1);
312
524
  }
313
- else {
314
- const definition = z.looseObject({
315
- author: z.string(),
316
- email: z.string()
317
- }).parse(await Bun.file("definition.json").json());
525
+ else try {
526
+ const raw = await Bun.file("definition.json").json();
527
+ const definition = z$1.looseObject({
528
+ author: z$1.string(),
529
+ email: z$1.string()
530
+ }).parse(raw);
318
531
  user = {
319
532
  name: definition.author,
320
533
  email: definition.email
321
534
  };
535
+ } catch (error) {
536
+ if (error instanceof ZodError) console.error(z$1.prettifyError(error));
537
+ else console.error("Error parsing definition.json:", error);
538
+ process.exit(1);
322
539
  }
323
540
  const { transporterOptions, version = process.env.npm_package_version, ...plugin } = options;
324
541
  const pluginDefinition = Object.assign(plugin, {
325
542
  author: user.name,
326
543
  email: user.email,
327
- organization_id: env.HUB_ORGANIZATION_ID,
328
544
  version
329
545
  });
330
546
  const registry = createRegistry(pluginDefinition);
@@ -343,68 +559,97 @@ async function createPlugin(options) {
343
559
  registry.register("model", definition);
344
560
  },
345
561
  run: async () => {
346
- const topic = isDebugMode ? `debug_plugin:${registry.plugin.name}` : `release_plugin:${pluginDefinition.organization_id}__${registry.plugin.name}__${env.HUB_MODE}__${pluginDefinition.version}`;
562
+ const topic = isDebugMode ? `debug_plugin:${registry.plugin.name}` : `release_plugin:${registry.plugin.name}__${env.HUB_MODE}__${pluginDefinition.version}`;
347
563
  const { channel, dispose } = await transporter.connect(topic);
348
- if (isDebugMode) {
349
- const definition = registry.serialize().plugin;
350
- channel.push("register_plugin", definition);
351
- await Bun.write("definition.json", JSON.stringify(definition, null, 2));
352
- }
353
- channel.on("credential_auth_spec", async (message) => {
354
- const request_id = message.request_id;
355
- try {
356
- const event = CredentialAuthenticateMessage.parse(message);
357
- const definition = registry.resolve("credential", event.credential_name);
358
- if (isNil(definition.authenticate)) throw new Error("Credential authenticate method is not implemented");
359
- const authenticate = CredentialDefinitionSchema.shape.authenticate.unwrap().implementAsync(definition.authenticate);
360
- const { credential, extra } = event;
361
- const data = await authenticate({ args: {
362
- credential,
363
- extra
364
- } });
365
- channel.push("credential_auth_spec_response", {
366
- request_id,
367
- data
368
- });
369
- } catch (error) {
370
- if (error instanceof Error) channel.push("credential_auth_spec_error", {
371
- request_id,
372
- ...error
373
- });
374
- else channel.push("credential_auth_spec_error", {
375
- request_id,
376
- message: "Unexpected Error"
377
- });
378
- }
564
+ const hubCaller = createHubCaller(channel);
565
+ const pluginContext = createPluginContext(hubCaller);
566
+ let cleanedUp = false;
567
+ const cleanup = () => {
568
+ if (cleanedUp) return;
569
+ cleanedUp = true;
570
+ hubCaller.dispose();
571
+ dispose();
572
+ };
573
+ ["SIGINT", "SIGTERM"].forEach((signal) => {
574
+ process.on(signal, cleanup);
379
575
  });
380
- channel.on("invoke_tool", async (message) => {
381
- const request_id = message.request_id;
382
- try {
383
- const event = ToolInvokeMessage.parse(message);
384
- const { credentials, parameters } = event;
385
- const definition = registry.resolve("tool", event.tool_name);
386
- const data = await ToolDefinitionSchema.shape.invoke.implementAsync(definition.invoke)({ args: {
387
- credentials,
388
- parameters
389
- } });
390
- channel.push("invoke_tool_response", {
391
- request_id,
392
- data
393
- });
394
- } catch (error) {
395
- if (error instanceof Error) channel.push("invoke_tool_error", {
396
- request_id,
397
- ...error
398
- });
399
- else channel.push("invoke_tool_error", {
400
- request_id,
401
- message: "Unexpected Error"
576
+ try {
577
+ if (isDebugMode) {
578
+ const definition = registry.serialize().plugin;
579
+ await new Promise((resolve, reject) => {
580
+ channel.push("register_plugin", definition).receive("ok", () => {
581
+ resolve();
582
+ }).receive("error", (response) => {
583
+ reject(/* @__PURE__ */ new Error(`Failed to register plugin: ${JSON.stringify(response)}`));
584
+ }).receive("timeout", () => {
585
+ reject(/* @__PURE__ */ new Error("Timed out while registering plugin"));
586
+ });
402
587
  });
588
+ await Bun.write("definition.json", JSON.stringify(definition, null, 2));
403
589
  }
404
- });
405
- ["SIGINT", "SIGTERM"].forEach((signal) => {
406
- process.on(signal, dispose);
407
- });
590
+ channel.on("credential_auth_spec", async (message) => {
591
+ const request_id = message.request_id;
592
+ try {
593
+ const event = CredentialAuthenticateMessage.parse(message);
594
+ const definition = registry.resolve("credential", event.credential_name);
595
+ if (isNil(definition.authenticate)) throw new Error("Credential authenticate method is not implemented");
596
+ const authenticate = CredentialDefinitionSchema.shape.authenticate.unwrap().implementAsync(definition.authenticate);
597
+ const { credential, extra } = event;
598
+ const data = await authenticate({
599
+ args: {
600
+ credential,
601
+ extra
602
+ },
603
+ context: pluginContext
604
+ });
605
+ channel.push("credential_auth_spec_response", {
606
+ request_id,
607
+ data
608
+ });
609
+ } catch (error) {
610
+ if (error instanceof Error) channel.push("credential_auth_spec_error", {
611
+ request_id,
612
+ error: serializeError(error)
613
+ });
614
+ else channel.push("credential_auth_spec_error", {
615
+ request_id,
616
+ error: serializeError(/* @__PURE__ */ new Error("Unexpected Error"))
617
+ });
618
+ }
619
+ });
620
+ channel.on("invoke_tool", async (message) => {
621
+ const request_id = message.request_id;
622
+ try {
623
+ const event = ToolInvokeMessage.parse(message);
624
+ const { credentials } = event;
625
+ const parameters = parseFileRefs(event.parameters);
626
+ const definition = registry.resolve("tool", event.tool_name);
627
+ const data = await ToolDefinitionSchema.shape.invoke.implementAsync(definition.invoke)({
628
+ args: {
629
+ credentials,
630
+ parameters
631
+ },
632
+ context: pluginContext
633
+ });
634
+ channel.push("invoke_tool_response", {
635
+ request_id,
636
+ data
637
+ });
638
+ } catch (error) {
639
+ if (error instanceof Error) channel.push("invoke_tool_error", {
640
+ request_id,
641
+ error: serializeError(error)
642
+ });
643
+ else channel.push("invoke_tool_error", {
644
+ request_id,
645
+ error: serializeError(/* @__PURE__ */ new Error("Unexpected Error"))
646
+ });
647
+ }
648
+ });
649
+ } catch (error) {
650
+ cleanup();
651
+ throw error;
652
+ }
408
653
  }
409
654
  };
410
655
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["z"],"sources":["../node_modules/es-toolkit/dist/predicate/isFunction.mjs","../node_modules/es-toolkit/dist/predicate/isNil.mjs","../node_modules/es-toolkit/dist/predicate/isString.mjs","../node_modules/es-toolkit/dist/util/invariant.mjs","../src/env.ts","../src/config.ts","../src/oneauth.ts","../src/utils/serialize-feature.ts","../src/registry.ts","../src/transporter.ts","../src/plugin.ts"],"sourcesContent":["function isFunction(value) {\n return typeof value === 'function';\n}\n\nexport { isFunction };\n","function isNil(x) {\n return x == null;\n}\n\nexport { isNil };\n","function isString(value) {\n return typeof value === 'string';\n}\n\nexport { isString };\n","function invariant(condition, message) {\n if (condition) {\n return;\n }\n if (typeof message === 'string') {\n throw new Error(message);\n }\n throw message;\n}\n\nexport { invariant };\n","import { isNil, isString } from \"es-toolkit/predicate\"\nimport z from \"zod\"\n\ndeclare module \"bun\" {\n interface Env {\n /** The Hub Server runtime mode. */\n readonly HUB_MODE: \"debug\" | \"release\"\n /** The URL of the Hub Server WebSocket. */\n readonly HUB_WS_URL: string | undefined\n /** Whether to enable debug mode. */\n readonly DEBUG: boolean\n /** The API key for the Hub Server. */\n readonly HUB_DEBUG_API_KEY: string | undefined\n /** The organization ID for the plugin. */\n readonly HUB_ORGANIZATION_ID: string | undefined\n }\n}\n\nconst EnvSchema = z.object({\n HUB_MODE: z.enum([\"debug\", \"release\"]).default(\"debug\").meta({\n description: `The Hub Server runtime mode. This will be \"debug\" by default.`,\n }),\n HUB_WS_URL: z.url({\n protocol: /wss?/,\n error: \"HUB_WS_URL must be a valid WebSocket URL.\",\n }),\n HUB_DEBUG_API_KEY: z\n .string({\n error: \"HUB_DEBUG_API_KEY must be a string.\",\n })\n .optional()\n .refine((value) => {\n return Bun.env.NODE_ENV === \"production\" || (isString(value) && value.length > 0)\n })\n .meta({ description: `The API key for the Hub Server` }),\n HUB_ORGANIZATION_ID: z\n .string()\n .optional()\n .meta({ description: `The organization ID for the plugin.` }),\n DEBUG: z\n .string()\n .optional()\n .transform((value) => {\n return isNil(value) ? process.env.NODE_ENV !== \"production\" : value.toLowerCase() === \"true\"\n })\n .meta({\n description: `Whether to enable debug mode. This will be enabled automatically when NODE_ENV is not \"production\". The value must be \"true\" (case-insensitive) to enable debug mode, otherwise it will be treated as false.`,\n }),\n NODE_ENV: z.enum([\"development\", \"production\", \"test\"]).default(\"development\").meta({\n description: `The environment mode. This will be \"development\" by default.`,\n }),\n})\n\nlet env: z.infer<typeof EnvSchema> | undefined\n\nexport function getEnv() {\n if (isNil(env)) {\n const result = EnvSchema.safeParse(process.env)\n\n if (!result.success) {\n console.error(z.prettifyError(result.error))\n process.exit(1)\n }\n\n env = result.data\n }\n\n return env\n}\n","import { readFileSync } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\nimport { z } from \"zod\"\n\nconst ConfigSchema = z.object({\n auth: z\n .object({\n endpoint: z.url().optional(),\n access_token: z.string().optional(),\n })\n .optional(),\n hub: z\n .object({\n endpoint: z.url().optional(),\n })\n .optional(),\n})\n\nexport type Config = z.infer<typeof ConfigSchema>\n\nconst CONFIG_PATH = join(homedir(), \".choiceform\", \"atomemo.json\")\n\n/**\n * Reads and parses the atomemo.json config file from the user's home directory.\n *\n * @returns The parsed config object, or undefined if the file doesn't exist.\n * @throws If the file exists but contains invalid JSON or doesn't match the schema.\n */\nexport function readConfig(): Config | undefined {\n try {\n const content = readFileSync(CONFIG_PATH, \"utf-8\")\n const json = JSON.parse(content)\n return ConfigSchema.parse(json)\n } catch (error) {\n if (error && typeof error === \"object\" && \"code\" in error && error.code === \"ENOENT\") {\n // File doesn't exist\n return undefined\n }\n // Re-throw other errors (parse errors, schema validation errors, etc.)\n throw error\n }\n}\n","import { z } from \"zod\"\nimport { readConfig } from \"./config\"\n\nconst SessionSchema = z.object({\n id: z.string().optional(),\n expiresAt: z.string(),\n token: z.string(),\n createdAt: z.string(),\n updatedAt: z.string(),\n ipAddress: z.string().optional(),\n userAgent: z.string().optional(),\n userId: z.string(),\n impersonatedBy: z.string().nullish(),\n activeOrganizationId: z.string().nullish(),\n activeTeamId: z.string().nullish(),\n})\n\nconst UserSchema = z.object({\n id: z.string().optional(),\n name: z.string(),\n email: z.string(),\n emailVerified: z.boolean().optional(),\n image: z.string().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n role: z.string().optional(),\n banned: z.boolean().optional(),\n banReason: z.string().nullish(),\n banExpires: z.string().nullish(),\n lastLoginMethod: z.string().optional(),\n inherentOrganizationId: z.string(),\n inherentTeamId: z.string(),\n metadata: z.unknown().optional(),\n stripeCustomerId: z.string().nullish(),\n})\n\nconst GetSessionResponseSchema = z.object({\n session: SessionSchema,\n user: UserSchema,\n})\n\nexport type Session = z.infer<typeof SessionSchema>\nexport type User = z.infer<typeof UserSchema>\nexport type GetSessionResponse = z.infer<typeof GetSessionResponseSchema>\n\nconst DEFAULT_ENDPOINT = \"https://oneauth.choiceform.io\"\n\n/**\n * Fetches the current session and user information from the OneAuth API.\n *\n * @returns The session and user information.\n * @throws If the config file is missing, access token is missing, or the API request fails.\n */\nexport async function getSession(): Promise<GetSessionResponse> {\n const config = readConfig()\n\n if (!config?.auth?.access_token) {\n throw new Error(\n \"Access token not found. Please ensure ~/.choiceform/atomemo.json contains auth.access_token\",\n )\n }\n\n const endpoint = config.auth.endpoint || DEFAULT_ENDPOINT\n const url = new URL(\"/v1/auth/get-session\", endpoint).toString()\n\n const response = await fetch(url, {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${config.auth.access_token}`,\n \"Content-Type\": \"application/json\",\n },\n })\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"Unknown error\")\n throw new Error(\n `OneAuth API request failed: ${response.status} ${response.statusText}. ${errorText}`,\n )\n }\n\n const data = await response.json()\n return GetSessionResponseSchema.parse(data)\n}\n","import { isFunction } from \"es-toolkit/predicate\"\nimport type { JsonValue } from \"type-fest\"\n\n/**\n * Serializes a Feature object by removing any function-type properties.\n *\n * @param feature - The Feature object to serialize.\n * @returns An object with only non-function properties of the Feature.\n */\nexport const serializeFeature = (feature: Record<string, unknown>) => {\n return Object.keys(feature).reduce<Record<string, JsonValue>>((finale, key) => {\n const value = feature[key]\n\n if (isFunction(value)) {\n return finale\n }\n\n return Object.assign(finale, { [key]: value as JsonValue })\n }, {})\n}\n","import type {\n CredentialDefinitionSchema,\n ModelDefinitionSchema,\n ToolDefinitionSchema,\n} from \"@choiceopen/atomemo-plugin-schema/schemas\"\nimport type {\n DataSourceDefinition,\n PluginDefinition,\n} from \"@choiceopen/atomemo-plugin-schema/types\"\nimport { assert } from \"es-toolkit\"\nimport type { JsonValue, Simplify } from \"type-fest\"\nimport type { z } from \"zod\"\nimport type { TransporterOptions } from \"./transporter\"\nimport { serializeFeature } from \"./utils/serialize-feature\"\n\ntype PluginRegistry = Simplify<\n Omit<PluginDefinition<string[], TransporterOptions>, \"transporterOptions\">\n>\n\ntype CredentialDefinition = z.infer<typeof CredentialDefinitionSchema>\ntype ModelDefinition = z.infer<typeof ModelDefinitionSchema>\ntype ToolDefinition = z.infer<typeof ToolDefinitionSchema>\ntype Feature = CredentialDefinition | DataSourceDefinition | ModelDefinition | ToolDefinition\n\ninterface RegistryStore {\n plugin: PluginRegistry\n credential: Map<CredentialDefinition[\"name\"], CredentialDefinition>\n // data_source: Map<DataSourceDefinition[\"name\"], DataSourceDefinition>\n model: Map<ModelDefinition[\"name\"], ModelDefinition>\n tool: Map<ToolDefinition[\"name\"], ToolDefinition>\n}\n\nexport type FeatureType = keyof Pick<RegistryStore, \"credential\" | \"model\" | \"tool\">\n\nexport interface Registry {\n /**\n * The plugin metadata and definitions, excluding transporter options.\n */\n plugin: PluginRegistry\n\n /**\n * Registers a feature (credential, data source, model, or tool) into the registry.\n *\n * @param type - The type of the feature to register (\"credential\", \"data_source\", \"model\", or \"tool\").\n * @param feature - The feature definition to register.\n */\n register: {\n (type: \"credential\", feature: CredentialDefinition): void\n // (type: \"data_source\", feature: DataSourceDefinition): void\n (type: \"model\", feature: ModelDefinition): void\n (type: \"tool\", feature: ToolDefinition): void\n }\n\n /**\n * Resolves and retrieves a registered feature (credential, data source, model, or tool) by its type and name.\n *\n * @param type - The type of the feature (\"credential\", \"data_source\", \"model\", or \"tool\").\n * @param featureName - The name of the feature to resolve.\n * @returns The resolved feature definition.\n * @throws If the feature is not registered.\n */\n resolve: {\n (type: \"credential\", featureName: string): CredentialDefinition\n // (type: \"data_source\", featureName: string): DataSourceDefinition\n (type: \"model\", featureName: string): ModelDefinition\n (type: \"tool\", featureName: string): ToolDefinition\n }\n\n /**\n * Serializes the registry into a JSON-like object.\n *\n * @returns The serialized registry.\n */\n serialize: () => {\n plugin: PluginRegistry & Record<`${FeatureType}s`, Array<Record<string, JsonValue>>>\n }\n}\n\nexport function createRegistry(plugin: PluginRegistry): Registry {\n const store: RegistryStore = {\n plugin,\n credential: new Map(),\n // data_source: new Map(),\n model: new Map(),\n tool: new Map(),\n }\n\n function register(type: \"credential\", feature: CredentialDefinition): void\n // function register(type: \"data_source\", feature: DataSourceDefinition): void\n function register(type: \"model\", feature: ModelDefinition): void\n function register(type: \"tool\", feature: ToolDefinition): void\n // biome-ignore lint/suspicious/noExplicitAny: any is used to avoid type errors\n function register(type: FeatureType, feature: any): void {\n store[type].set(feature.name, feature)\n }\n\n function resolve(type: \"credential\", featureName: string): CredentialDefinition\n // function resolve(type: \"data_source\", featureName: string): DataSourceDefinition\n function resolve(type: \"model\", featureName: string): ModelDefinition\n function resolve(type: \"tool\", featureName: string): ToolDefinition\n function resolve(type: FeatureType, featureName: string): Feature {\n const feature = store[type].get(featureName)\n assert(feature, `Feature \"${featureName}\" not registered`)\n return feature\n }\n\n return {\n plugin: store.plugin,\n register,\n resolve,\n serialize: () => {\n assert(store.plugin, \"Plugin is not registered\")\n\n return {\n plugin: Object.assign(store.plugin, {\n credentials: Array.from(store.credential.values()).map(serializeFeature),\n // data_sources: Array.from(store.data_source.values()).map(serializeFeature),\n models: Array.from(store.model.values()).map(serializeFeature),\n tools: Array.from(store.tool.values()).map(serializeFeature),\n }),\n }\n },\n }\n}\n","import chalk from \"chalk\"\nimport { type Channel, Socket, type SocketConnectOption } from \"phoenix\"\nimport { getEnv } from \"./env\"\n\nexport interface TransporterOptions\n extends Partial<Pick<SocketConnectOption, \"heartbeatIntervalMs\">> {\n onOpen?: Parameters<Socket[\"onOpen\"]>[0]\n onClose?: Parameters<Socket[\"onClose\"]>[0]\n onError?: Parameters<Socket[\"onError\"]>[0]\n onMessage?: Parameters<Socket[\"onMessage\"]>[0]\n}\n\n/**\n * Creates a network transporter for communication with the Hub Server.\n *\n * @param options - The options for the transporter.\n * @returns An object with a connect method to establish the connection and a dispose method to close it.\n */\nexport function createTransporter(options: TransporterOptions = {}) {\n const env = getEnv()\n\n const url = `${env.HUB_WS_URL}/${env.HUB_MODE}_socket`\n const socket = new Socket(url, {\n debug: env.DEBUG,\n heartbeatIntervalMs: options.heartbeatIntervalMs ?? 30 * 1000,\n logger(kind, message: unknown, data) {\n const timestamp = chalk.bgGrey(` ${new Date().toLocaleString()} `)\n const coloredKind = chalk.underline.bold.yellow(kind.toUpperCase())\n const coloredMessage =\n message instanceof Object && \"message\" in message\n ? chalk.italic.red(message.message)\n : chalk.italic.dim(message)\n const inspection = data ? Bun.inspect(data, { colors: true }) : \"\"\n console.debug(`${timestamp} ${coloredKind} ${coloredMessage}`, inspection)\n },\n params: Bun.env.NODE_ENV !== \"production\" ? { api_key: env.HUB_DEBUG_API_KEY } : undefined,\n })\n\n socket.onOpen(() => {\n options.onOpen?.()\n })\n\n socket.onClose((event) => {\n options.onClose?.(event)\n })\n\n socket.onError((error, transport, establishedConnections) => {\n if (error instanceof ErrorEvent && error.message.includes(\"failed: Expected 101 status code\")) {\n console.error(\"Error: Can't connect to the Plugin Hub server.\\n\")\n\n if (Bun.env.NODE_ENV !== \"production\") {\n console.error(\"This is usually because the Debug API Key is missing or has expired.\\n\")\n console.error(\"Run `atomemo plugin refresh-key` to get a new key.\\n\")\n }\n\n process.exit(1)\n }\n options.onError?.(error, transport, establishedConnections)\n })\n\n socket.onMessage((message) => {\n options.onMessage?.(message)\n })\n\n socket.connect()\n\n return {\n /**\n * Connects to the specified channel and returns a channel object and a dispose function.\n *\n * @returns An object with a channel property and a dispose function.\n */\n connect: (channelName: string) => {\n return new Promise<{ channel: Channel; dispose: () => void }>((resolve, reject) => {\n const channel = socket.channel(channelName, {})\n\n channel\n .join()\n .receive(\"ok\", (response) => {\n socket.log(\"channel:joined\", `Joined ${channelName} successfully`, response)\n\n resolve({\n channel,\n dispose: () => {\n channel.leave()\n socket.disconnect()\n process.exit(0)\n },\n })\n })\n .receive(\"error\", (response) => {\n socket.log(\"channel:error\", `Failed to join ${channelName}`, response)\n\n reject(new Error(`Failed to join ${channelName}: ${response.reason}`))\n })\n .receive(\"timeout\", (response) => {\n socket.log(\"channel:timeout\", `Timeout while joining ${channelName}`, response)\n reject(new Error(`Timeout while joining ${channelName}`))\n })\n })\n },\n }\n}\n","import {\n CredentialDefinitionSchema,\n ModelDefinitionSchema,\n ToolDefinitionSchema,\n} from \"@choiceopen/atomemo-plugin-schema/schemas\"\nimport type { PluginDefinition } from \"@choiceopen/atomemo-plugin-schema/types\"\nimport { isNil } from \"es-toolkit\"\nimport { z } from \"zod\"\nimport { getEnv } from \"./env\"\nimport { getSession } from \"./oneauth\"\nimport { createRegistry } from \"./registry\"\nimport { createTransporter, type TransporterOptions } from \"./transporter\"\n\nconst CredentialAuthenticateMessage = z.object({\n request_id: z.string(),\n credential: z.record(z.string(), z.any()),\n credential_name: z.string(),\n extra: z.record(z.string(), z.any()),\n})\n\nconst ToolInvokeMessage = z.object({\n request_id: z.string(),\n tool_name: z.string(),\n parameters: z.record(z.string(), z.any()),\n credentials: z.record(z.string(), z.any()).optional(),\n})\n\ntype CredentialDefinition = z.infer<typeof CredentialDefinitionSchema>\ntype ToolDefinition = z.infer<typeof ToolDefinitionSchema>\ntype ModelDefinition = z.infer<typeof ModelDefinitionSchema>\n\n/**\n * Creates a new plugin instance with the specified options.\n *\n * @param options - The options for configuring the plugin instance.\n * @returns An object containing methods to define providers and run the plugin process.\n */\nexport async function createPlugin<Locales extends string[]>(\n options: PluginDefinition<Locales, TransporterOptions>,\n) {\n // Validate organization ID before creating registry\n const env = getEnv()\n const isDebugMode = env.HUB_MODE === \"debug\"\n\n if (isDebugMode && !env.HUB_ORGANIZATION_ID) {\n console.error(\"DEBUG API Key is invalid. Please run `atomemo plugin refresh-key`\")\n process.exit(1)\n }\n\n let user: { name: string; email: string; inherentOrganizationId?: string }\n\n if (isDebugMode) {\n // Fetch user session and validate organization\n try {\n const sessionData = await getSession()\n user = sessionData.user\n\n if (user.inherentOrganizationId !== env.HUB_ORGANIZATION_ID) {\n console.info(\n \"Atomemo does not currently support developing plugins for other organizations. Please wait for official support.\",\n )\n process.exit(0)\n }\n } catch (error) {\n console.error(\"Failed to fetch session:\", error instanceof Error ? error.message : error)\n process.exit(1)\n }\n } else {\n const definition = z\n .looseObject({ author: z.string(), email: z.string() })\n .parse(await Bun.file(\"definition.json\").json())\n user = { name: definition.author, email: definition.email }\n }\n\n // Merge user info into plugin options\n const { transporterOptions, version = process.env.npm_package_version, ...plugin } = options\n const pluginDefinition = Object.assign(plugin, {\n author: user.name,\n email: user.email,\n organization_id: env.HUB_ORGANIZATION_ID,\n version,\n })\n\n const registry = createRegistry(pluginDefinition)\n const transporter = createTransporter(transporterOptions)\n\n return {\n /**\n * Adds a new credential definition in the registry.\n *\n * @param credential - The credential to add.\n * @throws Error if the credential is not registered.\n */\n addCredential: (credential: CredentialDefinition) => {\n const definition = CredentialDefinitionSchema.parse(credential)\n registry.register(\"credential\", definition)\n },\n\n /**\n * Adds a new tool definition in the registry.\n *\n * @param tool - The tool to add.\n * @throws Error if the tool is not registered.\n */\n addTool: (tool: ToolDefinition) => {\n const definition = ToolDefinitionSchema.parse(tool)\n registry.register(\"tool\", definition)\n },\n\n /**\n * Adds a new model definition in the registry.\n *\n * @param model - The model to add.\n * @throws Error if the model is not registered.\n */\n addModel: (model: ModelDefinition) => {\n const definition = ModelDefinitionSchema.parse(model)\n registry.register(\"model\", definition)\n },\n\n /**\n * Starts the plugin's main process. This establishes the transporter connection and\n * sets up signal handlers for graceful shutdown on SIGINT and SIGTERM.\n */\n run: async () => {\n const topic = isDebugMode\n ? `debug_plugin:${registry.plugin.name}`\n : `release_plugin:${pluginDefinition.organization_id}__${registry.plugin.name}__${env.HUB_MODE}__${pluginDefinition.version}`\n const { channel, dispose } = await transporter.connect(topic)\n\n if (isDebugMode) {\n const definition = registry.serialize().plugin\n channel.push(\"register_plugin\", definition)\n await Bun.write(\"definition.json\", JSON.stringify(definition, null, 2))\n }\n\n channel.on(\"credential_auth_spec\", async (message) => {\n const request_id = message.request_id\n\n try {\n const event = CredentialAuthenticateMessage.parse(message)\n const definition = registry.resolve(\"credential\", event.credential_name)\n if (isNil(definition.authenticate)) {\n throw new Error(\"Credential authenticate method is not implemented\")\n }\n\n const AuthenticateMethodWrapper = CredentialDefinitionSchema.shape.authenticate.unwrap()\n const authenticate = AuthenticateMethodWrapper.implementAsync(definition.authenticate)\n\n const { credential, extra } = event\n const data = await authenticate({ args: { credential, extra } })\n\n channel.push(\"credential_auth_spec_response\", { request_id, data })\n } catch (error) {\n if (error instanceof Error) {\n channel.push(\"credential_auth_spec_error\", { request_id, ...error })\n } else {\n channel.push(\"credential_auth_spec_error\", {\n request_id,\n message: \"Unexpected Error\",\n })\n }\n }\n })\n\n channel.on(\"invoke_tool\", async (message) => {\n const request_id = message.request_id\n\n try {\n const event = ToolInvokeMessage.parse(message)\n const { credentials, parameters } = event\n const definition = registry.resolve(\"tool\", event.tool_name)\n\n const InvokeMethodWrapper = ToolDefinitionSchema.shape.invoke\n const invoke = InvokeMethodWrapper.implementAsync(definition.invoke)\n\n const data = await invoke({ args: { credentials, parameters } })\n channel.push(\"invoke_tool_response\", { request_id, data })\n } catch (error) {\n if (error instanceof Error) {\n channel.push(\"invoke_tool_error\", { request_id, ...error })\n } else {\n channel.push(\"invoke_tool_error\", { request_id, message: \"Unexpected Error\" })\n }\n }\n })\n\n void [\"SIGINT\", \"SIGTERM\"].forEach((signal) => {\n void process.on(signal, dispose)\n })\n },\n }\n}\n"],"x_google_ignoreList":[0,1,2,3],"mappings":";;;;;;;;;;AAAA,SAAS,WAAW,OAAO;AACvB,QAAO,OAAO,UAAU;;;;;ACD5B,SAAS,MAAM,GAAG;AACd,QAAO,KAAK;;;;;ACDhB,SAAS,SAAS,OAAO;AACrB,QAAO,OAAO,UAAU;;;;;ACD5B,SAAS,UAAU,WAAW,SAAS;AACnC,KAAI,UACA;AAEJ,KAAI,OAAO,YAAY,SACnB,OAAM,IAAI,MAAM,QAAQ;AAE5B,OAAM;;;;;ACWV,MAAM,YAAYA,IAAE,OAAO;CACzB,UAAUA,IAAE,KAAK,CAAC,SAAS,UAAU,CAAC,CAAC,QAAQ,QAAQ,CAAC,KAAK,EAC3D,aAAa,iEACd,CAAC;CACF,YAAYA,IAAE,IAAI;EAChB,UAAU;EACV,OAAO;EACR,CAAC;CACF,mBAAmBA,IAChB,OAAO,EACN,OAAO,uCACR,CAAC,CACD,UAAU,CACV,QAAQ,UAAU;AACjB,SAAO,IAAI,IAAI,aAAa,gBAAiB,SAAS,MAAM,IAAI,MAAM,SAAS;GAC/E,CACD,KAAK,EAAE,aAAa,kCAAkC,CAAC;CAC1D,qBAAqBA,IAClB,QAAQ,CACR,UAAU,CACV,KAAK,EAAE,aAAa,uCAAuC,CAAC;CAC/D,OAAOA,IACJ,QAAQ,CACR,UAAU,CACV,WAAW,UAAU;AACpB,SAAO,MAAM,MAAM,GAAG,QAAQ,IAAI,aAAa,eAAe,MAAM,aAAa,KAAK;GACtF,CACD,KAAK,EACJ,aAAa,gNACd,CAAC;CACJ,UAAUA,IAAE,KAAK;EAAC;EAAe;EAAc;EAAO,CAAC,CAAC,QAAQ,cAAc,CAAC,KAAK,EAClF,aAAa,gEACd,CAAC;CACH,CAAC;AAEF,IAAI;AAEJ,SAAgB,SAAS;AACvB,KAAI,MAAM,IAAI,EAAE;EACd,MAAM,SAAS,UAAU,UAAU,QAAQ,IAAI;AAE/C,MAAI,CAAC,OAAO,SAAS;AACnB,WAAQ,MAAMA,IAAE,cAAc,OAAO,MAAM,CAAC;AAC5C,WAAQ,KAAK,EAAE;;AAGjB,QAAM,OAAO;;AAGf,QAAO;;;;;AC9DT,MAAM,eAAe,EAAE,OAAO;CAC5B,MAAM,EACH,OAAO;EACN,UAAU,EAAE,KAAK,CAAC,UAAU;EAC5B,cAAc,EAAE,QAAQ,CAAC,UAAU;EACpC,CAAC,CACD,UAAU;CACb,KAAK,EACF,OAAO,EACN,UAAU,EAAE,KAAK,CAAC,UAAU,EAC7B,CAAC,CACD,UAAU;CACd,CAAC;AAIF,MAAM,cAAc,KAAK,SAAS,EAAE,eAAe,eAAe;;;;;;;AAQlE,SAAgB,aAAiC;AAC/C,KAAI;EACF,MAAM,UAAU,aAAa,aAAa,QAAQ;EAClD,MAAM,OAAO,KAAK,MAAM,QAAQ;AAChC,SAAO,aAAa,MAAM,KAAK;UACxB,OAAO;AACd,MAAI,SAAS,OAAO,UAAU,YAAY,UAAU,SAAS,MAAM,SAAS,SAE1E;AAGF,QAAM;;;;;;ACrCV,MAAM,gBAAgB,EAAE,OAAO;CAC7B,IAAI,EAAE,QAAQ,CAAC,UAAU;CACzB,WAAW,EAAE,QAAQ;CACrB,OAAO,EAAE,QAAQ;CACjB,WAAW,EAAE,QAAQ;CACrB,WAAW,EAAE,QAAQ;CACrB,WAAW,EAAE,QAAQ,CAAC,UAAU;CAChC,WAAW,EAAE,QAAQ,CAAC,UAAU;CAChC,QAAQ,EAAE,QAAQ;CAClB,gBAAgB,EAAE,QAAQ,CAAC,SAAS;CACpC,sBAAsB,EAAE,QAAQ,CAAC,SAAS;CAC1C,cAAc,EAAE,QAAQ,CAAC,SAAS;CACnC,CAAC;AAEF,MAAM,aAAa,EAAE,OAAO;CAC1B,IAAI,EAAE,QAAQ,CAAC,UAAU;CACzB,MAAM,EAAE,QAAQ;CAChB,OAAO,EAAE,QAAQ;CACjB,eAAe,EAAE,SAAS,CAAC,UAAU;CACrC,OAAO,EAAE,QAAQ,CAAC,UAAU;CAC5B,WAAW,EAAE,QAAQ;CACrB,WAAW,EAAE,QAAQ;CACrB,MAAM,EAAE,QAAQ,CAAC,UAAU;CAC3B,QAAQ,EAAE,SAAS,CAAC,UAAU;CAC9B,WAAW,EAAE,QAAQ,CAAC,SAAS;CAC/B,YAAY,EAAE,QAAQ,CAAC,SAAS;CAChC,iBAAiB,EAAE,QAAQ,CAAC,UAAU;CACtC,wBAAwB,EAAE,QAAQ;CAClC,gBAAgB,EAAE,QAAQ;CAC1B,UAAU,EAAE,SAAS,CAAC,UAAU;CAChC,kBAAkB,EAAE,QAAQ,CAAC,SAAS;CACvC,CAAC;AAEF,MAAM,2BAA2B,EAAE,OAAO;CACxC,SAAS;CACT,MAAM;CACP,CAAC;AAMF,MAAM,mBAAmB;;;;;;;AAQzB,eAAsB,aAA0C;CAC9D,MAAM,SAAS,YAAY;AAE3B,KAAI,CAAC,QAAQ,MAAM,aACjB,OAAM,IAAI,MACR,8FACD;CAGH,MAAM,WAAW,OAAO,KAAK,YAAY;CACzC,MAAM,MAAM,IAAI,IAAI,wBAAwB,SAAS,CAAC,UAAU;CAEhE,MAAM,WAAW,MAAM,MAAM,KAAK;EAChC,QAAQ;EACR,SAAS;GACP,eAAe,UAAU,OAAO,KAAK;GACrC,gBAAgB;GACjB;EACF,CAAC;AAEF,KAAI,CAAC,SAAS,IAAI;EAChB,MAAM,YAAY,MAAM,SAAS,MAAM,CAAC,YAAY,gBAAgB;AACpE,QAAM,IAAI,MACR,+BAA+B,SAAS,OAAO,GAAG,SAAS,WAAW,IAAI,YAC3E;;CAGH,MAAM,OAAO,MAAM,SAAS,MAAM;AAClC,QAAO,yBAAyB,MAAM,KAAK;;;;;;;;;;;ACxE7C,MAAa,oBAAoB,YAAqC;AACpE,QAAO,OAAO,KAAK,QAAQ,CAAC,QAAmC,QAAQ,QAAQ;EAC7E,MAAM,QAAQ,QAAQ;AAEtB,MAAI,WAAW,MAAM,CACnB,QAAO;AAGT,SAAO,OAAO,OAAO,QAAQ,GAAG,MAAM,OAAoB,CAAC;IAC1D,EAAE,CAAC;;;;;AC4DR,SAAgB,eAAe,QAAkC;CAC/D,MAAM,QAAuB;EAC3B;EACA,4BAAY,IAAI,KAAK;EAErB,uBAAO,IAAI,KAAK;EAChB,sBAAM,IAAI,KAAK;EAChB;CAOD,SAAS,SAAS,MAAmB,SAAoB;AACvD,QAAM,MAAM,IAAI,QAAQ,MAAM,QAAQ;;CAOxC,SAAS,QAAQ,MAAmB,aAA8B;EAChE,MAAM,UAAU,MAAM,MAAM,IAAI,YAAY;AAC5C,YAAO,SAAS,YAAY,YAAY,kBAAkB;AAC1D,SAAO;;AAGT,QAAO;EACL,QAAQ,MAAM;EACd;EACA;EACA,iBAAiB;AACf,aAAO,MAAM,QAAQ,2BAA2B;AAEhD,UAAO,EACL,QAAQ,OAAO,OAAO,MAAM,QAAQ;IAClC,aAAa,MAAM,KAAK,MAAM,WAAW,QAAQ,CAAC,CAAC,IAAI,iBAAiB;IAExE,QAAQ,MAAM,KAAK,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,iBAAiB;IAC9D,OAAO,MAAM,KAAK,MAAM,KAAK,QAAQ,CAAC,CAAC,IAAI,iBAAiB;IAC7D,CAAC,EACH;;EAEJ;;;;;;;;;;;ACxGH,SAAgB,kBAAkB,UAA8B,EAAE,EAAE;CAClE,MAAM,MAAM,QAAQ;CAGpB,MAAM,SAAS,IAAI,OADP,GAAG,IAAI,WAAW,GAAG,IAAI,SAAS,UACf;EAC7B,OAAO,IAAI;EACX,qBAAqB,QAAQ,uBAAuB,KAAK;EACzD,OAAO,MAAM,SAAkB,MAAM;GACnC,MAAM,YAAY,MAAM,OAAO,qBAAI,IAAI,MAAM,EAAC,gBAAgB,CAAC,GAAG;GAClE,MAAM,cAAc,MAAM,UAAU,KAAK,OAAO,KAAK,aAAa,CAAC;GACnE,MAAM,iBACJ,mBAAmB,UAAU,aAAa,UACtC,MAAM,OAAO,IAAI,QAAQ,QAAQ,GACjC,MAAM,OAAO,IAAI,QAAQ;GAC/B,MAAM,aAAa,OAAO,IAAI,QAAQ,MAAM,EAAE,QAAQ,MAAM,CAAC,GAAG;AAChE,WAAQ,MAAM,GAAG,UAAU,GAAG,YAAY,GAAG,kBAAkB,WAAW;;EAE5E,QAAQ,IAAI,IAAI,aAAa,eAAe,EAAE,SAAS,IAAI,mBAAmB,GAAG;EAClF,CAAC;AAEF,QAAO,aAAa;AAClB,UAAQ,UAAU;GAClB;AAEF,QAAO,SAAS,UAAU;AACxB,UAAQ,UAAU,MAAM;GACxB;AAEF,QAAO,SAAS,OAAO,WAAW,2BAA2B;AAC3D,MAAI,iBAAiB,cAAc,MAAM,QAAQ,SAAS,mCAAmC,EAAE;AAC7F,WAAQ,MAAM,mDAAmD;AAEjE,OAAI,IAAI,IAAI,aAAa,cAAc;AACrC,YAAQ,MAAM,yEAAyE;AACvF,YAAQ,MAAM,uDAAuD;;AAGvE,WAAQ,KAAK,EAAE;;AAEjB,UAAQ,UAAU,OAAO,WAAW,uBAAuB;GAC3D;AAEF,QAAO,WAAW,YAAY;AAC5B,UAAQ,YAAY,QAAQ;GAC5B;AAEF,QAAO,SAAS;AAEhB,QAAO,EAML,UAAU,gBAAwB;AAChC,SAAO,IAAI,SAAoD,SAAS,WAAW;GACjF,MAAM,UAAU,OAAO,QAAQ,aAAa,EAAE,CAAC;AAE/C,WACG,MAAM,CACN,QAAQ,OAAO,aAAa;AAC3B,WAAO,IAAI,kBAAkB,UAAU,YAAY,gBAAgB,SAAS;AAE5E,YAAQ;KACN;KACA,eAAe;AACb,cAAQ,OAAO;AACf,aAAO,YAAY;AACnB,cAAQ,KAAK,EAAE;;KAElB,CAAC;KACF,CACD,QAAQ,UAAU,aAAa;AAC9B,WAAO,IAAI,iBAAiB,kBAAkB,eAAe,SAAS;AAEtE,2BAAO,IAAI,MAAM,kBAAkB,YAAY,IAAI,SAAS,SAAS,CAAC;KACtE,CACD,QAAQ,YAAY,aAAa;AAChC,WAAO,IAAI,mBAAmB,yBAAyB,eAAe,SAAS;AAC/E,2BAAO,IAAI,MAAM,yBAAyB,cAAc,CAAC;KACzD;IACJ;IAEL;;;;;ACxFH,MAAM,gCAAgC,EAAE,OAAO;CAC7C,YAAY,EAAE,QAAQ;CACtB,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,KAAK,CAAC;CACzC,iBAAiB,EAAE,QAAQ;CAC3B,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,KAAK,CAAC;CACrC,CAAC;AAEF,MAAM,oBAAoB,EAAE,OAAO;CACjC,YAAY,EAAE,QAAQ;CACtB,WAAW,EAAE,QAAQ;CACrB,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,KAAK,CAAC;CACzC,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC,UAAU;CACtD,CAAC;;;;;;;AAYF,eAAsB,aACpB,SACA;CAEA,MAAM,MAAM,QAAQ;CACpB,MAAM,cAAc,IAAI,aAAa;AAErC,KAAI,eAAe,CAAC,IAAI,qBAAqB;AAC3C,UAAQ,MAAM,oEAAoE;AAClF,UAAQ,KAAK,EAAE;;CAGjB,IAAI;AAEJ,KAAI,YAEF,KAAI;AAEF,UADoB,MAAM,YAAY,EACnB;AAEnB,MAAI,KAAK,2BAA2B,IAAI,qBAAqB;AAC3D,WAAQ,KACN,mHACD;AACD,WAAQ,KAAK,EAAE;;UAEV,OAAO;AACd,UAAQ,MAAM,4BAA4B,iBAAiB,QAAQ,MAAM,UAAU,MAAM;AACzF,UAAQ,KAAK,EAAE;;MAEZ;EACL,MAAM,aAAa,EAChB,YAAY;GAAE,QAAQ,EAAE,QAAQ;GAAE,OAAO,EAAE,QAAQ;GAAE,CAAC,CACtD,MAAM,MAAM,IAAI,KAAK,kBAAkB,CAAC,MAAM,CAAC;AAClD,SAAO;GAAE,MAAM,WAAW;GAAQ,OAAO,WAAW;GAAO;;CAI7D,MAAM,EAAE,oBAAoB,UAAU,QAAQ,IAAI,qBAAqB,GAAG,WAAW;CACrF,MAAM,mBAAmB,OAAO,OAAO,QAAQ;EAC7C,QAAQ,KAAK;EACb,OAAO,KAAK;EACZ,iBAAiB,IAAI;EACrB;EACD,CAAC;CAEF,MAAM,WAAW,eAAe,iBAAiB;CACjD,MAAM,cAAc,kBAAkB,mBAAmB;AAEzD,QAAO;EAOL,gBAAgB,eAAqC;GACnD,MAAM,aAAa,2BAA2B,MAAM,WAAW;AAC/D,YAAS,SAAS,cAAc,WAAW;;EAS7C,UAAU,SAAyB;GACjC,MAAM,aAAa,qBAAqB,MAAM,KAAK;AACnD,YAAS,SAAS,QAAQ,WAAW;;EASvC,WAAW,UAA2B;GACpC,MAAM,aAAa,sBAAsB,MAAM,MAAM;AACrD,YAAS,SAAS,SAAS,WAAW;;EAOxC,KAAK,YAAY;GACf,MAAM,QAAQ,cACV,gBAAgB,SAAS,OAAO,SAChC,kBAAkB,iBAAiB,gBAAgB,IAAI,SAAS,OAAO,KAAK,IAAI,IAAI,SAAS,IAAI,iBAAiB;GACtH,MAAM,EAAE,SAAS,YAAY,MAAM,YAAY,QAAQ,MAAM;AAE7D,OAAI,aAAa;IACf,MAAM,aAAa,SAAS,WAAW,CAAC;AACxC,YAAQ,KAAK,mBAAmB,WAAW;AAC3C,UAAM,IAAI,MAAM,mBAAmB,KAAK,UAAU,YAAY,MAAM,EAAE,CAAC;;AAGzE,WAAQ,GAAG,wBAAwB,OAAO,YAAY;IACpD,MAAM,aAAa,QAAQ;AAE3B,QAAI;KACF,MAAM,QAAQ,8BAA8B,MAAM,QAAQ;KAC1D,MAAM,aAAa,SAAS,QAAQ,cAAc,MAAM,gBAAgB;AACxE,SAAI,MAAM,WAAW,aAAa,CAChC,OAAM,IAAI,MAAM,oDAAoD;KAItE,MAAM,eAD4B,2BAA2B,MAAM,aAAa,QAAQ,CACzC,eAAe,WAAW,aAAa;KAEtF,MAAM,EAAE,YAAY,UAAU;KAC9B,MAAM,OAAO,MAAM,aAAa,EAAE,MAAM;MAAE;MAAY;MAAO,EAAE,CAAC;AAEhE,aAAQ,KAAK,iCAAiC;MAAE;MAAY;MAAM,CAAC;aAC5D,OAAO;AACd,SAAI,iBAAiB,MACnB,SAAQ,KAAK,8BAA8B;MAAE;MAAY,GAAG;MAAO,CAAC;SAEpE,SAAQ,KAAK,8BAA8B;MACzC;MACA,SAAS;MACV,CAAC;;KAGN;AAEF,WAAQ,GAAG,eAAe,OAAO,YAAY;IAC3C,MAAM,aAAa,QAAQ;AAE3B,QAAI;KACF,MAAM,QAAQ,kBAAkB,MAAM,QAAQ;KAC9C,MAAM,EAAE,aAAa,eAAe;KACpC,MAAM,aAAa,SAAS,QAAQ,QAAQ,MAAM,UAAU;KAK5D,MAAM,OAAO,MAHe,qBAAqB,MAAM,OACpB,eAAe,WAAW,OAAO,CAE1C,EAAE,MAAM;MAAE;MAAa;MAAY,EAAE,CAAC;AAChE,aAAQ,KAAK,wBAAwB;MAAE;MAAY;MAAM,CAAC;aACnD,OAAO;AACd,SAAI,iBAAiB,MACnB,SAAQ,KAAK,qBAAqB;MAAE;MAAY,GAAG;MAAO,CAAC;SAE3D,SAAQ,KAAK,qBAAqB;MAAE;MAAY,SAAS;MAAoB,CAAC;;KAGlF;AAEF,GAAK,CAAC,UAAU,UAAU,CAAC,SAAS,WAAW;AAC7C,IAAK,QAAQ,GAAG,QAAQ,QAAQ;KAChC;;EAEL"}
1
+ {"version":3,"file":"index.mjs","names":["z","z","z"],"sources":["../node_modules/es-toolkit/dist/predicate/isFunction.mjs","../node_modules/es-toolkit/dist/predicate/isNil.mjs","../node_modules/es-toolkit/dist/predicate/isString.mjs","../node_modules/es-toolkit/dist/util/invariant.mjs","../src/context.ts","../src/env.ts","../src/hub.ts","../src/config.ts","../src/oneauth.ts","../src/utils/serialize-feature.ts","../src/registry.ts","../src/transporter.ts","../src/utils/parse-file-refs.ts","../src/utils/serialize-error.ts","../src/plugin.ts"],"sourcesContent":["function isFunction(value) {\n return typeof value === 'function';\n}\n\nexport { isFunction };\n","function isNil(x) {\n return x == null;\n}\n\nexport { isNil };\n","function isString(value) {\n return typeof value === 'string';\n}\n\nexport { isString };\n","function invariant(condition, message) {\n if (condition) {\n return;\n }\n if (typeof message === 'string') {\n throw new Error(message);\n }\n throw message;\n}\n\nexport { invariant };\n","import { FileRefSchema } from \"@choiceopen/atomemo-plugin-schema/schemas\"\nimport type { PluginContext } from \"@choiceopen/atomemo-plugin-schema/types\"\nimport type { HubCaller } from \"./hub\"\n\nfunction inferMimeType(extension: string | null | undefined) {\n const type = Bun.file(`file${extension ?? \"\"}`).type\n\n return type.split(\";\")[0] || \"application/octet-stream\"\n}\n\nexport function createPluginContext(hubCaller: HubCaller): PluginContext {\n const attachRemoteUrl: PluginContext[\"files\"][\"attachRemoteUrl\"] = async (fileRef) => {\n if (fileRef.remote_url) {\n return {\n ...fileRef,\n remote_url: fileRef.remote_url,\n }\n }\n\n const response = await hubCaller.call<{ url: string }>(\"get_file_url\", {\n res_key: fileRef.res_key,\n })\n\n return {\n ...fileRef,\n remote_url: response.url,\n }\n }\n\n const download: PluginContext[\"files\"][\"download\"] = async (fileRef) => {\n if (fileRef.source === \"mem\") return fileRef\n\n const fileRefWithRemoteUrl = await attachRemoteUrl(fileRef)\n const response = await fetch(fileRefWithRemoteUrl.remote_url)\n const content = Buffer.from(await response.arrayBuffer()).toString(\"base64\")\n\n return {\n ...fileRefWithRemoteUrl,\n content,\n }\n }\n\n const upload: PluginContext[\"files\"][\"upload\"] = async (input, options) => {\n const fileRef = FileRefSchema.parse(input)\n\n if (fileRef.source === \"oss\") {\n return fileRef\n }\n\n const content = fileRef.content ?? \"\"\n const mimeType = fileRef.mime_type || inferMimeType(fileRef.extension)\n const payload = {\n extension: fileRef.extension,\n prefixKey: options?.prefixKey,\n }\n\n const { presigned_url, res_key } = await hubCaller.call<{\n presigned_url: string\n res_key: string\n }>(\"get_upload_url\", payload)\n\n const response = await fetch(presigned_url, {\n method: \"PUT\",\n body: Buffer.from(content, \"base64\"),\n headers: {\n \"content-type\": mimeType,\n },\n })\n\n if (!response.ok) {\n throw new Error(`Failed to upload file: ${response.status} ${response.statusText}`.trim())\n }\n\n return {\n ...fileRef,\n source: \"oss\",\n content: undefined,\n size: Buffer.from(content, \"base64\").byteLength,\n res_key,\n remote_url: undefined,\n }\n }\n\n return {\n files: {\n parseFileRef(input) {\n return FileRefSchema.parse(input)\n },\n attachRemoteUrl,\n download,\n upload,\n },\n }\n}\n","import { isNil, isString } from \"es-toolkit/predicate\"\nimport z from \"zod\"\n\ndeclare module \"bun\" {\n interface Env {\n /** The Hub Server runtime mode. */\n readonly HUB_MODE: \"debug\" | \"release\"\n /** The URL of the Hub Server WebSocket. */\n readonly HUB_WS_URL: string | undefined\n /** Whether to enable debug mode. */\n readonly DEBUG: boolean\n /** The API key for the Hub Server. */\n readonly HUB_DEBUG_API_KEY: string | undefined\n }\n}\n\nexport const EnvSchema = z.object({\n HUB_MODE: z.enum([\"debug\", \"release\"]).default(\"debug\").meta({\n description: `The Hub Server runtime mode. This will be \"debug\" by default.`,\n }),\n HUB_WS_URL: z.url({\n protocol: /wss?/,\n error: \"HUB_WS_URL must be a valid WebSocket URL.\",\n }),\n HUB_DEBUG_API_KEY: z\n .string({\n error: \"HUB_DEBUG_API_KEY must be a string.\",\n })\n .optional()\n .refine((value) => {\n return Bun.env.NODE_ENV === \"production\" || (isString(value) && value.length > 0)\n })\n .meta({ description: `The API key for the Hub Server` }),\n DEBUG: z\n .string()\n .optional()\n .transform((value) => {\n return isNil(value) ? process.env.NODE_ENV !== \"production\" : value.toLowerCase() === \"true\"\n })\n .meta({\n description: `Whether to enable debug mode. This will be enabled automatically when NODE_ENV is not \"production\". The value must be \"true\" (case-insensitive) to enable debug mode, otherwise it will be treated as false.`,\n }),\n NODE_ENV: z.enum([\"development\", \"production\", \"test\"]).default(\"development\").meta({\n description: `The environment mode. This will be \"development\" by default.`,\n }),\n})\n\nlet env: z.infer<typeof EnvSchema> | undefined\n\nexport function getEnv() {\n if (isNil(env)) {\n const result = EnvSchema.safeParse(process.env)\n\n if (!result.success) {\n console.error(z.prettifyError(result.error))\n process.exit(1)\n }\n\n env = result.data\n }\n\n return env\n}\n\nexport function __resetEnvForTesting() {\n env = undefined\n}\n","import type { Channel } from \"phoenix\"\n\nexport interface HubCallerOptions {\n timeoutMs?: number\n}\n\nexport interface HubCaller {\n call<T = unknown>(event: string, data: Record<string, unknown>): Promise<T>\n dispose(): void\n}\n\nexport class HubCallError extends Error {\n readonly code: string\n\n constructor(code: string, message: string) {\n super(message)\n this.name = \"HubCallError\"\n this.code = code\n }\n}\n\nexport class HubCallTimeoutError extends Error {\n constructor(event: string, timeoutMs: number) {\n super(`Hub call \"${event}\" timed out after ${timeoutMs}ms`)\n this.name = \"HubCallTimeoutError\"\n }\n}\n\ninterface PendingCall {\n resolve: (value: unknown) => void\n reject: (reason: unknown) => void\n timer: ReturnType<typeof setTimeout>\n}\n\nexport function createHubCaller(channel: Channel, options?: HubCallerOptions): HubCaller {\n const timeoutMs = options?.timeoutMs ?? 30_000\n const pending = new Map<string, PendingCall>()\n let disposed = false\n\n function settlePending(requestId: string) {\n const entry = pending.get(requestId)\n if (!entry) return undefined\n clearTimeout(entry.timer)\n pending.delete(requestId)\n return entry\n }\n\n const responseRef = channel.on(\n \"hub_call_response\",\n (payload: { request_id: string; data: unknown }) => {\n const entry = settlePending(payload.request_id)\n if (entry) entry.resolve(payload.data)\n },\n )\n\n const errorRef = channel.on(\n \"hub_call_error\",\n (payload: { request_id: string; error: { code: string; message: string } }) => {\n const entry = settlePending(payload.request_id)\n if (entry) entry.reject(new HubCallError(payload.error.code, payload.error.message))\n },\n )\n\n return {\n call<T = unknown>(event: string, data: Record<string, unknown>): Promise<T> {\n if (disposed) return Promise.reject(new Error(\"Hub caller is disposed\"))\n\n return new Promise<T>((resolve, reject) => {\n const requestId = crypto.randomUUID()\n\n const timer = setTimeout(() => {\n pending.delete(requestId)\n reject(new HubCallTimeoutError(event, timeoutMs))\n }, timeoutMs)\n\n pending.set(requestId, {\n resolve: resolve as (value: unknown) => void,\n reject,\n timer,\n })\n\n channel\n .push(`hub_call:${event}`, {\n request_id: requestId,\n data,\n })\n .receive(\"error\", (resp: unknown) => {\n const entry = settlePending(requestId)\n if (entry)\n entry.reject(\n new HubCallError(\"PUSH_FAILED\", `Push rejected: ${JSON.stringify(resp)}`),\n )\n })\n .receive(\"timeout\", () => {\n const entry = settlePending(requestId)\n if (entry) entry.reject(new HubCallTimeoutError(event, timeoutMs))\n })\n })\n },\n\n dispose() {\n disposed = true\n\n for (const [, entry] of pending) {\n clearTimeout(entry.timer)\n entry.reject(new Error(\"Hub caller disposed\"))\n }\n pending.clear()\n\n channel.off(\"hub_call_response\", responseRef)\n channel.off(\"hub_call_error\", errorRef)\n },\n }\n}\n","import { readFileSync } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\nimport { z } from \"zod\"\n\nconst ConfigSchema = z.object({\n auth: z\n .record(\n z.enum([\"staging\", \"production\"]),\n z.object({\n endpoint: z.url().optional(),\n access_token: z.string().optional(),\n }),\n )\n .optional(),\n hub: z\n .record(\n z.enum([\"staging\", \"production\"]),\n z.object({\n endpoint: z.url().optional(),\n }),\n )\n .optional(),\n})\n\nexport type Config = z.infer<typeof ConfigSchema>\n\nconst CONFIG_PATH = join(homedir(), \".choiceform\", \"atomemo.json\")\n\n/**\n * Reads and parses the atomemo.json config file from the user's home directory.\n *\n * @returns The parsed config object, or undefined if the file doesn't exist.\n * @throws If the file exists but contains invalid JSON or doesn't match the schema.\n */\nexport function readConfig(): Config | undefined {\n try {\n const content = readFileSync(CONFIG_PATH, \"utf-8\")\n const json = JSON.parse(content)\n return ConfigSchema.parse(json)\n } catch (error) {\n if (error && typeof error === \"object\" && \"code\" in error && error.code === \"ENOENT\") {\n // File doesn't exist\n return undefined\n }\n // Re-throw other errors (parse errors, schema validation errors, etc.)\n throw error\n }\n}\n","import { z } from \"zod\"\nimport { readConfig } from \"./config\"\n\nconst SessionSchema = z.object({\n id: z.string(),\n expiresAt: z.string(),\n token: z.string(),\n createdAt: z.string(),\n updatedAt: z.string(),\n ipAddress: z.string().nullish(),\n userAgent: z.string().nullish(),\n userId: z.string(),\n impersonatedBy: z.string().nullish(),\n activeOrganizationId: z.string().nullish(),\n activeTeamId: z.string().nullish(),\n})\n\nconst UserSchema = z.object({\n id: z.string(),\n name: z.string(),\n email: z.string(),\n emailVerified: z.boolean().optional(),\n image: z.string().nullish(),\n createdAt: z.string(),\n updatedAt: z.string(),\n role: z.string(),\n banned: z.boolean().optional(),\n banReason: z.string().nullish(),\n banExpires: z.string().nullish(),\n lastLoginMethod: z.string().optional(),\n inherentOrganizationId: z.string(),\n inherentTeamId: z.string(),\n referralCode: z.string(),\n referredBy: z.string().nullish(),\n metadata: z.record(z.string(), z.any()),\n stripeCustomerId: z.string().nullish(),\n})\n\nconst GetSessionResponseSchema = z.object({\n session: SessionSchema,\n user: UserSchema,\n})\n\nexport type Session = z.infer<typeof SessionSchema>\nexport type User = z.infer<typeof UserSchema>\nexport type GetSessionResponse = z.infer<typeof GetSessionResponseSchema>\n\nconst DEFAULT_ENDPOINT = \"https://oneauth.atomemo.ai\"\n\n/**\n * Fetches the current session and user information from the OneAuth API.\n *\n * @returns The session and user information.\n * @throws If the config file is missing, access token is missing, or the API request fails.\n */\nexport async function getSession(\n deployment: \"staging\" | \"production\",\n): Promise<GetSessionResponse> {\n const config = readConfig()\n\n if (!config?.auth?.[deployment]?.access_token) {\n throw new Error(\n \"Access token not found. Please ensure ~/.choiceform/atomemo.json contains auth.access_token\",\n )\n }\n\n const endpoint = config.auth?.[deployment]?.endpoint || DEFAULT_ENDPOINT\n const url = new URL(\"/v1/auth/get-session\", endpoint).toString()\n\n const response = await fetch(url, {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${config.auth?.[deployment]?.access_token}`,\n \"Content-Type\": \"application/json\",\n },\n })\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"Unknown error\")\n throw new Error(\n `OneAuth API request failed: ${response.status} ${response.statusText}. ${errorText}`,\n )\n }\n\n const data = await response.json()\n return GetSessionResponseSchema.parse(data)\n}\n","import { isFunction } from \"es-toolkit/predicate\"\nimport type { JsonValue } from \"type-fest\"\n\n/**\n * Serializes a Feature object by removing any function-type properties.\n *\n * @param feature - The Feature object to serialize.\n * @returns An object with only non-function properties of the Feature.\n */\nexport const serializeFeature = (feature: Record<string, unknown>) => {\n return Object.keys(feature).reduce<Record<string, JsonValue>>((finale, key) => {\n const value = feature[key]\n\n if (isFunction(value)) {\n return finale\n }\n\n return Object.assign(finale, { [key]: value as JsonValue })\n }, {})\n}\n","import type {\n CredentialDefinitionSchema,\n ModelDefinitionSchema,\n ToolDefinitionSchema,\n} from \"@choiceopen/atomemo-plugin-schema/schemas\"\nimport type {\n DataSourceDefinition,\n PluginDefinition,\n} from \"@choiceopen/atomemo-plugin-schema/types\"\nimport { assert } from \"es-toolkit\"\nimport type { JsonValue, Simplify } from \"type-fest\"\nimport type { z } from \"zod\"\nimport type { TransporterOptions } from \"./transporter\"\nimport { serializeFeature } from \"./utils/serialize-feature\"\n\ntype PluginRegistry = Simplify<\n Omit<PluginDefinition<string[], TransporterOptions>, \"transporterOptions\">\n>\n\ntype CredentialDefinition = z.infer<typeof CredentialDefinitionSchema>\ntype ModelDefinition = z.infer<typeof ModelDefinitionSchema>\ntype ToolDefinition = z.infer<typeof ToolDefinitionSchema>\ntype Feature = CredentialDefinition | DataSourceDefinition | ModelDefinition | ToolDefinition\n\ninterface RegistryStore {\n plugin: PluginRegistry\n credential: Map<CredentialDefinition[\"name\"], CredentialDefinition>\n // data_source: Map<DataSourceDefinition[\"name\"], DataSourceDefinition>\n model: Map<ModelDefinition[\"name\"], ModelDefinition>\n tool: Map<ToolDefinition[\"name\"], ToolDefinition>\n}\n\nexport type FeatureType = keyof Pick<RegistryStore, \"credential\" | \"model\" | \"tool\">\n\nexport interface Registry {\n /**\n * The plugin metadata and definitions, excluding transporter options.\n */\n plugin: PluginRegistry\n\n /**\n * Registers a feature (credential, data source, model, or tool) into the registry.\n *\n * @param type - The type of the feature to register (\"credential\", \"data_source\", \"model\", or \"tool\").\n * @param feature - The feature definition to register.\n */\n register: {\n (type: \"credential\", feature: CredentialDefinition): void\n // (type: \"data_source\", feature: DataSourceDefinition): void\n (type: \"model\", feature: ModelDefinition): void\n (type: \"tool\", feature: ToolDefinition): void\n }\n\n /**\n * Resolves and retrieves a registered feature (credential, data source, model, or tool) by its type and name.\n *\n * @param type - The type of the feature (\"credential\", \"data_source\", \"model\", or \"tool\").\n * @param featureName - The name of the feature to resolve.\n * @returns The resolved feature definition.\n * @throws If the feature is not registered.\n */\n resolve: {\n (type: \"credential\", featureName: string): CredentialDefinition\n // (type: \"data_source\", featureName: string): DataSourceDefinition\n (type: \"model\", featureName: string): ModelDefinition\n (type: \"tool\", featureName: string): ToolDefinition\n }\n\n /**\n * Serializes the registry into a JSON-like object.\n *\n * @returns The serialized registry.\n */\n serialize: () => {\n plugin: PluginRegistry & Record<`${FeatureType}s`, Array<Record<string, JsonValue>>>\n }\n}\n\nexport function createRegistry(plugin: PluginRegistry): Registry {\n const store: RegistryStore = {\n plugin,\n credential: new Map(),\n // data_source: new Map(),\n model: new Map(),\n tool: new Map(),\n }\n\n function register(type: \"credential\", feature: CredentialDefinition): void\n // function register(type: \"data_source\", feature: DataSourceDefinition): void\n function register(type: \"model\", feature: ModelDefinition): void\n function register(type: \"tool\", feature: ToolDefinition): void\n // biome-ignore lint/suspicious/noExplicitAny: any is used to avoid type errors\n function register(type: FeatureType, feature: any): void {\n store[type].set(feature.name, feature)\n }\n\n function resolve(type: \"credential\", featureName: string): CredentialDefinition\n // function resolve(type: \"data_source\", featureName: string): DataSourceDefinition\n function resolve(type: \"model\", featureName: string): ModelDefinition\n function resolve(type: \"tool\", featureName: string): ToolDefinition\n function resolve(type: FeatureType, featureName: string): Feature {\n const feature = store[type].get(featureName)\n assert(feature, `Feature \"${featureName}\" not registered`)\n return feature\n }\n\n return {\n plugin: store.plugin,\n register,\n resolve,\n serialize: () => {\n assert(store.plugin, \"Plugin is not registered\")\n\n return {\n plugin: Object.assign(store.plugin, {\n credentials: Array.from(store.credential.values()).map(serializeFeature),\n // data_sources: Array.from(store.data_source.values()).map(serializeFeature),\n models: Array.from(store.model.values()).map(serializeFeature),\n tools: Array.from(store.tool.values()).map(serializeFeature),\n }),\n }\n },\n }\n}\n","import chalk from \"chalk\"\nimport { type Channel, Socket, type SocketConnectOption } from \"phoenix\"\nimport { getEnv } from \"./env\"\n\nexport interface TransporterOptions\n extends Partial<Pick<SocketConnectOption, \"heartbeatIntervalMs\">> {\n onOpen?: Parameters<Socket[\"onOpen\"]>[0]\n onClose?: Parameters<Socket[\"onClose\"]>[0]\n onError?: Parameters<Socket[\"onError\"]>[0]\n onMessage?: Parameters<Socket[\"onMessage\"]>[0]\n}\n\n/**\n * Creates a network transporter for communication with the Hub Server.\n *\n * @param options - The options for the transporter.\n * @returns An object with a connect method to establish the connection and a dispose method to close it.\n */\nexport function createTransporter(options: TransporterOptions = {}) {\n const env = getEnv()\n\n const url = `${env.HUB_WS_URL}/${env.HUB_MODE}_socket`\n const socket = new Socket(url, {\n debug: env.DEBUG,\n heartbeatIntervalMs: options.heartbeatIntervalMs ?? 30 * 1000,\n logger(kind, message: unknown, data) {\n const timestamp = chalk.bgGrey(` ${new Date().toLocaleString()} `)\n const coloredKind = chalk.underline.bold.yellow(kind.toUpperCase())\n const coloredMessage =\n message instanceof Object && \"message\" in message\n ? chalk.italic.red(message.message)\n : chalk.italic.dim(message)\n const inspection = data ? Bun.inspect(data, { colors: true }) : \"\"\n console.debug(`${timestamp} ${coloredKind} ${coloredMessage}`, inspection)\n },\n params: Bun.env.NODE_ENV !== \"production\" ? { api_key: env.HUB_DEBUG_API_KEY } : undefined,\n })\n\n socket.onOpen(() => {\n options.onOpen?.()\n })\n\n socket.onClose((event) => {\n options.onClose?.(event)\n })\n\n socket.onError((error, transport, establishedConnections) => {\n if (error instanceof ErrorEvent && error.message.includes(\"failed: Expected 101 status code\")) {\n console.error(\"Error: Can't connect to the Plugin Hub server.\\n\")\n\n if (Bun.env.NODE_ENV !== \"production\") {\n console.error(\"This is usually because the Debug API Key is missing or has expired.\\n\")\n console.error(\"Run `atomemo plugin refresh-key` to get a new key.\\n\")\n }\n\n process.exit(1)\n }\n options.onError?.(error, transport, establishedConnections)\n })\n\n socket.onMessage((message) => {\n options.onMessage?.(message)\n })\n\n socket.connect()\n\n return {\n /**\n * Connects to the specified channel and returns a channel object and a dispose function.\n *\n * @returns An object with a channel property and a dispose function.\n */\n connect: (channelName: string) => {\n return new Promise<{ channel: Channel; dispose: () => void }>((resolve, reject) => {\n const channel = socket.channel(channelName, {})\n\n channel\n .join()\n .receive(\"ok\", (response) => {\n socket.log(\"channel:joined\", `Joined ${channelName} successfully`, response)\n\n resolve({\n channel,\n dispose: () => {\n channel.leave()\n socket.disconnect()\n process.exit(0)\n },\n })\n })\n .receive(\"error\", (response) => {\n socket.log(\"channel:error\", `Failed to join ${channelName}`, response)\n\n reject(new Error(`Failed to join ${channelName}: ${response.reason}`))\n })\n .receive(\"timeout\", (response) => {\n socket.log(\"channel:timeout\", `Timeout while joining ${channelName}`, response)\n reject(new Error(`Timeout while joining ${channelName}`))\n })\n })\n },\n }\n}\n","import { FileRefSchema } from \"@choiceopen/atomemo-plugin-schema/schemas\"\n\nfunction parseFileRefsInner(value: unknown, seen: WeakSet<object>): unknown {\n if (value === null || value === undefined) {\n return value\n }\n\n if (Array.isArray(value)) {\n if (seen.has(value)) return value\n seen.add(value)\n return value.map((item) => parseFileRefsInner(item, seen))\n }\n\n if (typeof value === \"object\") {\n if (seen.has(value as object)) return value\n seen.add(value as object)\n\n const obj = value as Record<string, unknown>\n\n if (obj.__type__ === \"file_ref\") {\n return FileRefSchema.parse(obj)\n }\n\n return Object.fromEntries(\n Object.entries(obj).map(([key, val]) => [key, parseFileRefsInner(val, seen)]),\n )\n }\n\n return value\n}\n\n/**\n * Recursively traverses a value and parses any plain objects with\n * `__type__: \"file_ref\"` into validated FileRef structures.\n *\n * This mirrors the behavior of Elixir SDK's recursive file_ref parsing\n * in invoke_tool parameter handling.\n */\nexport function parseFileRefs(value: unknown): unknown {\n return parseFileRefsInner(value, new WeakSet())\n}\n","import { isFunction } from \"es-toolkit/predicate\"\nimport type { JsonValue } from \"type-fest\"\n\ntype JsonObject = Record<string, JsonValue>\n\nconst toJsonValue = (value: unknown, seen: WeakSet<object>): JsonValue | undefined => {\n if (value === null) {\n return null\n }\n\n const type = typeof value\n\n if (type === \"string\" || type === \"number\" || type === \"boolean\") {\n return value as JsonValue\n }\n\n if (type === \"undefined\" || type === \"symbol\" || type === \"bigint\" || isFunction(value)) {\n return undefined\n }\n\n if (Array.isArray(value)) {\n const result: JsonValue[] = []\n\n for (const item of value) {\n const serialized = toJsonValue(item, seen)\n // 跟随 JSON 的行为:数组中的 undefined/function 等变为 null\n result.push(serialized === undefined ? null : serialized)\n }\n\n return result\n }\n\n if (type === \"object\" && value !== null) {\n if (seen.has(value as object)) {\n return undefined\n }\n\n seen.add(value as object)\n\n if (value instanceof Date) {\n return value.toISOString() as JsonValue\n }\n\n if (value instanceof Error) {\n return serializeError(value) as JsonValue\n }\n\n const result: JsonObject = {}\n\n for (const [key, v] of Object.entries(value as Record<string, unknown>)) {\n const serialized = toJsonValue(v, seen)\n\n if (serialized !== undefined) {\n result[key] = serialized\n }\n }\n\n return result\n }\n\n return undefined\n}\n\nexport const serializeError = (error: Error): JsonObject => {\n const base: Record<string, unknown> = {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n\n const anyError = error as unknown as { cause?: unknown }\n\n if (\"cause\" in anyError && anyError.cause !== undefined) {\n base.cause = anyError.cause\n }\n\n for (const [key, value] of Object.entries(error as unknown as Record<string, unknown>)) {\n if (key in base) {\n continue\n }\n\n base[key] = value\n }\n\n const seen = new WeakSet<object>([error])\n const serialized = toJsonValue(base, seen)\n\n if (!serialized || Array.isArray(serialized) || typeof serialized !== \"object\") {\n return {\n name: error.name,\n message: error.message,\n stack: error.stack ?? null,\n }\n }\n\n return serialized as JsonObject\n}\n","import {\n CredentialDefinitionSchema,\n ModelDefinitionSchema,\n ToolDefinitionSchema,\n} from \"@choiceopen/atomemo-plugin-schema/schemas\"\nimport type { PluginDefinition } from \"@choiceopen/atomemo-plugin-schema/types\"\nimport { isNil } from \"es-toolkit\"\nimport { ZodError, z } from \"zod\"\nimport { createPluginContext } from \"./context\"\nimport { getEnv } from \"./env\"\nimport { createHubCaller } from \"./hub\"\nimport { getSession } from \"./oneauth\"\nimport { createRegistry } from \"./registry\"\nimport { createTransporter, type TransporterOptions } from \"./transporter\"\nimport { parseFileRefs } from \"./utils/parse-file-refs\"\nimport { serializeError } from \"./utils/serialize-error\"\n\nconst CredentialAuthenticateMessage = z.object({\n request_id: z.string(),\n credential: z.record(z.string(), z.any()),\n credential_name: z.string(),\n extra: z.record(z.string(), z.any()).optional(),\n})\n\nconst ToolInvokeMessage = z.object({\n request_id: z.string(),\n plugin_identifier: z.string().optional(),\n tool_name: z.string(),\n parameters: z.record(z.string(), z.any()),\n credentials: z.record(z.string(), z.any()).optional(),\n})\n\ntype CredentialDefinition = z.infer<typeof CredentialDefinitionSchema>\ntype ToolDefinition = z.infer<typeof ToolDefinitionSchema>\ntype ModelDefinition = z.infer<typeof ModelDefinitionSchema>\n\n/**\n * Creates a new plugin instance with the specified options.\n *\n * @param options - The options for configuring the plugin instance.\n * @returns An object containing methods to define providers and run the plugin process.\n */\nexport async function createPlugin<Locales extends string[]>(\n options: PluginDefinition<Locales, TransporterOptions>,\n) {\n const env = getEnv()\n const isDebugMode = env.HUB_MODE === \"debug\"\n\n let user: { name: string; email: string }\n\n if (isDebugMode) {\n try {\n const deployment = env.HUB_WS_URL.includes(\"atomemo.ai\") ? \"production\" : \"staging\"\n const session = await getSession(deployment)\n user = { name: session.user.name, email: session.user.email }\n } catch (error) {\n console.error(\"Error fetching user session:\", error)\n process.exit(1)\n }\n } else {\n try {\n const raw = await Bun.file(\"definition.json\").json()\n const definition = z.looseObject({ author: z.string(), email: z.string() }).parse(raw)\n user = { name: definition.author, email: definition.email }\n } catch (error) {\n if (error instanceof ZodError) {\n console.error(z.prettifyError(error))\n } else {\n console.error(\"Error parsing definition.json:\", error)\n }\n process.exit(1)\n }\n }\n\n // Merge user info into plugin options\n const { transporterOptions, version = process.env.npm_package_version, ...plugin } = options\n const pluginDefinition = Object.assign(plugin, {\n author: user.name,\n email: user.email,\n version,\n })\n\n const registry = createRegistry(pluginDefinition)\n const transporter = createTransporter(transporterOptions)\n\n return {\n /**\n * Adds a new credential definition in the registry.\n *\n * @param credential - The credential to add.\n * @throws Error if the credential is not registered.\n */\n addCredential: (credential: CredentialDefinition) => {\n const definition = CredentialDefinitionSchema.parse(credential)\n registry.register(\"credential\", definition)\n },\n\n /**\n * Adds a new tool definition in the registry.\n *\n * @param tool - The tool to add.\n * @throws Error if the tool is not registered.\n */\n addTool: (tool: ToolDefinition) => {\n const definition = ToolDefinitionSchema.parse(tool)\n registry.register(\"tool\", definition)\n },\n\n /**\n * Adds a new model definition in the registry.\n *\n * @param model - The model to add.\n * @throws Error if the model is not registered.\n */\n addModel: (model: ModelDefinition) => {\n const definition = ModelDefinitionSchema.parse(model)\n registry.register(\"model\", definition)\n },\n\n /**\n * Starts the plugin's main process. This establishes the transporter connection and\n * sets up signal handlers for graceful shutdown on SIGINT and SIGTERM.\n */\n run: async () => {\n const topic = isDebugMode\n ? `debug_plugin:${registry.plugin.name}`\n : `release_plugin:${registry.plugin.name}__${env.HUB_MODE}__${pluginDefinition.version}`\n const { channel, dispose } = await transporter.connect(topic)\n const hubCaller = createHubCaller(channel)\n const pluginContext = createPluginContext(hubCaller)\n let cleanedUp = false\n const cleanup = () => {\n if (cleanedUp) return\n cleanedUp = true\n hubCaller.dispose()\n dispose()\n }\n\n void [\"SIGINT\", \"SIGTERM\"].forEach((signal) => {\n void process.on(signal, cleanup)\n })\n\n try {\n if (isDebugMode) {\n const definition = registry.serialize().plugin\n await new Promise<void>((resolve, reject) => {\n channel\n .push(\"register_plugin\", definition)\n .receive(\"ok\", () => {\n resolve()\n })\n .receive(\"error\", (response) => {\n reject(new Error(`Failed to register plugin: ${JSON.stringify(response)}`))\n })\n .receive(\"timeout\", () => {\n reject(new Error(\"Timed out while registering plugin\"))\n })\n })\n await Bun.write(\"definition.json\", JSON.stringify(definition, null, 2))\n }\n\n channel.on(\"credential_auth_spec\", async (message) => {\n const request_id = message.request_id\n\n try {\n const event = CredentialAuthenticateMessage.parse(message)\n const definition = registry.resolve(\"credential\", event.credential_name)\n if (isNil(definition.authenticate)) {\n throw new Error(\"Credential authenticate method is not implemented\")\n }\n\n const AuthenticateMethodWrapper = CredentialDefinitionSchema.shape.authenticate.unwrap()\n const authenticate = AuthenticateMethodWrapper.implementAsync(definition.authenticate)\n\n const { credential, extra } = event\n const data = await authenticate({ args: { credential, extra }, context: pluginContext })\n\n channel.push(\"credential_auth_spec_response\", { request_id, data })\n } catch (error) {\n if (error instanceof Error) {\n channel.push(\"credential_auth_spec_error\", {\n request_id,\n error: serializeError(error),\n })\n } else {\n channel.push(\"credential_auth_spec_error\", {\n request_id,\n error: serializeError(new Error(\"Unexpected Error\")),\n })\n }\n }\n })\n\n channel.on(\"invoke_tool\", async (message) => {\n const request_id = message.request_id\n\n try {\n const event = ToolInvokeMessage.parse(message)\n const { credentials } = event\n const parameters = parseFileRefs(event.parameters) as Record<string, unknown>\n const definition = registry.resolve(\"tool\", event.tool_name)\n\n const InvokeMethodWrapper = ToolDefinitionSchema.shape.invoke\n const invoke = InvokeMethodWrapper.implementAsync(definition.invoke)\n\n const data = await invoke({ args: { credentials, parameters }, context: pluginContext })\n channel.push(\"invoke_tool_response\", { request_id, data })\n } catch (error) {\n if (error instanceof Error) {\n channel.push(\"invoke_tool_error\", { request_id, error: serializeError(error) })\n } else {\n channel.push(\"invoke_tool_error\", {\n request_id,\n error: serializeError(new Error(\"Unexpected Error\")),\n })\n }\n }\n })\n } catch (error) {\n cleanup()\n throw error\n }\n },\n }\n}\n"],"x_google_ignoreList":[0,1,2,3],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@choiceopen/atomemo-plugin-sdk-js",
3
- "version": "0.3.4",
3
+ "version": "0.4.0",
4
4
  "description": "JavaScript/TypeScript SDK for developing Choiceform Atomemo plugins",
5
5
  "homepage": "https://github.com/choice-open/atomemo-plugin-sdk-js#readme",
6
6
  "bugs": {
@@ -31,20 +31,20 @@
31
31
  "typecheck": "tsc --noEmit"
32
32
  },
33
33
  "dependencies": {
34
- "@choiceopen/atomemo-plugin-schema": "^0.2.16",
35
- "phoenix": "^1.8.4",
34
+ "@choiceopen/atomemo-plugin-schema": "^0.4.1",
35
+ "phoenix": "^1.8.5",
36
36
  "pino": "^10.3.1",
37
37
  "pino-pretty": "^13.1.3",
38
38
  "type-fest": "^5.4.4"
39
39
  },
40
40
  "devDependencies": {
41
- "@biomejs/biome": "^2.4.5",
41
+ "@biomejs/biome": "^2.4.6",
42
42
  "@types/bun": "^1.3.10",
43
43
  "@types/phoenix": "^1.6.7",
44
44
  "bumpp": "^10.4.1",
45
45
  "chalk": "^5.6.2",
46
46
  "dotenv": "^17.3.1",
47
- "es-toolkit": "^1.45.0",
47
+ "es-toolkit": "^1.45.1",
48
48
  "tsdown": "^0.20.3",
49
49
  "typescript": "^5.9.3",
50
50
  "zod": "^4.3.6"
@@ -73,4 +73,4 @@
73
73
  "./package.json": "./package.json"
74
74
  }
75
75
  }
76
- }
76
+ }