@openacp/cli 2026.330.3 → 2026.331.2
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 +19 -1
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +25134 -278
- package/dist/cli.js.map +1 -1
- package/dist/data/registry-snapshot.json +1 -1
- package/dist/index.d.ts +259 -30
- package/dist/index.js +17632 -404
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/adapter-AWSI4GML.js +0 -13
- package/dist/adapter-AWSI4GML.js.map +0 -1
- package/dist/agent-catalog-SZQQERV7.js +0 -10
- package/dist/agent-catalog-SZQQERV7.js.map +0 -1
- package/dist/agent-dependencies-ED2ZTUHG.js +0 -23
- package/dist/agent-dependencies-ED2ZTUHG.js.map +0 -1
- package/dist/agent-registry-YOGP656W.js +0 -8
- package/dist/agent-registry-YOGP656W.js.map +0 -1
- package/dist/agent-store-5UHZH2XI.js +0 -8
- package/dist/agent-store-5UHZH2XI.js.map +0 -1
- package/dist/api-client-XTLRRFPX.js +0 -13
- package/dist/api-client-XTLRRFPX.js.map +0 -1
- package/dist/api-server-5VNYFWJE.js +0 -7
- package/dist/api-server-5VNYFWJE.js.map +0 -1
- package/dist/api-server-JLBDKCU4.js +0 -10
- package/dist/api-server-JLBDKCU4.js.map +0 -1
- package/dist/autostart-CUPZMKKC.js +0 -22
- package/dist/autostart-CUPZMKKC.js.map +0 -1
- package/dist/chunk-237WYH6H.js +0 -235
- package/dist/chunk-237WYH6H.js.map +0 -1
- package/dist/chunk-2HEFALTZ.js +0 -44
- package/dist/chunk-2HEFALTZ.js.map +0 -1
- package/dist/chunk-2KT6TROD.js +0 -129
- package/dist/chunk-2KT6TROD.js.map +0 -1
- package/dist/chunk-2R5XM3ES.js +0 -154
- package/dist/chunk-2R5XM3ES.js.map +0 -1
- package/dist/chunk-3EWTPOF7.js +0 -51
- package/dist/chunk-3EWTPOF7.js.map +0 -1
- package/dist/chunk-3NAFXVQM.js +0 -67
- package/dist/chunk-3NAFXVQM.js.map +0 -1
- package/dist/chunk-4WXALZA3.js +0 -45
- package/dist/chunk-4WXALZA3.js.map +0 -1
- package/dist/chunk-566W6INH.js +0 -83
- package/dist/chunk-566W6INH.js.map +0 -1
- package/dist/chunk-5HKQCYOI.js +0 -145
- package/dist/chunk-5HKQCYOI.js.map +0 -1
- package/dist/chunk-5OCGO27U.js +0 -125
- package/dist/chunk-5OCGO27U.js.map +0 -1
- package/dist/chunk-5WGVYX3C.js +0 -55
- package/dist/chunk-5WGVYX3C.js.map +0 -1
- package/dist/chunk-7ZCQF6QM.js +0 -27
- package/dist/chunk-7ZCQF6QM.js.map +0 -1
- package/dist/chunk-AFKX424Q.js +0 -92
- package/dist/chunk-AFKX424Q.js.map +0 -1
- package/dist/chunk-APS6UEFU.js +0 -259
- package/dist/chunk-APS6UEFU.js.map +0 -1
- package/dist/chunk-BTJHGSLM.js +0 -1116
- package/dist/chunk-BTJHGSLM.js.map +0 -1
- package/dist/chunk-CDAUYTVP.js +0 -41
- package/dist/chunk-CDAUYTVP.js.map +0 -1
- package/dist/chunk-FCTC7KDT.js +0 -101
- package/dist/chunk-FCTC7KDT.js.map +0 -1
- package/dist/chunk-FNRSWA2K.js +0 -1
- package/dist/chunk-FNRSWA2K.js.map +0 -1
- package/dist/chunk-GEOXPGCO.js +0 -650
- package/dist/chunk-GEOXPGCO.js.map +0 -1
- package/dist/chunk-IZ5UEZF7.js +0 -138
- package/dist/chunk-IZ5UEZF7.js.map +0 -1
- package/dist/chunk-KDU3ZEWT.js +0 -97
- package/dist/chunk-KDU3ZEWT.js.map +0 -1
- package/dist/chunk-LGFWH3AE.js +0 -26
- package/dist/chunk-LGFWH3AE.js.map +0 -1
- package/dist/chunk-MITTQMGZ.js +0 -543
- package/dist/chunk-MITTQMGZ.js.map +0 -1
- package/dist/chunk-MLF4W5R6.js +0 -101
- package/dist/chunk-MLF4W5R6.js.map +0 -1
- package/dist/chunk-MPGEHTGE.js +0 -679
- package/dist/chunk-MPGEHTGE.js.map +0 -1
- package/dist/chunk-OYSAN7UX.js +0 -15
- package/dist/chunk-OYSAN7UX.js.map +0 -1
- package/dist/chunk-PA6MNBG4.js +0 -190
- package/dist/chunk-PA6MNBG4.js.map +0 -1
- package/dist/chunk-QWVHCTCA.js +0 -172
- package/dist/chunk-QWVHCTCA.js.map +0 -1
- package/dist/chunk-R6KZYF7D.js +0 -231
- package/dist/chunk-R6KZYF7D.js.map +0 -1
- package/dist/chunk-S64CB6J3.js +0 -98
- package/dist/chunk-S64CB6J3.js.map +0 -1
- package/dist/chunk-TMVTSWVH.js +0 -228
- package/dist/chunk-TMVTSWVH.js.map +0 -1
- package/dist/chunk-UCIZM5SW.js +0 -3917
- package/dist/chunk-UCIZM5SW.js.map +0 -1
- package/dist/chunk-UWH7KIAA.js +0 -701
- package/dist/chunk-UWH7KIAA.js.map +0 -1
- package/dist/chunk-V2YZWYXT.js +0 -484
- package/dist/chunk-V2YZWYXT.js.map +0 -1
- package/dist/chunk-W26AUH5B.js +0 -61
- package/dist/chunk-W26AUH5B.js.map +0 -1
- package/dist/chunk-W4LK6WJP.js +0 -446
- package/dist/chunk-W4LK6WJP.js.map +0 -1
- package/dist/chunk-WQCJTU2C.js +0 -84
- package/dist/chunk-WQCJTU2C.js.map +0 -1
- package/dist/chunk-XBZIHNKV.js +0 -6410
- package/dist/chunk-XBZIHNKV.js.map +0 -1
- package/dist/chunk-ZSLHHQPQ.js +0 -282
- package/dist/chunk-ZSLHHQPQ.js.map +0 -1
- package/dist/config-KN6NKKPF.js +0 -20
- package/dist/config-KN6NKKPF.js.map +0 -1
- package/dist/config-editor-76RVZS4B.js +0 -10
- package/dist/config-editor-76RVZS4B.js.map +0 -1
- package/dist/config-registry-ZXAIJNYB.js +0 -17
- package/dist/config-registry-ZXAIJNYB.js.map +0 -1
- package/dist/context-NXXW62NJ.js +0 -9
- package/dist/context-NXXW62NJ.js.map +0 -1
- package/dist/core-plugins-BPZY7SEB.js +0 -22
- package/dist/core-plugins-BPZY7SEB.js.map +0 -1
- package/dist/daemon-XFEMMJSZ.js +0 -29
- package/dist/daemon-XFEMMJSZ.js.map +0 -1
- package/dist/dev-loader-7P3HZCIA.js +0 -37
- package/dist/dev-loader-7P3HZCIA.js.map +0 -1
- package/dist/doctor-AV6AUO22.js +0 -9
- package/dist/doctor-AV6AUO22.js.map +0 -1
- package/dist/file-service-HHB3JQIO.js +0 -8
- package/dist/file-service-HHB3JQIO.js.map +0 -1
- package/dist/install-cloudflared-JRJ4BSOM.js +0 -32
- package/dist/install-cloudflared-JRJ4BSOM.js.map +0 -1
- package/dist/install-context-EHYV5WRY.js +0 -77
- package/dist/install-context-EHYV5WRY.js.map +0 -1
- package/dist/install-jq-ISTGT263.js +0 -31
- package/dist/install-jq-ISTGT263.js.map +0 -1
- package/dist/integrate-JIEZYDOR.js +0 -371
- package/dist/integrate-JIEZYDOR.js.map +0 -1
- package/dist/log-YZ243M5G.js +0 -25
- package/dist/log-YZ243M5G.js.map +0 -1
- package/dist/main-VEJCG5PY.js +0 -654
- package/dist/main-VEJCG5PY.js.map +0 -1
- package/dist/menu-ALFN37IR.js +0 -15
- package/dist/menu-ALFN37IR.js.map +0 -1
- package/dist/notifications-MO23S7S3.js +0 -8
- package/dist/notifications-MO23S7S3.js.map +0 -1
- package/dist/plugin-create-EHL76ZZG.js +0 -966
- package/dist/plugin-create-EHL76ZZG.js.map +0 -1
- package/dist/plugin-installer-VSTYZSXC.js +0 -9
- package/dist/plugin-installer-VSTYZSXC.js.map +0 -1
- package/dist/plugin-registry-6J3YSFHF.js +0 -7
- package/dist/plugin-registry-6J3YSFHF.js.map +0 -1
- package/dist/plugin-search-MGKAL5JM.js +0 -39
- package/dist/plugin-search-MGKAL5JM.js.map +0 -1
- package/dist/post-upgrade-Y26S2ZQ7.js +0 -79
- package/dist/post-upgrade-Y26S2ZQ7.js.map +0 -1
- package/dist/read-text-file-DJBTITIB.js +0 -7
- package/dist/read-text-file-DJBTITIB.js.map +0 -1
- package/dist/registry-client-GTBWLXYU.js +0 -7
- package/dist/registry-client-GTBWLXYU.js.map +0 -1
- package/dist/security-2BA265LN.js +0 -8
- package/dist/security-2BA265LN.js.map +0 -1
- package/dist/settings-manager-B4UN2LAC.js +0 -7
- package/dist/settings-manager-B4UN2LAC.js.map +0 -1
- package/dist/setup-DISPNDEK.js +0 -802
- package/dist/setup-DISPNDEK.js.map +0 -1
- package/dist/speech-SG62JYIF.js +0 -9
- package/dist/speech-SG62JYIF.js.map +0 -1
- package/dist/suggest-RST5VOHB.js +0 -36
- package/dist/suggest-RST5VOHB.js.map +0 -1
- package/dist/telegram-L3YM6SQJ.js +0 -7
- package/dist/telegram-L3YM6SQJ.js.map +0 -1
- package/dist/tunnel-HWJ27WDH.js +0 -7
- package/dist/tunnel-HWJ27WDH.js.map +0 -1
- package/dist/tunnel-service-ZMO4THKE.js +0 -1261
- package/dist/tunnel-service-ZMO4THKE.js.map +0 -1
- package/dist/validators-GITLOFXC.js +0 -11
- package/dist/validators-GITLOFXC.js.map +0 -1
- package/dist/version-AXXV6IV2.js +0 -15
- package/dist/version-AXXV6IV2.js.map +0 -1
package/dist/chunk-MPGEHTGE.js
DELETED
|
@@ -1,679 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
installAutoStart,
|
|
3
|
-
isAutoStartInstalled,
|
|
4
|
-
isAutoStartSupported,
|
|
5
|
-
uninstallAutoStart
|
|
6
|
-
} from "./chunk-2R5XM3ES.js";
|
|
7
|
-
import {
|
|
8
|
-
expandHome
|
|
9
|
-
} from "./chunk-W4LK6WJP.js";
|
|
10
|
-
|
|
11
|
-
// src/core/config/config-editor.ts
|
|
12
|
-
import * as os from "os";
|
|
13
|
-
import * as path from "path";
|
|
14
|
-
import * as clack from "@clack/prompts";
|
|
15
|
-
async function select2(opts) {
|
|
16
|
-
const result = await clack.select({
|
|
17
|
-
message: opts.message,
|
|
18
|
-
options: opts.choices.map((ch) => ({ label: ch.name, value: ch.value, hint: ch.description })),
|
|
19
|
-
initialValue: opts.default
|
|
20
|
-
});
|
|
21
|
-
if (clack.isCancel(result)) {
|
|
22
|
-
clack.cancel("Cancelled.");
|
|
23
|
-
process.exit(0);
|
|
24
|
-
}
|
|
25
|
-
return result;
|
|
26
|
-
}
|
|
27
|
-
async function input(opts) {
|
|
28
|
-
const result = await clack.text({
|
|
29
|
-
message: opts.message,
|
|
30
|
-
initialValue: opts.default,
|
|
31
|
-
validate: opts.validate ? (val) => {
|
|
32
|
-
const r = opts.validate(val ?? "");
|
|
33
|
-
if (r === true || r === void 0) return void 0;
|
|
34
|
-
if (typeof r === "string") return r;
|
|
35
|
-
return void 0;
|
|
36
|
-
} : void 0
|
|
37
|
-
});
|
|
38
|
-
if (clack.isCancel(result)) {
|
|
39
|
-
clack.cancel("Cancelled.");
|
|
40
|
-
process.exit(0);
|
|
41
|
-
}
|
|
42
|
-
return result;
|
|
43
|
-
}
|
|
44
|
-
var c = {
|
|
45
|
-
reset: "\x1B[0m",
|
|
46
|
-
bold: "\x1B[1m",
|
|
47
|
-
dim: "\x1B[2m",
|
|
48
|
-
green: "\x1B[32m",
|
|
49
|
-
yellow: "\x1B[33m",
|
|
50
|
-
cyan: "\x1B[36m"
|
|
51
|
-
};
|
|
52
|
-
var ok = (msg) => `${c.green}${c.bold}\u2713${c.reset} ${c.green}${msg}${c.reset}`;
|
|
53
|
-
var warn = (msg) => `${c.yellow}\u26A0 ${msg}${c.reset}`;
|
|
54
|
-
var dim = (msg) => `${c.dim}${msg}${c.reset}`;
|
|
55
|
-
var header = (title) => `
|
|
56
|
-
${c.cyan}${c.bold}[${title}]${c.reset}
|
|
57
|
-
`;
|
|
58
|
-
async function editTelegram(config, updates) {
|
|
59
|
-
const tg = config.channels?.telegram ?? {};
|
|
60
|
-
const currentToken = tg.botToken ?? "";
|
|
61
|
-
const currentChatId = tg.chatId ?? 0;
|
|
62
|
-
const currentEnabled = tg.enabled ?? false;
|
|
63
|
-
console.log(header("Telegram"));
|
|
64
|
-
console.log(` Enabled : ${currentEnabled ? ok("yes") : dim("no")}`);
|
|
65
|
-
const tokenDisplay = currentToken.length > 12 ? currentToken.slice(0, 6) + "..." + currentToken.slice(-6) : currentToken || dim("(not set)");
|
|
66
|
-
console.log(` Bot Token : ${tokenDisplay}`);
|
|
67
|
-
console.log(` Chat ID : ${currentChatId || dim("(not set)")}`);
|
|
68
|
-
console.log("");
|
|
69
|
-
const ensureTelegramUpdates = () => {
|
|
70
|
-
if (!updates.channels) updates.channels = {};
|
|
71
|
-
if (!updates.channels.telegram) {
|
|
72
|
-
updates.channels.telegram = {};
|
|
73
|
-
}
|
|
74
|
-
return updates.channels.telegram;
|
|
75
|
-
};
|
|
76
|
-
while (true) {
|
|
77
|
-
const isEnabled = (() => {
|
|
78
|
-
const ch = updates.channels;
|
|
79
|
-
const tgUp = ch?.telegram;
|
|
80
|
-
if (tgUp && "enabled" in tgUp) return tgUp.enabled;
|
|
81
|
-
return currentEnabled;
|
|
82
|
-
})();
|
|
83
|
-
const choice = await select2({
|
|
84
|
-
message: "Telegram settings:",
|
|
85
|
-
choices: [
|
|
86
|
-
{ name: isEnabled ? "Disable Telegram" : "Enable Telegram", value: "toggle" },
|
|
87
|
-
{ name: "Change Bot Token", value: "token" },
|
|
88
|
-
{ name: "Change Chat ID", value: "chatid" },
|
|
89
|
-
{ name: "Back", value: "back" }
|
|
90
|
-
]
|
|
91
|
-
});
|
|
92
|
-
if (choice === "back") break;
|
|
93
|
-
if (choice === "toggle") {
|
|
94
|
-
const tgUp = ensureTelegramUpdates();
|
|
95
|
-
tgUp.enabled = !isEnabled;
|
|
96
|
-
console.log(!isEnabled ? ok("Telegram enabled") : ok("Telegram disabled"));
|
|
97
|
-
}
|
|
98
|
-
if (choice === "token") {
|
|
99
|
-
const token = await input({
|
|
100
|
-
message: "New bot token:",
|
|
101
|
-
default: currentToken,
|
|
102
|
-
validate: (val) => val.trim().length > 0 || "Token cannot be empty"
|
|
103
|
-
});
|
|
104
|
-
try {
|
|
105
|
-
const { validateBotToken } = await import("./validators-GITLOFXC.js");
|
|
106
|
-
const result = await validateBotToken(token.trim());
|
|
107
|
-
if (result.ok) {
|
|
108
|
-
console.log(ok(`Connected to @${result.botUsername}`));
|
|
109
|
-
} else {
|
|
110
|
-
console.log(warn(`Validation failed: ${result.error} \u2014 saving anyway`));
|
|
111
|
-
}
|
|
112
|
-
} catch {
|
|
113
|
-
console.log(warn("Telegram validator not available \u2014 skipping validation"));
|
|
114
|
-
}
|
|
115
|
-
const tgUp = ensureTelegramUpdates();
|
|
116
|
-
tgUp.botToken = token.trim();
|
|
117
|
-
tgUp.enabled = true;
|
|
118
|
-
}
|
|
119
|
-
if (choice === "chatid") {
|
|
120
|
-
const chatIdStr = await input({
|
|
121
|
-
message: "New chat ID (e.g. -1001234567890):",
|
|
122
|
-
default: String(currentChatId),
|
|
123
|
-
validate: (val) => {
|
|
124
|
-
const n = Number(val.trim());
|
|
125
|
-
if (isNaN(n) || !Number.isInteger(n)) return "Chat ID must be an integer";
|
|
126
|
-
return true;
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
const chatId = Number(chatIdStr.trim());
|
|
130
|
-
const tokenForValidation = (() => {
|
|
131
|
-
const ch = updates.channels;
|
|
132
|
-
const tgUp2 = ch?.telegram;
|
|
133
|
-
if (typeof tgUp2?.botToken === "string") return tgUp2.botToken;
|
|
134
|
-
return currentToken;
|
|
135
|
-
})();
|
|
136
|
-
try {
|
|
137
|
-
const { validateChatId } = await import("./validators-GITLOFXC.js");
|
|
138
|
-
const result = await validateChatId(tokenForValidation, chatId);
|
|
139
|
-
if (result.ok) {
|
|
140
|
-
console.log(ok(`Group: ${result.title}${result.isForum ? "" : warn(" (topics not enabled)")}`));
|
|
141
|
-
} else {
|
|
142
|
-
console.log(warn(`Validation failed: ${result.error} \u2014 saving anyway`));
|
|
143
|
-
}
|
|
144
|
-
} catch {
|
|
145
|
-
console.log(warn("Telegram validator not available \u2014 skipping validation"));
|
|
146
|
-
}
|
|
147
|
-
const tgUp = ensureTelegramUpdates();
|
|
148
|
-
tgUp.chatId = chatId;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
var DISCORD_PACKAGE = "@openacp/adapter-discord";
|
|
153
|
-
async function ensureDiscordPlugin() {
|
|
154
|
-
try {
|
|
155
|
-
return await import(DISCORD_PACKAGE);
|
|
156
|
-
} catch {
|
|
157
|
-
const shouldInstall = await select2({
|
|
158
|
-
message: `${DISCORD_PACKAGE} is not installed. Install it now?`,
|
|
159
|
-
choices: [
|
|
160
|
-
{ name: "Yes, install now", value: "yes" },
|
|
161
|
-
{ name: "No, skip", value: "no" }
|
|
162
|
-
]
|
|
163
|
-
});
|
|
164
|
-
if (shouldInstall === "no") {
|
|
165
|
-
console.log(warn(`Install later with: openacp plugin add ${DISCORD_PACKAGE}`));
|
|
166
|
-
return null;
|
|
167
|
-
}
|
|
168
|
-
try {
|
|
169
|
-
console.log(dim(`Installing ${DISCORD_PACKAGE}...`));
|
|
170
|
-
const { installNpmPlugin } = await import("./plugin-installer-VSTYZSXC.js");
|
|
171
|
-
const mod = await installNpmPlugin(DISCORD_PACKAGE);
|
|
172
|
-
console.log(ok(`${DISCORD_PACKAGE} installed`));
|
|
173
|
-
return mod;
|
|
174
|
-
} catch (err) {
|
|
175
|
-
console.log(warn(`Failed to install: ${err.message}`));
|
|
176
|
-
return null;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
async function editDiscord(_config, _updates) {
|
|
181
|
-
const pluginModule = await ensureDiscordPlugin();
|
|
182
|
-
if (!pluginModule) return;
|
|
183
|
-
const plugin = pluginModule.default;
|
|
184
|
-
if (plugin?.configure) {
|
|
185
|
-
const { SettingsManager } = await import("./settings-manager-B4UN2LAC.js");
|
|
186
|
-
const { createInstallContext } = await import("./install-context-EHYV5WRY.js");
|
|
187
|
-
const basePath = path.join(os.homedir(), ".openacp", "plugins");
|
|
188
|
-
const settingsManager = new SettingsManager(basePath);
|
|
189
|
-
const ctx = createInstallContext({
|
|
190
|
-
pluginName: plugin.name,
|
|
191
|
-
settingsManager,
|
|
192
|
-
basePath
|
|
193
|
-
});
|
|
194
|
-
await plugin.configure(ctx);
|
|
195
|
-
} else {
|
|
196
|
-
console.log(warn("This plugin does not have a configure() method yet."));
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
async function editChannels(config, updates) {
|
|
200
|
-
const tgEnabled = config.channels?.telegram?.enabled !== false && config.channels?.telegram;
|
|
201
|
-
const dcEnabled = config.channels?.discord?.enabled !== false && config.channels?.discord;
|
|
202
|
-
console.log(header("Channels"));
|
|
203
|
-
console.log(` Telegram : ${tgEnabled ? ok("configured") : dim("not configured")}`);
|
|
204
|
-
console.log(` Discord : ${dcEnabled ? ok("configured") : dim("not configured")}`);
|
|
205
|
-
console.log("");
|
|
206
|
-
while (true) {
|
|
207
|
-
const choice = await select2({
|
|
208
|
-
message: "Channel settings:",
|
|
209
|
-
choices: [
|
|
210
|
-
{ name: "Telegram", value: "telegram" },
|
|
211
|
-
{ name: "Discord", value: "discord" },
|
|
212
|
-
{ name: "Back", value: "back" }
|
|
213
|
-
]
|
|
214
|
-
});
|
|
215
|
-
if (choice === "back") break;
|
|
216
|
-
if (choice === "telegram") await editTelegram(config, updates);
|
|
217
|
-
if (choice === "discord") await editDiscord(config, updates);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
async function editAgent(config, updates) {
|
|
221
|
-
const agentNames = Object.keys(config.agents ?? {});
|
|
222
|
-
const currentDefault = config.defaultAgent;
|
|
223
|
-
console.log(header("Agent"));
|
|
224
|
-
console.log(` Default agent : ${c.bold}${currentDefault}${c.reset}`);
|
|
225
|
-
console.log(` Available : ${agentNames.join(", ") || dim("(none)")}`);
|
|
226
|
-
console.log("");
|
|
227
|
-
while (true) {
|
|
228
|
-
const choice = await select2({
|
|
229
|
-
message: "Agent settings:",
|
|
230
|
-
choices: [
|
|
231
|
-
{ name: "Change default agent", value: "default" },
|
|
232
|
-
{ name: "Back", value: "back" }
|
|
233
|
-
]
|
|
234
|
-
});
|
|
235
|
-
if (choice === "back") break;
|
|
236
|
-
if (choice === "default") {
|
|
237
|
-
if (agentNames.length === 0) {
|
|
238
|
-
console.log(warn("No agents configured."));
|
|
239
|
-
continue;
|
|
240
|
-
}
|
|
241
|
-
const chosen = await select2({
|
|
242
|
-
message: "Select default agent:",
|
|
243
|
-
choices: agentNames.map((name) => ({ name, value: name }))
|
|
244
|
-
});
|
|
245
|
-
updates.defaultAgent = chosen;
|
|
246
|
-
console.log(ok(`Default agent set to ${chosen}`));
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
async function editWorkspace(config, updates) {
|
|
251
|
-
const currentDir = config.workspace?.baseDir ?? "~/openacp-workspace";
|
|
252
|
-
console.log(header("Workspace"));
|
|
253
|
-
console.log(` Base directory : ${currentDir}`);
|
|
254
|
-
console.log("");
|
|
255
|
-
const newDir = await input({
|
|
256
|
-
message: "Workspace base directory:",
|
|
257
|
-
default: currentDir,
|
|
258
|
-
validate: (val) => val.trim().length > 0 || "Path cannot be empty"
|
|
259
|
-
});
|
|
260
|
-
updates.workspace = { baseDir: newDir.trim() };
|
|
261
|
-
console.log(ok(`Workspace set to ${newDir.trim()}`));
|
|
262
|
-
}
|
|
263
|
-
async function editSecurity(config, updates) {
|
|
264
|
-
const sec = config.security ?? { allowedUserIds: [], maxConcurrentSessions: 20, sessionTimeoutMinutes: 60 };
|
|
265
|
-
console.log(header("Security"));
|
|
266
|
-
console.log(` Allowed user IDs : ${sec.allowedUserIds?.length ? sec.allowedUserIds.join(", ") : dim("(all users allowed)")}`);
|
|
267
|
-
console.log(` Max concurrent sessions : ${sec.maxConcurrentSessions}`);
|
|
268
|
-
console.log(` Session timeout (min) : ${sec.sessionTimeoutMinutes}`);
|
|
269
|
-
console.log("");
|
|
270
|
-
while (true) {
|
|
271
|
-
const choice = await select2({
|
|
272
|
-
message: "Security settings:",
|
|
273
|
-
choices: [
|
|
274
|
-
{ name: "Max concurrent sessions", value: "maxSessions" },
|
|
275
|
-
{ name: "Session timeout (minutes)", value: "timeout" },
|
|
276
|
-
{ name: "Back", value: "back" }
|
|
277
|
-
]
|
|
278
|
-
});
|
|
279
|
-
if (choice === "back") break;
|
|
280
|
-
if (choice === "maxSessions") {
|
|
281
|
-
const val = await input({
|
|
282
|
-
message: "Max concurrent sessions:",
|
|
283
|
-
default: String(sec.maxConcurrentSessions),
|
|
284
|
-
validate: (v) => {
|
|
285
|
-
const n = Number(v.trim());
|
|
286
|
-
if (!Number.isInteger(n) || n < 1) return "Must be a positive integer";
|
|
287
|
-
return true;
|
|
288
|
-
}
|
|
289
|
-
});
|
|
290
|
-
if (!updates.security) updates.security = {};
|
|
291
|
-
updates.security.maxConcurrentSessions = Number(val.trim());
|
|
292
|
-
console.log(ok(`Max concurrent sessions set to ${val.trim()}`));
|
|
293
|
-
}
|
|
294
|
-
if (choice === "timeout") {
|
|
295
|
-
const val = await input({
|
|
296
|
-
message: "Session timeout in minutes:",
|
|
297
|
-
default: String(sec.sessionTimeoutMinutes),
|
|
298
|
-
validate: (v) => {
|
|
299
|
-
const n = Number(v.trim());
|
|
300
|
-
if (!Number.isInteger(n) || n < 1) return "Must be a positive integer";
|
|
301
|
-
return true;
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
if (!updates.security) updates.security = {};
|
|
305
|
-
updates.security.sessionTimeoutMinutes = Number(val.trim());
|
|
306
|
-
console.log(ok(`Session timeout set to ${val.trim()} minutes`));
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
async function editLogging(config, updates) {
|
|
311
|
-
const logging = config.logging ?? { level: "info", logDir: "~/.openacp/logs", maxFileSize: "10m", maxFiles: 7, sessionLogRetentionDays: 30 };
|
|
312
|
-
console.log(header("Logging"));
|
|
313
|
-
console.log(` Log level : ${logging.level}`);
|
|
314
|
-
console.log(` Log dir : ${logging.logDir}`);
|
|
315
|
-
console.log("");
|
|
316
|
-
while (true) {
|
|
317
|
-
const choice = await select2({
|
|
318
|
-
message: "Logging settings:",
|
|
319
|
-
choices: [
|
|
320
|
-
{ name: "Log level", value: "level" },
|
|
321
|
-
{ name: "Log directory", value: "logDir" },
|
|
322
|
-
{ name: "Back", value: "back" }
|
|
323
|
-
]
|
|
324
|
-
});
|
|
325
|
-
if (choice === "back") break;
|
|
326
|
-
if (choice === "level") {
|
|
327
|
-
const level = await select2({
|
|
328
|
-
message: "Select log level:",
|
|
329
|
-
choices: [
|
|
330
|
-
{ name: "silent", value: "silent" },
|
|
331
|
-
{ name: "debug", value: "debug" },
|
|
332
|
-
{ name: "info", value: "info" },
|
|
333
|
-
{ name: "warn", value: "warn" },
|
|
334
|
-
{ name: "error", value: "error" },
|
|
335
|
-
{ name: "fatal", value: "fatal" }
|
|
336
|
-
]
|
|
337
|
-
});
|
|
338
|
-
if (!updates.logging) updates.logging = {};
|
|
339
|
-
updates.logging.level = level;
|
|
340
|
-
console.log(ok(`Log level set to ${level}`));
|
|
341
|
-
}
|
|
342
|
-
if (choice === "logDir") {
|
|
343
|
-
const dir = await input({
|
|
344
|
-
message: "Log directory:",
|
|
345
|
-
default: logging.logDir,
|
|
346
|
-
validate: (val) => val.trim().length > 0 || "Path cannot be empty"
|
|
347
|
-
});
|
|
348
|
-
if (!updates.logging) updates.logging = {};
|
|
349
|
-
updates.logging.logDir = dir.trim();
|
|
350
|
-
console.log(ok(`Log directory set to ${dir.trim()}`));
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
async function editRunMode(config, updates) {
|
|
355
|
-
const currentMode = config.runMode ?? "foreground";
|
|
356
|
-
const currentAutoStart = config.autoStart ?? false;
|
|
357
|
-
const autoStartInstalled = isAutoStartInstalled();
|
|
358
|
-
const autoStartSupported = isAutoStartSupported();
|
|
359
|
-
console.log(header("Run Mode"));
|
|
360
|
-
console.log(` Current mode : ${c.bold}${currentMode}${c.reset}`);
|
|
361
|
-
console.log(` Auto-start : ${currentAutoStart ? ok("enabled") : dim("disabled")}${autoStartInstalled ? ` ${dim("(installed)")}` : ""}`);
|
|
362
|
-
console.log("");
|
|
363
|
-
while (true) {
|
|
364
|
-
const isDaemon = (() => {
|
|
365
|
-
if ("runMode" in updates) return updates.runMode === "daemon";
|
|
366
|
-
return currentMode === "daemon";
|
|
367
|
-
})();
|
|
368
|
-
const choices = [
|
|
369
|
-
isDaemon ? { name: "Switch to foreground mode", value: "foreground" } : { name: "Switch to daemon mode", value: "daemon" }
|
|
370
|
-
];
|
|
371
|
-
if (autoStartSupported) {
|
|
372
|
-
const autoStartCurrent = (() => {
|
|
373
|
-
if ("autoStart" in updates) return updates.autoStart;
|
|
374
|
-
return currentAutoStart;
|
|
375
|
-
})();
|
|
376
|
-
choices.push({
|
|
377
|
-
name: autoStartCurrent ? "Disable auto-start" : "Enable auto-start",
|
|
378
|
-
value: "toggleAutoStart"
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
choices.push({ name: "Back", value: "back" });
|
|
382
|
-
const choice = await select2({
|
|
383
|
-
message: "Run mode settings:",
|
|
384
|
-
choices
|
|
385
|
-
});
|
|
386
|
-
if (choice === "back") break;
|
|
387
|
-
if (choice === "daemon") {
|
|
388
|
-
updates.runMode = "daemon";
|
|
389
|
-
const logDir = config.logging?.logDir ?? "~/.openacp/logs";
|
|
390
|
-
const result = installAutoStart(expandHome(logDir));
|
|
391
|
-
if (result.success) {
|
|
392
|
-
updates.autoStart = true;
|
|
393
|
-
console.log(ok("Switched to daemon mode with auto-start"));
|
|
394
|
-
} else {
|
|
395
|
-
console.log(warn(`Switched to daemon mode (auto-start failed: ${result.error})`));
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
if (choice === "foreground") {
|
|
399
|
-
updates.runMode = "foreground";
|
|
400
|
-
updates.autoStart = false;
|
|
401
|
-
uninstallAutoStart();
|
|
402
|
-
console.log(ok("Switched to foreground mode"));
|
|
403
|
-
}
|
|
404
|
-
if (choice === "toggleAutoStart") {
|
|
405
|
-
const autoStartCurrent = (() => {
|
|
406
|
-
if ("autoStart" in updates) return updates.autoStart;
|
|
407
|
-
return currentAutoStart;
|
|
408
|
-
})();
|
|
409
|
-
if (autoStartCurrent) {
|
|
410
|
-
const result = uninstallAutoStart();
|
|
411
|
-
updates.autoStart = false;
|
|
412
|
-
if (result.success) {
|
|
413
|
-
console.log(ok("Auto-start disabled"));
|
|
414
|
-
} else {
|
|
415
|
-
console.log(warn(`Auto-start uninstall failed: ${result.error}`));
|
|
416
|
-
}
|
|
417
|
-
} else {
|
|
418
|
-
const logDir = config.logging?.logDir ?? "~/.openacp/logs";
|
|
419
|
-
const result = installAutoStart(expandHome(logDir));
|
|
420
|
-
updates.autoStart = result.success;
|
|
421
|
-
if (result.success) {
|
|
422
|
-
console.log(ok("Auto-start enabled"));
|
|
423
|
-
} else {
|
|
424
|
-
console.log(warn(`Auto-start install failed: ${result.error}`));
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
async function editApi(config, updates) {
|
|
431
|
-
const api = config.api ?? { port: 21420, host: "127.0.0.1" };
|
|
432
|
-
console.log(header("API"));
|
|
433
|
-
console.log(` Port : ${api.port}`);
|
|
434
|
-
console.log(` Host : ${api.host} ${dim("(localhost only)")}`);
|
|
435
|
-
console.log("");
|
|
436
|
-
const newPort = await input({
|
|
437
|
-
message: "API port:",
|
|
438
|
-
default: String(api.port),
|
|
439
|
-
validate: (v) => {
|
|
440
|
-
const n = Number(v.trim());
|
|
441
|
-
if (!Number.isInteger(n) || n < 1 || n > 65535) return "Must be a valid port (1-65535)";
|
|
442
|
-
return true;
|
|
443
|
-
}
|
|
444
|
-
});
|
|
445
|
-
updates.api = { port: Number(newPort.trim()) };
|
|
446
|
-
console.log(ok(`API port set to ${newPort.trim()}`));
|
|
447
|
-
}
|
|
448
|
-
async function editTunnel(config, updates) {
|
|
449
|
-
const tunnel = config.tunnel ?? { enabled: false, port: 3100, provider: "cloudflare", options: {}, storeTtlMinutes: 60, auth: { enabled: false } };
|
|
450
|
-
const currentUpdates = updates.tunnel ?? {};
|
|
451
|
-
const getVal = (key, fallback) => key in currentUpdates ? currentUpdates[key] : tunnel[key] ?? fallback;
|
|
452
|
-
console.log(header("Tunnel"));
|
|
453
|
-
console.log(` Enabled : ${getVal("enabled", false) ? ok("yes") : dim("no")}`);
|
|
454
|
-
console.log(` Provider : ${c.bold}${getVal("provider", "cloudflare")}${c.reset}`);
|
|
455
|
-
console.log(` Port : ${getVal("port", 3100)}`);
|
|
456
|
-
const authEnabled = getVal("auth", { enabled: false }).enabled;
|
|
457
|
-
console.log(` Auth : ${authEnabled ? ok("enabled") : dim("disabled")}`);
|
|
458
|
-
console.log("");
|
|
459
|
-
while (true) {
|
|
460
|
-
const choice = await select2({
|
|
461
|
-
message: "Tunnel settings:",
|
|
462
|
-
choices: [
|
|
463
|
-
{ name: getVal("enabled", false) ? "Disable tunnel" : "Enable tunnel", value: "toggle" },
|
|
464
|
-
{ name: "Change provider", value: "provider" },
|
|
465
|
-
{ name: "Change port", value: "port" },
|
|
466
|
-
{ name: "Provider options", value: "options" },
|
|
467
|
-
{ name: authEnabled ? "Disable auth" : "Enable auth", value: "auth" },
|
|
468
|
-
{ name: "Back", value: "back" }
|
|
469
|
-
]
|
|
470
|
-
});
|
|
471
|
-
if (choice === "back") break;
|
|
472
|
-
if (!updates.tunnel) updates.tunnel = { ...tunnel };
|
|
473
|
-
const tun = updates.tunnel;
|
|
474
|
-
if (choice === "toggle") {
|
|
475
|
-
const current = getVal("enabled", false);
|
|
476
|
-
tun.enabled = !current;
|
|
477
|
-
console.log(!current ? ok("Tunnel enabled") : ok("Tunnel disabled"));
|
|
478
|
-
}
|
|
479
|
-
if (choice === "provider") {
|
|
480
|
-
const provider = await select2({
|
|
481
|
-
message: "Select tunnel provider:",
|
|
482
|
-
choices: [
|
|
483
|
-
{ name: "Cloudflare (default)", value: "cloudflare" },
|
|
484
|
-
{ name: "ngrok", value: "ngrok" },
|
|
485
|
-
{ name: "bore", value: "bore" },
|
|
486
|
-
{ name: "Tailscale Funnel", value: "tailscale" }
|
|
487
|
-
]
|
|
488
|
-
});
|
|
489
|
-
tun.provider = provider;
|
|
490
|
-
tun.options = {};
|
|
491
|
-
console.log(ok(`Provider set to ${provider}`));
|
|
492
|
-
}
|
|
493
|
-
if (choice === "port") {
|
|
494
|
-
const val = await input({
|
|
495
|
-
message: "Tunnel port:",
|
|
496
|
-
default: String(getVal("port", 3100)),
|
|
497
|
-
validate: (v) => {
|
|
498
|
-
const n = Number(v.trim());
|
|
499
|
-
if (!Number.isInteger(n) || n < 1 || n > 65535) return "Must be a valid port (1-65535)";
|
|
500
|
-
return true;
|
|
501
|
-
}
|
|
502
|
-
});
|
|
503
|
-
tun.port = Number(val.trim());
|
|
504
|
-
console.log(ok(`Tunnel port set to ${val.trim()}`));
|
|
505
|
-
}
|
|
506
|
-
if (choice === "options") {
|
|
507
|
-
const provider = getVal("provider", "cloudflare");
|
|
508
|
-
const currentOptions = getVal("options", {});
|
|
509
|
-
await editProviderOptions(provider, currentOptions, tun);
|
|
510
|
-
}
|
|
511
|
-
if (choice === "auth") {
|
|
512
|
-
const currentAuth = getVal("auth", { enabled: false });
|
|
513
|
-
if (currentAuth.enabled) {
|
|
514
|
-
tun.auth = { enabled: false };
|
|
515
|
-
console.log(ok("Tunnel auth disabled"));
|
|
516
|
-
} else {
|
|
517
|
-
const token = await input({
|
|
518
|
-
message: "Auth token (leave empty to auto-generate):",
|
|
519
|
-
default: ""
|
|
520
|
-
});
|
|
521
|
-
tun.auth = token.trim() ? { enabled: true, token: token.trim() } : { enabled: true };
|
|
522
|
-
console.log(ok("Tunnel auth enabled"));
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
async function editProviderOptions(provider, currentOptions, tun) {
|
|
528
|
-
if (provider === "cloudflare") {
|
|
529
|
-
const domain = await input({
|
|
530
|
-
message: "Custom domain (leave empty for random):",
|
|
531
|
-
default: currentOptions.domain ?? ""
|
|
532
|
-
});
|
|
533
|
-
tun.options = domain.trim() ? { domain: domain.trim() } : {};
|
|
534
|
-
if (domain.trim()) console.log(ok(`Domain set to ${domain.trim()}`));
|
|
535
|
-
else console.log(dim("Using random cloudflare domain"));
|
|
536
|
-
} else if (provider === "ngrok") {
|
|
537
|
-
const authtoken = await input({
|
|
538
|
-
message: "ngrok authtoken (leave empty to skip):",
|
|
539
|
-
default: currentOptions.authtoken ?? ""
|
|
540
|
-
});
|
|
541
|
-
const domain = await input({
|
|
542
|
-
message: "ngrok domain (leave empty for random):",
|
|
543
|
-
default: currentOptions.domain ?? ""
|
|
544
|
-
});
|
|
545
|
-
const region = await input({
|
|
546
|
-
message: "ngrok region (us, eu, ap \u2014 leave empty for default):",
|
|
547
|
-
default: currentOptions.region ?? ""
|
|
548
|
-
});
|
|
549
|
-
const opts = {};
|
|
550
|
-
if (authtoken.trim()) opts.authtoken = authtoken.trim();
|
|
551
|
-
if (domain.trim()) opts.domain = domain.trim();
|
|
552
|
-
if (region.trim()) opts.region = region.trim();
|
|
553
|
-
tun.options = opts;
|
|
554
|
-
console.log(ok("ngrok options saved"));
|
|
555
|
-
} else if (provider === "bore") {
|
|
556
|
-
const server = await input({
|
|
557
|
-
message: "bore server:",
|
|
558
|
-
default: currentOptions.server ?? "bore.pub"
|
|
559
|
-
});
|
|
560
|
-
const port = await input({
|
|
561
|
-
message: "bore port (leave empty for auto):",
|
|
562
|
-
default: currentOptions.port ? String(currentOptions.port) : ""
|
|
563
|
-
});
|
|
564
|
-
const secret = await input({
|
|
565
|
-
message: "bore secret (leave empty to skip):",
|
|
566
|
-
default: currentOptions.secret ?? ""
|
|
567
|
-
});
|
|
568
|
-
const opts = { server: server.trim() };
|
|
569
|
-
if (port.trim()) opts.port = Number(port.trim());
|
|
570
|
-
if (secret.trim()) opts.secret = secret.trim();
|
|
571
|
-
tun.options = opts;
|
|
572
|
-
console.log(ok("bore options saved"));
|
|
573
|
-
} else if (provider === "tailscale") {
|
|
574
|
-
const bg = await select2({
|
|
575
|
-
message: "Run Tailscale Funnel in background?",
|
|
576
|
-
choices: [
|
|
577
|
-
{ name: "No", value: "no" },
|
|
578
|
-
{ name: "Yes", value: "yes" }
|
|
579
|
-
]
|
|
580
|
-
});
|
|
581
|
-
tun.options = bg === "yes" ? { bg: true } : {};
|
|
582
|
-
console.log(ok("Tailscale options saved"));
|
|
583
|
-
} else {
|
|
584
|
-
console.log(dim(`No configurable options for provider "${provider}"`));
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
async function runConfigEditor(configManager, mode = "file", apiPort) {
|
|
588
|
-
await configManager.load();
|
|
589
|
-
const config = configManager.get();
|
|
590
|
-
const updates = {};
|
|
591
|
-
console.log(`
|
|
592
|
-
${c.cyan}${c.bold}OpenACP Config Editor${c.reset}`);
|
|
593
|
-
console.log(dim(`Config: ${configManager.getConfigPath()}`));
|
|
594
|
-
console.log("");
|
|
595
|
-
try {
|
|
596
|
-
while (true) {
|
|
597
|
-
const hasChanges = mode === "file" ? Object.keys(updates).length > 0 : false;
|
|
598
|
-
const choice = await select2({
|
|
599
|
-
message: `What would you like to edit?${hasChanges ? ` ${c.yellow}(unsaved changes)${c.reset}` : ""}`,
|
|
600
|
-
choices: [
|
|
601
|
-
{ name: "Channels", value: "channels" },
|
|
602
|
-
{ name: "Agent", value: "agent" },
|
|
603
|
-
{ name: "Workspace", value: "workspace" },
|
|
604
|
-
{ name: "Security", value: "security" },
|
|
605
|
-
{ name: "Logging", value: "logging" },
|
|
606
|
-
{ name: "Run Mode", value: "runMode" },
|
|
607
|
-
{ name: "API", value: "api" },
|
|
608
|
-
{ name: "Tunnel", value: "tunnel" },
|
|
609
|
-
{ name: hasChanges ? "Save & Exit" : "Exit", value: "exit" }
|
|
610
|
-
]
|
|
611
|
-
});
|
|
612
|
-
if (choice === "exit") {
|
|
613
|
-
if (mode === "file" && hasChanges) {
|
|
614
|
-
await configManager.save(updates);
|
|
615
|
-
console.log(ok(`Config saved to ${configManager.getConfigPath()}`));
|
|
616
|
-
} else if (mode === "file") {
|
|
617
|
-
console.log(dim("No changes made."));
|
|
618
|
-
}
|
|
619
|
-
break;
|
|
620
|
-
}
|
|
621
|
-
const sectionUpdates = {};
|
|
622
|
-
if (choice === "channels") await editChannels(config, sectionUpdates);
|
|
623
|
-
else if (choice === "agent") await editAgent(config, sectionUpdates);
|
|
624
|
-
else if (choice === "workspace") await editWorkspace(config, sectionUpdates);
|
|
625
|
-
else if (choice === "security") await editSecurity(config, sectionUpdates);
|
|
626
|
-
else if (choice === "logging") await editLogging(config, sectionUpdates);
|
|
627
|
-
else if (choice === "runMode") await editRunMode(config, sectionUpdates);
|
|
628
|
-
else if (choice === "api") await editApi(config, sectionUpdates);
|
|
629
|
-
else if (choice === "tunnel") await editTunnel(config, sectionUpdates);
|
|
630
|
-
if (mode === "api" && Object.keys(sectionUpdates).length > 0) {
|
|
631
|
-
await sendConfigViaApi(apiPort, sectionUpdates);
|
|
632
|
-
await configManager.load();
|
|
633
|
-
Object.assign(config, configManager.get());
|
|
634
|
-
} else {
|
|
635
|
-
Object.assign(updates, sectionUpdates);
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
} catch (err) {
|
|
639
|
-
if (err.name === "ExitPromptError") {
|
|
640
|
-
console.log(dim("\nConfig editor cancelled. Changes discarded."));
|
|
641
|
-
return;
|
|
642
|
-
}
|
|
643
|
-
throw err;
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
async function sendConfigViaApi(port, updates) {
|
|
647
|
-
const { apiCall: call } = await import("./api-client-XTLRRFPX.js");
|
|
648
|
-
const paths = flattenToPaths(updates);
|
|
649
|
-
for (const { path: path2, value } of paths) {
|
|
650
|
-
const res = await call(port, "/api/config", {
|
|
651
|
-
method: "PATCH",
|
|
652
|
-
headers: { "Content-Type": "application/json" },
|
|
653
|
-
body: JSON.stringify({ path: path2, value })
|
|
654
|
-
});
|
|
655
|
-
const data = await res.json();
|
|
656
|
-
if (!res.ok) {
|
|
657
|
-
console.log(warn(`Failed to update ${path2}: ${data.error}`));
|
|
658
|
-
} else if (data.needsRestart) {
|
|
659
|
-
console.log(warn(`${path2} updated \u2014 restart required`));
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
function flattenToPaths(obj, prefix = "") {
|
|
664
|
-
const result = [];
|
|
665
|
-
for (const [key, val] of Object.entries(obj)) {
|
|
666
|
-
const fullPath = prefix ? `${prefix}.${key}` : key;
|
|
667
|
-
if (val && typeof val === "object" && !Array.isArray(val)) {
|
|
668
|
-
result.push(...flattenToPaths(val, fullPath));
|
|
669
|
-
} else {
|
|
670
|
-
result.push({ path: fullPath, value: val });
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
return result;
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
export {
|
|
677
|
-
runConfigEditor
|
|
678
|
-
};
|
|
679
|
-
//# sourceMappingURL=chunk-MPGEHTGE.js.map
|