@rync/moorline-discord-default 0.0.2 → 0.0.3
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/manifest.json +3 -3
- package/moorline.dist.json +3 -3
- package/package.json +2 -9
- package/packages/plugins/rync/discord-runtime/index.mjs +68 -1022
- package/packages/plugins/rync/discord-runtime/manifest.json +3 -12
- package/packages/plugins/rync/discord-runtime/moorline.dist.json +2 -2
- package/packages/transports/rync/discord/index.mjs +333 -584
- package/packages/transports/rync/discord/manifest.json +2 -2
- package/packages/transports/rync/discord/moorline.dist.json +2 -2
- package/packages/plugins/rync/discord-runtime/modules/routing/coordination.md +0 -9
|
@@ -4,29 +4,20 @@ import { createRequire as __moorlineCreateRequire } from 'node:module'; const re
|
|
|
4
4
|
var manifest_default = {
|
|
5
5
|
id: "rync/discord-runtime",
|
|
6
6
|
name: "rync/discord-runtime",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.3",
|
|
8
8
|
type: "plugin",
|
|
9
9
|
description: "Discord runtime commands and message routing for Moorline.",
|
|
10
10
|
entrypoint: "index.mjs",
|
|
11
11
|
priority: 100,
|
|
12
12
|
capabilities: [
|
|
13
|
-
"runtime.control",
|
|
14
|
-
"memory.read",
|
|
15
13
|
"transport.message.send",
|
|
16
|
-
"transport.resource.create",
|
|
17
|
-
"transport.resource.update",
|
|
18
|
-
"transport.resource.delete",
|
|
19
|
-
"net.connect",
|
|
20
14
|
"fs.read",
|
|
21
15
|
"session.inspect",
|
|
22
|
-
"
|
|
23
|
-
"session.archive",
|
|
24
|
-
"session.delete"
|
|
16
|
+
"provider.headless.run"
|
|
25
17
|
],
|
|
26
18
|
hooks: [
|
|
27
19
|
"onAction",
|
|
28
|
-
"
|
|
29
|
-
"onTransportEvent"
|
|
20
|
+
"onTransportIntent"
|
|
30
21
|
],
|
|
31
22
|
defaultEnabled: true,
|
|
32
23
|
dependencies: [
|
|
@@ -39,458 +30,9 @@ var manifest_default = {
|
|
|
39
30
|
]
|
|
40
31
|
};
|
|
41
32
|
|
|
42
|
-
// packages/discord-runtime/modules/shared.mjs
|
|
43
|
-
function discordAction(id, title, commandName, commandDescription, subcommandName, subcommandDescription, options, policy) {
|
|
44
|
-
if (Array.isArray(subcommandName) || subcommandName === void 0 && subcommandDescription && typeof subcommandDescription === "object" && !Array.isArray(subcommandDescription)) {
|
|
45
|
-
policy = subcommandDescription;
|
|
46
|
-
options = subcommandName;
|
|
47
|
-
subcommandDescription = void 0;
|
|
48
|
-
subcommandName = void 0;
|
|
49
|
-
}
|
|
50
|
-
return {
|
|
51
|
-
id,
|
|
52
|
-
title,
|
|
53
|
-
description: subcommandDescription ?? commandDescription,
|
|
54
|
-
...policy ? { policy } : {},
|
|
55
|
-
metadata: {
|
|
56
|
-
discordCommand: {
|
|
57
|
-
commandName,
|
|
58
|
-
commandDescription,
|
|
59
|
-
...subcommandName ? { subcommandName } : {},
|
|
60
|
-
...subcommandDescription ? { subcommandDescription } : {},
|
|
61
|
-
...options ? { options } : {}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
function stringOption(input, key) {
|
|
67
|
-
const value = input[key];
|
|
68
|
-
return typeof value === "string" ? value.trim() : "";
|
|
69
|
-
}
|
|
70
|
-
function toRuntimeReply(payload) {
|
|
71
|
-
const blocks = (payload.embeds ?? []).map((embed) => ({
|
|
72
|
-
kind: "fields",
|
|
73
|
-
...embed.title ? { title: embed.title } : {},
|
|
74
|
-
...embed.description ? { text: embed.description } : {},
|
|
75
|
-
...embed.fields ? {
|
|
76
|
-
fields: embed.fields.map((field) => ({
|
|
77
|
-
label: field.name,
|
|
78
|
-
value: field.value,
|
|
79
|
-
...field.inline !== void 0 ? { inline: field.inline } : {}
|
|
80
|
-
}))
|
|
81
|
-
} : {}
|
|
82
|
-
}));
|
|
83
|
-
return {
|
|
84
|
-
...payload.content ? { text: payload.content } : {},
|
|
85
|
-
...blocks.length > 0 ? { blocks } : {}
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
async function reply(event, payload) {
|
|
89
|
-
const native = event.native?.payload;
|
|
90
|
-
if (native && typeof native === "object" && typeof native.reply === "function") {
|
|
91
|
-
await native.reply(payload);
|
|
92
|
-
return { handled: true };
|
|
93
|
-
}
|
|
94
|
-
return { handled: true, reply: toRuntimeReply(payload) };
|
|
95
|
-
}
|
|
96
|
-
async function defer(event, payload) {
|
|
97
|
-
const native = event.native?.payload;
|
|
98
|
-
if (native && typeof native === "object" && typeof native.defer === "function") {
|
|
99
|
-
await native.defer(payload);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
function isMissingPermissions(error) {
|
|
103
|
-
return !!error && typeof error === "object" && error.code === 50013;
|
|
104
|
-
}
|
|
105
|
-
function workspaceDisplay(sessionId) {
|
|
106
|
-
return `runtime/workspaces/${sessionId}`;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// packages/discord-runtime/modules/admin-control/index.mjs
|
|
110
|
-
function currentThreadIdOrNull(context, transportResourceId) {
|
|
111
|
-
return context.getSessionByTransportResourceId(transportResourceId)?.threadId ?? null;
|
|
112
|
-
}
|
|
113
|
-
var admin_control_default = {
|
|
114
|
-
id: manifest_default.id,
|
|
115
|
-
manifest: manifest_default,
|
|
116
|
-
actions() {
|
|
117
|
-
return [
|
|
118
|
-
discordAction(
|
|
119
|
-
"runtime.admin.status",
|
|
120
|
-
"Admin status",
|
|
121
|
-
"admin",
|
|
122
|
-
"Administrative runtime controls",
|
|
123
|
-
"status",
|
|
124
|
-
"Show runtime control state",
|
|
125
|
-
void 0,
|
|
126
|
-
{ allowedWhileDraining: true, bypassQueue: true }
|
|
127
|
-
),
|
|
128
|
-
discordAction(
|
|
129
|
-
"runtime.admin.reload",
|
|
130
|
-
"Reload runtime",
|
|
131
|
-
"admin",
|
|
132
|
-
"Administrative runtime controls",
|
|
133
|
-
"reload",
|
|
134
|
-
"Reload the runtime worker",
|
|
135
|
-
[
|
|
136
|
-
{
|
|
137
|
-
type: "string",
|
|
138
|
-
name: "mode",
|
|
139
|
-
description: "Reload mode",
|
|
140
|
-
required: true,
|
|
141
|
-
choices: [
|
|
142
|
-
{ name: "graceful", value: "graceful" },
|
|
143
|
-
{ name: "force", value: "force" }
|
|
144
|
-
]
|
|
145
|
-
}
|
|
146
|
-
],
|
|
147
|
-
{ allowedWhileDraining: true, bypassQueue: true }
|
|
148
|
-
),
|
|
149
|
-
discordAction(
|
|
150
|
-
"runtime.admin.provider-stop",
|
|
151
|
-
"Stop provider sessions",
|
|
152
|
-
"admin",
|
|
153
|
-
"Administrative runtime controls",
|
|
154
|
-
"provider-stop",
|
|
155
|
-
"Stop provider sessions",
|
|
156
|
-
[
|
|
157
|
-
{
|
|
158
|
-
type: "string",
|
|
159
|
-
name: "scope",
|
|
160
|
-
description: "Whether to stop all sessions or only the current session",
|
|
161
|
-
required: true,
|
|
162
|
-
choices: [
|
|
163
|
-
{ name: "all", value: "all" },
|
|
164
|
-
{ name: "current", value: "current" }
|
|
165
|
-
]
|
|
166
|
-
}
|
|
167
|
-
],
|
|
168
|
-
{ allowedWhileDraining: true, bypassQueue: true }
|
|
169
|
-
),
|
|
170
|
-
discordAction(
|
|
171
|
-
"runtime.admin.provider-start",
|
|
172
|
-
"Recover provider sessions",
|
|
173
|
-
"admin",
|
|
174
|
-
"Administrative runtime controls",
|
|
175
|
-
"provider-start",
|
|
176
|
-
"Recover provider sessions",
|
|
177
|
-
[
|
|
178
|
-
{
|
|
179
|
-
type: "string",
|
|
180
|
-
name: "scope",
|
|
181
|
-
description: "Whether to recover all sessions or only the current session",
|
|
182
|
-
required: true,
|
|
183
|
-
choices: [
|
|
184
|
-
{ name: "all", value: "all" },
|
|
185
|
-
{ name: "current", value: "current" }
|
|
186
|
-
]
|
|
187
|
-
}
|
|
188
|
-
],
|
|
189
|
-
{ allowedWhileDraining: true, bypassQueue: true }
|
|
190
|
-
),
|
|
191
|
-
discordAction(
|
|
192
|
-
"runtime.admin.accepting",
|
|
193
|
-
"Toggle accepting work",
|
|
194
|
-
"admin",
|
|
195
|
-
"Administrative runtime controls",
|
|
196
|
-
"accepting",
|
|
197
|
-
"Enable or disable acceptance of new work",
|
|
198
|
-
[
|
|
199
|
-
{
|
|
200
|
-
type: "string",
|
|
201
|
-
name: "value",
|
|
202
|
-
description: "Whether the runtime should accept new work",
|
|
203
|
-
required: true,
|
|
204
|
-
choices: [
|
|
205
|
-
{ name: "true", value: "true" },
|
|
206
|
-
{ name: "false", value: "false" }
|
|
207
|
-
]
|
|
208
|
-
}
|
|
209
|
-
],
|
|
210
|
-
{ allowedWhileDraining: true, bypassQueue: true }
|
|
211
|
-
)
|
|
212
|
-
];
|
|
213
|
-
},
|
|
214
|
-
async onAction(event, context) {
|
|
215
|
-
if (!event.actionId.startsWith("runtime.admin.")) {
|
|
216
|
-
return { handled: false };
|
|
217
|
-
}
|
|
218
|
-
const requestedBy = event.actor;
|
|
219
|
-
if (!context.isAdminActor(requestedBy)) {
|
|
220
|
-
context.appendAuditEvent("runtime.admin.denied", {
|
|
221
|
-
actionId: event.actionId,
|
|
222
|
-
requestedBy: requestedBy.actorId,
|
|
223
|
-
accessGroupIds: requestedBy.accessGroupIds ?? [],
|
|
224
|
-
isSurfaceAdmin: requestedBy.isSurfaceAdmin === true
|
|
225
|
-
});
|
|
226
|
-
return await reply(event, {
|
|
227
|
-
content: "This command is restricted to Moorline admins.",
|
|
228
|
-
ephemeral: true
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
if (event.actionId === "runtime.admin.status") {
|
|
232
|
-
const control = context.getRuntimeControlStatus();
|
|
233
|
-
const runtime = context.getRuntimeStatus();
|
|
234
|
-
return await reply(event, {
|
|
235
|
-
content: "Moorline admin status",
|
|
236
|
-
embeds: [
|
|
237
|
-
{
|
|
238
|
-
title: "Runtime Control",
|
|
239
|
-
color: 3447003,
|
|
240
|
-
fields: [
|
|
241
|
-
{ name: "Supervised", value: control.supervised ? "yes" : "no", inline: true },
|
|
242
|
-
{ name: "Accepting Work", value: control.acceptingNewWork ? "yes" : "no", inline: true },
|
|
243
|
-
{ name: "Running Sessions", value: String(runtime.runningSessions), inline: true },
|
|
244
|
-
{ name: "Waiting Sessions", value: String(runtime.waitingSessions), inline: true }
|
|
245
|
-
],
|
|
246
|
-
timestamp: context.nowIso()
|
|
247
|
-
}
|
|
248
|
-
],
|
|
249
|
-
ephemeral: true
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
if (event.actionId === "runtime.admin.reload") {
|
|
253
|
-
const mode = stringOption(event.input, "mode") === "force" ? "force" : "graceful";
|
|
254
|
-
const result = await context.requestRuntimeReload({
|
|
255
|
-
mode,
|
|
256
|
-
reason: `Discord admin request from ${requestedBy.actorId}`,
|
|
257
|
-
requestedBy
|
|
258
|
-
});
|
|
259
|
-
context.appendAuditEvent("runtime.reload.requested.by-admin", {
|
|
260
|
-
requestedBy: requestedBy.actorId,
|
|
261
|
-
mode
|
|
262
|
-
});
|
|
263
|
-
return await reply(event, {
|
|
264
|
-
content: result.detail,
|
|
265
|
-
ephemeral: true
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
if (event.actionId === "runtime.admin.provider-stop") {
|
|
269
|
-
const threadId = stringOption(event.input, "scope") === "current" && event.transportResourceId ? currentThreadIdOrNull(context, event.transportResourceId) : null;
|
|
270
|
-
if (stringOption(event.input, "scope") === "current" && !threadId) {
|
|
271
|
-
return await reply(event, {
|
|
272
|
-
content: "This resource does not map to an active Moorline session.",
|
|
273
|
-
ephemeral: true
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
await context.stopProvider({
|
|
277
|
-
...threadId ? { threadId } : {},
|
|
278
|
-
reason: `Discord admin request from ${requestedBy.actorId}`,
|
|
279
|
-
requestedBy
|
|
280
|
-
});
|
|
281
|
-
return await reply(event, {
|
|
282
|
-
content: threadId ? `Stopped provider session ${threadId}.` : "Stopped all provider sessions.",
|
|
283
|
-
ephemeral: true
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
if (event.actionId === "runtime.admin.provider-start") {
|
|
287
|
-
const threadId = stringOption(event.input, "scope") === "current" && event.transportResourceId ? currentThreadIdOrNull(context, event.transportResourceId) : null;
|
|
288
|
-
if (stringOption(event.input, "scope") === "current" && !threadId) {
|
|
289
|
-
return await reply(event, {
|
|
290
|
-
content: "This resource does not map to an active Moorline session.",
|
|
291
|
-
ephemeral: true
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
await context.startProvider({
|
|
295
|
-
...threadId ? { threadId } : {},
|
|
296
|
-
reason: `Discord admin request from ${requestedBy.actorId}`,
|
|
297
|
-
requestedBy
|
|
298
|
-
});
|
|
299
|
-
return await reply(event, {
|
|
300
|
-
content: threadId ? `Recovered provider session ${threadId}.` : "Recovered all provider sessions.",
|
|
301
|
-
ephemeral: true
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
if (event.actionId === "runtime.admin.accepting") {
|
|
305
|
-
const accepting = stringOption(event.input, "value") === "true";
|
|
306
|
-
await context.setRuntimeAcceptingNewWork({
|
|
307
|
-
accepting,
|
|
308
|
-
reason: `Discord admin request from ${requestedBy.actorId}`,
|
|
309
|
-
requestedBy
|
|
310
|
-
});
|
|
311
|
-
return await reply(event, {
|
|
312
|
-
content: accepting ? "Runtime is now accepting new work." : "Runtime is no longer accepting new work.",
|
|
313
|
-
ephemeral: true
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
|
-
return await reply(event, {
|
|
317
|
-
content: `Unsupported admin action: ${event.actionId}`,
|
|
318
|
-
ephemeral: true
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
};
|
|
322
|
-
|
|
323
|
-
// packages/discord-runtime/modules/channel-lifecycle/index.mjs
|
|
324
|
-
function summarizeArchivedTarget(target) {
|
|
325
|
-
return {
|
|
326
|
-
id: target.session.sessionId,
|
|
327
|
-
transportResourceId: target.session.transportResourceId,
|
|
328
|
-
workspacePath: target.session.workspacePath
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
var channel_lifecycle_default = {
|
|
332
|
-
id: manifest_default.id,
|
|
333
|
-
manifest: manifest_default,
|
|
334
|
-
actions() {
|
|
335
|
-
return [
|
|
336
|
-
discordAction(
|
|
337
|
-
"resource.archive",
|
|
338
|
-
"Archive the current Moorline session resource",
|
|
339
|
-
"archive",
|
|
340
|
-
"Archive the current Moorline session resource",
|
|
341
|
-
void 0,
|
|
342
|
-
{ allowedWhileDraining: true, bypassQueue: true }
|
|
343
|
-
),
|
|
344
|
-
discordAction(
|
|
345
|
-
"resource.delete",
|
|
346
|
-
"Delete the current archived Moorline session resource",
|
|
347
|
-
"delete",
|
|
348
|
-
"Delete the current archived Moorline session resource",
|
|
349
|
-
[
|
|
350
|
-
{
|
|
351
|
-
type: "string",
|
|
352
|
-
name: "confirm",
|
|
353
|
-
description: "Type delete to confirm destructive removal",
|
|
354
|
-
required: true,
|
|
355
|
-
choices: [{ name: "delete", value: "delete" }]
|
|
356
|
-
}
|
|
357
|
-
],
|
|
358
|
-
{ allowedWhileDraining: true, bypassQueue: true }
|
|
359
|
-
)
|
|
360
|
-
];
|
|
361
|
-
},
|
|
362
|
-
async onAction(event, context) {
|
|
363
|
-
if (event.actionId === "resource.archive") {
|
|
364
|
-
if (!event.transportResourceId) {
|
|
365
|
-
return await reply(event, { content: "This action requires a target resource.", ephemeral: true });
|
|
366
|
-
}
|
|
367
|
-
try {
|
|
368
|
-
const archived = await context.archiveTransportResourceTarget({ transportResourceId: event.transportResourceId });
|
|
369
|
-
if (!archived) {
|
|
370
|
-
return await reply(event, {
|
|
371
|
-
content: "This resource is not an archivable Moorline session.",
|
|
372
|
-
ephemeral: true
|
|
373
|
-
});
|
|
374
|
-
}
|
|
375
|
-
const target = summarizeArchivedTarget(archived);
|
|
376
|
-
await context.sendMessage(target.transportResourceId, {
|
|
377
|
-
text: "Session archived. Use `/delete confirm:delete` to remove the local workspace.",
|
|
378
|
-
blocks: [
|
|
379
|
-
{
|
|
380
|
-
kind: "fields",
|
|
381
|
-
title: "Session Archived",
|
|
382
|
-
tone: "warning",
|
|
383
|
-
fields: [
|
|
384
|
-
{ label: "Session", value: target.id },
|
|
385
|
-
{ label: "Workspace", value: workspaceDisplay(target.id) }
|
|
386
|
-
]
|
|
387
|
-
}
|
|
388
|
-
]
|
|
389
|
-
});
|
|
390
|
-
await context.sendStatusUpdate({
|
|
391
|
-
text: `Archived session ${target.id} from ${target.transportResourceId}.`,
|
|
392
|
-
blocks: [
|
|
393
|
-
{
|
|
394
|
-
kind: "fields",
|
|
395
|
-
title: "Session Archived",
|
|
396
|
-
tone: "warning",
|
|
397
|
-
fields: [
|
|
398
|
-
{ label: "Session", value: target.id },
|
|
399
|
-
{ label: "Resource", value: target.transportResourceId }
|
|
400
|
-
]
|
|
401
|
-
}
|
|
402
|
-
]
|
|
403
|
-
});
|
|
404
|
-
context.appendAuditEvent("session.archived", {
|
|
405
|
-
sessionId: target.id,
|
|
406
|
-
transportResourceId: target.transportResourceId,
|
|
407
|
-
pluginId: manifest_default.id
|
|
408
|
-
});
|
|
409
|
-
return await reply(event, {
|
|
410
|
-
content: `Archived session ${target.id}.`,
|
|
411
|
-
ephemeral: true
|
|
412
|
-
});
|
|
413
|
-
} catch (error) {
|
|
414
|
-
if (!isMissingPermissions(error)) throw error;
|
|
415
|
-
return await reply(event, {
|
|
416
|
-
content: "Archive failed: Moorline needs permission to update the current resource and archive area.",
|
|
417
|
-
ephemeral: true
|
|
418
|
-
});
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
if (event.actionId === "resource.delete") {
|
|
422
|
-
if (!event.transportResourceId) {
|
|
423
|
-
return await reply(event, { content: "This action requires a target resource.", ephemeral: true });
|
|
424
|
-
}
|
|
425
|
-
if (stringOption(event.input, "confirm") !== "delete") {
|
|
426
|
-
return await reply(event, {
|
|
427
|
-
content: "Deletion cancelled: pass confirm:delete to remove the archived resource.",
|
|
428
|
-
ephemeral: true
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
const session = context.getSessionByTransportResourceId(event.transportResourceId);
|
|
432
|
-
if (session && session.lifecycleStatus !== "archived") {
|
|
433
|
-
return await reply(event, {
|
|
434
|
-
content: `Session ${session.sessionId} must be archived before deletion.`,
|
|
435
|
-
ephemeral: true
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
if (!session) {
|
|
439
|
-
return await reply(event, {
|
|
440
|
-
content: "This resource is not a deletable Moorline session.",
|
|
441
|
-
ephemeral: true
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
|
-
await defer(event, { ephemeral: true });
|
|
445
|
-
try {
|
|
446
|
-
const deleted = await context.deleteArchivedTransportResourceTarget({ transportResourceId: event.transportResourceId });
|
|
447
|
-
if (!deleted) {
|
|
448
|
-
return await reply(event, {
|
|
449
|
-
content: "This archived resource could not be deleted.",
|
|
450
|
-
ephemeral: true
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
|
-
const target = summarizeArchivedTarget(deleted);
|
|
454
|
-
await context.sendStatusUpdate({
|
|
455
|
-
text: `Deleted archived session ${target.id} and removed its local workspace.`,
|
|
456
|
-
blocks: [
|
|
457
|
-
{
|
|
458
|
-
kind: "fields",
|
|
459
|
-
title: "Session Deleted",
|
|
460
|
-
tone: "danger",
|
|
461
|
-
fields: [
|
|
462
|
-
{ label: "Session", value: target.id },
|
|
463
|
-
{ label: "Workspace", value: workspaceDisplay(target.id) }
|
|
464
|
-
]
|
|
465
|
-
}
|
|
466
|
-
]
|
|
467
|
-
});
|
|
468
|
-
context.appendAuditEvent("session.deleted", {
|
|
469
|
-
sessionId: target.id,
|
|
470
|
-
transportResourceId: target.transportResourceId,
|
|
471
|
-
workspacePath: target.workspacePath,
|
|
472
|
-
pluginId: manifest_default.id
|
|
473
|
-
});
|
|
474
|
-
return await reply(event, {
|
|
475
|
-
content: `Deleted archived session ${target.id} and removed its local workspace (${workspaceDisplay(target.id)}).`,
|
|
476
|
-
ephemeral: true
|
|
477
|
-
});
|
|
478
|
-
} catch (error) {
|
|
479
|
-
if (!isMissingPermissions(error)) throw error;
|
|
480
|
-
return await reply(event, {
|
|
481
|
-
content: "Delete failed: Moorline needs permission to delete the archived resource.",
|
|
482
|
-
ephemeral: true
|
|
483
|
-
});
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
return { handled: false };
|
|
487
|
-
}
|
|
488
|
-
};
|
|
489
|
-
|
|
490
33
|
// packages/discord-runtime/modules/routing/index.mjs
|
|
491
34
|
import { readFile } from "node:fs/promises";
|
|
492
35
|
var prompts = {
|
|
493
|
-
coordination: readFile(new globalThis.URL("./coordination.md", import.meta.url), "utf8").then((value) => value.trim()),
|
|
494
36
|
session: readFile(new globalThis.URL("./session.md", import.meta.url), "utf8").then((value) => value.trim())
|
|
495
37
|
};
|
|
496
38
|
function providerCommandLine(context) {
|
|
@@ -513,35 +55,6 @@ async function loadPromptSections(context, surface, dynamicSections = []) {
|
|
|
513
55
|
}
|
|
514
56
|
return sections;
|
|
515
57
|
}
|
|
516
|
-
function mainCoordinationRuntimeMode(context) {
|
|
517
|
-
return context.config?.defaults?.runtimeMode === "approval-required" ? "approval-required" : "full-access";
|
|
518
|
-
}
|
|
519
|
-
async function routeCoordinationMessage(event, context) {
|
|
520
|
-
const runtimeMode = mainCoordinationRuntimeMode(context);
|
|
521
|
-
const reply2 = await context.runAgent({
|
|
522
|
-
surface: "coordination",
|
|
523
|
-
transportResourceId: event.transportResourceId,
|
|
524
|
-
actorId: event.actor.actorId,
|
|
525
|
-
actorLabel: event.actor.displayName ?? event.actor.actorId,
|
|
526
|
-
message: event.message.text,
|
|
527
|
-
attachments: event.message.attachments,
|
|
528
|
-
session: null,
|
|
529
|
-
cwd: context.getRuntimeRootPath(),
|
|
530
|
-
runtimeMode,
|
|
531
|
-
context: {
|
|
532
|
-
systemPromptSections: await loadPromptSections(context, "coordination", [
|
|
533
|
-
"This coordination surface may use the runtime root for machine-level work, but it is not a durable worker workspace."
|
|
534
|
-
])
|
|
535
|
-
}
|
|
536
|
-
});
|
|
537
|
-
await context.sendMessage(event.transportResourceId, reply2);
|
|
538
|
-
context.appendAuditEvent("coordination.replied", {
|
|
539
|
-
transportResourceId: event.transportResourceId,
|
|
540
|
-
mode: runtimeMode,
|
|
541
|
-
pluginId: manifest_default.id
|
|
542
|
-
});
|
|
543
|
-
return { handled: true };
|
|
544
|
-
}
|
|
545
58
|
async function routeSessionMessage(event, context, session) {
|
|
546
59
|
const reply2 = await context.runAgent({
|
|
547
60
|
surface: "session",
|
|
@@ -572,325 +85,85 @@ async function routeSessionMessage(event, context, session) {
|
|
|
572
85
|
var routing_default = {
|
|
573
86
|
id: manifest_default.id,
|
|
574
87
|
manifest: manifest_default,
|
|
575
|
-
async
|
|
576
|
-
if (event.type !== "message.received") {
|
|
88
|
+
async onTransportIntent(event, context) {
|
|
89
|
+
if (event.type !== "transport.message.received") {
|
|
577
90
|
return { handled: false };
|
|
578
91
|
}
|
|
579
|
-
const surface = context.getSurfaceState();
|
|
580
|
-
if (event.transportResourceId === surface.coordinationResourceId) {
|
|
581
|
-
return await routeCoordinationMessage(event, context);
|
|
582
|
-
}
|
|
583
92
|
const session = context.getSessionByTransportResourceId(event.transportResourceId);
|
|
584
|
-
if (!session
|
|
93
|
+
if (!session) {
|
|
585
94
|
return { handled: false };
|
|
586
95
|
}
|
|
587
96
|
return await routeSessionMessage(event, context, session);
|
|
588
97
|
}
|
|
589
98
|
};
|
|
590
99
|
|
|
591
|
-
// packages/discord-runtime/modules/
|
|
592
|
-
function
|
|
593
|
-
if (
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
const openSessions = sessions.filter((session) => session.lifecycleStatus !== "archived");
|
|
600
|
-
const coolSessions = sessions.filter((session) => session.lifecycleStatus === "cool");
|
|
601
|
-
const archivedSessions = sessions.filter((session) => session.lifecycleStatus === "archived");
|
|
100
|
+
// packages/discord-runtime/modules/shared.mjs
|
|
101
|
+
function discordAction(id, title, commandName, commandDescription, subcommandName, subcommandDescription, options, policy) {
|
|
102
|
+
if (Array.isArray(subcommandName) || subcommandName === void 0 && subcommandDescription && typeof subcommandDescription === "object" && !Array.isArray(subcommandDescription)) {
|
|
103
|
+
policy = subcommandDescription;
|
|
104
|
+
options = subcommandName;
|
|
105
|
+
subcommandDescription = void 0;
|
|
106
|
+
subcommandName = void 0;
|
|
107
|
+
}
|
|
602
108
|
return {
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
109
|
+
id,
|
|
110
|
+
title,
|
|
111
|
+
description: subcommandDescription ?? commandDescription,
|
|
112
|
+
...policy ? { policy } : {},
|
|
113
|
+
metadata: {
|
|
114
|
+
discordCommand: {
|
|
115
|
+
commandName,
|
|
116
|
+
commandDescription,
|
|
117
|
+
...subcommandName ? { subcommandName } : {},
|
|
118
|
+
...subcommandDescription ? { subcommandDescription } : {},
|
|
119
|
+
...options ? { options } : {}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
612
122
|
};
|
|
613
123
|
}
|
|
614
|
-
function
|
|
615
|
-
const
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
124
|
+
function toRuntimeReply(payload) {
|
|
125
|
+
const blocks = (payload.embeds ?? []).map((embed) => ({
|
|
126
|
+
kind: "fields",
|
|
127
|
+
...embed.title ? { title: embed.title } : {},
|
|
128
|
+
...embed.description ? { text: embed.description } : {},
|
|
129
|
+
...embed.fields ? {
|
|
130
|
+
fields: embed.fields.map((field) => ({
|
|
131
|
+
label: field.name,
|
|
132
|
+
value: field.value,
|
|
133
|
+
...field.inline !== void 0 ? { inline: field.inline } : {}
|
|
134
|
+
}))
|
|
135
|
+
} : {}
|
|
136
|
+
}));
|
|
620
137
|
return {
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
...actorLabel ? { label: actorLabel } : {}
|
|
138
|
+
...payload.content ? { text: payload.content } : {},
|
|
139
|
+
...blocks.length > 0 ? { blocks } : {}
|
|
624
140
|
};
|
|
625
141
|
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
return
|
|
631
|
-
discordAction(
|
|
632
|
-
"session.create",
|
|
633
|
-
"Create a new worker session",
|
|
634
|
-
"session",
|
|
635
|
-
"Manage Moorline worker sessions",
|
|
636
|
-
"create",
|
|
637
|
-
"Create a new worker session",
|
|
638
|
-
[
|
|
639
|
-
{ type: "string", name: "name", description: "Short session name", required: true },
|
|
640
|
-
{
|
|
641
|
-
type: "string",
|
|
642
|
-
name: "mode",
|
|
643
|
-
description: "Runtime mode",
|
|
644
|
-
choices: [
|
|
645
|
-
{ name: "full-access", value: "full-access" },
|
|
646
|
-
{ name: "approval-required", value: "approval-required" }
|
|
647
|
-
]
|
|
648
|
-
}
|
|
649
|
-
]
|
|
650
|
-
),
|
|
651
|
-
discordAction(
|
|
652
|
-
"session.archive",
|
|
653
|
-
"Archive a session",
|
|
654
|
-
"session",
|
|
655
|
-
"Manage Moorline worker sessions",
|
|
656
|
-
"archive",
|
|
657
|
-
"Archive a session resource",
|
|
658
|
-
[{ type: "string", name: "session_id", description: "Archive a specific session id" }],
|
|
659
|
-
{ allowedWhileDraining: true, bypassQueue: true }
|
|
660
|
-
),
|
|
661
|
-
discordAction(
|
|
662
|
-
"session.delete",
|
|
663
|
-
"Delete an archived session",
|
|
664
|
-
"session",
|
|
665
|
-
"Manage Moorline worker sessions",
|
|
666
|
-
"delete",
|
|
667
|
-
"Delete an archived session and its local workspace",
|
|
668
|
-
[
|
|
669
|
-
{
|
|
670
|
-
type: "string",
|
|
671
|
-
name: "confirm",
|
|
672
|
-
description: "Type delete to confirm destructive removal",
|
|
673
|
-
required: true,
|
|
674
|
-
choices: [{ name: "delete", value: "delete" }]
|
|
675
|
-
},
|
|
676
|
-
{ type: "string", name: "session_id", description: "Delete a specific archived session id" }
|
|
677
|
-
],
|
|
678
|
-
{ allowedWhileDraining: true, bypassQueue: true }
|
|
679
|
-
),
|
|
680
|
-
discordAction(
|
|
681
|
-
"session.list",
|
|
682
|
-
"List sessions",
|
|
683
|
-
"session",
|
|
684
|
-
"Manage Moorline worker sessions",
|
|
685
|
-
"list",
|
|
686
|
-
"List active and archived sessions"
|
|
687
|
-
)
|
|
688
|
-
];
|
|
689
|
-
},
|
|
690
|
-
async onAction(event, context) {
|
|
691
|
-
if (!event.actionId.startsWith("session.")) {
|
|
692
|
-
return { handled: false };
|
|
693
|
-
}
|
|
694
|
-
if (event.actionId === "session.create") {
|
|
695
|
-
const requestedName = stringOption(event.input, "name");
|
|
696
|
-
if (!requestedName) {
|
|
697
|
-
return await reply(event, { content: "name is required", ephemeral: true });
|
|
698
|
-
}
|
|
699
|
-
const requestedMode = stringOption(event.input, "mode");
|
|
700
|
-
const runtimeMode = requestedMode === "full-access" || requestedMode === "approval-required" ? requestedMode : context.config.defaults.runtimeMode;
|
|
701
|
-
const created = await context.createSession({
|
|
702
|
-
requestedName,
|
|
703
|
-
runtimeMode,
|
|
704
|
-
owner: sessionOwnerFromEvent(event)
|
|
705
|
-
});
|
|
706
|
-
const notificationErrors = [];
|
|
707
|
-
try {
|
|
708
|
-
await context.sendMessage(created.transportResourceId, {
|
|
709
|
-
text: `Session ready: ${created.session.sessionId}. Start by sharing your first task.`
|
|
710
|
-
});
|
|
711
|
-
} catch (error) {
|
|
712
|
-
notificationErrors.push(error instanceof Error ? error.message : String(error));
|
|
713
|
-
}
|
|
714
|
-
context.appendAuditEvent("session.created", {
|
|
715
|
-
sessionId: created.session.sessionId,
|
|
716
|
-
transportResourceId: created.transportResourceId,
|
|
717
|
-
runtimeMode,
|
|
718
|
-
pluginId: manifest_default.id
|
|
719
|
-
});
|
|
720
|
-
if (notificationErrors.length > 0) {
|
|
721
|
-
context.appendAuditEvent("session.created.notification_failed", {
|
|
722
|
-
sessionId: created.session.sessionId,
|
|
723
|
-
transportResourceId: created.transportResourceId,
|
|
724
|
-
runtimeMode,
|
|
725
|
-
errors: notificationErrors,
|
|
726
|
-
pluginId: manifest_default.id
|
|
727
|
-
});
|
|
728
|
-
}
|
|
729
|
-
return await reply(event, {
|
|
730
|
-
content: notificationErrors.length === 0 ? `Created session ${created.session.sessionId} in <#${created.transportResourceId}>.` : `Created session ${created.session.sessionId} in <#${created.transportResourceId}>. Warning: follow-up notifications failed; check runtime status.`,
|
|
731
|
-
ephemeral: true
|
|
732
|
-
});
|
|
733
|
-
}
|
|
734
|
-
if (event.actionId === "session.archive") {
|
|
735
|
-
if (!event.transportResourceId && !stringOption(event.input, "session_id")) {
|
|
736
|
-
return await reply(event, {
|
|
737
|
-
content: "Run this in a session resource or pass session_id.",
|
|
738
|
-
ephemeral: true
|
|
739
|
-
});
|
|
740
|
-
}
|
|
741
|
-
try {
|
|
742
|
-
const session = await context.archiveSession({
|
|
743
|
-
transportResourceId: event.transportResourceId ?? "",
|
|
744
|
-
...stringOption(event.input, "session_id") ? { sessionId: stringOption(event.input, "session_id") } : {}
|
|
745
|
-
});
|
|
746
|
-
if (!session) {
|
|
747
|
-
return await reply(event, { content: "No matching session found.", ephemeral: true });
|
|
748
|
-
}
|
|
749
|
-
context.appendAuditEvent("session.archived", {
|
|
750
|
-
sessionId: session.sessionId,
|
|
751
|
-
transportResourceId: session.transportResourceId,
|
|
752
|
-
pluginId: manifest_default.id
|
|
753
|
-
});
|
|
754
|
-
return await reply(event, {
|
|
755
|
-
content: `Archived session ${session.sessionId}.`,
|
|
756
|
-
ephemeral: true
|
|
757
|
-
});
|
|
758
|
-
} catch (error) {
|
|
759
|
-
if (!isMissingPermissions(error)) throw error;
|
|
760
|
-
return await reply(event, {
|
|
761
|
-
content: "Archive failed: Moorline needs permission to update the session resource and archive area.",
|
|
762
|
-
ephemeral: true
|
|
763
|
-
});
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
if (event.actionId === "session.delete") {
|
|
767
|
-
if (!event.transportResourceId && !stringOption(event.input, "session_id")) {
|
|
768
|
-
return await reply(event, {
|
|
769
|
-
content: "Run this in a session resource or pass session_id.",
|
|
770
|
-
ephemeral: true
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
|
-
const requestedSessionId = stringOption(event.input, "session_id");
|
|
774
|
-
const target = (requestedSessionId ? context.getSessionById(requestedSessionId) : null) ?? (event.transportResourceId ? context.getSessionByTransportResourceId(event.transportResourceId) : null);
|
|
775
|
-
if (!target) {
|
|
776
|
-
return await reply(event, { content: "No matching session found.", ephemeral: true });
|
|
777
|
-
}
|
|
778
|
-
if (target.lifecycleStatus !== "archived") {
|
|
779
|
-
return await reply(event, {
|
|
780
|
-
content: `Session ${target.sessionId} must be archived before deletion.`,
|
|
781
|
-
ephemeral: true
|
|
782
|
-
});
|
|
783
|
-
}
|
|
784
|
-
if (stringOption(event.input, "confirm") !== "delete") {
|
|
785
|
-
return await reply(event, {
|
|
786
|
-
content: "Deletion cancelled: pass confirm:delete to remove the archived session.",
|
|
787
|
-
ephemeral: true
|
|
788
|
-
});
|
|
789
|
-
}
|
|
790
|
-
if (event.transportResourceId && target.transportResourceId === event.transportResourceId) {
|
|
791
|
-
await defer(event, { ephemeral: true });
|
|
792
|
-
}
|
|
793
|
-
try {
|
|
794
|
-
const deleted = await context.deleteArchivedSession({
|
|
795
|
-
transportResourceId: event.transportResourceId ?? target.transportResourceId,
|
|
796
|
-
...requestedSessionId ? { sessionId: requestedSessionId } : {}
|
|
797
|
-
});
|
|
798
|
-
if (!deleted) {
|
|
799
|
-
return await reply(event, { content: "No matching session found.", ephemeral: true });
|
|
800
|
-
}
|
|
801
|
-
context.appendAuditEvent("session.deleted", {
|
|
802
|
-
sessionId: deleted.sessionId,
|
|
803
|
-
transportResourceId: deleted.transportResourceId,
|
|
804
|
-
workspacePath: deleted.workspacePath,
|
|
805
|
-
pluginId: manifest_default.id
|
|
806
|
-
});
|
|
807
|
-
return await reply(event, {
|
|
808
|
-
content: `Deleted archived session ${deleted.sessionId} and removed its local workspace (${workspaceDisplay(deleted.sessionId)}).`,
|
|
809
|
-
ephemeral: true
|
|
810
|
-
});
|
|
811
|
-
} catch (error) {
|
|
812
|
-
if (!isMissingPermissions(error)) throw error;
|
|
813
|
-
return await reply(event, {
|
|
814
|
-
content: "Delete failed: Moorline needs permission to delete the archived session resource.",
|
|
815
|
-
ephemeral: true
|
|
816
|
-
});
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
if (event.actionId === "session.list") {
|
|
820
|
-
return await reply(event, {
|
|
821
|
-
content: "Current Moorline sessions",
|
|
822
|
-
embeds: [buildSessionListEmbed(context.listSessions())],
|
|
823
|
-
ephemeral: true
|
|
824
|
-
});
|
|
825
|
-
}
|
|
826
|
-
return await reply(event, {
|
|
827
|
-
content: `Unsupported session action: ${event.actionId}`,
|
|
828
|
-
ephemeral: true
|
|
829
|
-
});
|
|
142
|
+
async function reply(event, payload) {
|
|
143
|
+
const native = event.native?.payload;
|
|
144
|
+
if (native && typeof native === "object" && typeof native.reply === "function") {
|
|
145
|
+
await native.reply(payload);
|
|
146
|
+
return { handled: true };
|
|
830
147
|
}
|
|
831
|
-
};
|
|
148
|
+
return { handled: true, reply: toRuntimeReply(payload) };
|
|
149
|
+
}
|
|
832
150
|
|
|
833
151
|
// packages/discord-runtime/modules/status/index.mjs
|
|
834
|
-
|
|
835
|
-
function buildHealthEmbed(input) {
|
|
152
|
+
function statusEmbed(input) {
|
|
836
153
|
return {
|
|
837
|
-
title: "Moorline
|
|
838
|
-
color: input.
|
|
154
|
+
title: "Moorline Status",
|
|
155
|
+
color: input.acceptingNewWork ? 3066993 : 15844367,
|
|
839
156
|
fields: [
|
|
840
157
|
{ name: "Uptime", value: `${input.uptimeSeconds}s`, inline: true },
|
|
841
|
-
{ name: "
|
|
842
|
-
{ name: "
|
|
843
|
-
{ name: "
|
|
844
|
-
{ name: "
|
|
845
|
-
{ name: "
|
|
158
|
+
{ name: "Accepting Work", value: input.acceptingNewWork ? "Yes" : "No", inline: true },
|
|
159
|
+
{ name: "Open Sessions", value: String(input.openSessions), inline: true },
|
|
160
|
+
{ name: "Running", value: String(input.runningSessions), inline: true },
|
|
161
|
+
{ name: "Waiting", value: String(input.waitingSessions), inline: true },
|
|
162
|
+
{ name: "Provider", value: input.providerLabel ?? "unknown", inline: true }
|
|
846
163
|
],
|
|
847
164
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
848
165
|
};
|
|
849
166
|
}
|
|
850
|
-
function parseAnswers(raw) {
|
|
851
|
-
try {
|
|
852
|
-
const parsed = JSON.parse(raw);
|
|
853
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return { answer: raw };
|
|
854
|
-
const result = {};
|
|
855
|
-
for (const [key, value] of Object.entries(parsed)) {
|
|
856
|
-
if (typeof value === "string") result[key] = value;
|
|
857
|
-
else if (Array.isArray(value)) {
|
|
858
|
-
const normalized = value.filter((entry) => typeof entry === "string");
|
|
859
|
-
if (normalized.length > 0) result[key] = normalized;
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
return Object.keys(result).length > 0 ? result : { answer: raw };
|
|
863
|
-
} catch {
|
|
864
|
-
return { answer: raw };
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
function toBlock(title, tone, fields) {
|
|
868
|
-
return {
|
|
869
|
-
kind: "fields",
|
|
870
|
-
title,
|
|
871
|
-
tone,
|
|
872
|
-
fields: fields.map((field) => ({
|
|
873
|
-
label: field.name,
|
|
874
|
-
value: field.value,
|
|
875
|
-
...field.inline !== void 0 ? { inline: field.inline } : {}
|
|
876
|
-
}))
|
|
877
|
-
};
|
|
878
|
-
}
|
|
879
|
-
function truncateEmbedValue(value, maxLength = MAX_EMBED_FIELD_VALUE) {
|
|
880
|
-
const normalized = String(value ?? "").trim();
|
|
881
|
-
if (!normalized) return "None";
|
|
882
|
-
if (normalized.length <= maxLength) return normalized;
|
|
883
|
-
return `${normalized.slice(0, Math.max(0, maxLength - 14))}...(truncated)`;
|
|
884
|
-
}
|
|
885
|
-
function summarizeRuntimeIssue(event) {
|
|
886
|
-
if (event.type === "turn.failed") {
|
|
887
|
-
return "A turn failed. Check local runtime audit logs for detailed diagnostics.";
|
|
888
|
-
}
|
|
889
|
-
if (event.type === "provider.closed") {
|
|
890
|
-
return "A provider session closed unexpectedly. Check local runtime audit logs for details.";
|
|
891
|
-
}
|
|
892
|
-
return "A runtime error occurred. Check local runtime audit logs for details.";
|
|
893
|
-
}
|
|
894
167
|
var status_default = {
|
|
895
168
|
id: manifest_default.id,
|
|
896
169
|
manifest: manifest_default,
|
|
@@ -900,253 +173,32 @@ var status_default = {
|
|
|
900
173
|
"runtime.status",
|
|
901
174
|
"Show runtime status",
|
|
902
175
|
"status",
|
|
903
|
-
"Show Moorline
|
|
176
|
+
"Show Moorline runtime status",
|
|
904
177
|
void 0,
|
|
905
178
|
void 0,
|
|
906
179
|
void 0,
|
|
907
180
|
{ allowedWhileDraining: true }
|
|
908
|
-
),
|
|
909
|
-
discordAction(
|
|
910
|
-
"runtime.turn.stop",
|
|
911
|
-
"Stop the active turn",
|
|
912
|
-
"turn",
|
|
913
|
-
"Control the active provider turn in this session",
|
|
914
|
-
"stop",
|
|
915
|
-
"Interrupt the active turn for this session",
|
|
916
|
-
void 0,
|
|
917
|
-
{ allowedWhileDraining: true, bypassQueue: true }
|
|
918
|
-
),
|
|
919
|
-
discordAction(
|
|
920
|
-
"runtime.request.cancel",
|
|
921
|
-
"Cancel a pending runtime request",
|
|
922
|
-
"request",
|
|
923
|
-
"Respond to a pending runtime user-input request",
|
|
924
|
-
"cancel",
|
|
925
|
-
"Cancel a pending runtime request",
|
|
926
|
-
[{ type: "string", name: "request_id", description: "Pending request id", required: true }],
|
|
927
|
-
{ allowedWhileDraining: true, bypassQueue: true }
|
|
928
|
-
),
|
|
929
|
-
discordAction(
|
|
930
|
-
"runtime.request.answer",
|
|
931
|
-
"Answer a pending runtime request",
|
|
932
|
-
"request",
|
|
933
|
-
"Respond to a pending runtime user-input request",
|
|
934
|
-
"answer",
|
|
935
|
-
"Answer a pending runtime user-input request",
|
|
936
|
-
[
|
|
937
|
-
{ type: "string", name: "request_id", description: "Pending request id", required: true },
|
|
938
|
-
{
|
|
939
|
-
type: "string",
|
|
940
|
-
name: "answers",
|
|
941
|
-
description: "Plain text answer or JSON object keyed by question id",
|
|
942
|
-
required: true
|
|
943
|
-
}
|
|
944
|
-
],
|
|
945
|
-
{ allowedWhileDraining: true, bypassQueue: true }
|
|
946
181
|
)
|
|
947
182
|
];
|
|
948
183
|
},
|
|
949
|
-
async onDomainEvent(event, context) {
|
|
950
|
-
if (event.transportResourceId === null) return;
|
|
951
|
-
if (event.type === "turn.waiting_for_approval" || event.type === "turn.waiting_for_input") {
|
|
952
|
-
await context.sendStatusUpdate({
|
|
953
|
-
text: `Session ${event.sessionId ?? event.threadId} is waiting.`,
|
|
954
|
-
blocks: [
|
|
955
|
-
toBlock("Turn Waiting", "warning", [
|
|
956
|
-
{ name: "Session", value: event.sessionId ?? event.threadId },
|
|
957
|
-
{ name: "State", value: event.type.replace("turn.", "").replace(/_/g, " ") }
|
|
958
|
-
])
|
|
959
|
-
]
|
|
960
|
-
});
|
|
961
|
-
}
|
|
962
|
-
if (event.type === "turn.failed" || event.type === "runtime.error" || event.type === "provider.closed") {
|
|
963
|
-
const detail = summarizeRuntimeIssue(event);
|
|
964
|
-
await context.sendStatusUpdate({
|
|
965
|
-
text: `Session ${event.sessionId ?? event.threadId} hit a runtime problem.`,
|
|
966
|
-
blocks: [
|
|
967
|
-
toBlock("Runtime Issue", "danger", [
|
|
968
|
-
{ name: "Session", value: event.sessionId ?? event.threadId },
|
|
969
|
-
{ name: "Detail", value: detail }
|
|
970
|
-
])
|
|
971
|
-
]
|
|
972
|
-
});
|
|
973
|
-
}
|
|
974
|
-
},
|
|
975
184
|
async onAction(event, context) {
|
|
976
|
-
if (event.actionId === "runtime.turn.stop") {
|
|
977
|
-
if (!event.transportResourceId) {
|
|
978
|
-
return await reply(event, { content: "This action requires a target session resource.", ephemeral: true });
|
|
979
|
-
}
|
|
980
|
-
const session = context.getSessionByTransportResourceId(event.transportResourceId);
|
|
981
|
-
if (!session) {
|
|
982
|
-
return await reply(event, {
|
|
983
|
-
content: "This resource does not have an active Moorline session.",
|
|
984
|
-
ephemeral: true
|
|
985
|
-
});
|
|
986
|
-
}
|
|
987
|
-
await context.interruptTurn({ threadId: session.threadId });
|
|
988
|
-
return await reply(event, {
|
|
989
|
-
content: `Interrupt sent for ${session.sessionId}.`,
|
|
990
|
-
ephemeral: true
|
|
991
|
-
});
|
|
992
|
-
}
|
|
993
|
-
if (event.actionId === "runtime.request.cancel" || event.actionId === "runtime.request.answer") {
|
|
994
|
-
if (!event.transportResourceId) {
|
|
995
|
-
return await reply(event, { content: "This action requires a target resource.", ephemeral: true });
|
|
996
|
-
}
|
|
997
|
-
const requestId = stringOption(event.input, "request_id");
|
|
998
|
-
if (!requestId) {
|
|
999
|
-
return await reply(event, { content: "request_id is required.", ephemeral: true });
|
|
1000
|
-
}
|
|
1001
|
-
const request = context.listPendingRequests(event.transportResourceId).find((entry) => entry.requestId === requestId);
|
|
1002
|
-
if (!request) {
|
|
1003
|
-
return await reply(event, {
|
|
1004
|
-
content: `No pending request ${requestId} was found in this resource.`,
|
|
1005
|
-
ephemeral: true
|
|
1006
|
-
});
|
|
1007
|
-
}
|
|
1008
|
-
if (event.actionId === "runtime.request.cancel") {
|
|
1009
|
-
try {
|
|
1010
|
-
await context.cancelRuntimeRequest({
|
|
1011
|
-
threadId: request.threadId,
|
|
1012
|
-
requestId,
|
|
1013
|
-
requestType: request.requestType,
|
|
1014
|
-
requesterActor: event.actor
|
|
1015
|
-
});
|
|
1016
|
-
} catch (error) {
|
|
1017
|
-
return await reply(event, {
|
|
1018
|
-
content: error instanceof Error ? error.message : String(error),
|
|
1019
|
-
ephemeral: true
|
|
1020
|
-
});
|
|
1021
|
-
}
|
|
1022
|
-
return await reply(event, {
|
|
1023
|
-
content: `Cancelled request ${requestId}.`,
|
|
1024
|
-
ephemeral: true
|
|
1025
|
-
});
|
|
1026
|
-
}
|
|
1027
|
-
if (request.requestType !== "tool_user_input") {
|
|
1028
|
-
return await reply(event, {
|
|
1029
|
-
content: `Request ${requestId} is approval-driven. Use the request actions instead.`,
|
|
1030
|
-
ephemeral: true
|
|
1031
|
-
});
|
|
1032
|
-
}
|
|
1033
|
-
try {
|
|
1034
|
-
await context.respondToRuntimeUserInput({
|
|
1035
|
-
threadId: request.threadId,
|
|
1036
|
-
requestId,
|
|
1037
|
-
answers: parseAnswers(stringOption(event.input, "answers")),
|
|
1038
|
-
requesterActor: event.actor
|
|
1039
|
-
});
|
|
1040
|
-
} catch (error) {
|
|
1041
|
-
return await reply(event, {
|
|
1042
|
-
content: error instanceof Error ? error.message : String(error),
|
|
1043
|
-
ephemeral: true
|
|
1044
|
-
});
|
|
1045
|
-
}
|
|
1046
|
-
return await reply(event, {
|
|
1047
|
-
content: `Answered request ${requestId}.`,
|
|
1048
|
-
ephemeral: true
|
|
1049
|
-
});
|
|
1050
|
-
}
|
|
1051
185
|
if (event.actionId !== "runtime.status") {
|
|
1052
186
|
return { handled: false };
|
|
1053
187
|
}
|
|
1054
|
-
const surface = context.getSurfaceState();
|
|
1055
188
|
const runtimeStatus = context.getRuntimeStatus();
|
|
189
|
+
const controlStatus = context.getRuntimeControlStatus();
|
|
1056
190
|
const providerDiagnostics = context.getProviderDiagnostics();
|
|
1057
|
-
const overview = context.getRuntimeOverview();
|
|
1058
|
-
const receipts = overview.receipts;
|
|
1059
|
-
const activities = overview.sessions.flatMap((session) => session.recentActivities).slice(-5);
|
|
1060
|
-
const projectionStates = overview.projectionStates;
|
|
1061
|
-
const projectionFailures = projectionStates.filter((entry) => entry.failure !== null);
|
|
1062
|
-
const providerErrorCount = Number(providerDiagnostics.statusCounts.error ?? 0);
|
|
1063
|
-
const dbOk = projectionFailures.length === 0;
|
|
1064
|
-
const environmentOk = providerErrorCount === 0;
|
|
1065
|
-
const dbDetail = projectionFailures.length === 0 ? "OK" : `Error (${projectionFailures.length} projection failure${projectionFailures.length === 1 ? "" : "s"})`;
|
|
1066
|
-
const environmentDetail = providerErrorCount === 0 ? "OK" : `Error (${providerErrorCount} provider session${providerErrorCount === 1 ? "" : "s"})`;
|
|
1067
191
|
return await reply(event, {
|
|
1068
192
|
content: "Moorline runtime status",
|
|
1069
193
|
embeds: [
|
|
1070
|
-
|
|
194
|
+
statusEmbed({
|
|
1071
195
|
uptimeSeconds: runtimeStatus.uptimeSeconds,
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
archivedSessions: runtimeStatus.archivedSessions
|
|
1079
|
-
}),
|
|
1080
|
-
{
|
|
1081
|
-
title: "Runtime Activity",
|
|
1082
|
-
color: 1752220,
|
|
1083
|
-
fields: [
|
|
1084
|
-
{ name: "Running Sessions", value: String(runtimeStatus.runningSessions), inline: true },
|
|
1085
|
-
{ name: "Waiting Sessions", value: String(runtimeStatus.waitingSessions), inline: true },
|
|
1086
|
-
{
|
|
1087
|
-
name: "Pending Receipts",
|
|
1088
|
-
value: truncateEmbedValue(
|
|
1089
|
-
receipts.length === 0 ? "None" : receipts.slice(-5).map((receipt) => `${receipt.threadId}: ${receipt.state}`).join("\n")
|
|
1090
|
-
)
|
|
1091
|
-
},
|
|
1092
|
-
{
|
|
1093
|
-
name: "Recent Activity",
|
|
1094
|
-
value: truncateEmbedValue(
|
|
1095
|
-
activities.length === 0 ? "None" : activities.map((activity) => `${activity.title}${activity.detail ? ` - ${activity.detail}` : ""}`).join("\n")
|
|
1096
|
-
)
|
|
1097
|
-
}
|
|
1098
|
-
],
|
|
1099
|
-
timestamp: context.nowIso()
|
|
1100
|
-
},
|
|
1101
|
-
{
|
|
1102
|
-
title: "Provider Diagnostics",
|
|
1103
|
-
color: 10181046,
|
|
1104
|
-
fields: [
|
|
1105
|
-
{ name: "Account", value: providerDiagnostics.accountLabel ?? "unknown", inline: true },
|
|
1106
|
-
{ name: "Default Model", value: context.getDefaultModel(), inline: true },
|
|
1107
|
-
{ name: "Connected Sessions", value: String(providerDiagnostics.connectedSessions), inline: true },
|
|
1108
|
-
{
|
|
1109
|
-
name: "Models",
|
|
1110
|
-
value: truncateEmbedValue(providerDiagnostics.availableModels.join(", ") || "Unknown"),
|
|
1111
|
-
inline: true
|
|
1112
|
-
},
|
|
1113
|
-
{
|
|
1114
|
-
name: "Provider Statuses",
|
|
1115
|
-
value: truncateEmbedValue(
|
|
1116
|
-
Object.entries(providerDiagnostics.statusCounts).map(([status, count]) => `${status}: ${count}`).join("\n") || "None"
|
|
1117
|
-
)
|
|
1118
|
-
},
|
|
1119
|
-
{
|
|
1120
|
-
name: "Capabilities",
|
|
1121
|
-
value: truncateEmbedValue(Object.keys(providerDiagnostics.capabilityMetadata).join(", ") || "None")
|
|
1122
|
-
}
|
|
1123
|
-
],
|
|
1124
|
-
timestamp: context.nowIso()
|
|
1125
|
-
},
|
|
1126
|
-
{
|
|
1127
|
-
title: "Projection Health",
|
|
1128
|
-
color: projectionFailures.length === 0 ? 3066993 : 15158332,
|
|
1129
|
-
fields: [
|
|
1130
|
-
{
|
|
1131
|
-
name: "Pipelines",
|
|
1132
|
-
value: truncateEmbedValue(
|
|
1133
|
-
projectionStates.map((entry) => `${entry.projector}: ${entry.failure ? `failed (${entry.failure})` : "ok"}`).join("\n") || "None"
|
|
1134
|
-
)
|
|
1135
|
-
}
|
|
1136
|
-
],
|
|
1137
|
-
timestamp: context.nowIso()
|
|
1138
|
-
},
|
|
1139
|
-
{
|
|
1140
|
-
title: "Managed Surface",
|
|
1141
|
-
color: 3447003,
|
|
1142
|
-
fields: [
|
|
1143
|
-
{ name: "Coordination", value: `<#${surface.coordinationResourceId}>`, inline: true },
|
|
1144
|
-
{ name: "Status", value: `<#${surface.statusResourceId}>`, inline: true },
|
|
1145
|
-
{ name: "Sessions", value: surface.sessionsCategoryId, inline: true },
|
|
1146
|
-
{ name: "Archive", value: surface.archiveCategoryId, inline: true }
|
|
1147
|
-
],
|
|
1148
|
-
timestamp: context.nowIso()
|
|
1149
|
-
}
|
|
196
|
+
acceptingNewWork: controlStatus.acceptingNewWork,
|
|
197
|
+
openSessions: runtimeStatus.openSessions,
|
|
198
|
+
runningSessions: runtimeStatus.runningSessions,
|
|
199
|
+
waitingSessions: runtimeStatus.waitingSessions,
|
|
200
|
+
providerLabel: providerDiagnostics.accountLabel
|
|
201
|
+
})
|
|
1150
202
|
],
|
|
1151
203
|
ephemeral: true
|
|
1152
204
|
});
|
|
@@ -1155,10 +207,7 @@ var status_default = {
|
|
|
1155
207
|
|
|
1156
208
|
// packages/discord-runtime/index.mjs
|
|
1157
209
|
var modules = [
|
|
1158
|
-
admin_control_default,
|
|
1159
|
-
channel_lifecycle_default,
|
|
1160
210
|
routing_default,
|
|
1161
|
-
session_commands_default,
|
|
1162
211
|
status_default
|
|
1163
212
|
];
|
|
1164
213
|
async function firstHandled(hook, args) {
|
|
@@ -1183,11 +232,8 @@ var index_default = {
|
|
|
1183
232
|
async onAction(event, context) {
|
|
1184
233
|
return await firstHandled("onAction", [event, context]);
|
|
1185
234
|
},
|
|
1186
|
-
async
|
|
1187
|
-
return await firstHandled("
|
|
1188
|
-
},
|
|
1189
|
-
async onTransportEvent(event, context) {
|
|
1190
|
-
return await firstHandled("onTransportEvent", [event, context]);
|
|
235
|
+
async onTransportIntent(intent, context) {
|
|
236
|
+
return await firstHandled("onTransportIntent", [intent, context]);
|
|
1191
237
|
}
|
|
1192
238
|
};
|
|
1193
239
|
export {
|