@brantrusnak/openclaw-omadeus 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -61
- package/dist/_virtual/_rolldown/runtime.js +4 -0
- package/dist/api.js +5 -0
- package/dist/index.js +14 -0
- package/dist/runtime-api.js +15 -0
- package/dist/setup-entry.js +7 -0
- package/dist/src/allowed-reaction-emojis.js +21 -0
- package/dist/src/api/auth.api.js +118 -0
- package/dist/src/api/channel.api.js +23 -0
- package/dist/src/api/message.api.js +76 -0
- package/dist/src/api/nugget.api.js +127 -0
- package/dist/src/auth.js +30 -0
- package/dist/src/channel.js +626 -0
- package/dist/src/config.js +52 -0
- package/dist/src/defaults.js +5 -0
- package/dist/src/inbound-policy.js +205 -0
- package/dist/src/inbound.js +97 -0
- package/dist/src/member-resolve.js +53 -0
- package/dist/src/message-handler.js +262 -0
- package/dist/src/nugget-lookup.js +140 -0
- package/dist/src/onboarding.js +357 -0
- package/dist/src/outbound.js +17 -0
- package/dist/src/reply-dispatcher.js +46 -0
- package/dist/src/runtime.js +5 -0
- package/dist/src/setup-core.js +46 -0
- package/dist/src/setup-surface.js +2 -0
- package/dist/src/socket/dolphin.socket.js +18 -0
- package/dist/src/socket/jaguar.socket.js +22 -0
- package/dist/src/socket/socket.js +153 -0
- package/dist/src/store.js +13 -0
- package/dist/src/token.js +84 -0
- package/dist/src/types.js +15 -0
- package/dist/src/utils/http.util.js +43 -0
- package/dist/src/utils/jwt.util.js +15 -0
- package/package.json +10 -3
- package/src/api/auth.api.ts +27 -7
- package/src/channel.ts +127 -238
- package/src/member-resolve.ts +1 -1
- package/src/onboarding.ts +117 -163
- package/src/setup-core.ts +10 -1
- package/src/socket/socket.ts +24 -11
package/src/channel.ts
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
} from "./api/nugget.api.js";
|
|
29
29
|
import { addMessageReaction, deleteMessage, editMessage } from "./api/message.api.js";
|
|
30
30
|
import {
|
|
31
|
+
getOmadeusChannelConfig,
|
|
31
32
|
listOmadeusAccountIds,
|
|
32
33
|
resolveDefaultOmadeusAccountId,
|
|
33
34
|
resolveOmadeusAccount,
|
|
@@ -44,30 +45,55 @@ import { createJaguarSocketClient, type JaguarSocketClient } from "./socket/jagu
|
|
|
44
45
|
import { createTokenManager, type OmadeusTokenManager } from "./token.js";
|
|
45
46
|
import type { ResolvedOmadeusAccount as Account } from "./types.js";
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
const CHANNEL_ID = "omadeus" as const;
|
|
49
|
+
|
|
50
|
+
const gatewayState: {
|
|
51
|
+
tokenManager: OmadeusTokenManager | null;
|
|
52
|
+
dolphin: DolphinSocketClient | null;
|
|
53
|
+
jaguar: JaguarSocketClient | null;
|
|
54
|
+
} = { tokenManager: null, dolphin: null, jaguar: null };
|
|
55
|
+
|
|
56
|
+
const isUnconfigured = (account: Account) => account.credentialSource === "none";
|
|
57
|
+
|
|
58
|
+
let lastPersistedToken: string | null = null;
|
|
51
59
|
|
|
52
60
|
async function persistSessionToken(token: string): Promise<void> {
|
|
61
|
+
if (lastPersistedToken === token) return;
|
|
53
62
|
const runtime = getOmadeusRuntime();
|
|
54
|
-
const cfg = runtime.config.
|
|
55
|
-
const section = (
|
|
56
|
-
|
|
57
|
-
|
|
63
|
+
const cfg = runtime.config.current() as OpenClawConfig;
|
|
64
|
+
const section = getOmadeusChannelConfig(cfg) ?? {};
|
|
65
|
+
if (section.sessionToken === token) {
|
|
66
|
+
lastPersistedToken = token;
|
|
58
67
|
return;
|
|
59
68
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
await runtime.config.mutateConfigFile({
|
|
70
|
+
afterWrite: { mode: "auto" },
|
|
71
|
+
mutate: (draft) => {
|
|
72
|
+
draft.channels = {
|
|
73
|
+
...(draft.channels ?? {}),
|
|
74
|
+
omadeus: {
|
|
75
|
+
...(getOmadeusChannelConfig(draft) ?? {}),
|
|
76
|
+
sessionToken: token,
|
|
77
|
+
},
|
|
78
|
+
};
|
|
69
79
|
},
|
|
70
|
-
}
|
|
80
|
+
});
|
|
81
|
+
lastPersistedToken = token;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function actionError(text: string, error = text) {
|
|
85
|
+
return {
|
|
86
|
+
isError: true as const,
|
|
87
|
+
content: [{ type: "text" as const, text }],
|
|
88
|
+
details: { error },
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function actionOk(payload: Record<string, unknown>) {
|
|
93
|
+
return {
|
|
94
|
+
content: [{ type: "text" as const, text: JSON.stringify({ ok: true, channel: CHANNEL_ID, ...payload }) }],
|
|
95
|
+
details: { ok: true, channel: CHANNEL_ID, ...payload },
|
|
96
|
+
};
|
|
71
97
|
}
|
|
72
98
|
|
|
73
99
|
const omadeusConfigAdapter = createTopLevelChannelConfigAdapter<Account>({
|
|
@@ -212,7 +238,7 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
212
238
|
describeMessageTool: ({ cfg }) => {
|
|
213
239
|
const enabled =
|
|
214
240
|
cfg.channels?.omadeus?.enabled !== false &&
|
|
215
|
-
resolveOmadeusAccount({ cfg })
|
|
241
|
+
!isUnconfigured(resolveOmadeusAccount({ cfg }));
|
|
216
242
|
return {
|
|
217
243
|
actions: enabled ? ["send", "edit", "delete", "react"] : [],
|
|
218
244
|
capabilities: [],
|
|
@@ -220,28 +246,19 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
220
246
|
};
|
|
221
247
|
},
|
|
222
248
|
handleAction: async (ctx) => {
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
if (!
|
|
249
|
+
const account = resolveOmadeusAccount({ cfg: ctx.cfg });
|
|
250
|
+
const apiOpts = () => {
|
|
251
|
+
if (!gatewayState.tokenManager) {
|
|
226
252
|
throw new Error("Omadeus: not connected; gateway must be running with Omadeus enabled.");
|
|
227
253
|
}
|
|
228
|
-
return { maestroUrl: account.maestroUrl, tokenManager:
|
|
254
|
+
return { maestroUrl: account.maestroUrl, tokenManager: gatewayState.tokenManager };
|
|
229
255
|
};
|
|
230
256
|
|
|
231
257
|
if (ctx.action === "send" && isCreateNuggetRequest(ctx.params)) {
|
|
232
258
|
const title = readStringParam(ctx.params, ["title", "subject", "name"]);
|
|
233
259
|
const description = readStringParam(ctx.params, ["description", "details", "body"]);
|
|
234
260
|
if (!title || !description) {
|
|
235
|
-
return
|
|
236
|
-
isError: true,
|
|
237
|
-
content: [
|
|
238
|
-
{
|
|
239
|
-
type: "text" as const,
|
|
240
|
-
text: "Omadeus create task/nugget requires `title` and `description`.",
|
|
241
|
-
},
|
|
242
|
-
],
|
|
243
|
-
details: { error: "Missing title/description." },
|
|
244
|
-
};
|
|
261
|
+
return actionError("Omadeus create task/nugget requires `title` and `description`.", "Missing title/description.");
|
|
245
262
|
}
|
|
246
263
|
|
|
247
264
|
const kind = readNuggetKind(ctx.params);
|
|
@@ -249,25 +266,19 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
249
266
|
const stage = readStringParam(ctx.params, ["stage"]) ?? "Triage";
|
|
250
267
|
const memberReferenceId =
|
|
251
268
|
readNumberParam(ctx.params, ["memberReferenceId", "assigneeReferenceId"]) ??
|
|
252
|
-
|
|
269
|
+
gatewayState.tokenManager?.getPayload().referenceId;
|
|
253
270
|
const clientId = readNumberParam(ctx.params, ["clientId"]) ?? 1;
|
|
254
271
|
const folderId = readNumberParam(ctx.params, ["folderId"]) ?? 1;
|
|
255
272
|
|
|
256
273
|
if (!memberReferenceId) {
|
|
257
|
-
return
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
type: "text" as const,
|
|
262
|
-
text: "Omadeus create task/nugget needs `memberReferenceId` or an active authenticated user.",
|
|
263
|
-
},
|
|
264
|
-
],
|
|
265
|
-
details: { error: "Missing memberReferenceId." },
|
|
266
|
-
};
|
|
274
|
+
return actionError(
|
|
275
|
+
"Omadeus create task/nugget needs `memberReferenceId` or an active authenticated user.",
|
|
276
|
+
"Missing memberReferenceId.",
|
|
277
|
+
);
|
|
267
278
|
}
|
|
268
279
|
|
|
269
280
|
try {
|
|
270
|
-
const created = await createNugget(
|
|
281
|
+
const created = await createNugget(apiOpts(), {
|
|
271
282
|
title,
|
|
272
283
|
description,
|
|
273
284
|
stage,
|
|
@@ -277,39 +288,10 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
277
288
|
clientId,
|
|
278
289
|
folderId,
|
|
279
290
|
});
|
|
280
|
-
|
|
281
|
-
const id = created["id"];
|
|
282
|
-
return {
|
|
283
|
-
content: [
|
|
284
|
-
{
|
|
285
|
-
type: "text" as const,
|
|
286
|
-
text: JSON.stringify({
|
|
287
|
-
ok: true,
|
|
288
|
-
channel: "omadeus",
|
|
289
|
-
action: "create",
|
|
290
|
-
kind,
|
|
291
|
-
number,
|
|
292
|
-
id,
|
|
293
|
-
title,
|
|
294
|
-
}),
|
|
295
|
-
},
|
|
296
|
-
],
|
|
297
|
-
details: {
|
|
298
|
-
ok: true,
|
|
299
|
-
channel: "omadeus",
|
|
300
|
-
action: "create",
|
|
301
|
-
kind,
|
|
302
|
-
number,
|
|
303
|
-
id,
|
|
304
|
-
},
|
|
305
|
-
};
|
|
291
|
+
return actionOk({ action: "create", kind, number: created["number"], id: created["id"], title });
|
|
306
292
|
} catch (err) {
|
|
307
293
|
const msg = err instanceof Error ? err.message : String(err);
|
|
308
|
-
return
|
|
309
|
-
isError: true,
|
|
310
|
-
content: [{ type: "text" as const, text: msg }],
|
|
311
|
-
details: { error: msg },
|
|
312
|
-
};
|
|
294
|
+
return actionError(msg);
|
|
313
295
|
}
|
|
314
296
|
}
|
|
315
297
|
|
|
@@ -321,93 +303,47 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
321
303
|
(typeof ctx.params.content === "string" && ctx.params.content.trim()) ||
|
|
322
304
|
"";
|
|
323
305
|
if (messageId == null) {
|
|
324
|
-
return
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
type: "text" as const,
|
|
329
|
-
text: "Omadeus edit requires `messageId` (Jaguar message id) or current inbound MessageSid.",
|
|
330
|
-
},
|
|
331
|
-
],
|
|
332
|
-
details: { error: "Missing messageId for edit." },
|
|
333
|
-
};
|
|
306
|
+
return actionError(
|
|
307
|
+
"Omadeus edit requires `messageId` (Jaguar message id) or current inbound MessageSid.",
|
|
308
|
+
"Missing messageId for edit.",
|
|
309
|
+
);
|
|
334
310
|
}
|
|
335
311
|
if (!body) {
|
|
336
|
-
return
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
type: "text" as const,
|
|
341
|
-
text: "Omadeus edit requires new text in `message`, `text`, or `content`.",
|
|
342
|
-
},
|
|
343
|
-
],
|
|
344
|
-
details: { error: "Missing body for edit." },
|
|
345
|
-
};
|
|
312
|
+
return actionError(
|
|
313
|
+
"Omadeus edit requires new text in `message`, `text`, or `content`.",
|
|
314
|
+
"Missing body for edit.",
|
|
315
|
+
);
|
|
346
316
|
}
|
|
347
317
|
try {
|
|
348
|
-
await editMessage(
|
|
318
|
+
await editMessage(apiOpts(), { messageId, body });
|
|
349
319
|
} catch (err) {
|
|
350
320
|
const msg = err instanceof Error ? err.message : String(err);
|
|
351
|
-
return
|
|
352
|
-
isError: true,
|
|
353
|
-
content: [{ type: "text" as const, text: msg }],
|
|
354
|
-
details: { error: msg },
|
|
355
|
-
};
|
|
321
|
+
return actionError(msg);
|
|
356
322
|
}
|
|
357
|
-
return {
|
|
358
|
-
content: [
|
|
359
|
-
{
|
|
360
|
-
type: "text" as const,
|
|
361
|
-
text: JSON.stringify({ ok: true, channel: "omadeus", action: "edit", messageId }),
|
|
362
|
-
},
|
|
363
|
-
],
|
|
364
|
-
details: { ok: true, channel: "omadeus", messageId },
|
|
365
|
-
};
|
|
323
|
+
return actionOk({ action: "edit", messageId });
|
|
366
324
|
}
|
|
367
325
|
|
|
368
326
|
if (ctx.action === "delete") {
|
|
369
327
|
const messageId = readReactionMessageId(ctx.params, ctx.toolContext);
|
|
370
328
|
if (messageId == null) {
|
|
371
|
-
return
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
type: "text" as const,
|
|
376
|
-
text: "Omadeus delete requires `messageId` (Jaguar message id) or current inbound MessageSid.",
|
|
377
|
-
},
|
|
378
|
-
],
|
|
379
|
-
details: { error: "Missing messageId for delete." },
|
|
380
|
-
};
|
|
329
|
+
return actionError(
|
|
330
|
+
"Omadeus delete requires `messageId` (Jaguar message id) or current inbound MessageSid.",
|
|
331
|
+
"Missing messageId for delete.",
|
|
332
|
+
);
|
|
381
333
|
}
|
|
382
334
|
try {
|
|
383
|
-
await deleteMessage(
|
|
335
|
+
await deleteMessage(apiOpts(), { messageId });
|
|
384
336
|
} catch (err) {
|
|
385
337
|
const msg = err instanceof Error ? err.message : String(err);
|
|
386
|
-
return
|
|
387
|
-
isError: true,
|
|
388
|
-
content: [{ type: "text" as const, text: msg }],
|
|
389
|
-
details: { error: msg },
|
|
390
|
-
};
|
|
338
|
+
return actionError(msg);
|
|
391
339
|
}
|
|
392
|
-
return {
|
|
393
|
-
content: [
|
|
394
|
-
{
|
|
395
|
-
type: "text" as const,
|
|
396
|
-
text: JSON.stringify({ ok: true, channel: "omadeus", action: "delete", messageId }),
|
|
397
|
-
},
|
|
398
|
-
],
|
|
399
|
-
details: { ok: true, channel: "omadeus", messageId },
|
|
400
|
-
};
|
|
340
|
+
return actionOk({ action: "delete", messageId });
|
|
401
341
|
}
|
|
402
342
|
|
|
403
343
|
if (ctx.action === "react") {
|
|
404
344
|
const emoji = typeof ctx.params.emoji === "string" ? ctx.params.emoji.trim() : "";
|
|
405
345
|
if (!emoji) {
|
|
406
|
-
return
|
|
407
|
-
isError: true,
|
|
408
|
-
content: [{ type: "text" as const, text: "Omadeus react requires `emoji`." }],
|
|
409
|
-
details: { error: "Omadeus react requires emoji." },
|
|
410
|
-
};
|
|
346
|
+
return actionError("Omadeus react requires `emoji`.", "Omadeus react requires emoji.");
|
|
411
347
|
}
|
|
412
348
|
if (!isAllowedOmadeusReactionEmoji(emoji)) {
|
|
413
349
|
return {
|
|
@@ -416,7 +352,7 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
416
352
|
type: "text" as const,
|
|
417
353
|
text: JSON.stringify({
|
|
418
354
|
ok: true,
|
|
419
|
-
channel:
|
|
355
|
+
channel: CHANNEL_ID,
|
|
420
356
|
ignored: true,
|
|
421
357
|
reason: "unsupported_emoji",
|
|
422
358
|
emoji,
|
|
@@ -424,84 +360,42 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
424
360
|
}),
|
|
425
361
|
},
|
|
426
362
|
],
|
|
427
|
-
details: {
|
|
428
|
-
ok: true,
|
|
429
|
-
ignored: true,
|
|
430
|
-
channel: "omadeus",
|
|
431
|
-
},
|
|
363
|
+
details: { ok: true, ignored: true, channel: CHANNEL_ID },
|
|
432
364
|
};
|
|
433
365
|
}
|
|
434
366
|
const messageId = readReactionMessageId(ctx.params, ctx.toolContext);
|
|
435
367
|
if (messageId == null) {
|
|
436
|
-
return
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
type: "text" as const,
|
|
441
|
-
text: "Omadeus react requires `messageId` or a current inbound message id (MessageSid).",
|
|
442
|
-
},
|
|
443
|
-
],
|
|
444
|
-
details: { error: "Missing messageId for reaction." },
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
if (!activeTokenManager) {
|
|
448
|
-
return {
|
|
449
|
-
isError: true,
|
|
450
|
-
content: [
|
|
451
|
-
{
|
|
452
|
-
type: "text" as const,
|
|
453
|
-
text: "Omadeus is not connected; cannot react (gateway must be running).",
|
|
454
|
-
},
|
|
455
|
-
],
|
|
456
|
-
details: { error: "Omadeus not connected." },
|
|
457
|
-
};
|
|
368
|
+
return actionError(
|
|
369
|
+
"Omadeus react requires `messageId` or a current inbound message id (MessageSid).",
|
|
370
|
+
"Missing messageId for reaction.",
|
|
371
|
+
);
|
|
458
372
|
}
|
|
459
373
|
try {
|
|
460
|
-
await addMessageReaction(
|
|
374
|
+
await addMessageReaction(apiOpts(), { messageId, emoji });
|
|
461
375
|
} catch (err) {
|
|
462
376
|
const msg = err instanceof Error ? err.message : String(err);
|
|
463
|
-
return
|
|
464
|
-
isError: true,
|
|
465
|
-
content: [{ type: "text" as const, text: msg }],
|
|
466
|
-
details: { error: msg },
|
|
467
|
-
};
|
|
377
|
+
return actionError(msg);
|
|
468
378
|
}
|
|
469
|
-
return {
|
|
470
|
-
content: [
|
|
471
|
-
{
|
|
472
|
-
type: "text" as const,
|
|
473
|
-
text: JSON.stringify({
|
|
474
|
-
ok: true,
|
|
475
|
-
channel: "omadeus",
|
|
476
|
-
messageId,
|
|
477
|
-
emoji,
|
|
478
|
-
}),
|
|
479
|
-
},
|
|
480
|
-
],
|
|
481
|
-
details: { ok: true, channel: "omadeus", messageId, emoji },
|
|
482
|
-
};
|
|
379
|
+
return actionOk({ messageId, emoji });
|
|
483
380
|
}
|
|
484
|
-
|
|
485
|
-
|
|
381
|
+
|
|
382
|
+
throw new Error(`Unhandled Omadeus action: ${String(ctx.action)}`);
|
|
486
383
|
},
|
|
487
384
|
},
|
|
488
385
|
reload: { configPrefixes: ["channels.omadeus"] },
|
|
489
386
|
setup: omadeusSetupAdapter,
|
|
490
387
|
setupWizard: omadeusSetupWizard,
|
|
491
388
|
|
|
492
|
-
// -------------------------------------------------------------------------
|
|
493
|
-
// Config adapter
|
|
494
|
-
// -------------------------------------------------------------------------
|
|
495
389
|
config: {
|
|
496
390
|
...omadeusConfigAdapter,
|
|
497
|
-
isConfigured: (account) => account
|
|
391
|
+
isConfigured: (account) => !isUnconfigured(account),
|
|
498
392
|
unconfiguredReason: () =>
|
|
499
393
|
"Omadeus requires email, password, and organizationId. Run: openclaw setup omadeus",
|
|
500
394
|
describeAccount: (account) => ({
|
|
501
395
|
accountId: account.accountId,
|
|
502
396
|
name: account.name,
|
|
503
397
|
enabled: account.enabled,
|
|
504
|
-
configured: account
|
|
398
|
+
configured: !isUnconfigured(account),
|
|
505
399
|
credentialSource: account.credentialSource,
|
|
506
400
|
baseUrl: account.maestroUrl,
|
|
507
401
|
}),
|
|
@@ -519,13 +413,13 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
519
413
|
const id = normalizeOmadeusRoomId(input);
|
|
520
414
|
if (!id) {
|
|
521
415
|
const taskIntent = parseTaskChannelTargetIntent(input);
|
|
522
|
-
if (!taskIntent || !
|
|
416
|
+
if (!taskIntent || !gatewayState.tokenManager) {
|
|
523
417
|
return null;
|
|
524
418
|
}
|
|
525
419
|
const roomId = await resolveTaskRoomIdByNumber(
|
|
526
420
|
{
|
|
527
421
|
maestroUrl: resolveOmadeusAccount({ cfg }).maestroUrl,
|
|
528
|
-
tokenManager:
|
|
422
|
+
tokenManager: gatewayState.tokenManager,
|
|
529
423
|
},
|
|
530
424
|
{ nuggetNumber: taskIntent.nuggetNumber },
|
|
531
425
|
);
|
|
@@ -549,18 +443,15 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
549
443
|
},
|
|
550
444
|
},
|
|
551
445
|
|
|
552
|
-
// -------------------------------------------------------------------------
|
|
553
|
-
// Outbound adapter
|
|
554
|
-
// -------------------------------------------------------------------------
|
|
555
446
|
outbound: {
|
|
556
447
|
deliveryMode: "direct",
|
|
557
448
|
textChunkLimit: 4000,
|
|
558
449
|
chunker: (text, limit) => getOmadeusRuntime().channel.text.chunkMarkdownText(text, limit),
|
|
559
450
|
chunkerMode: "markdown",
|
|
560
451
|
...createAttachedChannelResultAdapter({
|
|
561
|
-
channel:
|
|
452
|
+
channel: CHANNEL_ID,
|
|
562
453
|
sendText: async ({ cfg, to, text }) => {
|
|
563
|
-
if (!
|
|
454
|
+
if (!gatewayState.jaguar || !gatewayState.tokenManager) {
|
|
564
455
|
throw new Error("Omadeus: not connected. Is the gateway running with Omadeus enabled?");
|
|
565
456
|
}
|
|
566
457
|
const deps: OutboundDeps = {
|
|
@@ -568,9 +459,9 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
568
459
|
maestroUrl: resolveOmadeusAccount({
|
|
569
460
|
cfg,
|
|
570
461
|
}).maestroUrl,
|
|
571
|
-
tokenManager:
|
|
462
|
+
tokenManager: gatewayState.tokenManager,
|
|
572
463
|
},
|
|
573
|
-
jaguarSocket:
|
|
464
|
+
jaguarSocket: gatewayState.jaguar,
|
|
574
465
|
};
|
|
575
466
|
return await sendOmadeusMessage(deps, { to, text });
|
|
576
467
|
},
|
|
@@ -592,9 +483,6 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
592
483
|
},
|
|
593
484
|
},
|
|
594
485
|
|
|
595
|
-
// -------------------------------------------------------------------------
|
|
596
|
-
// Status adapter
|
|
597
|
-
// -------------------------------------------------------------------------
|
|
598
486
|
status: {
|
|
599
487
|
defaultRuntime: defaultRuntimeState,
|
|
600
488
|
collectStatusIssues: (accounts): ChannelStatusIssue[] =>
|
|
@@ -602,7 +490,7 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
602
490
|
const issues: ChannelStatusIssue[] = [];
|
|
603
491
|
if (entry.enabled !== false && entry.configured !== true) {
|
|
604
492
|
issues.push({
|
|
605
|
-
channel:
|
|
493
|
+
channel: CHANNEL_ID,
|
|
606
494
|
accountId: String(entry.accountId ?? DEFAULT_ACCOUNT_ID),
|
|
607
495
|
kind: "config",
|
|
608
496
|
message: "Omadeus credentials are missing.",
|
|
@@ -625,7 +513,7 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
625
513
|
accountId: account.accountId,
|
|
626
514
|
name: account.name,
|
|
627
515
|
enabled: account.enabled,
|
|
628
|
-
configured: account
|
|
516
|
+
configured: !isUnconfigured(account),
|
|
629
517
|
runtime,
|
|
630
518
|
}),
|
|
631
519
|
baseUrl: account.maestroUrl,
|
|
@@ -635,15 +523,12 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
635
523
|
}),
|
|
636
524
|
},
|
|
637
525
|
|
|
638
|
-
// -------------------------------------------------------------------------
|
|
639
|
-
// Gateway adapter — starts sockets on gateway boot
|
|
640
|
-
// -------------------------------------------------------------------------
|
|
641
526
|
gateway: {
|
|
642
527
|
startAccount: async (ctx) => {
|
|
643
528
|
const { account, cfg, abortSignal } = ctx;
|
|
644
529
|
ctx.log?.info(`[omadeus] starting for org ${account.organizationId}`);
|
|
645
530
|
|
|
646
|
-
if (account
|
|
531
|
+
if (isUnconfigured(account)) {
|
|
647
532
|
ctx.log?.warn("[omadeus] skipping start: credentials not configured");
|
|
648
533
|
ctx.setStatus({
|
|
649
534
|
accountId: account.accountId,
|
|
@@ -665,8 +550,8 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
665
550
|
}
|
|
666
551
|
|
|
667
552
|
const log = ctx.log ?? { info: () => {}, warn: () => {}, error: () => {} };
|
|
553
|
+
let isConnected = false;
|
|
668
554
|
|
|
669
|
-
// Auth
|
|
670
555
|
const tokenManager = createTokenManager({
|
|
671
556
|
casUrl: account.casUrl,
|
|
672
557
|
maestroUrl: account.maestroUrl,
|
|
@@ -696,7 +581,7 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
696
581
|
}
|
|
697
582
|
|
|
698
583
|
tokenManager.startAutoRefresh();
|
|
699
|
-
|
|
584
|
+
gatewayState.tokenManager = tokenManager;
|
|
700
585
|
|
|
701
586
|
const selfReferenceId = tokenManager.getPayload().referenceId;
|
|
702
587
|
|
|
@@ -713,7 +598,6 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
713
598
|
selfReferenceId,
|
|
714
599
|
});
|
|
715
600
|
|
|
716
|
-
// Jaguar socket (chat — DMs, nugget/task/project rooms)
|
|
717
601
|
const jaguar = createJaguarSocketClient({
|
|
718
602
|
maestroUrl: account.maestroUrl,
|
|
719
603
|
tokenManager,
|
|
@@ -742,17 +626,19 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
742
626
|
onOtherEvent: (data) => {
|
|
743
627
|
log.info(`[jaguar] non-message event: ${JSON.stringify(data).slice(0, 120)}`);
|
|
744
628
|
},
|
|
745
|
-
onConnect: () =>
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
connected: true,
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
onDisconnect: () =>
|
|
629
|
+
onConnect: () => {
|
|
630
|
+
if (!isConnected) {
|
|
631
|
+
isConnected = true;
|
|
632
|
+
ctx.setStatus({ accountId: account.accountId, connected: true, lastConnectedAt: Date.now() });
|
|
633
|
+
}
|
|
634
|
+
},
|
|
635
|
+
onDisconnect: () => {
|
|
636
|
+
isConnected = false;
|
|
637
|
+
ctx.setStatus({ accountId: account.accountId, connected: false });
|
|
638
|
+
},
|
|
752
639
|
onError: (err) => ctx.setStatus({ accountId: account.accountId, lastError: err.message }),
|
|
753
640
|
});
|
|
754
641
|
|
|
755
|
-
// Dolphin socket (data — tasks, projects, sprints, releases)
|
|
756
642
|
const dolphin = createDolphinSocketClient({
|
|
757
643
|
maestroUrl: account.maestroUrl,
|
|
758
644
|
tokenManager,
|
|
@@ -761,13 +647,16 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
761
647
|
log.info(`[dolphin] event: ${JSON.stringify(data).slice(0, 120)}`);
|
|
762
648
|
// TODO: handle task assignment/update events as they are discovered
|
|
763
649
|
},
|
|
764
|
-
onConnect: () =>
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
connected: true,
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
onDisconnect: () =>
|
|
650
|
+
onConnect: () => {
|
|
651
|
+
if (!isConnected) {
|
|
652
|
+
isConnected = true;
|
|
653
|
+
ctx.setStatus({ accountId: account.accountId, connected: true, lastConnectedAt: Date.now() });
|
|
654
|
+
}
|
|
655
|
+
},
|
|
656
|
+
onDisconnect: () => {
|
|
657
|
+
isConnected = false;
|
|
658
|
+
ctx.setStatus({ accountId: account.accountId, connected: false });
|
|
659
|
+
},
|
|
771
660
|
onError: (err) => ctx.setStatus({ accountId: account.accountId, lastError: err.message }),
|
|
772
661
|
});
|
|
773
662
|
|
|
@@ -776,8 +665,8 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
776
665
|
|
|
777
666
|
jaguar.connect();
|
|
778
667
|
dolphin.connect();
|
|
779
|
-
|
|
780
|
-
|
|
668
|
+
gatewayState.jaguar = jaguar;
|
|
669
|
+
gatewayState.dolphin = dolphin;
|
|
781
670
|
|
|
782
671
|
ctx.setStatus({
|
|
783
672
|
accountId: account.accountId,
|
|
@@ -792,9 +681,10 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
792
681
|
tokenManager.stopAutoRefresh();
|
|
793
682
|
jaguar.disconnect();
|
|
794
683
|
dolphin.disconnect();
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
684
|
+
gatewayState.tokenManager = null;
|
|
685
|
+
gatewayState.jaguar = null;
|
|
686
|
+
gatewayState.dolphin = null;
|
|
687
|
+
lastPersistedToken = null;
|
|
798
688
|
ctx.setStatus({
|
|
799
689
|
accountId: account.accountId,
|
|
800
690
|
running: false,
|
|
@@ -802,7 +692,6 @@ export const omadeusPlugin: ChannelPlugin<Account> = {
|
|
|
802
692
|
});
|
|
803
693
|
};
|
|
804
694
|
|
|
805
|
-
// Keep this account runner alive until the gateway aborts it.
|
|
806
695
|
await new Promise<void>((resolve) => {
|
|
807
696
|
if (abortSignal.aborted) {
|
|
808
697
|
resolve();
|
package/src/member-resolve.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { listOrganizationMembers } from "./api/auth.api.js";
|
|
|
2
2
|
import type { OmadeusOrganizationMember } from "./types.js";
|
|
3
3
|
import type { OmadeusApiOptions } from "./utils/http.util.js";
|
|
4
4
|
|
|
5
|
-
function formatMemberLabel(m: OmadeusOrganizationMember): string {
|
|
5
|
+
export function formatMemberLabel(m: OmadeusOrganizationMember): string {
|
|
6
6
|
const fullName = `${m.firstName ?? ""} ${m.lastName ?? ""}`.trim();
|
|
7
7
|
if (fullName) {
|
|
8
8
|
return fullName;
|