@dreb/coding-agent 2.51.0 → 2.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -6
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +11 -6
- package/dist/cli/args.js.map +1 -1
- package/dist/core/extensions/types.d.ts +31 -11
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/slash-commands.d.ts +14 -0
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +28 -3
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tools/ask-user.d.ts +28 -20
- package/dist/core/tools/ask-user.d.ts.map +1 -1
- package/dist/core/tools/ask-user.js +130 -106
- package/dist/core/tools/ask-user.js.map +1 -1
- package/dist/core/tools/index.d.ts +9 -7
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/modes/interactive/components/ask-wizard.d.ts +83 -0
- package/dist/modes/interactive/components/ask-wizard.d.ts.map +1 -0
- package/dist/modes/interactive/components/ask-wizard.js +464 -0
- package/dist/modes/interactive/components/ask-wizard.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +4 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -5
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +11 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +15 -1
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +3 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +230 -47
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +66 -11
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/docs/dashboard.md +1 -3
- package/docs/extensions.md +39 -22
- package/docs/rpc.md +84 -25
- package/examples/extensions/rpc-demo.ts +29 -0
- package/examples/rpc-extension-ui.ts +162 -6
- package/package.json +1 -1
- package/dist/modes/interactive/components/ask-user.d.ts +0 -59
- package/dist/modes/interactive/components/ask-user.d.ts.map +0 -1
- package/dist/modes/interactive/components/ask-user.js +0 -240
- package/dist/modes/interactive/components/ask-user.js.map +0 -1
|
@@ -16,12 +16,15 @@ import { isValidThinkingLevel, VALID_THINKING_LEVELS } from "../../cli/args.js";
|
|
|
16
16
|
import { VERSION } from "../../config.js";
|
|
17
17
|
import { canonicalizeTrustedRoots, matchContextTrust, validateTrustedContextFolder, validateTrustedContextFolders, } from "../../core/context-trust.js";
|
|
18
18
|
import { DailyCostTracker } from "../../core/daily-cost-tracker.js";
|
|
19
|
+
import { acquireDreamLock, buildDreamPrompt, cleanupDreamTmpDirs, parseDreamCommand, performDreamBackup, pruneOldBackups, resolveDreamContext, validateArchivePath, validateMemoryLinks, } from "../../core/dream.js";
|
|
19
20
|
import { getGitBranch } from "../../core/git-branch.js";
|
|
20
21
|
import { parseModelPattern } from "../../core/model-resolver.js";
|
|
21
22
|
import { takeOverStdout, writeRawStdout } from "../../core/output-guard.js";
|
|
22
23
|
import { SessionManager } from "../../core/session-manager.js";
|
|
24
|
+
import { BUILTIN_SLASH_COMMANDS, parseBuiltinSlashCommand } from "../../core/slash-commands.js";
|
|
23
25
|
import { TabTitleGenerator } from "../../core/tab-title.js";
|
|
24
26
|
import { validateThinkingLevelForModel } from "../../core/thinking.js";
|
|
27
|
+
import { resolveToCwd } from "../../core/tools/path-utils.js";
|
|
25
28
|
import { discoverAgentTypes, getBackgroundAgents, rehydrateBackgroundAgentsFromDisk, } from "../../core/tools/subagent.js";
|
|
26
29
|
import { theme } from "../interactive/theme/theme.js";
|
|
27
30
|
import { attachJsonlLineReader, serializeJsonLine } from "./jsonl.js";
|
|
@@ -71,6 +74,111 @@ export function getResourcesForRpc(session) {
|
|
|
71
74
|
session.resourceLoader.getAppendSystemPrompt().length > 0,
|
|
72
75
|
};
|
|
73
76
|
}
|
|
77
|
+
export function getCommandsForRpc(session) {
|
|
78
|
+
const commands = new Map();
|
|
79
|
+
for (const command of session.extensionRunner?.getRegisteredCommands() ?? []) {
|
|
80
|
+
commands.set(command.invocationName, {
|
|
81
|
+
name: command.invocationName,
|
|
82
|
+
description: command.description,
|
|
83
|
+
source: "extension",
|
|
84
|
+
sourceInfo: command.sourceInfo,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
for (const template of session.promptTemplates) {
|
|
88
|
+
if (!commands.has(template.name)) {
|
|
89
|
+
commands.set(template.name, {
|
|
90
|
+
name: template.name,
|
|
91
|
+
description: template.description,
|
|
92
|
+
source: "prompt",
|
|
93
|
+
sourceInfo: template.sourceInfo,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
for (const skill of session.getFilteredSkills()) {
|
|
98
|
+
const name = `skill:${skill.name}`;
|
|
99
|
+
if (!commands.has(name)) {
|
|
100
|
+
commands.set(name, { name, description: skill.description, source: "skill", sourceInfo: skill.sourceInfo });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Built-ins deliberately win collisions, matching interactive autocomplete and
|
|
104
|
+
// ensuring a colliding resource can never make built-in text reach the model.
|
|
105
|
+
for (const command of BUILTIN_SLASH_COMMANDS) {
|
|
106
|
+
commands.set(command.name, {
|
|
107
|
+
name: command.name,
|
|
108
|
+
description: command.description,
|
|
109
|
+
source: "builtin",
|
|
110
|
+
dashboard: command.dashboard !== false,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return [...commands.values()];
|
|
114
|
+
}
|
|
115
|
+
export function getBuiltinPromptRejection(message) {
|
|
116
|
+
const parsed = parseBuiltinSlashCommand(message);
|
|
117
|
+
return parsed
|
|
118
|
+
? `Built-in slash command /${parsed.command.name} must be handled by the RPC client; it was not sent to the model.`
|
|
119
|
+
: undefined;
|
|
120
|
+
}
|
|
121
|
+
async function runDreamForRpc(session, args = "") {
|
|
122
|
+
const command = parseDreamCommand(`/dream${args ? ` ${args}` : ""}`);
|
|
123
|
+
if (command.type === "showBackup") {
|
|
124
|
+
return { message: `Dream backup path: ${session.settingsManager.getDreamArchivePath()}` };
|
|
125
|
+
}
|
|
126
|
+
if (command.type === "setBackup") {
|
|
127
|
+
const absolutePath = resolveToCwd(command.path, session.sessionManager.getCwd());
|
|
128
|
+
const context = await resolveDreamContext(session.settingsManager);
|
|
129
|
+
validateArchivePath(absolutePath, [
|
|
130
|
+
context.globalMemoryDir,
|
|
131
|
+
...context.projectMemoryDirs,
|
|
132
|
+
...context.claudeMemoryDirs,
|
|
133
|
+
]);
|
|
134
|
+
if (session.settingsManager.hasGlobalSettingsLoadError()) {
|
|
135
|
+
throw new Error("Cannot write dream backup path: the global settings file failed to load");
|
|
136
|
+
}
|
|
137
|
+
session.settingsManager.drainErrors();
|
|
138
|
+
session.settingsManager.setDreamArchivePath(absolutePath);
|
|
139
|
+
try {
|
|
140
|
+
await session.settingsManager.flush();
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
session.settingsManager.reload();
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
const writeErrors = session.settingsManager.drainErrors();
|
|
147
|
+
if (writeErrors.length > 0) {
|
|
148
|
+
session.settingsManager.reload();
|
|
149
|
+
throw new Error(`Failed to persist dream backup path: ${writeErrors.map((entry) => `${entry.scope}: ${entry.error.message}`).join("; ")}`);
|
|
150
|
+
}
|
|
151
|
+
return { message: `Dream backup path set to: ${absolutePath}` };
|
|
152
|
+
}
|
|
153
|
+
let releaseLock;
|
|
154
|
+
let context;
|
|
155
|
+
try {
|
|
156
|
+
releaseLock = await acquireDreamLock();
|
|
157
|
+
context = await resolveDreamContext(session.settingsManager);
|
|
158
|
+
validateArchivePath(context.archivePath, [
|
|
159
|
+
context.globalMemoryDir,
|
|
160
|
+
...context.projectMemoryDirs,
|
|
161
|
+
...context.claudeMemoryDirs,
|
|
162
|
+
]);
|
|
163
|
+
const backup = await performDreamBackup(context);
|
|
164
|
+
if (!backup.verified) {
|
|
165
|
+
throw new Error(`Backup verification failed; check ${backup.backupPath}`);
|
|
166
|
+
}
|
|
167
|
+
await session.prompt(buildDreamPrompt(context, backup), { source: "rpc" });
|
|
168
|
+
const links = validateMemoryLinks([context.globalMemoryDir, ...context.projectMemoryDirs]);
|
|
169
|
+
await pruneOldBackups(context.archivePath);
|
|
170
|
+
return {
|
|
171
|
+
message: links.valid
|
|
172
|
+
? `Dream completed. Backup: ${backup.backupPath}`
|
|
173
|
+
: `Dream completed with ${links.brokenLinks.length} broken memory link(s). Backup: ${backup.backupPath}`,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
releaseLock?.();
|
|
178
|
+
if (context)
|
|
179
|
+
cleanupDreamTmpDirs([context.globalMemoryDir, ...context.projectMemoryDirs]);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
74
182
|
export function getPendingMessagesForRpc(session) {
|
|
75
183
|
return {
|
|
76
184
|
steering: [...session.getSteeringMessages()],
|
|
@@ -915,6 +1023,74 @@ export function createRpcExtensionUIContext(output, pendingExtensionRequests, on
|
|
|
915
1023
|
output(rpcRequest);
|
|
916
1024
|
});
|
|
917
1025
|
}
|
|
1026
|
+
// Serialize `ask` requests so at most one ask wizard is ever pending, mirroring
|
|
1027
|
+
// the TUI's single-dialog queue (`enqueueExtensionDialog`). Tool execution runs
|
|
1028
|
+
// in parallel, so a turn can issue several `ask_user` calls at once; without
|
|
1029
|
+
// this the Dashboard (which renders a single pending ask) would leave the extra
|
|
1030
|
+
// wizards invisible and their promises hanging until the turn aborts. The first
|
|
1031
|
+
// ask runs synchronously (preserving immediate request emission); later ones
|
|
1032
|
+
// wait in a FIFO. A call whose signal aborts while still queued settles with the
|
|
1033
|
+
// aborted value and never emits a request.
|
|
1034
|
+
let askInFlight = false;
|
|
1035
|
+
const askWaiters = [];
|
|
1036
|
+
const runNextAsk = () => {
|
|
1037
|
+
if (askInFlight)
|
|
1038
|
+
return;
|
|
1039
|
+
const next = askWaiters.shift();
|
|
1040
|
+
if (!next)
|
|
1041
|
+
return;
|
|
1042
|
+
askInFlight = true;
|
|
1043
|
+
next();
|
|
1044
|
+
};
|
|
1045
|
+
function serializeAsk(opts, abortedValue, run) {
|
|
1046
|
+
const signal = opts?.signal;
|
|
1047
|
+
if (signal?.aborted)
|
|
1048
|
+
return Promise.resolve(abortedValue);
|
|
1049
|
+
return new Promise((resolve, reject) => {
|
|
1050
|
+
let settled = false;
|
|
1051
|
+
const finish = (value) => {
|
|
1052
|
+
if (settled)
|
|
1053
|
+
return;
|
|
1054
|
+
settled = true;
|
|
1055
|
+
resolve(value);
|
|
1056
|
+
};
|
|
1057
|
+
// A started run's outcome propagates verbatim (a host/protocol failure
|
|
1058
|
+
// must still reject so the ask_user tool reports it distinctly).
|
|
1059
|
+
const fail = (error) => {
|
|
1060
|
+
if (settled)
|
|
1061
|
+
return;
|
|
1062
|
+
settled = true;
|
|
1063
|
+
reject(error);
|
|
1064
|
+
};
|
|
1065
|
+
// While still queued, a signal abort removes this task and settles it
|
|
1066
|
+
// without ever emitting. Once started, createDialogPromise owns abort.
|
|
1067
|
+
const onAbort = () => {
|
|
1068
|
+
const index = askWaiters.indexOf(startTask);
|
|
1069
|
+
if (index === -1)
|
|
1070
|
+
return;
|
|
1071
|
+
askWaiters.splice(index, 1);
|
|
1072
|
+
finish(abortedValue);
|
|
1073
|
+
};
|
|
1074
|
+
const startTask = () => {
|
|
1075
|
+
signal?.removeEventListener("abort", onAbort);
|
|
1076
|
+
if (signal?.aborted) {
|
|
1077
|
+
finish(abortedValue);
|
|
1078
|
+
askInFlight = false;
|
|
1079
|
+
runNextAsk();
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
run()
|
|
1083
|
+
.then(finish, fail)
|
|
1084
|
+
.finally(() => {
|
|
1085
|
+
askInFlight = false;
|
|
1086
|
+
runNextAsk();
|
|
1087
|
+
});
|
|
1088
|
+
};
|
|
1089
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
1090
|
+
askWaiters.push(startTask);
|
|
1091
|
+
runNextAsk();
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
918
1094
|
/**
|
|
919
1095
|
* Create an extension UI context that uses the RPC protocol.
|
|
920
1096
|
*/
|
|
@@ -922,38 +1098,50 @@ export function createRpcExtensionUIContext(output, pendingExtensionRequests, on
|
|
|
922
1098
|
select: (title, options, opts) => createDialogPromise(opts, undefined, { method: "select", title, options, timeout: opts?.timeout }, (r) => "cancelled" in r && r.cancelled ? undefined : "value" in r ? r.value : undefined),
|
|
923
1099
|
confirm: (title, message, opts) => createDialogPromise(opts, false, { method: "confirm", title, message, timeout: opts?.timeout }, (r) => "cancelled" in r && r.cancelled ? false : "confirmed" in r ? r.confirmed : false),
|
|
924
1100
|
input: (title, placeholder, opts) => createDialogPromise(opts, undefined, { method: "input", title, placeholder, timeout: opts?.timeout }, (r) => "cancelled" in r && r.cancelled ? undefined : "value" in r ? r.value : undefined),
|
|
925
|
-
ask: (request, opts) => createDialogPromise(opts, undefined, {
|
|
1101
|
+
ask: (request, opts) => serializeAsk(opts, undefined, () => createDialogPromise(opts, undefined, {
|
|
926
1102
|
method: "ask",
|
|
927
1103
|
title: request.title ?? "Question",
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
1104
|
+
questions: request.questions.map((q) => ({
|
|
1105
|
+
question: q.question,
|
|
1106
|
+
title: q.title,
|
|
1107
|
+
options: q.options,
|
|
1108
|
+
allowFreeText: q.allowFreeText,
|
|
1109
|
+
multiSelect: q.multiSelect,
|
|
1110
|
+
multiline: q.multiline,
|
|
1111
|
+
})),
|
|
933
1112
|
timeout: opts?.timeout,
|
|
934
1113
|
// Preserve the authoritative deadline across Dashboard reload,
|
|
935
1114
|
// resync, and drill-in hydration instead of restarting the full
|
|
936
|
-
// duration whenever the
|
|
1115
|
+
// duration whenever the wizard remounts.
|
|
937
1116
|
expiresAt: opts?.timeout ? Date.now() + opts.timeout : undefined,
|
|
938
1117
|
}, (response) => {
|
|
939
1118
|
if ("cancelled" in response && response.cancelled) {
|
|
940
1119
|
onAskStop();
|
|
941
1120
|
return undefined;
|
|
942
1121
|
}
|
|
943
|
-
const
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
throw new Error("Invalid RPC ask response: selected must be an array of strings");
|
|
947
|
-
}
|
|
948
|
-
if (customText !== undefined && typeof customText !== "string") {
|
|
949
|
-
throw new Error("Invalid RPC ask response: customText must be a string");
|
|
950
|
-
}
|
|
951
|
-
if (selected.length === 0 && !customText?.trim()) {
|
|
952
|
-
onAskStop();
|
|
953
|
-
return undefined;
|
|
1122
|
+
const rawAnswers = response.answers;
|
|
1123
|
+
if (!Array.isArray(rawAnswers)) {
|
|
1124
|
+
throw new Error("Invalid RPC ask response: answers must be an array");
|
|
954
1125
|
}
|
|
955
|
-
|
|
956
|
-
|
|
1126
|
+
const answers = rawAnswers.map((entry) => {
|
|
1127
|
+
const selected = entry?.selected;
|
|
1128
|
+
const customText = entry?.customText;
|
|
1129
|
+
const skipped = entry?.skipped;
|
|
1130
|
+
if (!Array.isArray(selected) || !selected.every((value) => typeof value === "string")) {
|
|
1131
|
+
throw new Error("Invalid RPC ask response: each answer's selected must be an array of strings");
|
|
1132
|
+
}
|
|
1133
|
+
if (customText !== undefined && typeof customText !== "string") {
|
|
1134
|
+
throw new Error("Invalid RPC ask response: customText must be a string");
|
|
1135
|
+
}
|
|
1136
|
+
const answered = selected.length > 0 || !!customText?.trim();
|
|
1137
|
+
return {
|
|
1138
|
+
selected,
|
|
1139
|
+
customText: customText || undefined,
|
|
1140
|
+
skipped: skipped === true || !answered,
|
|
1141
|
+
};
|
|
1142
|
+
});
|
|
1143
|
+
return { answers };
|
|
1144
|
+
}, onAskStop)),
|
|
957
1145
|
notify(message, type) {
|
|
958
1146
|
// Fire and forget - no response needed
|
|
959
1147
|
output({
|
|
@@ -1193,6 +1381,9 @@ export async function runRpcMode(session, modelFallbackMessage) {
|
|
|
1193
1381
|
// Prompting
|
|
1194
1382
|
// =================================================================
|
|
1195
1383
|
case "prompt": {
|
|
1384
|
+
const rejection = getBuiltinPromptRejection(command.message);
|
|
1385
|
+
if (rejection)
|
|
1386
|
+
return error(id, "prompt", rejection);
|
|
1196
1387
|
// Don't await - events will stream
|
|
1197
1388
|
// Extension commands are executed immediately, file prompt templates are expanded
|
|
1198
1389
|
// If streaming and streamingBehavior specified, queues via steer/followUp
|
|
@@ -1206,10 +1397,16 @@ export async function runRpcMode(session, modelFallbackMessage) {
|
|
|
1206
1397
|
return success(id, "prompt");
|
|
1207
1398
|
}
|
|
1208
1399
|
case "steer": {
|
|
1400
|
+
const rejection = getBuiltinPromptRejection(command.message);
|
|
1401
|
+
if (rejection)
|
|
1402
|
+
return error(id, "steer", rejection);
|
|
1209
1403
|
await session.steer(command.message, command.images);
|
|
1210
1404
|
return success(id, "steer");
|
|
1211
1405
|
}
|
|
1212
1406
|
case "follow_up": {
|
|
1407
|
+
const rejection = getBuiltinPromptRejection(command.message);
|
|
1408
|
+
if (rejection)
|
|
1409
|
+
return error(id, "follow_up", rejection);
|
|
1213
1410
|
await session.followUp(command.message, command.images);
|
|
1214
1411
|
return success(id, "follow_up");
|
|
1215
1412
|
}
|
|
@@ -1224,6 +1421,13 @@ export async function runRpcMode(session, modelFallbackMessage) {
|
|
|
1224
1421
|
const cancelled = !(await session.newSession(options));
|
|
1225
1422
|
return success(id, "new_session", { cancelled });
|
|
1226
1423
|
}
|
|
1424
|
+
case "reload": {
|
|
1425
|
+
await session.reload();
|
|
1426
|
+
return success(id, "reload");
|
|
1427
|
+
}
|
|
1428
|
+
case "dream": {
|
|
1429
|
+
return success(id, "dream", await runDreamForRpc(session, command.args));
|
|
1430
|
+
}
|
|
1227
1431
|
// =================================================================
|
|
1228
1432
|
// State
|
|
1229
1433
|
// =================================================================
|
|
@@ -1399,6 +1603,10 @@ export async function runRpcMode(session, modelFallbackMessage) {
|
|
|
1399
1603
|
const path = await session.exportToHtml(command.outputPath);
|
|
1400
1604
|
return success(id, "export_html", { path });
|
|
1401
1605
|
}
|
|
1606
|
+
case "import_jsonl": {
|
|
1607
|
+
const cancelled = !(await session.importFromJsonl(command.inputPath));
|
|
1608
|
+
return success(id, "import_jsonl", { cancelled });
|
|
1609
|
+
}
|
|
1402
1610
|
case "switch_session": {
|
|
1403
1611
|
const cancelled = !(await session.switchSession(command.sessionPath));
|
|
1404
1612
|
return success(id, "switch_session", { cancelled });
|
|
@@ -1454,7 +1662,7 @@ export async function runRpcMode(session, modelFallbackMessage) {
|
|
|
1454
1662
|
return success(id, "get_messages", { messages: session.messages });
|
|
1455
1663
|
}
|
|
1456
1664
|
// =================================================================
|
|
1457
|
-
//
|
|
1665
|
+
// Command discovery (resource commands plus client-handled built-ins)
|
|
1458
1666
|
// =================================================================
|
|
1459
1667
|
// =================================================================
|
|
1460
1668
|
// Session Listing
|
|
@@ -1528,32 +1736,7 @@ export async function runRpcMode(session, modelFallbackMessage) {
|
|
|
1528
1736
|
return success(id, "get_version", { version: VERSION });
|
|
1529
1737
|
}
|
|
1530
1738
|
case "get_commands": {
|
|
1531
|
-
|
|
1532
|
-
for (const command of session.extensionRunner?.getRegisteredCommands() ?? []) {
|
|
1533
|
-
commands.push({
|
|
1534
|
-
name: command.invocationName,
|
|
1535
|
-
description: command.description,
|
|
1536
|
-
source: "extension",
|
|
1537
|
-
sourceInfo: command.sourceInfo,
|
|
1538
|
-
});
|
|
1539
|
-
}
|
|
1540
|
-
for (const template of session.promptTemplates) {
|
|
1541
|
-
commands.push({
|
|
1542
|
-
name: template.name,
|
|
1543
|
-
description: template.description,
|
|
1544
|
-
source: "prompt",
|
|
1545
|
-
sourceInfo: template.sourceInfo,
|
|
1546
|
-
});
|
|
1547
|
-
}
|
|
1548
|
-
for (const skill of session.getFilteredSkills()) {
|
|
1549
|
-
commands.push({
|
|
1550
|
-
name: `skill:${skill.name}`,
|
|
1551
|
-
description: skill.description,
|
|
1552
|
-
source: "skill",
|
|
1553
|
-
sourceInfo: skill.sourceInfo,
|
|
1554
|
-
});
|
|
1555
|
-
}
|
|
1556
|
-
return success(id, "get_commands", { commands });
|
|
1739
|
+
return success(id, "get_commands", { commands: getCommandsForRpc(session) });
|
|
1557
1740
|
}
|
|
1558
1741
|
default: {
|
|
1559
1742
|
const unknownCommand = command;
|