@serkanalgur/opencode-nexus 1.0.5 → 1.2.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 +296 -248
- package/dist/index.js +2294 -432
- package/dist/tui.js +328 -20
- package/package.json +1 -1
package/dist/tui.js
CHANGED
|
@@ -107,6 +107,64 @@ var SuspenseContext = createContext();
|
|
|
107
107
|
// node_modules/@opencode/plugin/dist/tui/solid.js
|
|
108
108
|
var PluginContext = createContext();
|
|
109
109
|
// src/config.ts
|
|
110
|
+
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
111
|
+
import { homedir } from "node:os";
|
|
112
|
+
import { join, dirname } from "node:path";
|
|
113
|
+
function stripJsonComments(jsonc) {
|
|
114
|
+
const result = [];
|
|
115
|
+
let i = 0;
|
|
116
|
+
const len = jsonc.length;
|
|
117
|
+
while (i < len) {
|
|
118
|
+
const ch = jsonc[i];
|
|
119
|
+
if (ch === '"') {
|
|
120
|
+
result.push(ch);
|
|
121
|
+
i++;
|
|
122
|
+
while (i < len && jsonc[i] !== '"') {
|
|
123
|
+
if (jsonc[i] === "\\") {
|
|
124
|
+
result.push(jsonc[i], jsonc[i + 1] ?? "");
|
|
125
|
+
i += 2;
|
|
126
|
+
} else {
|
|
127
|
+
result.push(jsonc[i]);
|
|
128
|
+
i++;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (i < len) {
|
|
132
|
+
result.push(jsonc[i]);
|
|
133
|
+
i++;
|
|
134
|
+
}
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (ch === "/" && jsonc[i + 1] === "/") {
|
|
138
|
+
while (i < len && jsonc[i] !== `
|
|
139
|
+
`)
|
|
140
|
+
i++;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (ch === "/" && jsonc[i + 1] === "*") {
|
|
144
|
+
i += 2;
|
|
145
|
+
while (i < len && !(jsonc[i] === "*" && jsonc[i + 1] === "/"))
|
|
146
|
+
i++;
|
|
147
|
+
i += 2;
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
result.push(ch);
|
|
151
|
+
i++;
|
|
152
|
+
}
|
|
153
|
+
return result.join("");
|
|
154
|
+
}
|
|
155
|
+
function readJsoncFile(filePath) {
|
|
156
|
+
try {
|
|
157
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
158
|
+
const stripped = stripJsonComments(raw);
|
|
159
|
+
const parsed = JSON.parse(stripped);
|
|
160
|
+
return parsed;
|
|
161
|
+
} catch (err) {
|
|
162
|
+
if (err.code !== "ENOENT") {
|
|
163
|
+
console.warn(`[nexus] Failed to load config from ${filePath}: ${err.message}`);
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
110
168
|
var DEFAULT_CONFIG = {
|
|
111
169
|
models: {
|
|
112
170
|
architect: "anthropic/claude-sonnet-4-6",
|
|
@@ -134,12 +192,18 @@ class NexusConfigManager {
|
|
|
134
192
|
globalConfig = null;
|
|
135
193
|
storageConfig = null;
|
|
136
194
|
constructor() {
|
|
137
|
-
this.loadConfigs();
|
|
138
|
-
}
|
|
139
|
-
loadConfigs() {
|
|
140
195
|
this.projectConfig = null;
|
|
141
196
|
this.globalConfig = null;
|
|
142
197
|
}
|
|
198
|
+
loadConfigs(basePath) {
|
|
199
|
+
const projectPath = join(basePath, ".opencode", "nexus.jsonc");
|
|
200
|
+
this.projectConfig = readJsoncFile(projectPath);
|
|
201
|
+
const globalPath = join(homedir(), ".config", "opencode", "nexus.jsonc");
|
|
202
|
+
this.globalConfig = readJsoncFile(globalPath);
|
|
203
|
+
}
|
|
204
|
+
loadFromPath(basePath) {
|
|
205
|
+
this.loadConfigs(basePath);
|
|
206
|
+
}
|
|
143
207
|
getConfig() {
|
|
144
208
|
return {
|
|
145
209
|
models: {
|
|
@@ -197,24 +261,108 @@ class NexusConfigManager {
|
|
|
197
261
|
}
|
|
198
262
|
getRoleDisplayName(role) {
|
|
199
263
|
const names = {
|
|
200
|
-
architect: "
|
|
201
|
-
coder: "
|
|
202
|
-
reviewer: "
|
|
203
|
-
tester: "
|
|
204
|
-
explorer: "
|
|
205
|
-
documenter: "
|
|
264
|
+
architect: "Architect",
|
|
265
|
+
coder: "Coder",
|
|
266
|
+
reviewer: "Reviewer",
|
|
267
|
+
tester: "Tester",
|
|
268
|
+
explorer: "Explorer",
|
|
269
|
+
documenter: "Documenter"
|
|
206
270
|
};
|
|
207
271
|
return names[role] || role;
|
|
208
272
|
}
|
|
273
|
+
getRoleEmoji(role) {
|
|
274
|
+
const emojis = {
|
|
275
|
+
architect: "\uD83C\uDFD7️",
|
|
276
|
+
coder: "\uD83D\uDCBB",
|
|
277
|
+
reviewer: "\uD83D\uDD0D",
|
|
278
|
+
tester: "\uD83E\uDDEA",
|
|
279
|
+
explorer: "\uD83D\uDD2C",
|
|
280
|
+
documenter: "\uD83D\uDCDD"
|
|
281
|
+
};
|
|
282
|
+
return emojis[role] || "\uD83E\uDD16";
|
|
283
|
+
}
|
|
209
284
|
exportConfig() {
|
|
210
285
|
return this.getConfig();
|
|
211
286
|
}
|
|
212
287
|
importConfig(config) {
|
|
213
288
|
this.storageConfig = { ...config };
|
|
214
289
|
}
|
|
290
|
+
writeJsoncFile(filePath, config) {
|
|
291
|
+
const dir = dirname(filePath);
|
|
292
|
+
mkdirSync(dir, { recursive: true });
|
|
293
|
+
const jsonc = [
|
|
294
|
+
"// Nexus Configuration — https://github.com/serkanalgur/opencode-nexus",
|
|
295
|
+
"// Precedence: this file > global config > TUI settings > defaults",
|
|
296
|
+
"",
|
|
297
|
+
JSON.stringify(config, null, 2)
|
|
298
|
+
].join(`
|
|
299
|
+
`);
|
|
300
|
+
writeFileSync(filePath, jsonc + `
|
|
301
|
+
`, "utf-8");
|
|
302
|
+
}
|
|
303
|
+
saveProjectConfig(basePath) {
|
|
304
|
+
const projectPath = join(basePath, ".opencode", "nexus.jsonc");
|
|
305
|
+
const config = this.getNonDefaultConfig();
|
|
306
|
+
this.writeJsoncFile(projectPath, config);
|
|
307
|
+
}
|
|
308
|
+
saveGlobalConfig() {
|
|
309
|
+
const globalPath = join(homedir(), ".config", "opencode", "nexus.jsonc");
|
|
310
|
+
const config = this.getNonDefaultConfig();
|
|
311
|
+
this.writeJsoncFile(globalPath, config);
|
|
312
|
+
}
|
|
313
|
+
saveConfig(level, basePath) {
|
|
314
|
+
if (level === "project") {
|
|
315
|
+
this.saveProjectConfig(basePath || process.cwd());
|
|
316
|
+
} else {
|
|
317
|
+
this.saveGlobalConfig();
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
getNonDefaultConfig() {
|
|
321
|
+
const current = this.getConfig();
|
|
322
|
+
const result = {};
|
|
323
|
+
const models = {};
|
|
324
|
+
for (const role of this.getRoles()) {
|
|
325
|
+
if (current.models[role] !== DEFAULT_CONFIG.models[role]) {
|
|
326
|
+
models[role] = current.models[role];
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (Object.keys(models).length > 0) {
|
|
330
|
+
result.models = models;
|
|
331
|
+
}
|
|
332
|
+
const budget = {};
|
|
333
|
+
const budgetKeys = ["maxTotalCost", "maxCostPerTask", "maxCostPerAgent", "alertThreshold"];
|
|
334
|
+
for (const key of budgetKeys) {
|
|
335
|
+
if (current.budget[key] !== DEFAULT_CONFIG.budget[key]) {
|
|
336
|
+
budget[key] = current.budget[key];
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (Object.keys(budget).length > 0) {
|
|
340
|
+
result.budget = budget;
|
|
341
|
+
}
|
|
342
|
+
const selfHealing = {};
|
|
343
|
+
const shKeys = ["enabled", "maxRetries", "contextTransfer"];
|
|
344
|
+
for (const key of shKeys) {
|
|
345
|
+
if (current.selfHealing[key] !== DEFAULT_CONFIG.selfHealing[key]) {
|
|
346
|
+
selfHealing[key] = current.selfHealing[key];
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
if (Object.keys(selfHealing).length > 0) {
|
|
350
|
+
result.selfHealing = selfHealing;
|
|
351
|
+
}
|
|
352
|
+
return result;
|
|
353
|
+
}
|
|
215
354
|
resetToDefaults() {
|
|
216
355
|
this.storageConfig = null;
|
|
217
356
|
}
|
|
357
|
+
applyPreset(name) {
|
|
358
|
+
const preset = PRESETS[name];
|
|
359
|
+
if (!preset)
|
|
360
|
+
throw new Error(`Unknown preset: ${name}. Available: ${Object.keys(PRESETS).join(", ")}`);
|
|
361
|
+
this.storageConfig = { ...this.storageConfig, ...preset.config };
|
|
362
|
+
}
|
|
363
|
+
listPresets() {
|
|
364
|
+
return Object.keys(PRESETS);
|
|
365
|
+
}
|
|
218
366
|
getSummary() {
|
|
219
367
|
const config = this.getConfig();
|
|
220
368
|
const lines = [
|
|
@@ -242,23 +390,125 @@ class NexusConfigManager {
|
|
|
242
390
|
`);
|
|
243
391
|
}
|
|
244
392
|
}
|
|
393
|
+
var PRESETS = {
|
|
394
|
+
minimal: {
|
|
395
|
+
name: "Minimal",
|
|
396
|
+
description: "Low-cost setup with free/cheap models, minimal budget",
|
|
397
|
+
config: {
|
|
398
|
+
models: {
|
|
399
|
+
architect: "google/gemini-2.5-flash",
|
|
400
|
+
coder: "google/gemini-2.5-flash",
|
|
401
|
+
reviewer: "google/gemini-2.5-flash",
|
|
402
|
+
tester: "google/gemini-2.5-flash",
|
|
403
|
+
explorer: "google/gemini-2.5-flash",
|
|
404
|
+
documenter: "google/gemini-2.5-flash"
|
|
405
|
+
},
|
|
406
|
+
budget: {
|
|
407
|
+
maxTotalCost: 1,
|
|
408
|
+
maxCostPerTask: 0.1,
|
|
409
|
+
maxCostPerAgent: 0.5,
|
|
410
|
+
alertThreshold: 0.5
|
|
411
|
+
},
|
|
412
|
+
selfHealing: {
|
|
413
|
+
enabled: false,
|
|
414
|
+
maxRetries: 1,
|
|
415
|
+
contextTransfer: false
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
},
|
|
419
|
+
balanced: {
|
|
420
|
+
name: "Balanced",
|
|
421
|
+
description: "Good quality models with moderate budget",
|
|
422
|
+
config: {
|
|
423
|
+
models: {
|
|
424
|
+
architect: "anthropic/claude-sonnet-4-6",
|
|
425
|
+
coder: "anthropic/claude-sonnet-4-6",
|
|
426
|
+
reviewer: "openai/gpt-5-mini",
|
|
427
|
+
tester: "anthropic/claude-haiku-4-5",
|
|
428
|
+
explorer: "google/gemini-2.5-flash",
|
|
429
|
+
documenter: "anthropic/claude-haiku-4-5"
|
|
430
|
+
},
|
|
431
|
+
budget: {
|
|
432
|
+
maxTotalCost: 10,
|
|
433
|
+
maxCostPerTask: 1,
|
|
434
|
+
maxCostPerAgent: 2,
|
|
435
|
+
alertThreshold: 0.2
|
|
436
|
+
},
|
|
437
|
+
selfHealing: {
|
|
438
|
+
enabled: true,
|
|
439
|
+
maxRetries: 3,
|
|
440
|
+
contextTransfer: true
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
enterprise: {
|
|
445
|
+
name: "Enterprise",
|
|
446
|
+
description: "High-quality models with generous budget and full self-healing",
|
|
447
|
+
config: {
|
|
448
|
+
models: {
|
|
449
|
+
architect: "anthropic/claude-sonnet-4-6",
|
|
450
|
+
coder: "anthropic/claude-sonnet-4-6",
|
|
451
|
+
reviewer: "openai/gpt-5",
|
|
452
|
+
tester: "anthropic/claude-sonnet-4-6",
|
|
453
|
+
explorer: "anthropic/claude-sonnet-4-6",
|
|
454
|
+
documenter: "anthropic/claude-haiku-4-5"
|
|
455
|
+
},
|
|
456
|
+
budget: {
|
|
457
|
+
maxTotalCost: 50,
|
|
458
|
+
maxCostPerTask: 5,
|
|
459
|
+
maxCostPerAgent: 10,
|
|
460
|
+
alertThreshold: 0.1
|
|
461
|
+
},
|
|
462
|
+
selfHealing: {
|
|
463
|
+
enabled: true,
|
|
464
|
+
maxRetries: 5,
|
|
465
|
+
contextTransfer: true
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
"cost-optimized": {
|
|
470
|
+
name: "Cost-Optimized",
|
|
471
|
+
description: "Minimize costs while maintaining reasonable quality",
|
|
472
|
+
config: {
|
|
473
|
+
models: {
|
|
474
|
+
architect: "anthropic/claude-haiku-4-5",
|
|
475
|
+
coder: "google/gemini-2.5-flash",
|
|
476
|
+
reviewer: "openai/gpt-5-mini",
|
|
477
|
+
tester: "google/gemini-2.5-flash",
|
|
478
|
+
explorer: "google/gemini-2.5-flash",
|
|
479
|
+
documenter: "google/gemini-2.5-flash"
|
|
480
|
+
},
|
|
481
|
+
budget: {
|
|
482
|
+
maxTotalCost: 3,
|
|
483
|
+
maxCostPerTask: 0.3,
|
|
484
|
+
maxCostPerAgent: 1,
|
|
485
|
+
alertThreshold: 0.3
|
|
486
|
+
},
|
|
487
|
+
selfHealing: {
|
|
488
|
+
enabled: true,
|
|
489
|
+
maxRetries: 2,
|
|
490
|
+
contextTransfer: false
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
};
|
|
245
495
|
|
|
246
496
|
// node_modules/@opentui/core/chunk-node-70eg2nhg.js
|
|
247
497
|
import { createRequire } from "node:module";
|
|
248
498
|
import { fileURLToPath } from "node:url";
|
|
249
499
|
import { mkdir, writeFile as writeFileNode } from "node:fs/promises";
|
|
250
|
-
import { dirname, isAbsolute as isAbsolute2, resolve } from "node:path";
|
|
500
|
+
import { dirname as dirname2, isAbsolute as isAbsolute2, resolve } from "node:path";
|
|
251
501
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
252
502
|
import { statSync } from "node:fs";
|
|
253
|
-
import { isAbsolute, join } from "node:path";
|
|
503
|
+
import { isAbsolute, join as join2 } from "node:path";
|
|
254
504
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
255
|
-
import { existsSync as existsSync3, writeFileSync } from "fs";
|
|
505
|
+
import { existsSync as existsSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
256
506
|
import { EventEmitter as EventEmitter4 } from "events";
|
|
257
507
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
258
508
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
259
509
|
import { resolve as resolve2, isAbsolute as isAbsolute3, parse } from "path";
|
|
260
510
|
import { existsSync as existsSync2 } from "fs";
|
|
261
|
-
import { basename, join as
|
|
511
|
+
import { basename, join as join22 } from "node:path";
|
|
262
512
|
import os from "os";
|
|
263
513
|
import path from "path";
|
|
264
514
|
import { EventEmitter as EventEmitter3 } from "events";
|
|
@@ -1117,7 +1367,7 @@ function resolveAssetRootPath(key) {
|
|
|
1117
1367
|
if (!isAbsolute(root)) {
|
|
1118
1368
|
throw new Error(`OTUI_ASSET_ROOT must be an absolute directory, got ${JSON.stringify(root)}`);
|
|
1119
1369
|
}
|
|
1120
|
-
const assetPath =
|
|
1370
|
+
const assetPath = join2(root, key);
|
|
1121
1371
|
let isFile = false;
|
|
1122
1372
|
try {
|
|
1123
1373
|
isFile = statSync(assetPath).isFile();
|
|
@@ -1145,7 +1395,7 @@ function standardSleep(msOrDate) {
|
|
|
1145
1395
|
async function writeFilePortable(destination, data, options) {
|
|
1146
1396
|
const destinationPath = destination instanceof URL ? fileURLToPath3(destination) : destination;
|
|
1147
1397
|
if (options?.createPath) {
|
|
1148
|
-
await mkdir(
|
|
1398
|
+
await mkdir(dirname2(destinationPath), { recursive: true });
|
|
1149
1399
|
}
|
|
1150
1400
|
const bytes = typeof data === "string" ? TEXT_ENCODER.encode(data) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
1151
1401
|
await writeFileNode(destinationPath, bytes, { mode: options?.mode });
|
|
@@ -5408,7 +5658,7 @@ function getBunfsRootPath() {
|
|
|
5408
5658
|
return process.platform === "win32" ? "B:\\~BUN\\root" : "/$bunfs/root";
|
|
5409
5659
|
}
|
|
5410
5660
|
function normalizeBunfsPath(fileName) {
|
|
5411
|
-
return
|
|
5661
|
+
return join22(getBunfsRootPath(), basename(fileName));
|
|
5412
5662
|
}
|
|
5413
5663
|
var WORKER_UNAVAILABLE = "OpenTUI tree-sitter workers are not available for this runtime yet.";
|
|
5414
5664
|
var globalWithWorker = globalThis;
|
|
@@ -11573,7 +11823,7 @@ function convertToDebugSymbols(symbols) {
|
|
|
11573
11823
|
if (env2.OTUI_DEBUG_FFI && globalFFILogPath) {
|
|
11574
11824
|
const logPath = globalFFILogPath;
|
|
11575
11825
|
const writeSync = (msg) => {
|
|
11576
|
-
|
|
11826
|
+
writeFileSync2(logPath, msg + `
|
|
11577
11827
|
`, { flag: "a" });
|
|
11578
11828
|
};
|
|
11579
11829
|
Object.entries(symbols).forEach(([key, value]) => {
|
|
@@ -20191,7 +20441,7 @@ var RendererControlState2;
|
|
|
20191
20441
|
import { EventEmitter as EventEmitter5 } from "events";
|
|
20192
20442
|
import { randomBytes } from "node:crypto";
|
|
20193
20443
|
import { open as openFile, readFile, rename, unlink } from "node:fs/promises";
|
|
20194
|
-
import { basename as basename2, dirname as
|
|
20444
|
+
import { basename as basename2, dirname as dirname3, join as join3 } from "node:path";
|
|
20195
20445
|
import { open, stat } from "node:fs/promises";
|
|
20196
20446
|
function isGraphemeCell(char) {
|
|
20197
20447
|
return char >>> 30 >= 2;
|
|
@@ -22517,7 +22767,7 @@ class AudioRecorder extends EventEmitter5 {
|
|
|
22517
22767
|
return this.fileHandle != null || this.tempPath != null;
|
|
22518
22768
|
}
|
|
22519
22769
|
async openTemporaryFile() {
|
|
22520
|
-
const directory =
|
|
22770
|
+
const directory = dirname3(this.filePath);
|
|
22521
22771
|
const destinationName = basename2(this.filePath);
|
|
22522
22772
|
const tempNameLength = Math.max(1, Math.min(24, destinationName.length));
|
|
22523
22773
|
const singleCharacterNames = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-";
|
|
@@ -34207,6 +34457,48 @@ var tui_default = define({
|
|
|
34207
34457
|
variant: "success"
|
|
34208
34458
|
});
|
|
34209
34459
|
};
|
|
34460
|
+
const handleDashboard = async () => {
|
|
34461
|
+
const config = configManager.getConfig();
|
|
34462
|
+
const lines = [
|
|
34463
|
+
"⚡ Nexus Dashboard",
|
|
34464
|
+
"═══════════════════════════════════",
|
|
34465
|
+
"",
|
|
34466
|
+
"\uD83E\uDD16 Agent Models:"
|
|
34467
|
+
];
|
|
34468
|
+
for (const role of configManager.getRoles()) {
|
|
34469
|
+
const model = config.models[role] || "(not set)";
|
|
34470
|
+
const displayName = configManager.getRoleDisplayName(role);
|
|
34471
|
+
lines.push(` ${displayName}: ${model}`);
|
|
34472
|
+
}
|
|
34473
|
+
lines.push("");
|
|
34474
|
+
lines.push("\uD83D\uDCB0 Budget:");
|
|
34475
|
+
lines.push(` Max Total: $${config.budget.maxTotalCost}`);
|
|
34476
|
+
lines.push(` Max Per Task: $${config.budget.maxCostPerTask}`);
|
|
34477
|
+
lines.push(` Alert Threshold: ${config.budget.alertThreshold * 100}%`);
|
|
34478
|
+
lines.push("");
|
|
34479
|
+
lines.push("\uD83D\uDEE1️ Self-Healing:");
|
|
34480
|
+
lines.push(` Enabled: ${config.selfHealing.enabled ? "✅" : "❌"}`);
|
|
34481
|
+
lines.push(` Max Retries: ${config.selfHealing.maxRetries}`);
|
|
34482
|
+
lines.push("");
|
|
34483
|
+
lines.push("\uD83D\uDCA1 Commands:");
|
|
34484
|
+
lines.push(" /nexus status - Show config summary");
|
|
34485
|
+
lines.push(" /nexus config - Configure models & budget");
|
|
34486
|
+
lines.push(" /nexus model - Select model for role");
|
|
34487
|
+
lines.push(" /nexus reset - Reset to defaults");
|
|
34488
|
+
lines.push("");
|
|
34489
|
+
lines.push("\uD83D\uDD27 Tools (use in agent prompt):");
|
|
34490
|
+
lines.push(" nexus.status - Orchestrator status");
|
|
34491
|
+
lines.push(" nexus.agents - List spawned agents");
|
|
34492
|
+
lines.push(" nexus.costs - Cost report");
|
|
34493
|
+
lines.push(" nexus.spawn - Spawn a sub-agent");
|
|
34494
|
+
context.ui.toast.show({
|
|
34495
|
+
title: "Nexus Dashboard",
|
|
34496
|
+
message: lines.join(`
|
|
34497
|
+
`),
|
|
34498
|
+
variant: "info",
|
|
34499
|
+
duration: 15000
|
|
34500
|
+
});
|
|
34501
|
+
};
|
|
34210
34502
|
context.ui.slot({
|
|
34211
34503
|
append: "app",
|
|
34212
34504
|
render: () => {
|
|
@@ -34241,6 +34533,10 @@ var tui_default = define({
|
|
|
34241
34533
|
duration: 8000
|
|
34242
34534
|
});
|
|
34243
34535
|
break;
|
|
34536
|
+
case "dashboard":
|
|
34537
|
+
case "d":
|
|
34538
|
+
await handleDashboard();
|
|
34539
|
+
break;
|
|
34244
34540
|
case "model":
|
|
34245
34541
|
case "m":
|
|
34246
34542
|
if (parts[1]) {
|
|
@@ -34277,7 +34573,7 @@ var tui_default = define({
|
|
|
34277
34573
|
default:
|
|
34278
34574
|
context.ui.toast.show({
|
|
34279
34575
|
title: "Nexus",
|
|
34280
|
-
message: "Commands: config, status, model <role>, reset",
|
|
34576
|
+
message: "Commands: config, status, dashboard, model <role>, reset",
|
|
34281
34577
|
variant: "info"
|
|
34282
34578
|
});
|
|
34283
34579
|
}
|
|
@@ -34298,6 +34594,18 @@ var tui_default = define({
|
|
|
34298
34594
|
await handleFullConfig();
|
|
34299
34595
|
}
|
|
34300
34596
|
},
|
|
34597
|
+
{
|
|
34598
|
+
id: "nexus.dashboard",
|
|
34599
|
+
title: "Nexus Dashboard",
|
|
34600
|
+
group: "Nexus",
|
|
34601
|
+
palette: true,
|
|
34602
|
+
slash: { name: "nexus-dashboard", aliases: ["nd"], arguments: true },
|
|
34603
|
+
enabled: () => true,
|
|
34604
|
+
suggested: true,
|
|
34605
|
+
run: async () => {
|
|
34606
|
+
await handleDashboard();
|
|
34607
|
+
}
|
|
34608
|
+
},
|
|
34301
34609
|
{
|
|
34302
34610
|
id: "nexus.model",
|
|
34303
34611
|
title: "Select Agent Model",
|