@elizaos/plugin-commands 2.0.3-beta.2 → 2.0.3-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +1757 -0
- package/dist/cjs/index.cjs.map +23 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1719 -0
- package/dist/index.js.map +23 -0
- package/dist/src/actions/command-actions.d.ts +17 -0
- package/dist/src/actions/command-actions.d.ts.map +1 -0
- package/dist/src/actions/command-settings.d.ts +35 -0
- package/dist/src/actions/command-settings.d.ts.map +1 -0
- package/dist/src/actions/dispatch.d.ts +54 -0
- package/dist/src/actions/dispatch.d.ts.map +1 -0
- package/dist/src/actions/handlers.d.ts +26 -0
- package/dist/src/actions/handlers.d.ts.map +1 -0
- package/dist/src/actions/index.d.ts +19 -0
- package/dist/src/actions/index.d.ts.map +1 -0
- package/dist/src/actions/shortcuts.d.ts +41 -0
- package/dist/src/actions/shortcuts.d.ts.map +1 -0
- package/dist/src/connector-bridge.d.ts +128 -0
- package/dist/src/connector-bridge.d.ts.map +1 -0
- package/dist/src/connector-catalog.d.ts +71 -0
- package/dist/src/connector-catalog.d.ts.map +1 -0
- package/dist/src/index.d.ts +68 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/navigation-commands.d.ts +28 -0
- package/dist/src/navigation-commands.d.ts.map +1 -0
- package/dist/src/parser.d.ts +32 -0
- package/dist/src/parser.d.ts.map +1 -0
- package/dist/src/registry.d.ts +66 -0
- package/dist/src/registry.d.ts.map +1 -0
- package/dist/src/serialize.d.ts +30 -0
- package/dist/src/serialize.d.ts.map +1 -0
- package/dist/src/settings-sections.d.ts +32 -0
- package/dist/src/settings-sections.d.ts.map +1 -0
- package/dist/src/types.d.ts +175 -0
- package/dist/src/types.d.ts.map +1 -0
- package/package.json +4 -3
- package/registry-entry.json +63 -0
|
@@ -0,0 +1,1757 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
function __accessProp(key) {
|
|
6
|
+
return this[key];
|
|
7
|
+
}
|
|
8
|
+
var __toCommonJS = (from) => {
|
|
9
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
10
|
+
if (entry)
|
|
11
|
+
return entry;
|
|
12
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (var key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(entry, key))
|
|
16
|
+
__defProp(entry, key, {
|
|
17
|
+
get: __accessProp.bind(from, key),
|
|
18
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
__moduleCache.set(from, entry);
|
|
22
|
+
return entry;
|
|
23
|
+
};
|
|
24
|
+
var __moduleCache;
|
|
25
|
+
var __returnValue = (v) => v;
|
|
26
|
+
function __exportSetter(name, newValue) {
|
|
27
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
28
|
+
}
|
|
29
|
+
var __export = (target, all) => {
|
|
30
|
+
for (var name in all)
|
|
31
|
+
__defProp(target, name, {
|
|
32
|
+
get: all[name],
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
set: __exportSetter.bind(all, name)
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// src/index.ts
|
|
40
|
+
var exports_src = {};
|
|
41
|
+
__export(exports_src, {
|
|
42
|
+
useRuntime: () => useRuntime,
|
|
43
|
+
unregisterCommand: () => unregisterCommand,
|
|
44
|
+
startsWithCommand: () => startsWithCommand,
|
|
45
|
+
setCommandSetting: () => setCommandSetting,
|
|
46
|
+
serializeCommand: () => serializeCommand,
|
|
47
|
+
runCommand: () => runCommand,
|
|
48
|
+
resolveSettingsSection: () => resolveSettingsSection,
|
|
49
|
+
resolveConnectorCommandAuth: () => resolveConnectorCommandAuth,
|
|
50
|
+
resolveCommand: () => resolveCommand,
|
|
51
|
+
resetCommands: () => resetCommands,
|
|
52
|
+
registerCommands: () => registerCommands,
|
|
53
|
+
registerCommand: () => registerCommand,
|
|
54
|
+
parseCommand: () => parseCommand,
|
|
55
|
+
normalizeCommandBody: () => normalizeCommandBody,
|
|
56
|
+
navigationCommandDefinitions: () => navigationCommandDefinitions,
|
|
57
|
+
naturalShortcuts: () => naturalShortcuts,
|
|
58
|
+
isElevated: () => isElevated,
|
|
59
|
+
isDeterministicCommand: () => isDeterministicCommand,
|
|
60
|
+
isCommandOnly: () => isCommandOnly,
|
|
61
|
+
isAuthorized: () => isAuthorized,
|
|
62
|
+
initForRuntime: () => initForRuntime,
|
|
63
|
+
hasCommand: () => hasCommand,
|
|
64
|
+
getSettingsSections: () => getSettingsSections,
|
|
65
|
+
getSettingsSectionChoices: () => getSettingsSectionChoices,
|
|
66
|
+
getEnabledCommandsForRuntime: () => getEnabledCommandsForRuntime,
|
|
67
|
+
getEnabledCommands: () => getEnabledCommands,
|
|
68
|
+
getConnectorCommands: () => getConnectorCommands,
|
|
69
|
+
getCommandsForRuntime: () => getCommandsForRuntime,
|
|
70
|
+
getCommandsByCategoryForRuntime: () => getCommandsByCategoryForRuntime,
|
|
71
|
+
getCommandsByCategory: () => getCommandsByCategory,
|
|
72
|
+
getCommands: () => getCommands,
|
|
73
|
+
getCommandSettings: () => getCommandSettings,
|
|
74
|
+
getCatalogCommands: () => getCatalogCommands,
|
|
75
|
+
gateConnectorCommandByName: () => gateConnectorCommandByName,
|
|
76
|
+
gateConnectorCommand: () => gateConnectorCommand,
|
|
77
|
+
formatCommandResult: () => formatCommandResult,
|
|
78
|
+
findCommandByKeyForRuntime: () => findCommandByKeyForRuntime,
|
|
79
|
+
findCommandByKey: () => findCommandByKey,
|
|
80
|
+
findCommandByAliasForRuntime: () => findCommandByAliasForRuntime,
|
|
81
|
+
findCommandByAlias: () => findCommandByAlias,
|
|
82
|
+
extractCommand: () => extractCommand,
|
|
83
|
+
explicitCommandShortcuts: () => explicitCommandShortcuts,
|
|
84
|
+
dispatchCommandMessage: () => dispatchCommandMessage,
|
|
85
|
+
detectCommand: () => detectCommand,
|
|
86
|
+
default: () => src_default,
|
|
87
|
+
createCommandShortcuts: () => createCommandShortcuts,
|
|
88
|
+
createCommandActions: () => createCommandActions,
|
|
89
|
+
commandsPlugin: () => commandsPlugin,
|
|
90
|
+
commandVisibleForView: () => commandVisibleForView,
|
|
91
|
+
commandVisibleForSurface: () => commandVisibleForSurface,
|
|
92
|
+
commandShortcuts: () => commandShortcuts,
|
|
93
|
+
commandRegistryProvider: () => commandRegistryProvider,
|
|
94
|
+
commandActions: () => commandActions,
|
|
95
|
+
clearCommandSettings: () => clearCommandSettings,
|
|
96
|
+
DETERMINISTIC_COMMAND_KEYS: () => DETERMINISTIC_COMMAND_KEYS,
|
|
97
|
+
DEFAULT_COMMANDS: () => DEFAULT_COMMANDS,
|
|
98
|
+
COMMAND_SETTING_CHOICES: () => COMMAND_SETTING_CHOICES
|
|
99
|
+
});
|
|
100
|
+
module.exports = __toCommonJS(exports_src);
|
|
101
|
+
var import_core = require("@elizaos/core");
|
|
102
|
+
|
|
103
|
+
// src/registry.ts
|
|
104
|
+
var DEFAULT_COMMANDS = [
|
|
105
|
+
{
|
|
106
|
+
key: "help",
|
|
107
|
+
nativeName: "help",
|
|
108
|
+
description: "Show available commands",
|
|
109
|
+
textAliases: ["/help", "/h", "/?"],
|
|
110
|
+
scope: "both",
|
|
111
|
+
category: "status",
|
|
112
|
+
acceptsArgs: false
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
key: "commands",
|
|
116
|
+
nativeName: "commands",
|
|
117
|
+
description: "List all commands",
|
|
118
|
+
textAliases: ["/commands", "/cmds"],
|
|
119
|
+
scope: "both",
|
|
120
|
+
category: "status",
|
|
121
|
+
acceptsArgs: false
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
key: "status",
|
|
125
|
+
nativeName: "status",
|
|
126
|
+
description: "Show current session status",
|
|
127
|
+
textAliases: ["/status", "/s"],
|
|
128
|
+
scope: "both",
|
|
129
|
+
category: "status",
|
|
130
|
+
acceptsArgs: false
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
key: "context",
|
|
134
|
+
nativeName: "context",
|
|
135
|
+
description: "Show current context information",
|
|
136
|
+
textAliases: ["/context", "/ctx"],
|
|
137
|
+
scope: "both",
|
|
138
|
+
category: "status",
|
|
139
|
+
acceptsArgs: true,
|
|
140
|
+
args: [{ name: "mode", description: "Output mode (list, detail, json)" }]
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
key: "whoami",
|
|
144
|
+
nativeName: "whoami",
|
|
145
|
+
description: "Show your identity information",
|
|
146
|
+
textAliases: ["/whoami", "/who"],
|
|
147
|
+
scope: "both",
|
|
148
|
+
category: "status",
|
|
149
|
+
acceptsArgs: false
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
key: "stop",
|
|
153
|
+
nativeName: "stop",
|
|
154
|
+
description: "Stop current operation",
|
|
155
|
+
textAliases: ["/stop", "/abort", "/cancel"],
|
|
156
|
+
scope: "both",
|
|
157
|
+
category: "session",
|
|
158
|
+
acceptsArgs: false
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
key: "restart",
|
|
162
|
+
nativeName: "restart",
|
|
163
|
+
description: "Restart the session",
|
|
164
|
+
textAliases: ["/restart"],
|
|
165
|
+
scope: "both",
|
|
166
|
+
category: "session",
|
|
167
|
+
acceptsArgs: false,
|
|
168
|
+
requiresAuth: true
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
key: "reset",
|
|
172
|
+
nativeName: "reset",
|
|
173
|
+
description: "Reset session state",
|
|
174
|
+
textAliases: ["/reset"],
|
|
175
|
+
scope: "both",
|
|
176
|
+
category: "session",
|
|
177
|
+
acceptsArgs: false,
|
|
178
|
+
requiresAuth: true
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
key: "new",
|
|
182
|
+
nativeName: "new",
|
|
183
|
+
description: "Start a new conversation",
|
|
184
|
+
textAliases: ["/new"],
|
|
185
|
+
scope: "both",
|
|
186
|
+
category: "session",
|
|
187
|
+
acceptsArgs: false
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
key: "compact",
|
|
191
|
+
nativeName: "compact",
|
|
192
|
+
description: "Compact conversation history",
|
|
193
|
+
textAliases: ["/compact"],
|
|
194
|
+
scope: "both",
|
|
195
|
+
category: "session",
|
|
196
|
+
acceptsArgs: true,
|
|
197
|
+
requiresAuth: true,
|
|
198
|
+
args: [
|
|
199
|
+
{ name: "instructions", description: "Optional compaction instructions" }
|
|
200
|
+
]
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
key: "think",
|
|
204
|
+
nativeName: "think",
|
|
205
|
+
description: "Set thinking level",
|
|
206
|
+
textAliases: ["/think", "/thinking", "/t"],
|
|
207
|
+
scope: "both",
|
|
208
|
+
category: "options",
|
|
209
|
+
acceptsArgs: true,
|
|
210
|
+
args: [
|
|
211
|
+
{ name: "level", description: "off, minimal, low, medium, high, xhigh" }
|
|
212
|
+
]
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
key: "verbose",
|
|
216
|
+
nativeName: "verbose",
|
|
217
|
+
description: "Set verbose output level",
|
|
218
|
+
textAliases: ["/verbose", "/v"],
|
|
219
|
+
scope: "both",
|
|
220
|
+
category: "options",
|
|
221
|
+
acceptsArgs: true,
|
|
222
|
+
args: [{ name: "level", description: "off, on, full" }]
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
key: "reasoning",
|
|
226
|
+
nativeName: "reasoning",
|
|
227
|
+
description: "Set reasoning visibility",
|
|
228
|
+
textAliases: ["/reasoning", "/reason"],
|
|
229
|
+
scope: "both",
|
|
230
|
+
category: "options",
|
|
231
|
+
acceptsArgs: true,
|
|
232
|
+
args: [{ name: "level", description: "off, on, stream" }]
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
key: "elevated",
|
|
236
|
+
nativeName: "elevated",
|
|
237
|
+
description: "Set elevated permission mode",
|
|
238
|
+
textAliases: ["/elevated", "/elev"],
|
|
239
|
+
scope: "both",
|
|
240
|
+
category: "options",
|
|
241
|
+
acceptsArgs: true,
|
|
242
|
+
args: [{ name: "level", description: "off, on, ask, full" }],
|
|
243
|
+
requiresAuth: true
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
key: "model",
|
|
247
|
+
nativeName: "model",
|
|
248
|
+
description: "Set or show current model",
|
|
249
|
+
textAliases: ["/model", "/m"],
|
|
250
|
+
scope: "both",
|
|
251
|
+
category: "options",
|
|
252
|
+
acceptsArgs: true,
|
|
253
|
+
args: [
|
|
254
|
+
{
|
|
255
|
+
name: "model",
|
|
256
|
+
description: "provider/model or alias",
|
|
257
|
+
dynamicChoices: "models"
|
|
258
|
+
}
|
|
259
|
+
]
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
key: "models",
|
|
263
|
+
nativeName: "models",
|
|
264
|
+
description: "List available models",
|
|
265
|
+
textAliases: ["/models"],
|
|
266
|
+
scope: "both",
|
|
267
|
+
category: "options",
|
|
268
|
+
acceptsArgs: false
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
key: "usage",
|
|
272
|
+
nativeName: "usage",
|
|
273
|
+
description: "Show token usage",
|
|
274
|
+
textAliases: ["/usage"],
|
|
275
|
+
scope: "both",
|
|
276
|
+
category: "options",
|
|
277
|
+
acceptsArgs: false
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
key: "queue",
|
|
281
|
+
nativeName: "queue",
|
|
282
|
+
description: "Set queue mode",
|
|
283
|
+
textAliases: ["/queue", "/q"],
|
|
284
|
+
scope: "both",
|
|
285
|
+
category: "options",
|
|
286
|
+
acceptsArgs: true,
|
|
287
|
+
args: [
|
|
288
|
+
{
|
|
289
|
+
name: "mode",
|
|
290
|
+
description: "steer, followup, collect, interrupt, or options"
|
|
291
|
+
}
|
|
292
|
+
]
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
key: "allowlist",
|
|
296
|
+
nativeName: "allowlist",
|
|
297
|
+
description: "Manage sender allowlist",
|
|
298
|
+
textAliases: ["/allowlist", "/allow"],
|
|
299
|
+
scope: "both",
|
|
300
|
+
category: "management",
|
|
301
|
+
acceptsArgs: true,
|
|
302
|
+
args: [
|
|
303
|
+
{ name: "action", description: "list, add, remove" },
|
|
304
|
+
{ name: "value", description: "sender to add/remove" }
|
|
305
|
+
],
|
|
306
|
+
requiresAuth: true
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
key: "approve",
|
|
310
|
+
nativeName: "approve",
|
|
311
|
+
description: "Approve or deny a pending action",
|
|
312
|
+
textAliases: ["/approve"],
|
|
313
|
+
scope: "both",
|
|
314
|
+
category: "management",
|
|
315
|
+
acceptsArgs: true,
|
|
316
|
+
args: [
|
|
317
|
+
{ name: "id", description: "Approval ID", required: true },
|
|
318
|
+
{ name: "action", description: "allow-once, allow-always, deny" }
|
|
319
|
+
],
|
|
320
|
+
requiresAuth: true
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
key: "subagents",
|
|
324
|
+
nativeName: "subagents",
|
|
325
|
+
description: "Manage subagents",
|
|
326
|
+
textAliases: ["/subagents", "/sub"],
|
|
327
|
+
scope: "both",
|
|
328
|
+
category: "management",
|
|
329
|
+
acceptsArgs: true,
|
|
330
|
+
args: [{ name: "action", description: "list, stop, log, info, send" }],
|
|
331
|
+
requiresAuth: true
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
key: "config",
|
|
335
|
+
nativeName: "config",
|
|
336
|
+
description: "View or set configuration",
|
|
337
|
+
textAliases: ["/config", "/cfg"],
|
|
338
|
+
scope: "both",
|
|
339
|
+
category: "management",
|
|
340
|
+
acceptsArgs: true,
|
|
341
|
+
args: [
|
|
342
|
+
{ name: "key", description: "Configuration key" },
|
|
343
|
+
{ name: "value", description: "Value to set" }
|
|
344
|
+
],
|
|
345
|
+
requiresAuth: true,
|
|
346
|
+
enabled: false
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
key: "debug",
|
|
350
|
+
nativeName: "debug",
|
|
351
|
+
description: "Debug information",
|
|
352
|
+
textAliases: ["/debug"],
|
|
353
|
+
scope: "both",
|
|
354
|
+
category: "management",
|
|
355
|
+
acceptsArgs: true,
|
|
356
|
+
requiresAuth: true,
|
|
357
|
+
enabled: false
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
key: "tts",
|
|
361
|
+
nativeName: "tts",
|
|
362
|
+
description: "Text-to-speech settings",
|
|
363
|
+
textAliases: ["/tts", "/voice"],
|
|
364
|
+
scope: "both",
|
|
365
|
+
category: "media",
|
|
366
|
+
acceptsArgs: true,
|
|
367
|
+
args: [
|
|
368
|
+
{
|
|
369
|
+
name: "action",
|
|
370
|
+
description: "on, off, status, provider, limit, audio"
|
|
371
|
+
}
|
|
372
|
+
]
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
key: "transcribe",
|
|
376
|
+
nativeName: "transcribe",
|
|
377
|
+
description: "Toggle long-form transcription mode (record-only; agent stays silent until an exit phrase)",
|
|
378
|
+
textAliases: ["/transcribe", "/transcription", "/dictate"],
|
|
379
|
+
scope: "both",
|
|
380
|
+
category: "media",
|
|
381
|
+
acceptsArgs: false
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
key: "bash",
|
|
385
|
+
nativeName: "bash",
|
|
386
|
+
description: "Execute shell command",
|
|
387
|
+
textAliases: ["/bash", "/sh", "/!"],
|
|
388
|
+
scope: "text",
|
|
389
|
+
category: "tools",
|
|
390
|
+
acceptsArgs: true,
|
|
391
|
+
args: [
|
|
392
|
+
{
|
|
393
|
+
name: "command",
|
|
394
|
+
description: "Shell command to execute",
|
|
395
|
+
captureRemaining: true
|
|
396
|
+
}
|
|
397
|
+
],
|
|
398
|
+
requiresAuth: true,
|
|
399
|
+
requiresElevated: true
|
|
400
|
+
}
|
|
401
|
+
];
|
|
402
|
+
var runtimeStores = new Map;
|
|
403
|
+
var fallbackStore = {
|
|
404
|
+
commands: DEFAULT_COMMANDS.map((c) => ({ ...c })),
|
|
405
|
+
aliasMap: null
|
|
406
|
+
};
|
|
407
|
+
var activeStore = fallbackStore;
|
|
408
|
+
function initForRuntime(agentId) {
|
|
409
|
+
const store = {
|
|
410
|
+
commands: DEFAULT_COMMANDS.map((c) => ({ ...c })),
|
|
411
|
+
aliasMap: null
|
|
412
|
+
};
|
|
413
|
+
runtimeStores.set(agentId, store);
|
|
414
|
+
activeStore = store;
|
|
415
|
+
}
|
|
416
|
+
function useRuntime(agentId) {
|
|
417
|
+
activeStore = storeForRuntime(agentId);
|
|
418
|
+
}
|
|
419
|
+
function getCommands() {
|
|
420
|
+
return [...activeStore.commands];
|
|
421
|
+
}
|
|
422
|
+
function getEnabledCommands() {
|
|
423
|
+
return activeStore.commands.filter((cmd) => cmd.enabled !== false);
|
|
424
|
+
}
|
|
425
|
+
function getCommandsByCategory(category) {
|
|
426
|
+
return activeStore.commands.filter((cmd) => cmd.category === category && cmd.enabled !== false);
|
|
427
|
+
}
|
|
428
|
+
function registerCommand(command) {
|
|
429
|
+
activeStore.commands = activeStore.commands.filter((c) => c.key !== command.key);
|
|
430
|
+
activeStore.commands.push(command);
|
|
431
|
+
activeStore.aliasMap = null;
|
|
432
|
+
}
|
|
433
|
+
function registerCommands(newCommands) {
|
|
434
|
+
for (const command of newCommands) {
|
|
435
|
+
registerCommand(command);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
function unregisterCommand(key) {
|
|
439
|
+
activeStore.commands = activeStore.commands.filter((c) => c.key !== key);
|
|
440
|
+
activeStore.aliasMap = null;
|
|
441
|
+
}
|
|
442
|
+
function resetCommands() {
|
|
443
|
+
activeStore.commands = DEFAULT_COMMANDS.map((c) => ({ ...c }));
|
|
444
|
+
activeStore.aliasMap = null;
|
|
445
|
+
}
|
|
446
|
+
function getAliasMap() {
|
|
447
|
+
if (activeStore.aliasMap)
|
|
448
|
+
return activeStore.aliasMap;
|
|
449
|
+
activeStore.aliasMap = new Map;
|
|
450
|
+
for (const command of activeStore.commands) {
|
|
451
|
+
if (command.enabled === false)
|
|
452
|
+
continue;
|
|
453
|
+
for (const alias of command.textAliases) {
|
|
454
|
+
const normalized = alias.toLowerCase().trim();
|
|
455
|
+
if (!activeStore.aliasMap.has(normalized)) {
|
|
456
|
+
activeStore.aliasMap.set(normalized, command);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return activeStore.aliasMap;
|
|
461
|
+
}
|
|
462
|
+
function findCommandByAlias(alias) {
|
|
463
|
+
const map = getAliasMap();
|
|
464
|
+
return map.get(alias.toLowerCase().trim());
|
|
465
|
+
}
|
|
466
|
+
function findCommandByKey(key) {
|
|
467
|
+
return activeStore.commands.find((c) => c.key === key);
|
|
468
|
+
}
|
|
469
|
+
function startsWithCommand(text) {
|
|
470
|
+
const map = getAliasMap();
|
|
471
|
+
const normalized = text.toLowerCase().trim();
|
|
472
|
+
for (const [alias, command] of map) {
|
|
473
|
+
if (normalized === alias) {
|
|
474
|
+
return command;
|
|
475
|
+
}
|
|
476
|
+
const remainder = normalized.slice(alias.length);
|
|
477
|
+
if (normalized.startsWith(alias) && /^[\s:]/.test(remainder)) {
|
|
478
|
+
return command;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
function storeForRuntime(agentId) {
|
|
484
|
+
if (!agentId)
|
|
485
|
+
return fallbackStore;
|
|
486
|
+
return runtimeStores.get(agentId) ?? fallbackStore;
|
|
487
|
+
}
|
|
488
|
+
function getEnabledCommandsFromStore(store) {
|
|
489
|
+
return store.commands.filter((cmd) => cmd.enabled !== false);
|
|
490
|
+
}
|
|
491
|
+
function getCommandsByCategoryFromStore(store, category) {
|
|
492
|
+
return store.commands.filter((cmd) => cmd.category === category && cmd.enabled !== false);
|
|
493
|
+
}
|
|
494
|
+
function getAliasMapForStore(store) {
|
|
495
|
+
if (store.aliasMap)
|
|
496
|
+
return store.aliasMap;
|
|
497
|
+
store.aliasMap = new Map;
|
|
498
|
+
for (const command of store.commands) {
|
|
499
|
+
if (command.enabled === false)
|
|
500
|
+
continue;
|
|
501
|
+
for (const alias of command.textAliases) {
|
|
502
|
+
const normalized = alias.toLowerCase().trim();
|
|
503
|
+
if (!store.aliasMap.has(normalized)) {
|
|
504
|
+
store.aliasMap.set(normalized, command);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return store.aliasMap;
|
|
509
|
+
}
|
|
510
|
+
function getCommandsForRuntime(agentId) {
|
|
511
|
+
return [...storeForRuntime(agentId).commands];
|
|
512
|
+
}
|
|
513
|
+
function getEnabledCommandsForRuntime(agentId) {
|
|
514
|
+
return getEnabledCommandsFromStore(storeForRuntime(agentId));
|
|
515
|
+
}
|
|
516
|
+
function getCommandsByCategoryForRuntime(category, agentId) {
|
|
517
|
+
return getCommandsByCategoryFromStore(storeForRuntime(agentId), category);
|
|
518
|
+
}
|
|
519
|
+
function findCommandByAliasForRuntime(alias, agentId) {
|
|
520
|
+
return getAliasMapForStore(storeForRuntime(agentId)).get(alias.toLowerCase().trim());
|
|
521
|
+
}
|
|
522
|
+
function findCommandByKeyForRuntime(key, agentId) {
|
|
523
|
+
return storeForRuntime(agentId).commands.find((c) => c.key === key);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// src/parser.ts
|
|
527
|
+
var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
528
|
+
function hasCommand(text) {
|
|
529
|
+
if (!text)
|
|
530
|
+
return false;
|
|
531
|
+
const trimmed = text.trim();
|
|
532
|
+
if (!trimmed.startsWith("/") && !trimmed.startsWith("!"))
|
|
533
|
+
return false;
|
|
534
|
+
return Boolean(startsWithCommand(trimmed));
|
|
535
|
+
}
|
|
536
|
+
function detectCommand(text) {
|
|
537
|
+
if (!text) {
|
|
538
|
+
return { isCommand: false };
|
|
539
|
+
}
|
|
540
|
+
const trimmed = text.trim();
|
|
541
|
+
if (!trimmed.startsWith("/") && !trimmed.startsWith("!")) {
|
|
542
|
+
return { isCommand: false };
|
|
543
|
+
}
|
|
544
|
+
const command = startsWithCommand(trimmed);
|
|
545
|
+
if (!command) {
|
|
546
|
+
return { isCommand: false };
|
|
547
|
+
}
|
|
548
|
+
const parsed = parseCommand(trimmed, command);
|
|
549
|
+
if (!parsed) {
|
|
550
|
+
return { isCommand: false };
|
|
551
|
+
}
|
|
552
|
+
return { isCommand: true, command: parsed };
|
|
553
|
+
}
|
|
554
|
+
function parseCommand(text, definition) {
|
|
555
|
+
const trimmed = text.trim();
|
|
556
|
+
let matchedAlias = null;
|
|
557
|
+
for (const alias of definition.textAliases) {
|
|
558
|
+
const normalized = alias.toLowerCase();
|
|
559
|
+
if (trimmed.toLowerCase() === normalized) {
|
|
560
|
+
matchedAlias = alias;
|
|
561
|
+
break;
|
|
562
|
+
}
|
|
563
|
+
const remainder = trimmed.slice(alias.length);
|
|
564
|
+
if (trimmed.toLowerCase().startsWith(normalized) && /^[\s:]/.test(remainder)) {
|
|
565
|
+
matchedAlias = alias;
|
|
566
|
+
break;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
if (!matchedAlias) {
|
|
570
|
+
return null;
|
|
571
|
+
}
|
|
572
|
+
let rawArgs = trimmed.slice(matchedAlias.length).trim();
|
|
573
|
+
if (rawArgs.startsWith(":")) {
|
|
574
|
+
rawArgs = rawArgs.slice(1).trim();
|
|
575
|
+
}
|
|
576
|
+
const args = parseArgs(rawArgs, definition);
|
|
577
|
+
const parsed = {
|
|
578
|
+
key: definition.key,
|
|
579
|
+
canonical: definition.textAliases[0] ?? `/${definition.key}`,
|
|
580
|
+
args
|
|
581
|
+
};
|
|
582
|
+
if (rawArgs) {
|
|
583
|
+
parsed.rawArgs = rawArgs;
|
|
584
|
+
}
|
|
585
|
+
return parsed;
|
|
586
|
+
}
|
|
587
|
+
function parseArgs(rawArgs, definition) {
|
|
588
|
+
if (!rawArgs || !definition.acceptsArgs) {
|
|
589
|
+
return [];
|
|
590
|
+
}
|
|
591
|
+
const parsing = definition.argsParsing ?? "positional";
|
|
592
|
+
if (parsing === "none") {
|
|
593
|
+
return rawArgs ? [rawArgs] : [];
|
|
594
|
+
}
|
|
595
|
+
const args = [];
|
|
596
|
+
const argDefs = definition.args ?? [];
|
|
597
|
+
const tokens = tokenize(rawArgs);
|
|
598
|
+
for (const [i, token] of tokens.entries()) {
|
|
599
|
+
const argDef = argDefs[i];
|
|
600
|
+
if (argDef?.captureRemaining) {
|
|
601
|
+
args.push(tokens.slice(i).join(" "));
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
args.push(token);
|
|
605
|
+
}
|
|
606
|
+
return args;
|
|
607
|
+
}
|
|
608
|
+
function tokenize(input) {
|
|
609
|
+
const tokens = [];
|
|
610
|
+
let current = "";
|
|
611
|
+
let inQuote = false;
|
|
612
|
+
let quoteChar = "";
|
|
613
|
+
for (const char of input) {
|
|
614
|
+
if (inQuote) {
|
|
615
|
+
if (char === quoteChar) {
|
|
616
|
+
inQuote = false;
|
|
617
|
+
if (current) {
|
|
618
|
+
tokens.push(current);
|
|
619
|
+
current = "";
|
|
620
|
+
}
|
|
621
|
+
} else {
|
|
622
|
+
current += char;
|
|
623
|
+
}
|
|
624
|
+
} else if (char === '"' || char === "'") {
|
|
625
|
+
inQuote = true;
|
|
626
|
+
quoteChar = char;
|
|
627
|
+
} else if (/\s/.test(char)) {
|
|
628
|
+
if (current) {
|
|
629
|
+
tokens.push(current);
|
|
630
|
+
current = "";
|
|
631
|
+
}
|
|
632
|
+
} else {
|
|
633
|
+
current += char;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
if (current) {
|
|
637
|
+
tokens.push(current);
|
|
638
|
+
}
|
|
639
|
+
return tokens;
|
|
640
|
+
}
|
|
641
|
+
function normalizeCommandBody(text, botMention) {
|
|
642
|
+
let normalized = text.trim();
|
|
643
|
+
if (botMention) {
|
|
644
|
+
const mentionPattern = new RegExp(`^@${escapeRegExp(botMention)}\\s*`, "i");
|
|
645
|
+
normalized = normalized.replace(mentionPattern, "");
|
|
646
|
+
}
|
|
647
|
+
normalized = normalized.replace(/^([/!][^\s:]+):\s*/, "$1 ");
|
|
648
|
+
return normalized.trim();
|
|
649
|
+
}
|
|
650
|
+
function isCommandOnly(text) {
|
|
651
|
+
const detection = detectCommand(text);
|
|
652
|
+
if (!detection.isCommand || !detection.command) {
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
if (!detection.command.rawArgs) {
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
658
|
+
return detection.command.rawArgs.trim().length === 0;
|
|
659
|
+
}
|
|
660
|
+
function extractCommand(text) {
|
|
661
|
+
const detection = detectCommand(text);
|
|
662
|
+
if (!detection.isCommand || !detection.command) {
|
|
663
|
+
return null;
|
|
664
|
+
}
|
|
665
|
+
const { command } = detection;
|
|
666
|
+
if (!command.rawArgs) {
|
|
667
|
+
return { command, remainingText: "" };
|
|
668
|
+
}
|
|
669
|
+
return { command, remainingText: command.rawArgs };
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// src/actions/command-settings.ts
|
|
673
|
+
var COMMAND_SETTING_CHOICES = {
|
|
674
|
+
thinking: ["off", "minimal", "low", "medium", "high", "xhigh"],
|
|
675
|
+
verbose: ["off", "on", "full"],
|
|
676
|
+
reasoning: ["off", "on", "stream"],
|
|
677
|
+
queue: ["steer", "followup", "collect", "interrupt"],
|
|
678
|
+
elevated: ["off", "on", "ask", "full"],
|
|
679
|
+
model: null,
|
|
680
|
+
tts: ["on", "off"]
|
|
681
|
+
};
|
|
682
|
+
function cacheKey(roomId) {
|
|
683
|
+
return `command-settings:${roomId}`;
|
|
684
|
+
}
|
|
685
|
+
async function clearCommandSettings(runtime, roomId) {
|
|
686
|
+
return runtime.deleteCache(cacheKey(roomId));
|
|
687
|
+
}
|
|
688
|
+
async function getCommandSettings(runtime, roomId) {
|
|
689
|
+
const stored = await runtime.getCache(cacheKey(roomId));
|
|
690
|
+
return stored ?? {};
|
|
691
|
+
}
|
|
692
|
+
async function setCommandSetting(runtime, roomId, key, rawValue) {
|
|
693
|
+
const value = rawValue.trim().toLowerCase();
|
|
694
|
+
const choices = COMMAND_SETTING_CHOICES[key];
|
|
695
|
+
if (choices && !choices.includes(value)) {
|
|
696
|
+
return {
|
|
697
|
+
error: `Invalid ${key} value "${rawValue}". Choose one of: ${choices.join(", ")}.`
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
const normalized = choices ? value : rawValue.trim();
|
|
701
|
+
const current = await getCommandSettings(runtime, roomId);
|
|
702
|
+
await runtime.setCache(cacheKey(roomId), {
|
|
703
|
+
...current,
|
|
704
|
+
[key]: normalized
|
|
705
|
+
});
|
|
706
|
+
return { value: normalized };
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// src/actions/handlers.ts
|
|
710
|
+
var DETERMINISTIC_COMMAND_KEYS = [
|
|
711
|
+
"help",
|
|
712
|
+
"commands",
|
|
713
|
+
"status",
|
|
714
|
+
"whoami",
|
|
715
|
+
"context",
|
|
716
|
+
"reset",
|
|
717
|
+
"new",
|
|
718
|
+
"compact",
|
|
719
|
+
"models",
|
|
720
|
+
"usage",
|
|
721
|
+
"think",
|
|
722
|
+
"verbose",
|
|
723
|
+
"reasoning",
|
|
724
|
+
"queue",
|
|
725
|
+
"elevated",
|
|
726
|
+
"model",
|
|
727
|
+
"tts"
|
|
728
|
+
];
|
|
729
|
+
var DETERMINISTIC_KEYS = new Set(DETERMINISTIC_COMMAND_KEYS);
|
|
730
|
+
function isDeterministicCommand(key) {
|
|
731
|
+
return DETERMINISTIC_KEYS.has(key);
|
|
732
|
+
}
|
|
733
|
+
var CATEGORY_ORDER = [
|
|
734
|
+
"status",
|
|
735
|
+
"session",
|
|
736
|
+
"options",
|
|
737
|
+
"media",
|
|
738
|
+
"management",
|
|
739
|
+
"tools",
|
|
740
|
+
"docks",
|
|
741
|
+
"skills"
|
|
742
|
+
];
|
|
743
|
+
var OPTION_COMMANDS = {
|
|
744
|
+
think: { key: "thinking", label: "Thinking" },
|
|
745
|
+
verbose: { key: "verbose", label: "Verbose" },
|
|
746
|
+
reasoning: { key: "reasoning", label: "Reasoning" },
|
|
747
|
+
queue: { key: "queue", label: "Queue mode" },
|
|
748
|
+
elevated: { key: "elevated", label: "Elevated mode" },
|
|
749
|
+
model: { key: "model", label: "Model" },
|
|
750
|
+
tts: { key: "tts", label: "TTS" }
|
|
751
|
+
};
|
|
752
|
+
function reply(text) {
|
|
753
|
+
return { handled: true, reply: text, shouldContinue: false };
|
|
754
|
+
}
|
|
755
|
+
function authError() {
|
|
756
|
+
return reply("This command requires authorization.");
|
|
757
|
+
}
|
|
758
|
+
function formatCommandList(agentId) {
|
|
759
|
+
const lines = [];
|
|
760
|
+
for (const category of CATEGORY_ORDER) {
|
|
761
|
+
const commands = getCommandsByCategoryForRuntime(category, agentId);
|
|
762
|
+
if (commands.length === 0)
|
|
763
|
+
continue;
|
|
764
|
+
lines.push(`**${category}**`);
|
|
765
|
+
for (const command of commands) {
|
|
766
|
+
const alias = command.textAliases[0] ?? `/${command.key}`;
|
|
767
|
+
const auth = command.requiresAuth ? " (requires auth)" : "";
|
|
768
|
+
lines.push(` ${alias} — ${command.description}${auth}`);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
return lines.join(`
|
|
772
|
+
`);
|
|
773
|
+
}
|
|
774
|
+
function resolveModelLabel(runtime) {
|
|
775
|
+
const fromSetting = runtime.getSetting("LARGE_MODEL") ?? runtime.getSetting("ANTHROPIC_LARGE_MODEL") ?? runtime.getSetting("OPENAI_LARGE_MODEL");
|
|
776
|
+
if (typeof fromSetting === "string" && fromSetting.trim()) {
|
|
777
|
+
return fromSetting.trim();
|
|
778
|
+
}
|
|
779
|
+
const fromCharacter = runtime.character?.settings?.model;
|
|
780
|
+
if (typeof fromCharacter === "string" && fromCharacter.trim()) {
|
|
781
|
+
return fromCharacter.trim();
|
|
782
|
+
}
|
|
783
|
+
return "default";
|
|
784
|
+
}
|
|
785
|
+
async function countRoomMessages(runtime, roomId) {
|
|
786
|
+
if (typeof runtime.countMemories !== "function")
|
|
787
|
+
return null;
|
|
788
|
+
try {
|
|
789
|
+
return await runtime.countMemories({
|
|
790
|
+
roomIds: [roomId],
|
|
791
|
+
tableName: "messages",
|
|
792
|
+
unique: false
|
|
793
|
+
});
|
|
794
|
+
} catch {
|
|
795
|
+
return null;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
async function clearRoomMessages(runtime, roomId) {
|
|
799
|
+
const before = await countRoomMessages(runtime, roomId);
|
|
800
|
+
if (typeof runtime.deleteAllMemories !== "function")
|
|
801
|
+
return null;
|
|
802
|
+
await runtime.deleteAllMemories([roomId], "messages");
|
|
803
|
+
return before;
|
|
804
|
+
}
|
|
805
|
+
function findAction(runtime, name) {
|
|
806
|
+
return runtime.actions?.find((action) => action.name === name);
|
|
807
|
+
}
|
|
808
|
+
async function runCompactAction(runtime, message, callback) {
|
|
809
|
+
const action = findAction(runtime, "COMPACT_CONVERSATION");
|
|
810
|
+
if (!action || !message) {
|
|
811
|
+
return reply("Conversation compaction is not available in this runtime.");
|
|
812
|
+
}
|
|
813
|
+
const result = await action.handler(runtime, message, undefined, undefined, callback);
|
|
814
|
+
if (result?.text && result.text.trim().length > 0)
|
|
815
|
+
return reply(result.text);
|
|
816
|
+
return reply("Conversation compaction completed.");
|
|
817
|
+
}
|
|
818
|
+
async function setOptionCommand(runtime, roomId, parsed, option) {
|
|
819
|
+
const rawValue = parsed.rawArgs?.trim() ?? parsed.args[0]?.trim() ?? "";
|
|
820
|
+
if (!rawValue) {
|
|
821
|
+
const settings = await getCommandSettings(runtime, roomId);
|
|
822
|
+
const current = option.key === "model" ? settings.model ?? resolveModelLabel(runtime) : settings[option.key] ?? "default";
|
|
823
|
+
return reply(`${option.label} is ${current}.`);
|
|
824
|
+
}
|
|
825
|
+
const result = await setCommandSetting(runtime, roomId, option.key, rawValue);
|
|
826
|
+
if ("error" in result)
|
|
827
|
+
return reply(result.error);
|
|
828
|
+
return reply(`${option.label} set to ${result.value}.`);
|
|
829
|
+
}
|
|
830
|
+
async function runCommand(runtime, parsed, context) {
|
|
831
|
+
const agentId = runtime.agentId;
|
|
832
|
+
useRuntime(agentId);
|
|
833
|
+
const definition = findCommandByKeyForRuntime(parsed.key, agentId);
|
|
834
|
+
if (definition?.requiresAuth && !context.isAuthorized)
|
|
835
|
+
return authError();
|
|
836
|
+
if (definition?.requiresElevated && !context.isElevated) {
|
|
837
|
+
return reply("This command requires elevated permissions.");
|
|
838
|
+
}
|
|
839
|
+
const roomId = context.roomId;
|
|
840
|
+
switch (parsed.key) {
|
|
841
|
+
case "help":
|
|
842
|
+
case "commands":
|
|
843
|
+
return reply(`Available commands:
|
|
844
|
+
${formatCommandList(agentId)}`);
|
|
845
|
+
case "status": {
|
|
846
|
+
const settings = await getCommandSettings(runtime, roomId);
|
|
847
|
+
const messageCount = await countRoomMessages(runtime, roomId);
|
|
848
|
+
const lines = [
|
|
849
|
+
`Agent: ${runtime.character?.name ?? runtime.agentId}`,
|
|
850
|
+
`Model: ${settings.model ?? resolveModelLabel(runtime)}`,
|
|
851
|
+
`Thinking: ${settings.thinking ?? "default"}`,
|
|
852
|
+
`Reasoning: ${settings.reasoning ?? "default"}`,
|
|
853
|
+
`Verbose: ${settings.verbose ?? "default"}`,
|
|
854
|
+
`Queue: ${settings.queue ?? "default"}`,
|
|
855
|
+
`TTS: ${settings.tts ?? "default"}`,
|
|
856
|
+
messageCount === null ? null : `Messages: ${messageCount}`,
|
|
857
|
+
`Commands enabled: ${getEnabledCommandsForRuntime(agentId).length}`
|
|
858
|
+
].filter(Boolean);
|
|
859
|
+
return reply(lines.join(`
|
|
860
|
+
`));
|
|
861
|
+
}
|
|
862
|
+
case "whoami": {
|
|
863
|
+
const who = context.senderName ?? context.senderId ?? "you";
|
|
864
|
+
return reply(`You are ${who}.
|
|
865
|
+
Authorized: ${context.isAuthorized ? "yes" : "no"}
|
|
866
|
+
Elevated: ${context.isElevated ? "yes" : "no"}`);
|
|
867
|
+
}
|
|
868
|
+
case "context": {
|
|
869
|
+
const settings = await getCommandSettings(runtime, roomId);
|
|
870
|
+
const lines = [
|
|
871
|
+
`Room: ${roomId}`,
|
|
872
|
+
context.channelId ? `Channel: ${context.channelId}` : null,
|
|
873
|
+
`Active settings: ${describeSettings(settings)}`
|
|
874
|
+
].filter(Boolean);
|
|
875
|
+
return reply(lines.join(`
|
|
876
|
+
`));
|
|
877
|
+
}
|
|
878
|
+
case "models":
|
|
879
|
+
return reply(`Current model: ${resolveModelLabel(runtime)}`);
|
|
880
|
+
case "usage": {
|
|
881
|
+
const usage = await runtime.getCache(`token-usage:${roomId}`);
|
|
882
|
+
if (!usage?.totalTokens) {
|
|
883
|
+
return reply("No token usage recorded for this conversation yet.");
|
|
884
|
+
}
|
|
885
|
+
return reply(`Token usage — prompt: ${usage.promptTokens ?? 0}, completion: ${usage.completionTokens ?? 0}, total: ${usage.totalTokens}.`);
|
|
886
|
+
}
|
|
887
|
+
case "think":
|
|
888
|
+
case "verbose":
|
|
889
|
+
case "reasoning":
|
|
890
|
+
case "queue":
|
|
891
|
+
case "elevated":
|
|
892
|
+
case "model":
|
|
893
|
+
case "tts":
|
|
894
|
+
return setOptionCommand(runtime, roomId, parsed, OPTION_COMMANDS[parsed.key]);
|
|
895
|
+
case "reset": {
|
|
896
|
+
await clearCommandSettings(runtime, roomId);
|
|
897
|
+
const deleted = await clearRoomMessages(runtime, roomId);
|
|
898
|
+
if (deleted === null) {
|
|
899
|
+
return reply("Reset command settings for this room. Message history is unchanged because memory deletion is unavailable.");
|
|
900
|
+
}
|
|
901
|
+
return reply(`Reset this room: cleared command settings and ${deleted} message(s).`);
|
|
902
|
+
}
|
|
903
|
+
case "new":
|
|
904
|
+
await clearCommandSettings(runtime, roomId);
|
|
905
|
+
return reply("Started a new conversation context for this room.");
|
|
906
|
+
case "compact":
|
|
907
|
+
return runCompactAction(runtime, context.message, context.callback);
|
|
908
|
+
default:
|
|
909
|
+
return { handled: false, shouldContinue: true };
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
function describeSettings(settings) {
|
|
913
|
+
const entries = Object.entries(settings).filter(([, v]) => v);
|
|
914
|
+
if (entries.length === 0)
|
|
915
|
+
return "none";
|
|
916
|
+
return entries.map(([k, v]) => `${k}=${v}`).join(", ");
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
// src/actions/dispatch.ts
|
|
920
|
+
function buildContext(message, options) {
|
|
921
|
+
const content = message.content;
|
|
922
|
+
const context = {
|
|
923
|
+
senderId: message.entityId,
|
|
924
|
+
isAuthorized: options.isAuthorized ?? false,
|
|
925
|
+
isElevated: options.isElevated ?? false,
|
|
926
|
+
roomId: message.roomId,
|
|
927
|
+
message
|
|
928
|
+
};
|
|
929
|
+
if (options.senderName)
|
|
930
|
+
context.senderName = options.senderName;
|
|
931
|
+
if (options.callback)
|
|
932
|
+
context.callback = options.callback;
|
|
933
|
+
const channelId = content.channelId ?? content.source;
|
|
934
|
+
if (channelId)
|
|
935
|
+
context.channelId = channelId;
|
|
936
|
+
return context;
|
|
937
|
+
}
|
|
938
|
+
async function resolveCommand(runtime, message, options = {}) {
|
|
939
|
+
const text = message.content.text ?? "";
|
|
940
|
+
if (!hasCommand(text))
|
|
941
|
+
return { handled: false };
|
|
942
|
+
const detection = detectCommand(text);
|
|
943
|
+
if (!detection.isCommand || !detection.command)
|
|
944
|
+
return { handled: false };
|
|
945
|
+
const parsed = detection.command;
|
|
946
|
+
const definition = findCommandByKeyForRuntime(parsed.key, runtime.agentId);
|
|
947
|
+
if (definition?.target && definition.target.kind !== "agent") {
|
|
948
|
+
return { handled: false, command: parsed };
|
|
949
|
+
}
|
|
950
|
+
const deterministicOnly = options.deterministicOnly ?? options.gateSafeOnly ?? true;
|
|
951
|
+
if (deterministicOnly && !isDeterministicCommand(parsed.key)) {
|
|
952
|
+
return { handled: false, command: parsed };
|
|
953
|
+
}
|
|
954
|
+
const result = await runCommand(runtime, parsed, buildContext(message, options));
|
|
955
|
+
if (!result.handled)
|
|
956
|
+
return { handled: false, command: parsed };
|
|
957
|
+
const dispatched = { handled: true, command: parsed };
|
|
958
|
+
if (result.reply !== undefined)
|
|
959
|
+
dispatched.reply = result.reply;
|
|
960
|
+
return dispatched;
|
|
961
|
+
}
|
|
962
|
+
async function dispatchCommandMessage(runtime, message, callback, options = {}) {
|
|
963
|
+
const result = await resolveCommand(runtime, message, options);
|
|
964
|
+
if (!result.handled || result.reply === undefined)
|
|
965
|
+
return false;
|
|
966
|
+
await callback({ text: result.reply, source: "command" });
|
|
967
|
+
return true;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// src/actions/command-actions.ts
|
|
971
|
+
var OWNER_SOURCES = new Set([
|
|
972
|
+
"client_chat",
|
|
973
|
+
"gui",
|
|
974
|
+
"tui",
|
|
975
|
+
"direct",
|
|
976
|
+
"dashboard"
|
|
977
|
+
]);
|
|
978
|
+
function resolveTrust(message) {
|
|
979
|
+
const source = message.content.source;
|
|
980
|
+
const trusted = !source || OWNER_SOURCES.has(source);
|
|
981
|
+
return { isAuthorized: trusted, isElevated: trusted };
|
|
982
|
+
}
|
|
983
|
+
function buildAction(key, _nativeName, description, aliases) {
|
|
984
|
+
return {
|
|
985
|
+
name: `${key.toUpperCase()}_COMMAND`,
|
|
986
|
+
description,
|
|
987
|
+
similes: aliases,
|
|
988
|
+
suppressEarlyReply: true,
|
|
989
|
+
suppressPostActionContinuation: true,
|
|
990
|
+
validate: async (_runtime, message) => {
|
|
991
|
+
const text = message.content.text ?? "";
|
|
992
|
+
if (!hasCommand(text))
|
|
993
|
+
return false;
|
|
994
|
+
const detection = detectCommand(text);
|
|
995
|
+
return detection.isCommand && detection.command?.key === key;
|
|
996
|
+
},
|
|
997
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
998
|
+
const result = await resolveCommand(runtime, message, {
|
|
999
|
+
...resolveTrust(message),
|
|
1000
|
+
deterministicOnly: true,
|
|
1001
|
+
...callback ? { callback } : {}
|
|
1002
|
+
});
|
|
1003
|
+
if (!result.handled || result.reply === undefined) {
|
|
1004
|
+
return { success: false };
|
|
1005
|
+
}
|
|
1006
|
+
if (callback) {
|
|
1007
|
+
await callback({ text: result.reply, source: "command" });
|
|
1008
|
+
}
|
|
1009
|
+
return { success: true, text: result.reply };
|
|
1010
|
+
}
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
function createCommandActions(commandKeys) {
|
|
1014
|
+
const actions = [];
|
|
1015
|
+
for (const key of commandKeys) {
|
|
1016
|
+
if (!isDeterministicCommand(key))
|
|
1017
|
+
continue;
|
|
1018
|
+
const definition = findCommandByKey(key);
|
|
1019
|
+
if (!definition)
|
|
1020
|
+
continue;
|
|
1021
|
+
if (definition.target && definition.target.kind !== "agent")
|
|
1022
|
+
continue;
|
|
1023
|
+
actions.push(buildAction(key, definition.nativeName ?? key, definition.description, definition.textAliases));
|
|
1024
|
+
}
|
|
1025
|
+
return actions;
|
|
1026
|
+
}
|
|
1027
|
+
// src/actions/shortcuts.ts
|
|
1028
|
+
function createCommandShortcuts(commandKeys = DETERMINISTIC_COMMAND_KEYS) {
|
|
1029
|
+
const shortcuts = [];
|
|
1030
|
+
for (const key of commandKeys) {
|
|
1031
|
+
const definition = findCommandByKey(key);
|
|
1032
|
+
if (!definition)
|
|
1033
|
+
continue;
|
|
1034
|
+
if (definition.target && definition.target.kind !== "agent")
|
|
1035
|
+
continue;
|
|
1036
|
+
shortcuts.push({
|
|
1037
|
+
id: `cmd:${key}`,
|
|
1038
|
+
kind: "explicit",
|
|
1039
|
+
aliases: definition.textAliases,
|
|
1040
|
+
target: { kind: "action", name: `${key.toUpperCase()}_COMMAND` }
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
1043
|
+
return shortcuts;
|
|
1044
|
+
}
|
|
1045
|
+
var explicitCommandShortcuts = createCommandShortcuts();
|
|
1046
|
+
var naturalShortcuts = [
|
|
1047
|
+
{
|
|
1048
|
+
id: "nl:commands",
|
|
1049
|
+
kind: "natural",
|
|
1050
|
+
patterns: [
|
|
1051
|
+
{
|
|
1052
|
+
regex: /^what commands (?:can i (?:use|run)|are (?:there|available)|do you (?:have|support))$/u
|
|
1053
|
+
},
|
|
1054
|
+
{
|
|
1055
|
+
regex: /^(?:show|list|give|tell)(?: me)?(?: a list of| the list of| all(?: of)?| the| your| available)* commands$/u
|
|
1056
|
+
},
|
|
1057
|
+
{ regex: /^what are(?: all)?(?: the| your| available)* commands$/u }
|
|
1058
|
+
],
|
|
1059
|
+
target: { kind: "action", name: "COMMANDS_COMMAND" },
|
|
1060
|
+
requiresAction: "COMMANDS_COMMAND",
|
|
1061
|
+
confidence: 0.95
|
|
1062
|
+
}
|
|
1063
|
+
];
|
|
1064
|
+
var commandShortcuts = [
|
|
1065
|
+
...explicitCommandShortcuts,
|
|
1066
|
+
...naturalShortcuts
|
|
1067
|
+
];
|
|
1068
|
+
|
|
1069
|
+
// src/actions/index.ts
|
|
1070
|
+
var commandActions = createCommandActions([
|
|
1071
|
+
...DETERMINISTIC_COMMAND_KEYS
|
|
1072
|
+
]);
|
|
1073
|
+
// src/connector-bridge.ts
|
|
1074
|
+
function resolveConnectorCommandAuth(agentId, name) {
|
|
1075
|
+
const definition = findCommandByKeyForRuntime(name, agentId);
|
|
1076
|
+
return {
|
|
1077
|
+
requiresAuth: definition?.requiresAuth ?? false,
|
|
1078
|
+
requiresElevated: definition?.requiresElevated ?? false
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
function gateConnectorCommand(requirements, sender) {
|
|
1082
|
+
if (requirements.requiresAuth && !sender.isAuthorized) {
|
|
1083
|
+
return {
|
|
1084
|
+
allowed: false,
|
|
1085
|
+
reply: "This command requires authorization. Pair your account or ask an owner to run it."
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
if (requirements.requiresElevated && !sender.isElevated) {
|
|
1089
|
+
return {
|
|
1090
|
+
allowed: false,
|
|
1091
|
+
reply: "This command requires elevated permissions."
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
return { allowed: true };
|
|
1095
|
+
}
|
|
1096
|
+
function gateConnectorCommandByName(agentId, name, sender) {
|
|
1097
|
+
return gateConnectorCommand(resolveConnectorCommandAuth(agentId, name), sender);
|
|
1098
|
+
}
|
|
1099
|
+
// src/settings-sections.ts
|
|
1100
|
+
var SETTINGS_SECTIONS = [
|
|
1101
|
+
{
|
|
1102
|
+
id: "ai-model",
|
|
1103
|
+
label: "AI Model & Providers",
|
|
1104
|
+
aliases: ["model", "models", "providers", "provider", "llm"]
|
|
1105
|
+
},
|
|
1106
|
+
{ id: "general", label: "General", aliases: ["basics"] },
|
|
1107
|
+
{ id: "agent", label: "Agent", aliases: ["character", "persona"] },
|
|
1108
|
+
{ id: "voice", label: "Voice", aliases: ["audio", "tts", "speech"] },
|
|
1109
|
+
{ id: "connectors", label: "Connectors", aliases: ["integrations"] },
|
|
1110
|
+
{ id: "skills", label: "Skills" },
|
|
1111
|
+
{ id: "memory", label: "Memory", aliases: ["knowledge"] },
|
|
1112
|
+
{ id: "permissions", label: "Permissions", aliases: ["security", "access"] },
|
|
1113
|
+
{ id: "billing", label: "Billing", aliases: ["plan", "subscription"] },
|
|
1114
|
+
{ id: "appearance", label: "Appearance", aliases: ["theme", "display"] },
|
|
1115
|
+
{ id: "notifications", label: "Notifications", aliases: ["alerts"] },
|
|
1116
|
+
{ id: "advanced", label: "Advanced", aliases: ["developer", "debug"] }
|
|
1117
|
+
];
|
|
1118
|
+
var lookup = null;
|
|
1119
|
+
function getLookup() {
|
|
1120
|
+
if (lookup)
|
|
1121
|
+
return lookup;
|
|
1122
|
+
const map = new Map;
|
|
1123
|
+
for (const section of SETTINGS_SECTIONS) {
|
|
1124
|
+
map.set(section.id, section);
|
|
1125
|
+
for (const alias of section.aliases ?? []) {
|
|
1126
|
+
map.set(alias, section);
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
lookup = map;
|
|
1130
|
+
return map;
|
|
1131
|
+
}
|
|
1132
|
+
function getSettingsSections() {
|
|
1133
|
+
return [...SETTINGS_SECTIONS];
|
|
1134
|
+
}
|
|
1135
|
+
function getSettingsSectionChoices() {
|
|
1136
|
+
return SETTINGS_SECTIONS.map((section) => section.id);
|
|
1137
|
+
}
|
|
1138
|
+
function resolveSettingsSection(raw) {
|
|
1139
|
+
const normalized = raw.trim().toLowerCase();
|
|
1140
|
+
if (!normalized)
|
|
1141
|
+
return;
|
|
1142
|
+
return getLookup().get(normalized)?.id;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
// src/navigation-commands.ts
|
|
1146
|
+
var IN_APP_SURFACES = ["gui", "tui"];
|
|
1147
|
+
var NAVIGATE_COMMANDS = [
|
|
1148
|
+
{
|
|
1149
|
+
key: "settings",
|
|
1150
|
+
nativeName: "settings",
|
|
1151
|
+
description: "Open agent settings",
|
|
1152
|
+
textAliases: ["/settings"],
|
|
1153
|
+
scope: "both",
|
|
1154
|
+
category: "docks",
|
|
1155
|
+
icon: "settings",
|
|
1156
|
+
target: { kind: "navigate", path: "/settings", tab: "settings" },
|
|
1157
|
+
acceptsArgs: true,
|
|
1158
|
+
args: [
|
|
1159
|
+
{
|
|
1160
|
+
name: "section",
|
|
1161
|
+
description: "Settings section to open",
|
|
1162
|
+
required: false,
|
|
1163
|
+
choices: getSettingsSectionChoices(),
|
|
1164
|
+
dynamicChoices: "settings-sections"
|
|
1165
|
+
}
|
|
1166
|
+
]
|
|
1167
|
+
},
|
|
1168
|
+
{
|
|
1169
|
+
key: "chat",
|
|
1170
|
+
nativeName: "chat",
|
|
1171
|
+
description: "Return to the chat",
|
|
1172
|
+
textAliases: ["/chat"],
|
|
1173
|
+
scope: "both",
|
|
1174
|
+
category: "docks",
|
|
1175
|
+
icon: "message-circle",
|
|
1176
|
+
target: { kind: "navigate", path: "/chat", tab: "chat" }
|
|
1177
|
+
},
|
|
1178
|
+
{
|
|
1179
|
+
key: "views",
|
|
1180
|
+
nativeName: "views",
|
|
1181
|
+
description: "Open the agent's views",
|
|
1182
|
+
textAliases: ["/views"],
|
|
1183
|
+
scope: "both",
|
|
1184
|
+
category: "docks",
|
|
1185
|
+
icon: "layout-grid",
|
|
1186
|
+
target: { kind: "navigate", path: "/views", tab: "views" },
|
|
1187
|
+
acceptsArgs: true,
|
|
1188
|
+
args: [
|
|
1189
|
+
{
|
|
1190
|
+
name: "view",
|
|
1191
|
+
description: "View to open",
|
|
1192
|
+
required: false,
|
|
1193
|
+
dynamicChoices: "views"
|
|
1194
|
+
}
|
|
1195
|
+
]
|
|
1196
|
+
},
|
|
1197
|
+
{
|
|
1198
|
+
key: "orchestrator",
|
|
1199
|
+
nativeName: "orchestrator",
|
|
1200
|
+
description: "Open the agent orchestrator",
|
|
1201
|
+
textAliases: ["/orchestrator"],
|
|
1202
|
+
scope: "both",
|
|
1203
|
+
category: "docks",
|
|
1204
|
+
icon: "workflow",
|
|
1205
|
+
target: { kind: "navigate", path: "/orchestrator", viewId: "orchestrator" }
|
|
1206
|
+
},
|
|
1207
|
+
{
|
|
1208
|
+
key: "character",
|
|
1209
|
+
nativeName: "character",
|
|
1210
|
+
description: "Open the character editor",
|
|
1211
|
+
textAliases: ["/character"],
|
|
1212
|
+
scope: "both",
|
|
1213
|
+
category: "docks",
|
|
1214
|
+
icon: "user",
|
|
1215
|
+
target: { kind: "navigate", path: "/character", tab: "character" }
|
|
1216
|
+
},
|
|
1217
|
+
{
|
|
1218
|
+
key: "knowledge",
|
|
1219
|
+
nativeName: "knowledge",
|
|
1220
|
+
description: "Open the knowledge base",
|
|
1221
|
+
textAliases: ["/knowledge"],
|
|
1222
|
+
scope: "both",
|
|
1223
|
+
category: "docks",
|
|
1224
|
+
icon: "book-open",
|
|
1225
|
+
target: {
|
|
1226
|
+
kind: "navigate",
|
|
1227
|
+
path: "/character/documents",
|
|
1228
|
+
tab: "documents"
|
|
1229
|
+
}
|
|
1230
|
+
},
|
|
1231
|
+
{
|
|
1232
|
+
key: "wallet",
|
|
1233
|
+
nativeName: "wallet",
|
|
1234
|
+
description: "Open the wallet & inventory",
|
|
1235
|
+
textAliases: ["/wallet"],
|
|
1236
|
+
scope: "both",
|
|
1237
|
+
category: "docks",
|
|
1238
|
+
icon: "wallet",
|
|
1239
|
+
target: { kind: "navigate", path: "/wallet", tab: "inventory" }
|
|
1240
|
+
},
|
|
1241
|
+
{
|
|
1242
|
+
key: "automations",
|
|
1243
|
+
nativeName: "automations",
|
|
1244
|
+
description: "Open automations",
|
|
1245
|
+
textAliases: ["/automations"],
|
|
1246
|
+
scope: "both",
|
|
1247
|
+
category: "docks",
|
|
1248
|
+
icon: "zap",
|
|
1249
|
+
target: { kind: "navigate", path: "/automations", tab: "automations" }
|
|
1250
|
+
},
|
|
1251
|
+
{
|
|
1252
|
+
key: "tasks",
|
|
1253
|
+
nativeName: "tasks",
|
|
1254
|
+
description: "Open tasks",
|
|
1255
|
+
textAliases: ["/tasks"],
|
|
1256
|
+
scope: "both",
|
|
1257
|
+
category: "docks",
|
|
1258
|
+
icon: "check-square",
|
|
1259
|
+
target: { kind: "navigate", path: "/apps/tasks", tab: "tasks" }
|
|
1260
|
+
},
|
|
1261
|
+
{
|
|
1262
|
+
key: "skills",
|
|
1263
|
+
nativeName: "skills",
|
|
1264
|
+
description: "Open the skills library",
|
|
1265
|
+
textAliases: ["/skills"],
|
|
1266
|
+
scope: "both",
|
|
1267
|
+
category: "docks",
|
|
1268
|
+
icon: "sparkles",
|
|
1269
|
+
target: { kind: "navigate", path: "/apps/skills", tab: "skills" }
|
|
1270
|
+
},
|
|
1271
|
+
{
|
|
1272
|
+
key: "plugins",
|
|
1273
|
+
nativeName: "plugins",
|
|
1274
|
+
description: "Open installed plugins",
|
|
1275
|
+
textAliases: ["/plugins"],
|
|
1276
|
+
scope: "both",
|
|
1277
|
+
category: "docks",
|
|
1278
|
+
icon: "plug",
|
|
1279
|
+
target: { kind: "navigate", path: "/apps/plugins", tab: "plugins" }
|
|
1280
|
+
},
|
|
1281
|
+
{
|
|
1282
|
+
key: "logs",
|
|
1283
|
+
nativeName: "logs",
|
|
1284
|
+
description: "Open the logs",
|
|
1285
|
+
textAliases: ["/logs"],
|
|
1286
|
+
scope: "both",
|
|
1287
|
+
category: "docks",
|
|
1288
|
+
icon: "scroll-text",
|
|
1289
|
+
target: { kind: "navigate", path: "/apps/logs", tab: "logs" }
|
|
1290
|
+
},
|
|
1291
|
+
{
|
|
1292
|
+
key: "database",
|
|
1293
|
+
nativeName: "database",
|
|
1294
|
+
description: "Open the database browser",
|
|
1295
|
+
textAliases: ["/database"],
|
|
1296
|
+
scope: "both",
|
|
1297
|
+
category: "docks",
|
|
1298
|
+
icon: "database",
|
|
1299
|
+
target: { kind: "navigate", path: "/apps/database", tab: "database" }
|
|
1300
|
+
}
|
|
1301
|
+
];
|
|
1302
|
+
var CLIENT_COMMANDS = [
|
|
1303
|
+
{
|
|
1304
|
+
key: "clear",
|
|
1305
|
+
nativeName: "clear",
|
|
1306
|
+
description: "Clear the current chat",
|
|
1307
|
+
textAliases: ["/clear"],
|
|
1308
|
+
scope: "both",
|
|
1309
|
+
category: "docks",
|
|
1310
|
+
icon: "eraser",
|
|
1311
|
+
surfaces: IN_APP_SURFACES,
|
|
1312
|
+
target: { kind: "client", clientAction: "clear-chat" }
|
|
1313
|
+
},
|
|
1314
|
+
{
|
|
1315
|
+
key: "fullscreen",
|
|
1316
|
+
nativeName: "fullscreen",
|
|
1317
|
+
description: "Toggle full-screen chat",
|
|
1318
|
+
textAliases: ["/fullscreen"],
|
|
1319
|
+
scope: "both",
|
|
1320
|
+
category: "docks",
|
|
1321
|
+
icon: "maximize",
|
|
1322
|
+
surfaces: IN_APP_SURFACES,
|
|
1323
|
+
target: { kind: "client", clientAction: "toggle-fullscreen" }
|
|
1324
|
+
},
|
|
1325
|
+
{
|
|
1326
|
+
key: "transcribe",
|
|
1327
|
+
nativeName: "transcribe",
|
|
1328
|
+
description: "Toggle long-form transcription mode (record-only; agent stays silent until an exit phrase)",
|
|
1329
|
+
textAliases: ["/transcribe"],
|
|
1330
|
+
scope: "both",
|
|
1331
|
+
category: "docks",
|
|
1332
|
+
icon: "mic",
|
|
1333
|
+
surfaces: IN_APP_SURFACES,
|
|
1334
|
+
target: { kind: "client", clientAction: "toggle-transcription" }
|
|
1335
|
+
}
|
|
1336
|
+
];
|
|
1337
|
+
var VIEW_SCOPED_COMMANDS = [
|
|
1338
|
+
{
|
|
1339
|
+
key: "calendar-add",
|
|
1340
|
+
nativeName: "calendar-add",
|
|
1341
|
+
description: "Add a calendar event (in the calendar view)",
|
|
1342
|
+
textAliases: ["/calendar-add"],
|
|
1343
|
+
scope: "both",
|
|
1344
|
+
category: "docks",
|
|
1345
|
+
icon: "calendar-plus",
|
|
1346
|
+
surfaces: IN_APP_SURFACES,
|
|
1347
|
+
views: ["calendar"],
|
|
1348
|
+
target: { kind: "agent" },
|
|
1349
|
+
acceptsArgs: true,
|
|
1350
|
+
args: [{ name: "event", description: "What to schedule", required: false }]
|
|
1351
|
+
},
|
|
1352
|
+
{
|
|
1353
|
+
key: "todos-add",
|
|
1354
|
+
nativeName: "todos-add",
|
|
1355
|
+
description: "Add a to-do (in the todos view)",
|
|
1356
|
+
textAliases: ["/todos-add"],
|
|
1357
|
+
scope: "both",
|
|
1358
|
+
category: "docks",
|
|
1359
|
+
icon: "list-plus",
|
|
1360
|
+
surfaces: IN_APP_SURFACES,
|
|
1361
|
+
views: ["todos"],
|
|
1362
|
+
target: { kind: "agent" },
|
|
1363
|
+
acceptsArgs: true,
|
|
1364
|
+
args: [{ name: "task", description: "What to do", required: false }]
|
|
1365
|
+
},
|
|
1366
|
+
{
|
|
1367
|
+
key: "todos-done",
|
|
1368
|
+
nativeName: "todos-done",
|
|
1369
|
+
description: "Complete a to-do (in the todos view)",
|
|
1370
|
+
textAliases: ["/todos-done"],
|
|
1371
|
+
scope: "both",
|
|
1372
|
+
category: "docks",
|
|
1373
|
+
icon: "check",
|
|
1374
|
+
surfaces: IN_APP_SURFACES,
|
|
1375
|
+
views: ["todos"],
|
|
1376
|
+
target: { kind: "agent" },
|
|
1377
|
+
acceptsArgs: true,
|
|
1378
|
+
args: [
|
|
1379
|
+
{ name: "task", description: "Which to-do to complete", required: false }
|
|
1380
|
+
]
|
|
1381
|
+
},
|
|
1382
|
+
{
|
|
1383
|
+
key: "documents-search",
|
|
1384
|
+
nativeName: "documents-search",
|
|
1385
|
+
description: "Search the knowledge base (in the documents view)",
|
|
1386
|
+
textAliases: ["/documents-search"],
|
|
1387
|
+
scope: "both",
|
|
1388
|
+
category: "docks",
|
|
1389
|
+
icon: "search",
|
|
1390
|
+
surfaces: IN_APP_SURFACES,
|
|
1391
|
+
views: ["documents"],
|
|
1392
|
+
target: { kind: "agent" },
|
|
1393
|
+
acceptsArgs: true,
|
|
1394
|
+
args: [
|
|
1395
|
+
{ name: "query", description: "What to search for", required: false }
|
|
1396
|
+
]
|
|
1397
|
+
}
|
|
1398
|
+
];
|
|
1399
|
+
function navigationCommandDefinitions() {
|
|
1400
|
+
return [...NAVIGATE_COMMANDS, ...CLIENT_COMMANDS, ...VIEW_SCOPED_COMMANDS];
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
// src/serialize.ts
|
|
1404
|
+
var DEFAULT_TARGET = { kind: "agent" };
|
|
1405
|
+
function commandVisibleForSurface(surfaces, surface) {
|
|
1406
|
+
if (!surface)
|
|
1407
|
+
return true;
|
|
1408
|
+
if (!surfaces || surfaces.length === 0)
|
|
1409
|
+
return true;
|
|
1410
|
+
return surfaces.includes(surface);
|
|
1411
|
+
}
|
|
1412
|
+
function serializeArg(arg) {
|
|
1413
|
+
const serialized = {
|
|
1414
|
+
name: arg.name,
|
|
1415
|
+
description: arg.description
|
|
1416
|
+
};
|
|
1417
|
+
if (arg.required)
|
|
1418
|
+
serialized.required = true;
|
|
1419
|
+
if (arg.captureRemaining)
|
|
1420
|
+
serialized.captureRemaining = true;
|
|
1421
|
+
if (arg.dynamicChoices)
|
|
1422
|
+
serialized.dynamicChoices = arg.dynamicChoices;
|
|
1423
|
+
if (Array.isArray(arg.choices) && arg.choices.length > 0) {
|
|
1424
|
+
serialized.choices = arg.choices;
|
|
1425
|
+
}
|
|
1426
|
+
return serialized;
|
|
1427
|
+
}
|
|
1428
|
+
function serializeCommand(command, options = {}) {
|
|
1429
|
+
const args = (command.args ?? []).map(serializeArg);
|
|
1430
|
+
const serialized = {
|
|
1431
|
+
key: command.key,
|
|
1432
|
+
nativeName: command.nativeName ?? command.key,
|
|
1433
|
+
description: command.description,
|
|
1434
|
+
textAliases: command.textAliases,
|
|
1435
|
+
scope: command.scope,
|
|
1436
|
+
acceptsArgs: command.acceptsArgs ?? args.length > 0,
|
|
1437
|
+
args,
|
|
1438
|
+
requiresAuth: command.requiresAuth ?? false,
|
|
1439
|
+
requiresElevated: command.requiresElevated ?? false,
|
|
1440
|
+
target: command.target ?? DEFAULT_TARGET,
|
|
1441
|
+
source: options.source ?? "builtin"
|
|
1442
|
+
};
|
|
1443
|
+
if (command.category)
|
|
1444
|
+
serialized.category = command.category;
|
|
1445
|
+
if (command.surfaces && command.surfaces.length > 0) {
|
|
1446
|
+
serialized.surfaces = command.surfaces;
|
|
1447
|
+
}
|
|
1448
|
+
if (command.icon)
|
|
1449
|
+
serialized.icon = command.icon;
|
|
1450
|
+
if (command.views && command.views.length > 0) {
|
|
1451
|
+
serialized.views = command.views;
|
|
1452
|
+
}
|
|
1453
|
+
return serialized;
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
// src/connector-catalog.ts
|
|
1457
|
+
var KNOWN_SURFACES = new Set([
|
|
1458
|
+
"gui",
|
|
1459
|
+
"tui",
|
|
1460
|
+
"discord",
|
|
1461
|
+
"telegram"
|
|
1462
|
+
]);
|
|
1463
|
+
function commandVisibleForView(views, activeViewId) {
|
|
1464
|
+
if (!views || views.length === 0)
|
|
1465
|
+
return true;
|
|
1466
|
+
if (!activeViewId)
|
|
1467
|
+
return false;
|
|
1468
|
+
return views.includes(activeViewId);
|
|
1469
|
+
}
|
|
1470
|
+
function isConnectorScoped(command) {
|
|
1471
|
+
return command.scope !== "text";
|
|
1472
|
+
}
|
|
1473
|
+
function commandName(command) {
|
|
1474
|
+
return command.nativeName ?? command.key;
|
|
1475
|
+
}
|
|
1476
|
+
function unifiedDefinitions(agentId) {
|
|
1477
|
+
const agentCommands = agentId ? getEnabledCommandsForRuntime(agentId) : DEFAULT_COMMANDS.filter((command) => command.enabled !== false);
|
|
1478
|
+
const agent = agentCommands.filter(isConnectorScoped);
|
|
1479
|
+
const navigation = navigationCommandDefinitions();
|
|
1480
|
+
const navigationNames = new Set(navigation.map(commandName));
|
|
1481
|
+
const agentOnly = agent.filter((command) => !navigationNames.has(commandName(command)));
|
|
1482
|
+
return [...agentOnly, ...navigation];
|
|
1483
|
+
}
|
|
1484
|
+
function normalizeSurface(surface) {
|
|
1485
|
+
return KNOWN_SURFACES.has(surface) ? surface : null;
|
|
1486
|
+
}
|
|
1487
|
+
function visibleDefinitions(surface, activeViewId, agentId) {
|
|
1488
|
+
const normalized = normalizeSurface(surface);
|
|
1489
|
+
return unifiedDefinitions(agentId).filter((command) => commandVisibleForSurface(command.surfaces, normalized)).filter((command) => commandVisibleForView(command.views, activeViewId));
|
|
1490
|
+
}
|
|
1491
|
+
function mapDefinitionArg(arg) {
|
|
1492
|
+
return {
|
|
1493
|
+
name: arg.name,
|
|
1494
|
+
description: arg.description,
|
|
1495
|
+
required: arg.required ?? false,
|
|
1496
|
+
choices: Array.isArray(arg.choices) ? arg.choices : []
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1499
|
+
function toConnectorCommand(command) {
|
|
1500
|
+
return {
|
|
1501
|
+
name: commandName(command),
|
|
1502
|
+
description: command.description,
|
|
1503
|
+
target: command.target ?? { kind: "agent" },
|
|
1504
|
+
options: (command.args ?? []).map(mapDefinitionArg),
|
|
1505
|
+
...command.views && command.views.length > 0 ? { views: command.views } : {}
|
|
1506
|
+
};
|
|
1507
|
+
}
|
|
1508
|
+
function getConnectorCommands(surface, options = {}) {
|
|
1509
|
+
return visibleDefinitions(surface, options.activeViewId, options.agentId).map(toConnectorCommand);
|
|
1510
|
+
}
|
|
1511
|
+
function getCatalogCommands(surface, options = {}) {
|
|
1512
|
+
return visibleDefinitions(surface, options.activeViewId, options.agentId).map((command) => serializeCommand(command, options.source ? { source: options.source } : {}));
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
// src/index.ts
|
|
1516
|
+
var commandRegistryProvider = {
|
|
1517
|
+
name: "COMMAND_REGISTRY",
|
|
1518
|
+
description: "Available chat commands and their descriptions",
|
|
1519
|
+
descriptionCompressed: "Available chat commands and descriptions.",
|
|
1520
|
+
dynamic: true,
|
|
1521
|
+
contexts: ["general", "automation"],
|
|
1522
|
+
contextGate: { anyOf: ["general", "automation"] },
|
|
1523
|
+
cacheStable: true,
|
|
1524
|
+
cacheScope: "agent",
|
|
1525
|
+
async get(runtime, message, _state) {
|
|
1526
|
+
const text = message.content.text ?? "";
|
|
1527
|
+
const isCommand = hasCommand(text);
|
|
1528
|
+
const commands = getEnabledCommandsForRuntime(runtime.agentId);
|
|
1529
|
+
if (isCommand) {
|
|
1530
|
+
const commandList = commands.map((cmd) => {
|
|
1531
|
+
const auth = cmd.requiresAuth ? " (requires auth)" : "";
|
|
1532
|
+
return `- ${cmd.textAliases[0]}: ${cmd.description}${auth}`;
|
|
1533
|
+
});
|
|
1534
|
+
return {
|
|
1535
|
+
text: `The user sent a slash command. Available commands:
|
|
1536
|
+
${commandList.join(`
|
|
1537
|
+
`)}
|
|
1538
|
+
|
|
1539
|
+
IMPORTANT: This is a slash command — respond by executing the matching command action, not with conversational text.`,
|
|
1540
|
+
values: {
|
|
1541
|
+
commandCount: commands.length,
|
|
1542
|
+
isCommand: true,
|
|
1543
|
+
hasElevatedCommands: commands.some((c) => c.requiresElevated)
|
|
1544
|
+
},
|
|
1545
|
+
data: { commands, isCommand: true }
|
|
1546
|
+
};
|
|
1547
|
+
}
|
|
1548
|
+
return {
|
|
1549
|
+
text: "",
|
|
1550
|
+
values: {
|
|
1551
|
+
commandCount: commands.length,
|
|
1552
|
+
isCommand: false
|
|
1553
|
+
},
|
|
1554
|
+
data: { isCommand: false }
|
|
1555
|
+
};
|
|
1556
|
+
}
|
|
1557
|
+
};
|
|
1558
|
+
function formatCommandResult(result) {
|
|
1559
|
+
if (result.error) {
|
|
1560
|
+
return `Error: ${result.error}`;
|
|
1561
|
+
}
|
|
1562
|
+
return result.reply ?? "Command executed";
|
|
1563
|
+
}
|
|
1564
|
+
function isAuthorized(context, command) {
|
|
1565
|
+
if (!command.requiresAuth) {
|
|
1566
|
+
return true;
|
|
1567
|
+
}
|
|
1568
|
+
return context.isAuthorized;
|
|
1569
|
+
}
|
|
1570
|
+
function isElevated(context, command) {
|
|
1571
|
+
if (!command.requiresElevated) {
|
|
1572
|
+
return true;
|
|
1573
|
+
}
|
|
1574
|
+
return context.isElevated;
|
|
1575
|
+
}
|
|
1576
|
+
var commandsPlugin = {
|
|
1577
|
+
name: "commands",
|
|
1578
|
+
description: "Chat command system with /help, /status, /reset, etc.",
|
|
1579
|
+
providers: [commandRegistryProvider],
|
|
1580
|
+
actions: commandActions,
|
|
1581
|
+
shortcuts: commandShortcuts,
|
|
1582
|
+
autoEnable: {
|
|
1583
|
+
shouldEnable: (_env, config) => {
|
|
1584
|
+
const f = config.features?.commands;
|
|
1585
|
+
return f === true || typeof f === "object" && f !== null && f.enabled !== false;
|
|
1586
|
+
}
|
|
1587
|
+
},
|
|
1588
|
+
config: {
|
|
1589
|
+
COMMANDS_CONFIG_ENABLED: "false",
|
|
1590
|
+
COMMANDS_DEBUG_ENABLED: "false",
|
|
1591
|
+
COMMANDS_BASH_ENABLED: "false",
|
|
1592
|
+
COMMANDS_RESTART_ENABLED: "true"
|
|
1593
|
+
},
|
|
1594
|
+
tests: [
|
|
1595
|
+
{
|
|
1596
|
+
name: "command-detection",
|
|
1597
|
+
tests: [
|
|
1598
|
+
{
|
|
1599
|
+
name: "Detect command prefix",
|
|
1600
|
+
fn: async (_runtime) => {
|
|
1601
|
+
if (!hasCommand("/help")) {
|
|
1602
|
+
throw new Error("Should detect /help command");
|
|
1603
|
+
}
|
|
1604
|
+
if (!hasCommand("/status test")) {
|
|
1605
|
+
throw new Error("Should detect /status with args");
|
|
1606
|
+
}
|
|
1607
|
+
if (hasCommand("hello world")) {
|
|
1608
|
+
throw new Error("Should not detect plain text as command");
|
|
1609
|
+
}
|
|
1610
|
+
import_core.logger.success("Command prefix detection works correctly");
|
|
1611
|
+
}
|
|
1612
|
+
},
|
|
1613
|
+
{
|
|
1614
|
+
name: "Parse command with args",
|
|
1615
|
+
fn: async (_runtime) => {
|
|
1616
|
+
const detection = detectCommand("/think:high");
|
|
1617
|
+
if (!detection.isCommand) {
|
|
1618
|
+
throw new Error("Should detect think command");
|
|
1619
|
+
}
|
|
1620
|
+
if (detection.command?.key !== "think") {
|
|
1621
|
+
throw new Error(`Expected key 'think', got '${detection.command?.key}'`);
|
|
1622
|
+
}
|
|
1623
|
+
if (detection.command.args[0] !== "high") {
|
|
1624
|
+
throw new Error(`Expected arg 'high', got '${detection.command.args[0]}'`);
|
|
1625
|
+
}
|
|
1626
|
+
import_core.logger.success("Command argument parsing works correctly");
|
|
1627
|
+
}
|
|
1628
|
+
},
|
|
1629
|
+
{
|
|
1630
|
+
name: "Normalize command body",
|
|
1631
|
+
fn: async (_runtime) => {
|
|
1632
|
+
const normalized1 = normalizeCommandBody("/status: test");
|
|
1633
|
+
if (normalized1 !== "/status test") {
|
|
1634
|
+
throw new Error(`Expected '/status test', got '${normalized1}'`);
|
|
1635
|
+
}
|
|
1636
|
+
const normalized2 = normalizeCommandBody("@bot /help", "bot");
|
|
1637
|
+
if (normalized2 !== "/help") {
|
|
1638
|
+
throw new Error(`Expected '/help', got '${normalized2}'`);
|
|
1639
|
+
}
|
|
1640
|
+
import_core.logger.success("Command normalization works correctly");
|
|
1641
|
+
}
|
|
1642
|
+
},
|
|
1643
|
+
{
|
|
1644
|
+
name: "Find command by alias",
|
|
1645
|
+
fn: async (_runtime) => {
|
|
1646
|
+
const cmd = findCommandByAlias("/h");
|
|
1647
|
+
if (!cmd) {
|
|
1648
|
+
throw new Error("Should find help command by /h alias");
|
|
1649
|
+
}
|
|
1650
|
+
if (cmd.key !== "help") {
|
|
1651
|
+
throw new Error(`Expected key 'help', got '${cmd.key}'`);
|
|
1652
|
+
}
|
|
1653
|
+
import_core.logger.success("Command alias lookup works correctly");
|
|
1654
|
+
}
|
|
1655
|
+
},
|
|
1656
|
+
{
|
|
1657
|
+
name: "Find command by key",
|
|
1658
|
+
fn: async (_runtime) => {
|
|
1659
|
+
const cmd = findCommandByKey("status");
|
|
1660
|
+
if (!cmd) {
|
|
1661
|
+
throw new Error("Should find status command by key");
|
|
1662
|
+
}
|
|
1663
|
+
if (cmd.key !== "status") {
|
|
1664
|
+
throw new Error(`Expected key 'status', got '${cmd.key}'`);
|
|
1665
|
+
}
|
|
1666
|
+
import_core.logger.success("Command key lookup works correctly");
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
]
|
|
1670
|
+
},
|
|
1671
|
+
{
|
|
1672
|
+
name: "command-registry",
|
|
1673
|
+
tests: [
|
|
1674
|
+
{
|
|
1675
|
+
name: "Get enabled commands",
|
|
1676
|
+
fn: async (_runtime) => {
|
|
1677
|
+
const commands = getEnabledCommands();
|
|
1678
|
+
if (commands.length === 0) {
|
|
1679
|
+
throw new Error("Should have enabled commands");
|
|
1680
|
+
}
|
|
1681
|
+
const cmdHelp = commands.some((c) => c.key === "help");
|
|
1682
|
+
const cmdStatus = commands.some((c) => c.key === "status");
|
|
1683
|
+
if (!cmdHelp || !cmdStatus) {
|
|
1684
|
+
throw new Error("Should have help and status commands");
|
|
1685
|
+
}
|
|
1686
|
+
import_core.logger.success("Command registry works correctly");
|
|
1687
|
+
}
|
|
1688
|
+
},
|
|
1689
|
+
{
|
|
1690
|
+
name: "Register custom command",
|
|
1691
|
+
fn: async (_runtime) => {
|
|
1692
|
+
const customCmd = {
|
|
1693
|
+
key: "test-custom",
|
|
1694
|
+
description: "Test custom command",
|
|
1695
|
+
textAliases: ["/test-custom", "/tc"],
|
|
1696
|
+
scope: "text"
|
|
1697
|
+
};
|
|
1698
|
+
registerCommand(customCmd);
|
|
1699
|
+
const found = findCommandByKey("test-custom");
|
|
1700
|
+
if (!found) {
|
|
1701
|
+
throw new Error("Should find registered custom command");
|
|
1702
|
+
}
|
|
1703
|
+
unregisterCommand("test-custom");
|
|
1704
|
+
const notFound = findCommandByKey("test-custom");
|
|
1705
|
+
if (notFound) {
|
|
1706
|
+
throw new Error("Should not find unregistered command");
|
|
1707
|
+
}
|
|
1708
|
+
import_core.logger.success("Custom command registration works correctly");
|
|
1709
|
+
}
|
|
1710
|
+
},
|
|
1711
|
+
{
|
|
1712
|
+
name: "Get commands by category",
|
|
1713
|
+
fn: async (_runtime) => {
|
|
1714
|
+
const statusCommands = getCommandsByCategory("status");
|
|
1715
|
+
if (statusCommands.length === 0) {
|
|
1716
|
+
throw new Error("Should have status category commands");
|
|
1717
|
+
}
|
|
1718
|
+
const allStatus = statusCommands.every((c) => c.category === "status");
|
|
1719
|
+
if (!allStatus) {
|
|
1720
|
+
throw new Error("All returned commands should be in status category");
|
|
1721
|
+
}
|
|
1722
|
+
import_core.logger.success("Command categorization works correctly");
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
]
|
|
1726
|
+
}
|
|
1727
|
+
],
|
|
1728
|
+
async init(config, runtime) {
|
|
1729
|
+
import_core.logger.log("[plugin-commands] Initializing command system");
|
|
1730
|
+
initForRuntime(runtime.agentId);
|
|
1731
|
+
const configEnabled = config.COMMANDS_CONFIG_ENABLED === "true";
|
|
1732
|
+
const debugEnabled = config.COMMANDS_DEBUG_ENABLED === "true";
|
|
1733
|
+
const bashEnabled = config.COMMANDS_BASH_ENABLED === "true";
|
|
1734
|
+
const restartEnabled = config.COMMANDS_RESTART_ENABLED !== "false";
|
|
1735
|
+
const configCmd = findCommandByKey("config");
|
|
1736
|
+
if (configCmd) {
|
|
1737
|
+
configCmd.enabled = configEnabled;
|
|
1738
|
+
}
|
|
1739
|
+
const debugCmd = findCommandByKey("debug");
|
|
1740
|
+
if (debugCmd) {
|
|
1741
|
+
debugCmd.enabled = debugEnabled;
|
|
1742
|
+
}
|
|
1743
|
+
const bashCmd = findCommandByKey("bash");
|
|
1744
|
+
if (bashCmd) {
|
|
1745
|
+
bashCmd.enabled = bashEnabled;
|
|
1746
|
+
}
|
|
1747
|
+
const restartCmd = findCommandByKey("restart");
|
|
1748
|
+
if (restartCmd) {
|
|
1749
|
+
restartCmd.enabled = restartEnabled;
|
|
1750
|
+
}
|
|
1751
|
+
const enabledCount = getEnabledCommands().length;
|
|
1752
|
+
import_core.logger.log(`[plugin-commands] ${enabledCount} commands enabled for agent ${runtime.agentId}`);
|
|
1753
|
+
}
|
|
1754
|
+
};
|
|
1755
|
+
var src_default = commandsPlugin;
|
|
1756
|
+
|
|
1757
|
+
//# debugId=D816A7531DE8F68364756E2164756E21
|