nextclaw 0.8.33 → 0.8.35
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/cli/index.js +416 -57
- package/package.json +3 -3
- package/ui-dist/assets/ChannelsList-AKnD2r1L.js +1 -0
- package/ui-dist/assets/ChatPage-DidO_pAN.js +32 -0
- package/ui-dist/assets/{CronConfig-9dYfTRJl.js → CronConfig-C1pm-oKA.js} +1 -1
- package/ui-dist/assets/{DocBrowser-BIV0vpA0.js → DocBrowser-BY90Lf6L.js} +1 -1
- package/ui-dist/assets/{MarketplacePage-2Zi0JSVi.js → MarketplacePage-BRtmhP3G.js} +1 -1
- package/ui-dist/assets/{ModelConfig-h21P5rV0.js → ModelConfig-Dga1Ko7_.js} +1 -1
- package/ui-dist/assets/{ProvidersList-DEaK1a3y.js → ProvidersList-DvCoBTrT.js} +1 -1
- package/ui-dist/assets/{RuntimeConfig-DXMzf-gF.js → RuntimeConfig-2aqBJ6Xn.js} +1 -1
- package/ui-dist/assets/SecretsConfig-wlnh__z0.js +3 -0
- package/ui-dist/assets/{SessionsConfig-SdXvn_9E.js → SessionsConfig-CN2WymbH.js} +2 -2
- package/ui-dist/assets/{action-link-C9xMkxl2.js → action-link-DLZDwUfD.js} +1 -1
- package/ui-dist/assets/{card-Cnqfntk5.js → card-D3dD-I5t.js} +1 -1
- package/ui-dist/assets/chat-message-DZV2Z5oc.js +5 -0
- package/ui-dist/assets/{dialog-DJs630RE.js → dialog-DZ0VC-RD.js} +1 -1
- package/ui-dist/assets/index-BsDasSXm.css +1 -0
- package/ui-dist/assets/index-D_vv0E-O.js +2 -0
- package/ui-dist/assets/{label-CXGuE6Oa.js → label-CJIvvG6o.js} +1 -1
- package/ui-dist/assets/{page-layout-BVZlyPFt.js → page-layout-CLgr0qym.js} +1 -1
- package/ui-dist/assets/{switch-BLF45eI3.js → switch-C-0Q8OH2.js} +1 -1
- package/ui-dist/assets/{tabs-custom-DQ0GpEV5.js → tabs-custom-D4Gs3BGM.js} +1 -1
- package/ui-dist/assets/useConfig-R5uGhZtD.js +1 -0
- package/ui-dist/assets/{useConfirmDialog-CK7KAyDf.js → useConfirmDialog-AMeSTA83.js} +1 -1
- package/ui-dist/assets/{vendor-RXIbhDBC.js → vendor-H2M3a_4Z.js} +1 -1
- package/ui-dist/index.html +3 -3
- package/ui-dist/assets/ChannelsList-TFFw4Cem.js +0 -1
- package/ui-dist/assets/ChatPage-BUm3UPap.js +0 -32
- package/ui-dist/assets/chat-message-B7oqvJ2d.js +0 -3
- package/ui-dist/assets/index-CrUDzcei.js +0 -2
- package/ui-dist/assets/index-Zy7fAOe1.css +0 -1
- package/ui-dist/assets/useConfig-vFQvF4kn.js +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -6,9 +6,9 @@ import { APP_NAME as APP_NAME5, APP_TAGLINE } from "@nextclaw/core";
|
|
|
6
6
|
|
|
7
7
|
// src/cli/runtime.ts
|
|
8
8
|
import {
|
|
9
|
-
loadConfig as
|
|
10
|
-
saveConfig as
|
|
11
|
-
getConfigPath as
|
|
9
|
+
loadConfig as loadConfig7,
|
|
10
|
+
saveConfig as saveConfig6,
|
|
11
|
+
getConfigPath as getConfigPath4,
|
|
12
12
|
getDataDir as getDataDir7,
|
|
13
13
|
ConfigSchema as ConfigSchema2,
|
|
14
14
|
getWorkspacePath as getWorkspacePath6,
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
MessageBus as MessageBus2,
|
|
17
17
|
AgentLoop as AgentLoop2,
|
|
18
18
|
ProviderManager as ProviderManager2,
|
|
19
|
+
resolveConfigSecrets as resolveConfigSecrets3,
|
|
19
20
|
APP_NAME as APP_NAME4,
|
|
20
21
|
DEFAULT_WORKSPACE_DIR,
|
|
21
22
|
DEFAULT_WORKSPACE_PATH
|
|
@@ -25,7 +26,7 @@ import {
|
|
|
25
26
|
resolvePluginChannelMessageToolHints as resolvePluginChannelMessageToolHints2,
|
|
26
27
|
setPluginRuntimeBridge as setPluginRuntimeBridge2
|
|
27
28
|
} from "@nextclaw/openclaw-compat";
|
|
28
|
-
import { existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as
|
|
29
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
29
30
|
import { join as join6, resolve as resolve9 } from "path";
|
|
30
31
|
import { createInterface as createInterface2 } from "readline";
|
|
31
32
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -1312,9 +1313,332 @@ var ConfigCommands = class {
|
|
|
1312
1313
|
}
|
|
1313
1314
|
};
|
|
1314
1315
|
|
|
1316
|
+
// src/cli/commands/secrets.ts
|
|
1317
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
1318
|
+
import {
|
|
1319
|
+
buildReloadPlan as buildReloadPlan2,
|
|
1320
|
+
diffConfigPaths as diffConfigPaths2,
|
|
1321
|
+
getConfigPath,
|
|
1322
|
+
loadConfig as loadConfig3,
|
|
1323
|
+
resolveConfigSecrets,
|
|
1324
|
+
saveConfig as saveConfig3
|
|
1325
|
+
} from "@nextclaw/core";
|
|
1326
|
+
var SECRET_SOURCES = ["env", "file", "exec"];
|
|
1327
|
+
function normalizeSecretSource(value) {
|
|
1328
|
+
if (typeof value !== "string") {
|
|
1329
|
+
return null;
|
|
1330
|
+
}
|
|
1331
|
+
const normalized = value.trim().toLowerCase();
|
|
1332
|
+
return SECRET_SOURCES.includes(normalized) ? normalized : null;
|
|
1333
|
+
}
|
|
1334
|
+
function normalizeOptionalString(value) {
|
|
1335
|
+
if (typeof value !== "string") {
|
|
1336
|
+
return void 0;
|
|
1337
|
+
}
|
|
1338
|
+
const trimmed = value.trim();
|
|
1339
|
+
return trimmed || void 0;
|
|
1340
|
+
}
|
|
1341
|
+
function parseTimeoutMs(value) {
|
|
1342
|
+
if (value === void 0 || value === null || value === "") {
|
|
1343
|
+
return void 0;
|
|
1344
|
+
}
|
|
1345
|
+
const parsed = Number(value);
|
|
1346
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
1347
|
+
throw new Error(`invalid timeout: ${String(value)}`);
|
|
1348
|
+
}
|
|
1349
|
+
return Math.trunc(parsed);
|
|
1350
|
+
}
|
|
1351
|
+
function inferProviderAlias(config2, ref) {
|
|
1352
|
+
const explicit = normalizeOptionalString(ref.provider);
|
|
1353
|
+
if (explicit) {
|
|
1354
|
+
return explicit;
|
|
1355
|
+
}
|
|
1356
|
+
const defaultAlias = normalizeOptionalString(config2.secrets.defaults[ref.source]);
|
|
1357
|
+
if (defaultAlias) {
|
|
1358
|
+
return defaultAlias;
|
|
1359
|
+
}
|
|
1360
|
+
return ref.source;
|
|
1361
|
+
}
|
|
1362
|
+
function summarizeAudit(items) {
|
|
1363
|
+
const ok = items.filter((item) => item.ok).length;
|
|
1364
|
+
return {
|
|
1365
|
+
total: items.length,
|
|
1366
|
+
ok,
|
|
1367
|
+
failed: items.length - ok
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1370
|
+
function parseRefsPatch(raw) {
|
|
1371
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
1372
|
+
throw new Error("refs patch must be an object");
|
|
1373
|
+
}
|
|
1374
|
+
const output = {};
|
|
1375
|
+
for (const [path, value] of Object.entries(raw)) {
|
|
1376
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1377
|
+
throw new Error(`invalid ref for ${path}`);
|
|
1378
|
+
}
|
|
1379
|
+
const source = normalizeSecretSource(value.source);
|
|
1380
|
+
const id = normalizeOptionalString(value.id);
|
|
1381
|
+
const provider = normalizeOptionalString(value.provider);
|
|
1382
|
+
if (!source || !id) {
|
|
1383
|
+
throw new Error(`invalid ref for ${path}: source/id is required`);
|
|
1384
|
+
}
|
|
1385
|
+
output[path] = { source, ...provider ? { provider } : {}, id };
|
|
1386
|
+
}
|
|
1387
|
+
return output;
|
|
1388
|
+
}
|
|
1389
|
+
function parseApplyFile(raw) {
|
|
1390
|
+
const data = JSON.parse(raw);
|
|
1391
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
1392
|
+
throw new Error("apply file must be an object");
|
|
1393
|
+
}
|
|
1394
|
+
const record = data;
|
|
1395
|
+
if (record.refs || record.providers || record.defaults || Object.prototype.hasOwnProperty.call(record, "enabled")) {
|
|
1396
|
+
const patch = {};
|
|
1397
|
+
if (Object.prototype.hasOwnProperty.call(record, "enabled")) {
|
|
1398
|
+
patch.enabled = Boolean(record.enabled);
|
|
1399
|
+
}
|
|
1400
|
+
if (record.defaults && typeof record.defaults === "object" && !Array.isArray(record.defaults)) {
|
|
1401
|
+
patch.defaults = record.defaults;
|
|
1402
|
+
}
|
|
1403
|
+
if (record.providers && typeof record.providers === "object" && !Array.isArray(record.providers)) {
|
|
1404
|
+
patch.providers = record.providers;
|
|
1405
|
+
}
|
|
1406
|
+
if (record.refs) {
|
|
1407
|
+
patch.refs = parseRefsPatch(record.refs);
|
|
1408
|
+
}
|
|
1409
|
+
return patch;
|
|
1410
|
+
}
|
|
1411
|
+
return { refs: parseRefsPatch(record) };
|
|
1412
|
+
}
|
|
1413
|
+
var SecretsCommands = class {
|
|
1414
|
+
constructor(deps) {
|
|
1415
|
+
this.deps = deps;
|
|
1416
|
+
}
|
|
1417
|
+
secretsAudit(opts = {}) {
|
|
1418
|
+
const config2 = loadConfig3();
|
|
1419
|
+
const configPath = getConfigPath();
|
|
1420
|
+
const refs = config2.secrets.refs;
|
|
1421
|
+
const items = [];
|
|
1422
|
+
for (const [path, ref] of Object.entries(refs)) {
|
|
1423
|
+
const provider = inferProviderAlias(config2, ref);
|
|
1424
|
+
const scopedConfig = structuredClone(config2);
|
|
1425
|
+
scopedConfig.secrets.refs = { [path]: ref };
|
|
1426
|
+
try {
|
|
1427
|
+
const resolved = resolveConfigSecrets(scopedConfig, { configPath });
|
|
1428
|
+
const parsedPath = parseRequiredConfigPath(path);
|
|
1429
|
+
const target = getAtConfigPath(resolved, parsedPath);
|
|
1430
|
+
if (!target.found) {
|
|
1431
|
+
items.push({
|
|
1432
|
+
path,
|
|
1433
|
+
source: ref.source,
|
|
1434
|
+
provider,
|
|
1435
|
+
id: ref.id,
|
|
1436
|
+
ok: false,
|
|
1437
|
+
detail: "resolved but path not found"
|
|
1438
|
+
});
|
|
1439
|
+
continue;
|
|
1440
|
+
}
|
|
1441
|
+
const resolvedValue = target.value;
|
|
1442
|
+
const detail = typeof resolvedValue === "string" ? `resolved (length=${resolvedValue.length})` : `resolved (${typeof resolvedValue})`;
|
|
1443
|
+
items.push({
|
|
1444
|
+
path,
|
|
1445
|
+
source: ref.source,
|
|
1446
|
+
provider,
|
|
1447
|
+
id: ref.id,
|
|
1448
|
+
ok: true,
|
|
1449
|
+
detail
|
|
1450
|
+
});
|
|
1451
|
+
} catch (error) {
|
|
1452
|
+
items.push({
|
|
1453
|
+
path,
|
|
1454
|
+
source: ref.source,
|
|
1455
|
+
provider,
|
|
1456
|
+
id: ref.id,
|
|
1457
|
+
ok: false,
|
|
1458
|
+
detail: String(error)
|
|
1459
|
+
});
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
const summary = summarizeAudit(items);
|
|
1463
|
+
if (opts.json) {
|
|
1464
|
+
console.log(JSON.stringify({ summary, items }, null, 2));
|
|
1465
|
+
} else if (!items.length) {
|
|
1466
|
+
console.log("No secret refs configured.");
|
|
1467
|
+
} else {
|
|
1468
|
+
for (const item of items) {
|
|
1469
|
+
const status = item.ok ? "OK" : "ERROR";
|
|
1470
|
+
console.log(
|
|
1471
|
+
`[${status}] ${item.path} <- ${item.source}:${item.provider}:${item.id} (${item.detail})`
|
|
1472
|
+
);
|
|
1473
|
+
}
|
|
1474
|
+
console.log(`Summary: total=${summary.total}, ok=${summary.ok}, failed=${summary.failed}`);
|
|
1475
|
+
}
|
|
1476
|
+
const strict = Boolean(opts.strict);
|
|
1477
|
+
if (strict && summary.failed > 0) {
|
|
1478
|
+
process.exitCode = 1;
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
async secretsConfigure(opts) {
|
|
1482
|
+
const alias = normalizeOptionalString(opts.provider);
|
|
1483
|
+
if (!alias) {
|
|
1484
|
+
throw new Error("provider alias is required");
|
|
1485
|
+
}
|
|
1486
|
+
const prevConfig = loadConfig3();
|
|
1487
|
+
const nextConfig = structuredClone(prevConfig);
|
|
1488
|
+
const remove = Boolean(opts.remove);
|
|
1489
|
+
if (remove) {
|
|
1490
|
+
delete nextConfig.secrets.providers[alias];
|
|
1491
|
+
for (const source of SECRET_SOURCES) {
|
|
1492
|
+
if (nextConfig.secrets.defaults[source] === alias) {
|
|
1493
|
+
delete nextConfig.secrets.defaults[source];
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
} else {
|
|
1497
|
+
const source = normalizeSecretSource(opts.source);
|
|
1498
|
+
if (!source) {
|
|
1499
|
+
throw new Error("source is required and must be one of env/file/exec");
|
|
1500
|
+
}
|
|
1501
|
+
if (source === "env") {
|
|
1502
|
+
nextConfig.secrets.providers[alias] = {
|
|
1503
|
+
source,
|
|
1504
|
+
...normalizeOptionalString(opts.prefix) ? { prefix: normalizeOptionalString(opts.prefix) } : {}
|
|
1505
|
+
};
|
|
1506
|
+
} else if (source === "file") {
|
|
1507
|
+
const path = normalizeOptionalString(opts.path);
|
|
1508
|
+
if (!path) {
|
|
1509
|
+
throw new Error("file source requires --path");
|
|
1510
|
+
}
|
|
1511
|
+
nextConfig.secrets.providers[alias] = {
|
|
1512
|
+
source,
|
|
1513
|
+
path,
|
|
1514
|
+
format: "json"
|
|
1515
|
+
};
|
|
1516
|
+
} else {
|
|
1517
|
+
const command = normalizeOptionalString(opts.command);
|
|
1518
|
+
if (!command) {
|
|
1519
|
+
throw new Error("exec source requires --command");
|
|
1520
|
+
}
|
|
1521
|
+
nextConfig.secrets.providers[alias] = {
|
|
1522
|
+
source,
|
|
1523
|
+
command,
|
|
1524
|
+
args: Array.isArray(opts.arg) ? opts.arg : [],
|
|
1525
|
+
...normalizeOptionalString(opts.cwd) ? { cwd: normalizeOptionalString(opts.cwd) } : {},
|
|
1526
|
+
timeoutMs: parseTimeoutMs(opts.timeoutMs) ?? 5e3
|
|
1527
|
+
};
|
|
1528
|
+
}
|
|
1529
|
+
if (opts.setDefault) {
|
|
1530
|
+
nextConfig.secrets.defaults[source] = alias;
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
resolveConfigSecrets(nextConfig, { configPath: getConfigPath() });
|
|
1534
|
+
saveConfig3(nextConfig);
|
|
1535
|
+
await this.requestRestartForConfigDiff({
|
|
1536
|
+
prevConfig,
|
|
1537
|
+
nextConfig,
|
|
1538
|
+
reason: `secrets.configure ${alias}`,
|
|
1539
|
+
manualMessage: "Secrets provider updated. Restart the gateway if required."
|
|
1540
|
+
});
|
|
1541
|
+
if (opts.json) {
|
|
1542
|
+
console.log(JSON.stringify({ ok: true, providers: nextConfig.secrets.providers, defaults: nextConfig.secrets.defaults }, null, 2));
|
|
1543
|
+
return;
|
|
1544
|
+
}
|
|
1545
|
+
console.log(`Secrets provider ${remove ? "removed" : "configured"}: ${alias}`);
|
|
1546
|
+
}
|
|
1547
|
+
async secretsApply(opts) {
|
|
1548
|
+
const prevConfig = loadConfig3();
|
|
1549
|
+
const nextConfig = structuredClone(prevConfig);
|
|
1550
|
+
if (opts.enable && opts.disable) {
|
|
1551
|
+
throw new Error("cannot set --enable and --disable at the same time");
|
|
1552
|
+
}
|
|
1553
|
+
if (opts.enable) {
|
|
1554
|
+
nextConfig.secrets.enabled = true;
|
|
1555
|
+
}
|
|
1556
|
+
if (opts.disable) {
|
|
1557
|
+
nextConfig.secrets.enabled = false;
|
|
1558
|
+
}
|
|
1559
|
+
if (opts.file) {
|
|
1560
|
+
const raw = readFileSync3(opts.file, "utf-8");
|
|
1561
|
+
const patch = parseApplyFile(raw);
|
|
1562
|
+
if (patch.defaults) {
|
|
1563
|
+
nextConfig.secrets.defaults = patch.defaults;
|
|
1564
|
+
}
|
|
1565
|
+
if (patch.providers) {
|
|
1566
|
+
nextConfig.secrets.providers = patch.providers;
|
|
1567
|
+
}
|
|
1568
|
+
if (patch.refs) {
|
|
1569
|
+
nextConfig.secrets.refs = {
|
|
1570
|
+
...nextConfig.secrets.refs,
|
|
1571
|
+
...patch.refs
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
if (opts.path) {
|
|
1576
|
+
const path = opts.path.trim();
|
|
1577
|
+
if (!path) {
|
|
1578
|
+
throw new Error("path is empty");
|
|
1579
|
+
}
|
|
1580
|
+
if (opts.remove) {
|
|
1581
|
+
delete nextConfig.secrets.refs[path];
|
|
1582
|
+
} else {
|
|
1583
|
+
const source = normalizeSecretSource(opts.source);
|
|
1584
|
+
const id = normalizeOptionalString(opts.id);
|
|
1585
|
+
if (!source || !id) {
|
|
1586
|
+
throw new Error("apply single ref requires --source and --id");
|
|
1587
|
+
}
|
|
1588
|
+
const provider = normalizeOptionalString(opts.provider);
|
|
1589
|
+
nextConfig.secrets.refs[path] = {
|
|
1590
|
+
source,
|
|
1591
|
+
id,
|
|
1592
|
+
...provider ? { provider } : {}
|
|
1593
|
+
};
|
|
1594
|
+
}
|
|
1595
|
+
} else if (opts.remove && !opts.file) {
|
|
1596
|
+
throw new Error("--remove requires --path");
|
|
1597
|
+
}
|
|
1598
|
+
resolveConfigSecrets(nextConfig, { configPath: getConfigPath() });
|
|
1599
|
+
saveConfig3(nextConfig);
|
|
1600
|
+
await this.requestRestartForConfigDiff({
|
|
1601
|
+
prevConfig,
|
|
1602
|
+
nextConfig,
|
|
1603
|
+
reason: "secrets.apply",
|
|
1604
|
+
manualMessage: "Secrets updated. Restart the gateway if required."
|
|
1605
|
+
});
|
|
1606
|
+
if (opts.json) {
|
|
1607
|
+
console.log(JSON.stringify({ ok: true, secrets: nextConfig.secrets }, null, 2));
|
|
1608
|
+
return;
|
|
1609
|
+
}
|
|
1610
|
+
console.log("Secrets applied.");
|
|
1611
|
+
}
|
|
1612
|
+
async secretsReload(opts = {}) {
|
|
1613
|
+
const config2 = loadConfig3();
|
|
1614
|
+
const configPath = getConfigPath();
|
|
1615
|
+
resolveConfigSecrets(config2, { configPath });
|
|
1616
|
+
saveConfig3(config2);
|
|
1617
|
+
if (opts.json) {
|
|
1618
|
+
console.log(JSON.stringify({ ok: true, message: "secrets reload signal emitted" }, null, 2));
|
|
1619
|
+
return;
|
|
1620
|
+
}
|
|
1621
|
+
console.log("Secrets reload signal emitted.");
|
|
1622
|
+
}
|
|
1623
|
+
async requestRestartForConfigDiff(params) {
|
|
1624
|
+
const changedPaths = diffConfigPaths2(params.prevConfig, params.nextConfig);
|
|
1625
|
+
if (!changedPaths.length) {
|
|
1626
|
+
return;
|
|
1627
|
+
}
|
|
1628
|
+
const plan = buildReloadPlan2(changedPaths);
|
|
1629
|
+
if (plan.restartRequired.length === 0) {
|
|
1630
|
+
return;
|
|
1631
|
+
}
|
|
1632
|
+
await this.deps.requestRestart({
|
|
1633
|
+
reason: `${params.reason} (${plan.restartRequired.join(", ")})`,
|
|
1634
|
+
manualMessage: params.manualMessage
|
|
1635
|
+
});
|
|
1636
|
+
}
|
|
1637
|
+
};
|
|
1638
|
+
|
|
1315
1639
|
// src/cli/commands/channels.ts
|
|
1316
1640
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
1317
|
-
import { BUILTIN_CHANNEL_PLUGIN_IDS, getWorkspacePath as getWorkspacePath2, loadConfig as
|
|
1641
|
+
import { BUILTIN_CHANNEL_PLUGIN_IDS, getWorkspacePath as getWorkspacePath2, loadConfig as loadConfig4, saveConfig as saveConfig4, PROVIDERS as PROVIDERS2 } from "@nextclaw/core";
|
|
1318
1642
|
import { buildPluginStatusReport as buildPluginStatusReport2, enablePluginInConfig as enablePluginInConfig2, getPluginChannelBindings } from "@nextclaw/openclaw-compat";
|
|
1319
1643
|
var CHANNEL_LABELS = {
|
|
1320
1644
|
telegram: "Telegram",
|
|
@@ -1333,7 +1657,7 @@ var ChannelCommands = class {
|
|
|
1333
1657
|
this.deps = deps;
|
|
1334
1658
|
}
|
|
1335
1659
|
channelsStatus() {
|
|
1336
|
-
const config2 =
|
|
1660
|
+
const config2 = loadConfig4();
|
|
1337
1661
|
console.log("Channel Status");
|
|
1338
1662
|
const channelConfig = config2.channels;
|
|
1339
1663
|
for (const channelId of BUILTIN_CHANNEL_PLUGIN_IDS) {
|
|
@@ -1372,7 +1696,7 @@ var ChannelCommands = class {
|
|
|
1372
1696
|
console.error("--channel is required");
|
|
1373
1697
|
process.exit(1);
|
|
1374
1698
|
}
|
|
1375
|
-
const config2 =
|
|
1699
|
+
const config2 = loadConfig4();
|
|
1376
1700
|
const workspaceDir = getWorkspacePath2(config2.agents.defaults.workspace);
|
|
1377
1701
|
const pluginRegistry = loadPluginRegistry(config2, workspaceDir);
|
|
1378
1702
|
const bindings = getPluginChannelBindings(pluginRegistry);
|
|
@@ -1415,7 +1739,7 @@ var ChannelCommands = class {
|
|
|
1415
1739
|
}
|
|
1416
1740
|
let next = mergePluginConfigView(config2, nextView, bindings);
|
|
1417
1741
|
next = enablePluginInConfig2(next, binding.pluginId);
|
|
1418
|
-
|
|
1742
|
+
saveConfig4(next);
|
|
1419
1743
|
console.log(`Configured channel "${binding.channelId}" via plugin "${binding.pluginId}".`);
|
|
1420
1744
|
await this.deps.requestRestart({
|
|
1421
1745
|
reason: `channel configured via plugin: ${binding.pluginId}`,
|
|
@@ -1502,14 +1826,15 @@ var CronCommands = class {
|
|
|
1502
1826
|
|
|
1503
1827
|
// src/cli/commands/diagnostics.ts
|
|
1504
1828
|
import { createServer as createNetServer } from "net";
|
|
1505
|
-
import { existsSync as existsSync5, readFileSync as
|
|
1829
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
1506
1830
|
import { resolve as resolve6 } from "path";
|
|
1507
1831
|
import {
|
|
1508
1832
|
APP_NAME,
|
|
1509
|
-
getConfigPath,
|
|
1833
|
+
getConfigPath as getConfigPath2,
|
|
1510
1834
|
getDataDir as getDataDir4,
|
|
1511
1835
|
getWorkspacePath as getWorkspacePath3,
|
|
1512
|
-
|
|
1836
|
+
hasSecretRef,
|
|
1837
|
+
loadConfig as loadConfig5,
|
|
1513
1838
|
PROVIDERS as PROVIDERS3
|
|
1514
1839
|
} from "@nextclaw/core";
|
|
1515
1840
|
var DiagnosticsCommands = class {
|
|
@@ -1670,8 +1995,8 @@ var DiagnosticsCommands = class {
|
|
|
1670
1995
|
process.exitCode = exitCode;
|
|
1671
1996
|
}
|
|
1672
1997
|
async collectRuntimeStatus(params) {
|
|
1673
|
-
const configPath =
|
|
1674
|
-
const config2 =
|
|
1998
|
+
const configPath = getConfigPath2();
|
|
1999
|
+
const config2 = loadConfig5();
|
|
1675
2000
|
const workspacePath = getWorkspacePath3(config2.agents.defaults.workspace);
|
|
1676
2001
|
const serviceStatePath = resolve6(getDataDir4(), "run", "service.json");
|
|
1677
2002
|
const fixActions = [];
|
|
@@ -1694,6 +2019,7 @@ var DiagnosticsCommands = class {
|
|
|
1694
2019
|
const orphanSuspected = !running && configuredHealth.state === "ok";
|
|
1695
2020
|
const providers = PROVIDERS3.map((spec) => {
|
|
1696
2021
|
const provider = config2.providers[spec.name];
|
|
2022
|
+
const apiKeyRefSet = hasSecretRef(config2, `providers.${spec.name}.apiKey`);
|
|
1697
2023
|
if (!provider) {
|
|
1698
2024
|
return { name: spec.displayName ?? spec.name, configured: false, detail: "missing config" };
|
|
1699
2025
|
}
|
|
@@ -1706,8 +2032,8 @@ var DiagnosticsCommands = class {
|
|
|
1706
2032
|
}
|
|
1707
2033
|
return {
|
|
1708
2034
|
name: spec.displayName ?? spec.name,
|
|
1709
|
-
configured: Boolean(provider.apiKey),
|
|
1710
|
-
detail: provider.apiKey ? "apiKey set" : "apiKey not set"
|
|
2035
|
+
configured: Boolean(provider.apiKey) || apiKeyRefSet,
|
|
2036
|
+
detail: provider.apiKey ? "apiKey set" : apiKeyRefSet ? "apiKey ref set" : "apiKey not set"
|
|
1711
2037
|
};
|
|
1712
2038
|
});
|
|
1713
2039
|
const issues = [];
|
|
@@ -1804,7 +2130,7 @@ var DiagnosticsCommands = class {
|
|
|
1804
2130
|
return [];
|
|
1805
2131
|
}
|
|
1806
2132
|
try {
|
|
1807
|
-
const lines =
|
|
2133
|
+
const lines = readFileSync4(path, "utf-8").split(/\r?\n/).filter(Boolean);
|
|
1808
2134
|
if (lines.length <= maxLines) {
|
|
1809
2135
|
return lines;
|
|
1810
2136
|
}
|
|
@@ -1852,19 +2178,20 @@ import chokidar from "chokidar";
|
|
|
1852
2178
|
|
|
1853
2179
|
// src/cli/gateway/controller.ts
|
|
1854
2180
|
import { createHash } from "crypto";
|
|
1855
|
-
import { existsSync as existsSync6, readFileSync as
|
|
2181
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
1856
2182
|
import {
|
|
1857
2183
|
buildConfigSchema,
|
|
1858
2184
|
ConfigSchema,
|
|
2185
|
+
normalizeInlineSecretRefs,
|
|
1859
2186
|
redactConfigObject
|
|
1860
2187
|
} from "@nextclaw/core";
|
|
1861
2188
|
var hashRaw = (raw) => createHash("sha256").update(raw).digest("hex");
|
|
1862
|
-
var readConfigSnapshot = (
|
|
1863
|
-
const path =
|
|
2189
|
+
var readConfigSnapshot = (getConfigPath5) => {
|
|
2190
|
+
const path = getConfigPath5();
|
|
1864
2191
|
let raw = "";
|
|
1865
2192
|
let parsed = {};
|
|
1866
2193
|
if (existsSync6(path)) {
|
|
1867
|
-
raw =
|
|
2194
|
+
raw = readFileSync5(path, "utf-8");
|
|
1868
2195
|
try {
|
|
1869
2196
|
parsed = JSON.parse(raw);
|
|
1870
2197
|
} catch {
|
|
@@ -1874,7 +2201,7 @@ var readConfigSnapshot = (getConfigPath4) => {
|
|
|
1874
2201
|
let config2;
|
|
1875
2202
|
let valid = true;
|
|
1876
2203
|
try {
|
|
1877
|
-
config2 = ConfigSchema.parse(parsed);
|
|
2204
|
+
config2 = ConfigSchema.parse(normalizeInlineSecretRefs(parsed));
|
|
1878
2205
|
} catch {
|
|
1879
2206
|
config2 = ConfigSchema.parse({});
|
|
1880
2207
|
valid = false;
|
|
@@ -2031,7 +2358,7 @@ var GatewayControllerImpl = class {
|
|
|
2031
2358
|
}
|
|
2032
2359
|
let validated;
|
|
2033
2360
|
try {
|
|
2034
|
-
validated = ConfigSchema.parse(parsedRaw);
|
|
2361
|
+
validated = ConfigSchema.parse(normalizeInlineSecretRefs(parsedRaw));
|
|
2035
2362
|
} catch (err) {
|
|
2036
2363
|
return { ok: false, error: `invalid config: ${String(err)}` };
|
|
2037
2364
|
}
|
|
@@ -2074,7 +2401,7 @@ var GatewayControllerImpl = class {
|
|
|
2074
2401
|
const merged = mergeDeep(snapshot.config, patch);
|
|
2075
2402
|
let validated;
|
|
2076
2403
|
try {
|
|
2077
|
-
validated = ConfigSchema.parse(merged);
|
|
2404
|
+
validated = ConfigSchema.parse(normalizeInlineSecretRefs(merged));
|
|
2078
2405
|
} catch (err) {
|
|
2079
2406
|
return { ok: false, error: `invalid config: ${String(err)}` };
|
|
2080
2407
|
}
|
|
@@ -2141,8 +2468,8 @@ var GatewayControllerImpl = class {
|
|
|
2141
2468
|
|
|
2142
2469
|
// src/cli/config-reloader.ts
|
|
2143
2470
|
import {
|
|
2144
|
-
buildReloadPlan as
|
|
2145
|
-
diffConfigPaths as
|
|
2471
|
+
buildReloadPlan as buildReloadPlan3,
|
|
2472
|
+
diffConfigPaths as diffConfigPaths3,
|
|
2146
2473
|
ChannelManager
|
|
2147
2474
|
} from "@nextclaw/core";
|
|
2148
2475
|
var ConfigReloader = class {
|
|
@@ -2168,13 +2495,13 @@ var ConfigReloader = class {
|
|
|
2168
2495
|
this.options.reloadPlugins = callback;
|
|
2169
2496
|
}
|
|
2170
2497
|
async applyReloadPlan(nextConfig) {
|
|
2171
|
-
const changedPaths =
|
|
2498
|
+
const changedPaths = diffConfigPaths3(this.currentConfig, nextConfig);
|
|
2172
2499
|
if (!changedPaths.length) {
|
|
2173
2500
|
return;
|
|
2174
2501
|
}
|
|
2175
2502
|
this.currentConfig = nextConfig;
|
|
2176
2503
|
this.options.providerManager?.setConfig(nextConfig);
|
|
2177
|
-
const plan =
|
|
2504
|
+
const plan = buildReloadPlan3(changedPaths);
|
|
2178
2505
|
if (plan.reloadPlugins) {
|
|
2179
2506
|
await this.reloadPlugins(nextConfig);
|
|
2180
2507
|
console.log("Config reload: plugins reloaded.");
|
|
@@ -2482,17 +2809,18 @@ var {
|
|
|
2482
2809
|
ChannelManager: ChannelManager2,
|
|
2483
2810
|
CronService: CronService2,
|
|
2484
2811
|
getApiBase,
|
|
2485
|
-
getConfigPath:
|
|
2812
|
+
getConfigPath: getConfigPath3,
|
|
2486
2813
|
getDataDir: getDataDir5,
|
|
2487
2814
|
getProvider,
|
|
2488
2815
|
getProviderName,
|
|
2489
2816
|
getWorkspacePath: getWorkspacePath5,
|
|
2490
2817
|
HeartbeatService,
|
|
2491
2818
|
LiteLLMProvider,
|
|
2492
|
-
loadConfig:
|
|
2819
|
+
loadConfig: loadConfig6,
|
|
2493
2820
|
MessageBus,
|
|
2494
2821
|
ProviderManager,
|
|
2495
|
-
|
|
2822
|
+
resolveConfigSecrets: resolveConfigSecrets2,
|
|
2823
|
+
saveConfig: saveConfig5,
|
|
2496
2824
|
SessionManager,
|
|
2497
2825
|
parseAgentScopedSessionKey: parseAgentScopedSessionKey2
|
|
2498
2826
|
} = NextclawCore;
|
|
@@ -2508,7 +2836,8 @@ var ServiceCommands = class {
|
|
|
2508
2836
|
this.deps = deps;
|
|
2509
2837
|
}
|
|
2510
2838
|
async startGateway(options = {}) {
|
|
2511
|
-
const
|
|
2839
|
+
const runtimeConfigPath = getConfigPath3();
|
|
2840
|
+
const config2 = resolveConfigSecrets2(loadConfig6(), { configPath: runtimeConfigPath });
|
|
2512
2841
|
const workspace = getWorkspacePath5(config2.agents.defaults.workspace);
|
|
2513
2842
|
let pluginRegistry = loadPluginRegistry(config2, workspace);
|
|
2514
2843
|
let extensionRegistry = toExtensionRegistry(pluginRegistry);
|
|
@@ -2553,7 +2882,7 @@ var ServiceCommands = class {
|
|
|
2553
2882
|
sessionManager,
|
|
2554
2883
|
providerManager,
|
|
2555
2884
|
makeProvider: (nextConfig) => this.makeProvider(nextConfig, { allowMissing: true }) ?? this.makeMissingProvider(nextConfig),
|
|
2556
|
-
loadConfig:
|
|
2885
|
+
loadConfig: () => resolveConfigSecrets2(loadConfig6(), { configPath: runtimeConfigPath }),
|
|
2557
2886
|
getExtensionChannels: () => extensionRegistry.channels,
|
|
2558
2887
|
onRestartRequired: (paths) => {
|
|
2559
2888
|
void this.deps.requestRestart({
|
|
@@ -2567,8 +2896,8 @@ var ServiceCommands = class {
|
|
|
2567
2896
|
reloader,
|
|
2568
2897
|
cron: cron2,
|
|
2569
2898
|
sessionManager,
|
|
2570
|
-
getConfigPath:
|
|
2571
|
-
saveConfig:
|
|
2899
|
+
getConfigPath: getConfigPath3,
|
|
2900
|
+
saveConfig: saveConfig5,
|
|
2572
2901
|
requestRestart: async (options2) => {
|
|
2573
2902
|
await this.deps.requestRestart({
|
|
2574
2903
|
reason: options2?.reason ?? "gateway tool restart",
|
|
@@ -2594,7 +2923,7 @@ var ServiceCommands = class {
|
|
|
2594
2923
|
resolveMessageToolHints: ({ channel, accountId }) => resolvePluginChannelMessageToolHints({
|
|
2595
2924
|
registry: pluginRegistry,
|
|
2596
2925
|
channel,
|
|
2597
|
-
cfg:
|
|
2926
|
+
cfg: resolveConfigSecrets2(loadConfig6(), { configPath: runtimeConfigPath }),
|
|
2598
2927
|
accountId
|
|
2599
2928
|
})
|
|
2600
2929
|
});
|
|
@@ -2620,14 +2949,14 @@ var ServiceCommands = class {
|
|
|
2620
2949
|
});
|
|
2621
2950
|
let pluginChannelBindings = getPluginChannelBindings2(pluginRegistry);
|
|
2622
2951
|
setPluginRuntimeBridge({
|
|
2623
|
-
loadConfig: () => toPluginConfigView(
|
|
2952
|
+
loadConfig: () => toPluginConfigView(resolveConfigSecrets2(loadConfig6(), { configPath: runtimeConfigPath }), pluginChannelBindings),
|
|
2624
2953
|
writeConfigFile: async (nextConfigView) => {
|
|
2625
2954
|
if (!nextConfigView || typeof nextConfigView !== "object" || Array.isArray(nextConfigView)) {
|
|
2626
2955
|
throw new Error("plugin runtime writeConfigFile expects an object config");
|
|
2627
2956
|
}
|
|
2628
|
-
const current =
|
|
2957
|
+
const current = loadConfig6();
|
|
2629
2958
|
const next = mergePluginConfigView(current, nextConfigView, pluginChannelBindings);
|
|
2630
|
-
|
|
2959
|
+
saveConfig5(next);
|
|
2631
2960
|
},
|
|
2632
2961
|
dispatchReplyWithBufferedBlockDispatcher: async ({ ctx, dispatcherOptions }) => {
|
|
2633
2962
|
const bodyForAgent = typeof ctx.BodyForAgent === "string" ? ctx.BodyForAgent : "";
|
|
@@ -2698,7 +3027,7 @@ var ServiceCommands = class {
|
|
|
2698
3027
|
console.log(`\u2713 Cron: ${cronStatus.jobs} scheduled jobs`);
|
|
2699
3028
|
}
|
|
2700
3029
|
console.log("\u2713 Heartbeat: every 30m");
|
|
2701
|
-
const configPath = resolve7(
|
|
3030
|
+
const configPath = resolve7(getConfigPath3());
|
|
2702
3031
|
const watcher = chokidar.watch(configPath, {
|
|
2703
3032
|
ignoreInitial: true,
|
|
2704
3033
|
awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 }
|
|
@@ -2842,7 +3171,7 @@ var ServiceCommands = class {
|
|
|
2842
3171
|
});
|
|
2843
3172
|
}
|
|
2844
3173
|
async runForeground(options) {
|
|
2845
|
-
const config2 =
|
|
3174
|
+
const config2 = loadConfig6();
|
|
2846
3175
|
const uiConfig = resolveUiConfig(config2, options.uiOverrides);
|
|
2847
3176
|
const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
|
|
2848
3177
|
if (options.open) {
|
|
@@ -2855,7 +3184,7 @@ var ServiceCommands = class {
|
|
|
2855
3184
|
});
|
|
2856
3185
|
}
|
|
2857
3186
|
async startService(options) {
|
|
2858
|
-
const config2 =
|
|
3187
|
+
const config2 = loadConfig6();
|
|
2859
3188
|
const uiConfig = resolveUiConfig(config2, options.uiOverrides);
|
|
2860
3189
|
const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
|
|
2861
3190
|
const apiUrl = `${uiUrl}/api`;
|
|
@@ -3038,7 +3367,7 @@ var ServiceCommands = class {
|
|
|
3038
3367
|
return null;
|
|
3039
3368
|
}
|
|
3040
3369
|
console.error("Error: No API key configured.");
|
|
3041
|
-
console.error(`Set one in ${
|
|
3370
|
+
console.error(`Set one in ${getConfigPath3()} under providers section`);
|
|
3042
3371
|
process.exit(1);
|
|
3043
3372
|
}
|
|
3044
3373
|
return new LiteLLMProvider({
|
|
@@ -3071,7 +3400,7 @@ var ServiceCommands = class {
|
|
|
3071
3400
|
const uiServer = startUiServer({
|
|
3072
3401
|
host: uiConfig.host,
|
|
3073
3402
|
port: uiConfig.port,
|
|
3074
|
-
configPath:
|
|
3403
|
+
configPath: getConfigPath3(),
|
|
3075
3404
|
staticDir: uiStaticDir ?? void 0,
|
|
3076
3405
|
cronService,
|
|
3077
3406
|
marketplace: {
|
|
@@ -3164,7 +3493,7 @@ var ServiceCommands = class {
|
|
|
3164
3493
|
if (!source) {
|
|
3165
3494
|
throw new Error("Git skill source is required");
|
|
3166
3495
|
}
|
|
3167
|
-
const workspace = getWorkspacePath5(
|
|
3496
|
+
const workspace = getWorkspacePath5(loadConfig6().agents.defaults.workspace);
|
|
3168
3497
|
const skillName = this.resolveGitSkillName(params.skill, source);
|
|
3169
3498
|
const destination = this.resolveSkillInstallPath(workspace, params.installPath, skillName);
|
|
3170
3499
|
const destinationSkillFile = join4(destination, "SKILL.md");
|
|
@@ -3246,7 +3575,7 @@ var ServiceCommands = class {
|
|
|
3246
3575
|
return { message: summary, output };
|
|
3247
3576
|
}
|
|
3248
3577
|
async uninstallMarketplaceSkill(slug) {
|
|
3249
|
-
const workspace = getWorkspacePath5(
|
|
3578
|
+
const workspace = getWorkspacePath5(loadConfig6().agents.defaults.workspace);
|
|
3250
3579
|
const targetDir = join4(workspace, "skills", slug);
|
|
3251
3580
|
const skildDir = join4(workspace, ".agents", "skills", slug);
|
|
3252
3581
|
const existingTargets = [targetDir, skildDir].filter((path) => existsSync7(path));
|
|
@@ -3262,7 +3591,7 @@ var ServiceCommands = class {
|
|
|
3262
3591
|
};
|
|
3263
3592
|
}
|
|
3264
3593
|
installBuiltinMarketplaceSkill(slug, force) {
|
|
3265
|
-
const workspace = getWorkspacePath5(
|
|
3594
|
+
const workspace = getWorkspacePath5(loadConfig6().agents.defaults.workspace);
|
|
3266
3595
|
const destination = join4(workspace, "skills", slug);
|
|
3267
3596
|
const destinationSkillFile = join4(destination, "SKILL.md");
|
|
3268
3597
|
if (existsSync7(destinationSkillFile) && !force) {
|
|
@@ -3424,7 +3753,7 @@ ${stderr}`.trim();
|
|
|
3424
3753
|
};
|
|
3425
3754
|
|
|
3426
3755
|
// src/cli/workspace.ts
|
|
3427
|
-
import { cpSync as cpSync2, existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as
|
|
3756
|
+
import { cpSync as cpSync2, existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync6, readdirSync, rmSync as rmSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
3428
3757
|
import { createRequire } from "module";
|
|
3429
3758
|
import { dirname as dirname2, join as join5, resolve as resolve8 } from "path";
|
|
3430
3759
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -3465,7 +3794,7 @@ var WorkspaceManager = class {
|
|
|
3465
3794
|
console.warn(`Warning: Template file missing: ${templatePath}`);
|
|
3466
3795
|
continue;
|
|
3467
3796
|
}
|
|
3468
|
-
const raw =
|
|
3797
|
+
const raw = readFileSync6(templatePath, "utf-8");
|
|
3469
3798
|
const content = raw.replace(/\$\{APP_NAME\}/g, APP_NAME3);
|
|
3470
3799
|
mkdirSync4(dirname2(filePath), { recursive: true });
|
|
3471
3800
|
writeFileSync3(filePath, content);
|
|
@@ -3609,6 +3938,7 @@ var CliRuntime = class {
|
|
|
3609
3938
|
workspaceManager;
|
|
3610
3939
|
serviceCommands;
|
|
3611
3940
|
configCommands;
|
|
3941
|
+
secretsCommands;
|
|
3612
3942
|
pluginCommands;
|
|
3613
3943
|
channelCommands;
|
|
3614
3944
|
cronCommands;
|
|
@@ -3622,6 +3952,9 @@ var CliRuntime = class {
|
|
|
3622
3952
|
this.configCommands = new ConfigCommands({
|
|
3623
3953
|
requestRestart: (params) => this.requestRestart(params)
|
|
3624
3954
|
});
|
|
3955
|
+
this.secretsCommands = new SecretsCommands({
|
|
3956
|
+
requestRestart: (params) => this.requestRestart(params)
|
|
3957
|
+
});
|
|
3625
3958
|
this.pluginCommands = new PluginCommands();
|
|
3626
3959
|
this.channelCommands = new ChannelCommands({
|
|
3627
3960
|
logo: this.logo,
|
|
@@ -3822,14 +4155,14 @@ var CliRuntime = class {
|
|
|
3822
4155
|
const source = options.source ?? "init";
|
|
3823
4156
|
const prefix = options.auto ? "Auto init" : "Init";
|
|
3824
4157
|
const force = Boolean(options.force);
|
|
3825
|
-
const configPath =
|
|
4158
|
+
const configPath = getConfigPath4();
|
|
3826
4159
|
let createdConfig = false;
|
|
3827
4160
|
if (!existsSync9(configPath)) {
|
|
3828
4161
|
const config3 = ConfigSchema2.parse({});
|
|
3829
|
-
|
|
4162
|
+
saveConfig6(config3);
|
|
3830
4163
|
createdConfig = true;
|
|
3831
4164
|
}
|
|
3832
|
-
const config2 =
|
|
4165
|
+
const config2 = loadConfig7();
|
|
3833
4166
|
const workspaceSetting = config2.agents.defaults.workspace;
|
|
3834
4167
|
const workspacePath = !workspaceSetting || workspaceSetting === DEFAULT_WORKSPACE_PATH ? join6(getDataDir7(), DEFAULT_WORKSPACE_DIR) : expandHome2(workspaceSetting);
|
|
3835
4168
|
const workspaceExisted = existsSync9(workspacePath);
|
|
@@ -3938,27 +4271,31 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
|
|
|
3938
4271
|
await this.serviceCommands.stopService();
|
|
3939
4272
|
}
|
|
3940
4273
|
async agent(opts) {
|
|
3941
|
-
const
|
|
4274
|
+
const configPath = getConfigPath4();
|
|
4275
|
+
const config2 = resolveConfigSecrets3(loadConfig7(), { configPath });
|
|
3942
4276
|
const workspace = getWorkspacePath6(config2.agents.defaults.workspace);
|
|
3943
4277
|
const pluginRegistry = loadPluginRegistry(config2, workspace);
|
|
3944
4278
|
const extensionRegistry = toExtensionRegistry(pluginRegistry);
|
|
3945
4279
|
logPluginDiagnostics(pluginRegistry);
|
|
3946
4280
|
const pluginChannelBindings = getPluginChannelBindings3(pluginRegistry);
|
|
3947
4281
|
setPluginRuntimeBridge2({
|
|
3948
|
-
loadConfig: () => toPluginConfigView(
|
|
4282
|
+
loadConfig: () => toPluginConfigView(
|
|
4283
|
+
resolveConfigSecrets3(loadConfig7(), { configPath }),
|
|
4284
|
+
pluginChannelBindings
|
|
4285
|
+
),
|
|
3949
4286
|
writeConfigFile: async (nextConfigView) => {
|
|
3950
4287
|
if (!nextConfigView || typeof nextConfigView !== "object" || Array.isArray(nextConfigView)) {
|
|
3951
4288
|
throw new Error(
|
|
3952
4289
|
"plugin runtime writeConfigFile expects an object config"
|
|
3953
4290
|
);
|
|
3954
4291
|
}
|
|
3955
|
-
const current =
|
|
4292
|
+
const current = loadConfig7();
|
|
3956
4293
|
const next = mergePluginConfigView(
|
|
3957
4294
|
current,
|
|
3958
4295
|
nextConfigView,
|
|
3959
4296
|
pluginChannelBindings
|
|
3960
4297
|
);
|
|
3961
|
-
|
|
4298
|
+
saveConfig6(next);
|
|
3962
4299
|
}
|
|
3963
4300
|
});
|
|
3964
4301
|
try {
|
|
@@ -3985,7 +4322,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
|
|
|
3985
4322
|
resolveMessageToolHints: ({ channel, accountId }) => resolvePluginChannelMessageToolHints2({
|
|
3986
4323
|
registry: pluginRegistry,
|
|
3987
4324
|
channel,
|
|
3988
|
-
cfg:
|
|
4325
|
+
cfg: resolveConfigSecrets3(loadConfig7(), { configPath }),
|
|
3989
4326
|
accountId
|
|
3990
4327
|
})
|
|
3991
4328
|
});
|
|
@@ -4007,7 +4344,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
|
|
|
4007
4344
|
const historyFile = join6(getDataDir7(), "history", "cli_history");
|
|
4008
4345
|
const historyDir = resolve9(historyFile, "..");
|
|
4009
4346
|
mkdirSync5(historyDir, { recursive: true });
|
|
4010
|
-
const history = existsSync9(historyFile) ?
|
|
4347
|
+
const history = existsSync9(historyFile) ? readFileSync7(historyFile, "utf-8").split("\n").filter(Boolean) : [];
|
|
4011
4348
|
const rl = createInterface2({
|
|
4012
4349
|
input: process.stdin,
|
|
4013
4350
|
output: process.stdout
|
|
@@ -4119,6 +4456,18 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
|
|
|
4119
4456
|
async configUnset(pathExpr) {
|
|
4120
4457
|
await this.configCommands.configUnset(pathExpr);
|
|
4121
4458
|
}
|
|
4459
|
+
secretsAudit(opts = {}) {
|
|
4460
|
+
this.secretsCommands.secretsAudit(opts);
|
|
4461
|
+
}
|
|
4462
|
+
async secretsConfigure(opts) {
|
|
4463
|
+
await this.secretsCommands.secretsConfigure(opts);
|
|
4464
|
+
}
|
|
4465
|
+
async secretsApply(opts) {
|
|
4466
|
+
await this.secretsCommands.secretsApply(opts);
|
|
4467
|
+
}
|
|
4468
|
+
async secretsReload(opts = {}) {
|
|
4469
|
+
await this.secretsCommands.secretsReload(opts);
|
|
4470
|
+
}
|
|
4122
4471
|
channelsStatus() {
|
|
4123
4472
|
this.channelCommands.channelsStatus();
|
|
4124
4473
|
}
|
|
@@ -4205,6 +4554,16 @@ var config = program.command("config").description("Manage config values");
|
|
|
4205
4554
|
config.command("get <path>").description("Get a config value by dot path").option("--json", "Output JSON", false).action((path, opts) => runtime.configGet(path, opts));
|
|
4206
4555
|
config.command("set <path> <value>").description("Set a config value by dot path").option("--json", "Parse value as JSON", false).action((path, value, opts) => runtime.configSet(path, value, opts));
|
|
4207
4556
|
config.command("unset <path>").description("Remove a config value by dot path").action((path) => runtime.configUnset(path));
|
|
4557
|
+
var secrets = program.command("secrets").description("Manage secrets refs/providers");
|
|
4558
|
+
secrets.command("audit").description("Audit secret refs resolution status").option("--json", "Output JSON", false).option("--strict", "Exit non-zero when unresolved refs exist", false).action((opts) => runtime.secretsAudit(opts));
|
|
4559
|
+
secrets.command("configure").description("Configure a secret provider alias").requiredOption("--provider <alias>", "Provider alias").option("--source <source>", "Provider source (env|file|exec)").option("--prefix <prefix>", "Env key prefix (env source)").option("--path <path>", "Secret JSON file path (file source)").option("--command <command>", "Command for exec source").option(
|
|
4560
|
+
"--arg <value>",
|
|
4561
|
+
"Exec argument (repeatable)",
|
|
4562
|
+
(value, previous = []) => [...previous, value],
|
|
4563
|
+
[]
|
|
4564
|
+
).option("--cwd <dir>", "Exec working directory").option("--timeout-ms <ms>", "Exec timeout in milliseconds").option("--set-default", "Set as default alias for this source", false).option("--remove", "Remove provider alias", false).option("--json", "Output JSON", false).action((opts) => runtime.secretsConfigure(opts));
|
|
4565
|
+
secrets.command("apply").description("Apply secret refs/providers/defaults patch").option("--file <path>", "Apply patch from JSON file").option("--path <config-path>", "Single ref target config path").option("--source <source>", "Single ref source (env|file|exec)").option("--id <secret-id>", "Single ref secret id").option("--provider <alias>", "Single ref provider alias").option("--remove", "Remove single ref (--path required)", false).option("--enable", "Enable secrets resolution", false).option("--disable", "Disable secrets resolution", false).option("--json", "Output JSON", false).action((opts) => runtime.secretsApply(opts));
|
|
4566
|
+
secrets.command("reload").description("Trigger runtime secrets reload signal").option("--json", "Output JSON", false).action((opts) => runtime.secretsReload(opts));
|
|
4208
4567
|
var channels = program.command("channels").description("Manage channels");
|
|
4209
4568
|
channels.command("add").description("Configure a plugin channel (OpenClaw-compatible setup)").requiredOption("--channel <id>", "Plugin channel id").option("--code <code>", "Pairing code").option("--token <token>", "Connector token").option("--name <name>", "Display name").option("--url <url>", "API base URL").option("--http-url <url>", "Alias for --url").action((opts) => runtime.channelsAdd(opts));
|
|
4210
4569
|
channels.command("status").description("Show channel status").action(() => runtime.channelsStatus());
|