@openacp/cli 2026.326.4 → 2026.327.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 +2 -2
- package/dist/{adapter-6ANPBSVU.js → adapter-LC2QSDAS.js} +4 -5
- package/dist/{adapter-PQGHVG4K.js → adapter-Y55NXX6I.js} +2 -2
- package/dist/{api-server-3PYLRBCN.js → api-server-7G3ZUZRM.js} +2 -2
- package/dist/{api-server-CHVSUDBX.js → api-server-CAYNPUF2.js} +2 -2
- package/dist/{chunk-UNJUWWQO.js → chunk-2YCW3QDV.js} +21 -14
- package/dist/chunk-2YCW3QDV.js.map +1 -0
- package/dist/{chunk-Y64XWMJ4.js → chunk-36YQ44D7.js} +2 -2
- package/dist/{chunk-UB2QB6DE.js → chunk-3ASUU6WW.js} +2 -2
- package/dist/{chunk-V5JT5TPD.js → chunk-4GMLGCF2.js} +2 -2
- package/dist/chunk-CDAUYTVP.js +41 -0
- package/dist/chunk-CDAUYTVP.js.map +1 -0
- package/dist/{chunk-Q6ZXJTZB.js → chunk-HUWOFP2H.js} +9 -17
- package/dist/chunk-HUWOFP2H.js.map +1 -0
- package/dist/{chunk-P4SNGQNI.js → chunk-KMMEFXIE.js} +2 -2
- package/dist/{chunk-RKB2ZK6S.js → chunk-LP45RCA4.js} +579 -153
- package/dist/chunk-LP45RCA4.js.map +1 -0
- package/dist/{chunk-L7YNNBI5.js → chunk-QAQDGPB4.js} +1 -75
- package/dist/chunk-QAQDGPB4.js.map +1 -0
- package/dist/{chunk-V2M243KZ.js → chunk-TRXBJEZ5.js} +55 -53
- package/dist/chunk-TRXBJEZ5.js.map +1 -0
- package/dist/{chunk-NBFIBGAT.js → chunk-UMT7RU77.js} +45 -118
- package/dist/chunk-UMT7RU77.js.map +1 -0
- package/dist/{chunk-FQEBWOZR.js → chunk-XIBG7LSL.js} +181 -128
- package/dist/chunk-XIBG7LSL.js.map +1 -0
- package/dist/cli.js +155 -49
- package/dist/cli.js.map +1 -1
- package/dist/{config-editor-HNEKXRLQ.js → config-editor-3IKBPZA7.js} +2 -2
- package/dist/{core-plugins-VEUNFTMB.js → core-plugins-ROU4GPLT.js} +8 -12
- package/dist/{dev-loader-RDC5E2CW.js → dev-loader-DRU3R7ZM.js} +7 -18
- package/dist/dev-loader-DRU3R7ZM.js.map +1 -0
- package/dist/{doctor-H72BZOPA.js → doctor-QZQAP46W.js} +2 -2
- package/dist/index.d.ts +128 -66
- package/dist/index.js +41 -20
- package/dist/index.js.map +1 -1
- package/dist/{integrate-5C6KSU6D.js → integrate-G6CVXTGT.js} +3 -4
- package/dist/integrate-G6CVXTGT.js.map +1 -0
- package/dist/{main-T5WVCCFN.js → main-UVTZ46WP.js} +39 -185
- package/dist/main-UVTZ46WP.js.map +1 -0
- package/dist/plugin-create-5HQRF2ID.js +967 -0
- package/dist/plugin-create-5HQRF2ID.js.map +1 -0
- package/dist/plugin-installer-GQ2P3Q3E.js +23 -0
- package/dist/plugin-installer-GQ2P3Q3E.js.map +1 -0
- package/dist/plugin-search-HQ4WQKOF.js +40 -0
- package/dist/plugin-search-HQ4WQKOF.js.map +1 -0
- package/dist/{post-upgrade-XLHZ6ZB7.js → post-upgrade-3ADZRMYJ.js} +2 -2
- package/dist/registry-client-AVGRE4CF.js +8 -0
- package/dist/{setup-BAI2F24H.js → setup-EYAFK2WI.js} +77 -50
- package/dist/setup-EYAFK2WI.js.map +1 -0
- package/dist/{slack-KH7E3VBS.js → slack-37ZWBDUI.js} +2 -2
- package/dist/{telegram-ZDC3JQF2.js → telegram-2ZCCCZIY.js} +2 -2
- package/dist/{tunnel-M47I7H4B.js → tunnel-45HA72MB.js} +2 -2
- package/dist/{tunnel-service-WADYHREX.js → tunnel-service-QJPUYEKU.js} +11 -3
- package/dist/tunnel-service-QJPUYEKU.js.map +1 -0
- package/package.json +2 -3
- package/dist/action-detect-QPA775HB.js +0 -16
- package/dist/adapter-77ZCVABT.js +0 -2394
- package/dist/adapter-77ZCVABT.js.map +0 -1
- package/dist/admin-GBPZFFAU.js +0 -23
- package/dist/agents-BWU4MRRD.js +0 -15
- package/dist/chunk-2CX4IEEC.js +0 -124
- package/dist/chunk-2CX4IEEC.js.map +0 -1
- package/dist/chunk-4KGLKKQK.js +0 -298
- package/dist/chunk-4KGLKKQK.js.map +0 -1
- package/dist/chunk-5ZOFBTOR.js +0 -553
- package/dist/chunk-5ZOFBTOR.js.map +0 -1
- package/dist/chunk-6RXVEXF3.js +0 -23
- package/dist/chunk-6RXVEXF3.js.map +0 -1
- package/dist/chunk-FQEBWOZR.js.map +0 -1
- package/dist/chunk-GJOY37U7.js +0 -265
- package/dist/chunk-GJOY37U7.js.map +0 -1
- package/dist/chunk-HVBNCPAY.js +0 -71
- package/dist/chunk-HVBNCPAY.js.map +0 -1
- package/dist/chunk-I3CGU5W7.js +0 -134
- package/dist/chunk-I3CGU5W7.js.map +0 -1
- package/dist/chunk-L7YNNBI5.js.map +0 -1
- package/dist/chunk-MTSDOSXS.js +0 -219
- package/dist/chunk-MTSDOSXS.js.map +0 -1
- package/dist/chunk-NAM4ERUW.js +0 -203
- package/dist/chunk-NAM4ERUW.js.map +0 -1
- package/dist/chunk-NBFIBGAT.js.map +0 -1
- package/dist/chunk-O5RG4YZY.js +0 -122
- package/dist/chunk-O5RG4YZY.js.map +0 -1
- package/dist/chunk-Q6ZXJTZB.js.map +0 -1
- package/dist/chunk-QSDZDHNS.js +0 -145
- package/dist/chunk-QSDZDHNS.js.map +0 -1
- package/dist/chunk-RKB2ZK6S.js.map +0 -1
- package/dist/chunk-UNJUWWQO.js.map +0 -1
- package/dist/chunk-V2M243KZ.js.map +0 -1
- package/dist/chunk-WAAD23KY.js +0 -222
- package/dist/chunk-WAAD23KY.js.map +0 -1
- package/dist/chunk-WVLDNYOJ.js +0 -150
- package/dist/chunk-WVLDNYOJ.js.map +0 -1
- package/dist/dev-loader-RDC5E2CW.js.map +0 -1
- package/dist/discord-NOJQ5PZO.js +0 -8
- package/dist/doctor-RF6BHMCC.js +0 -15
- package/dist/doctor-RF6BHMCC.js.map +0 -1
- package/dist/integrate-5C6KSU6D.js.map +0 -1
- package/dist/main-T5WVCCFN.js.map +0 -1
- package/dist/new-session-AVQCNXRG.js +0 -17
- package/dist/new-session-AVQCNXRG.js.map +0 -1
- package/dist/plugin-create-AQ3B22BZ.js +0 -334
- package/dist/plugin-create-AQ3B22BZ.js.map +0 -1
- package/dist/session-KZFA6Z26.js +0 -20
- package/dist/session-KZFA6Z26.js.map +0 -1
- package/dist/settings-MFYM7CZO.js +0 -14
- package/dist/settings-MFYM7CZO.js.map +0 -1
- package/dist/setup-BAI2F24H.js.map +0 -1
- package/dist/slack-KH7E3VBS.js.map +0 -1
- package/dist/telegram-ZDC3JQF2.js.map +0 -1
- package/dist/tunnel-M47I7H4B.js.map +0 -1
- package/dist/tunnel-service-WADYHREX.js.map +0 -1
- package/dist/usage-WYNK6ZC5.js +0 -10
- package/dist/usage-WYNK6ZC5.js.map +0 -1
- package/dist/validators-6CLEZUBD.js +0 -8
- package/dist/validators-6CLEZUBD.js.map +0 -1
- /package/dist/{action-detect-QPA775HB.js.map → adapter-LC2QSDAS.js.map} +0 -0
- /package/dist/{adapter-PQGHVG4K.js.map → adapter-Y55NXX6I.js.map} +0 -0
- /package/dist/{adapter-6ANPBSVU.js.map → api-server-7G3ZUZRM.js.map} +0 -0
- /package/dist/{admin-GBPZFFAU.js.map → api-server-CAYNPUF2.js.map} +0 -0
- /package/dist/{chunk-Y64XWMJ4.js.map → chunk-36YQ44D7.js.map} +0 -0
- /package/dist/{chunk-UB2QB6DE.js.map → chunk-3ASUU6WW.js.map} +0 -0
- /package/dist/{chunk-V5JT5TPD.js.map → chunk-4GMLGCF2.js.map} +0 -0
- /package/dist/{chunk-P4SNGQNI.js.map → chunk-KMMEFXIE.js.map} +0 -0
- /package/dist/{agents-BWU4MRRD.js.map → config-editor-3IKBPZA7.js.map} +0 -0
- /package/dist/{api-server-3PYLRBCN.js.map → core-plugins-ROU4GPLT.js.map} +0 -0
- /package/dist/{api-server-CHVSUDBX.js.map → doctor-QZQAP46W.js.map} +0 -0
- /package/dist/{post-upgrade-XLHZ6ZB7.js.map → post-upgrade-3ADZRMYJ.js.map} +0 -0
- /package/dist/{config-editor-HNEKXRLQ.js.map → registry-client-AVGRE4CF.js.map} +0 -0
- /package/dist/{core-plugins-VEUNFTMB.js.map → slack-37ZWBDUI.js.map} +0 -0
- /package/dist/{discord-NOJQ5PZO.js.map → telegram-2ZCCCZIY.js.map} +0 -0
- /package/dist/{doctor-H72BZOPA.js.map → tunnel-45HA72MB.js.map} +0 -0
|
@@ -208,79 +208,6 @@ var telegramCheck = {
|
|
|
208
208
|
}
|
|
209
209
|
};
|
|
210
210
|
|
|
211
|
-
// src/core/doctor/checks/discord.ts
|
|
212
|
-
var BOT_TOKEN_REGEX2 = /^[A-Za-z0-9_-]{24,28}\.[A-Za-z0-9_-]{6,7}\.[A-Za-z0-9_-]{27,}$/;
|
|
213
|
-
var discordCheck = {
|
|
214
|
-
name: "Discord",
|
|
215
|
-
order: 3.5,
|
|
216
|
-
async run(ctx) {
|
|
217
|
-
const results = [];
|
|
218
|
-
if (!ctx.config) {
|
|
219
|
-
results.push({ status: "fail", message: "Cannot check Discord \u2014 config not loaded" });
|
|
220
|
-
return results;
|
|
221
|
-
}
|
|
222
|
-
const discordConfig = ctx.config.channels.discord;
|
|
223
|
-
if (!discordConfig || !discordConfig.enabled) {
|
|
224
|
-
results.push({ status: "pass", message: "Discord not enabled (skipped)" });
|
|
225
|
-
return results;
|
|
226
|
-
}
|
|
227
|
-
const botToken = discordConfig.botToken;
|
|
228
|
-
if (!botToken || !BOT_TOKEN_REGEX2.test(botToken)) {
|
|
229
|
-
results.push({ status: "fail", message: "Discord bot token format invalid or missing" });
|
|
230
|
-
return results;
|
|
231
|
-
}
|
|
232
|
-
results.push({ status: "pass", message: "Discord bot token format valid" });
|
|
233
|
-
let botUsername;
|
|
234
|
-
try {
|
|
235
|
-
const res = await fetch("https://discord.com/api/v10/users/@me", {
|
|
236
|
-
headers: { Authorization: `Bot ${botToken}` }
|
|
237
|
-
});
|
|
238
|
-
if (res.status === 200) {
|
|
239
|
-
const data = await res.json();
|
|
240
|
-
botUsername = data.username;
|
|
241
|
-
results.push({ status: "pass", message: `Bot token valid (@${data.username}, id: ${data.id})` });
|
|
242
|
-
} else if (res.status === 401) {
|
|
243
|
-
results.push({ status: "fail", message: "Bot token rejected by Discord (401 Unauthorized)" });
|
|
244
|
-
return results;
|
|
245
|
-
} else {
|
|
246
|
-
const text = await res.text();
|
|
247
|
-
results.push({ status: "fail", message: `Discord API error ${res.status}: ${text.slice(0, 100)}` });
|
|
248
|
-
return results;
|
|
249
|
-
}
|
|
250
|
-
} catch (err) {
|
|
251
|
-
results.push({ status: "fail", message: `Cannot reach Discord API: ${err instanceof Error ? err.message : String(err)}` });
|
|
252
|
-
return results;
|
|
253
|
-
}
|
|
254
|
-
const guildId = discordConfig.guildId;
|
|
255
|
-
if (!guildId) {
|
|
256
|
-
results.push({ status: "fail", message: "Guild ID not configured" });
|
|
257
|
-
return results;
|
|
258
|
-
}
|
|
259
|
-
try {
|
|
260
|
-
const res = await fetch(`https://discord.com/api/v10/guilds/${guildId}`, {
|
|
261
|
-
headers: { Authorization: `Bot ${botToken}` }
|
|
262
|
-
});
|
|
263
|
-
if (res.status === 200) {
|
|
264
|
-
const data = await res.json();
|
|
265
|
-
results.push({ status: "pass", message: `Bot has access to guild "${data.name}" (id: ${data.id})` });
|
|
266
|
-
} else if (res.status === 403) {
|
|
267
|
-
results.push({
|
|
268
|
-
status: "fail",
|
|
269
|
-
message: `Bot (${botUsername ?? "unknown"}) is not a member of guild ${guildId} or lacks access. Invite the bot to your server.`
|
|
270
|
-
});
|
|
271
|
-
} else if (res.status === 404) {
|
|
272
|
-
results.push({ status: "fail", message: `Guild ${guildId} not found \u2014 check the guild ID` });
|
|
273
|
-
} else {
|
|
274
|
-
const text = await res.text();
|
|
275
|
-
results.push({ status: "fail", message: `Guild check error ${res.status}: ${text.slice(0, 100)}` });
|
|
276
|
-
}
|
|
277
|
-
} catch (err) {
|
|
278
|
-
results.push({ status: "fail", message: `Cannot validate guild: ${err instanceof Error ? err.message : String(err)}` });
|
|
279
|
-
}
|
|
280
|
-
return results;
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
|
|
284
211
|
// src/core/doctor/checks/storage.ts
|
|
285
212
|
import * as fs3 from "fs";
|
|
286
213
|
var storageCheck = {
|
|
@@ -630,7 +557,6 @@ var ALL_CHECKS = [
|
|
|
630
557
|
configCheck,
|
|
631
558
|
agentsCheck,
|
|
632
559
|
telegramCheck,
|
|
633
|
-
discordCheck,
|
|
634
560
|
storageCheck,
|
|
635
561
|
workspaceCheck,
|
|
636
562
|
pluginsCheck,
|
|
@@ -721,4 +647,4 @@ var DoctorEngine = class {
|
|
|
721
647
|
export {
|
|
722
648
|
DoctorEngine
|
|
723
649
|
};
|
|
724
|
-
//# sourceMappingURL=chunk-
|
|
650
|
+
//# sourceMappingURL=chunk-QAQDGPB4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/doctor/index.ts","../../src/core/doctor/checks/config.ts","../../src/core/doctor/checks/agents.ts","../../src/core/doctor/checks/telegram.ts","../../src/core/doctor/checks/storage.ts","../../src/core/doctor/checks/workspace.ts","../../src/core/doctor/checks/plugins.ts","../../src/core/doctor/checks/daemon.ts","../../src/core/doctor/checks/tunnel.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport type { DoctorCheck, DoctorContext, DoctorReport, CategoryResult, PendingFix, CheckResult } from \"./types.js\";\nimport { ConfigManager, expandHome } from \"../config/config.js\";\n\nimport { configCheck } from \"./checks/config.js\";\nimport { agentsCheck } from \"./checks/agents.js\";\nimport { telegramCheck } from \"./checks/telegram.js\";\nimport { storageCheck } from \"./checks/storage.js\";\nimport { workspaceCheck } from \"./checks/workspace.js\";\nimport { pluginsCheck } from \"./checks/plugins.js\";\nimport { daemonCheck } from \"./checks/daemon.js\";\nimport { tunnelCheck } from \"./checks/tunnel.js\";\n\nconst ALL_CHECKS: DoctorCheck[] = [\n configCheck,\n agentsCheck,\n telegramCheck,\n storageCheck,\n workspaceCheck,\n pluginsCheck,\n daemonCheck,\n tunnelCheck,\n];\n\nconst CHECK_TIMEOUT_MS = 10_000;\n\nexport class DoctorEngine {\n private dryRun: boolean;\n\n constructor(options?: { dryRun?: boolean }) {\n this.dryRun = options?.dryRun ?? false;\n }\n\n async runAll(): Promise<DoctorReport> {\n const ctx = await this.buildContext();\n const checks = [...ALL_CHECKS].sort((a, b) => a.order - b.order);\n\n const categories: CategoryResult[] = [];\n const pendingFixes: PendingFix[] = [];\n const summary = { passed: 0, warnings: 0, failed: 0, fixed: 0 };\n\n for (const check of checks) {\n let results: CheckResult[];\n try {\n results = await Promise.race([\n check.run(ctx),\n new Promise<CheckResult[]>((_, reject) =>\n setTimeout(() => reject(new Error(\"timeout\")), CHECK_TIMEOUT_MS),\n ),\n ]);\n } catch {\n results = [{ status: \"fail\", message: `${check.name} check timed out` }];\n }\n\n for (const result of results) {\n if (result.fixable && result.fix) {\n if (result.fixRisk === \"safe\" && !this.dryRun) {\n try {\n const fixResult = await result.fix();\n if (fixResult.success) {\n result.message += ` → Fixed (${fixResult.message})`;\n result.status = \"warn\";\n delete result.fix;\n summary.fixed++;\n }\n } catch {\n // Fix failed, leave as-is\n }\n } else if (result.fixRisk === \"risky\") {\n pendingFixes.push({\n category: check.name,\n message: result.message,\n fix: result.fix,\n });\n }\n }\n\n if (result.status === \"pass\") summary.passed++;\n else if (result.status === \"warn\") summary.warnings++;\n else if (result.status === \"fail\") summary.failed++;\n }\n\n categories.push({ name: check.name, results });\n }\n\n return { categories, summary, pendingFixes };\n }\n\n private async buildContext(): Promise<DoctorContext> {\n const dataDir = path.join(os.homedir(), \".openacp\");\n const configPath = process.env.OPENACP_CONFIG_PATH || path.join(dataDir, \"config.json\");\n\n let config = null;\n let rawConfig: unknown = null;\n\n try {\n const content = fs.readFileSync(configPath, \"utf-8\");\n rawConfig = JSON.parse(content);\n const cm = new ConfigManager();\n await cm.load();\n config = cm.get();\n } catch {\n // Config may not exist or may be invalid — checks will handle this\n }\n\n const logsDir = config\n ? expandHome(config.logging.logDir)\n : path.join(dataDir, \"logs\");\n\n return {\n config,\n rawConfig,\n configPath,\n dataDir,\n sessionsPath: path.join(dataDir, \"sessions.json\"),\n pidPath: path.join(dataDir, \"openacp.pid\"),\n portFilePath: path.join(dataDir, \"api.port\"),\n pluginsDir: path.join(dataDir, \"plugins\"),\n logsDir,\n };\n }\n}\n\nexport type { DoctorReport, CategoryResult, PendingFix, CheckResult, DoctorContext } from \"./types.js\";\n","import * as fs from \"node:fs\";\nimport { ConfigSchema } from \"../../config/config.js\";\nimport { applyMigrations } from \"../../config/config-migrations.js\";\nimport type { DoctorCheck, CheckResult } from \"../types.js\";\n\nexport const configCheck: DoctorCheck = {\n name: \"Config\",\n order: 1,\n async run(ctx) {\n const results: CheckResult[] = [];\n\n if (!fs.existsSync(ctx.configPath)) {\n results.push({ status: \"fail\", message: \"Config file not found\" });\n return results;\n }\n results.push({ status: \"pass\", message: \"Config file exists\" });\n\n let raw: Record<string, unknown>;\n try {\n raw = JSON.parse(fs.readFileSync(ctx.configPath, \"utf-8\"));\n } catch (err) {\n results.push({\n status: \"fail\",\n message: `Config JSON invalid: ${err instanceof Error ? err.message : String(err)}`,\n });\n return results;\n }\n results.push({ status: \"pass\", message: \"JSON valid\" });\n\n const testRaw = structuredClone(raw);\n const { changed } = applyMigrations(testRaw);\n if (changed) {\n results.push({\n status: \"warn\",\n message: \"Pending config migrations\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n applyMigrations(raw);\n fs.writeFileSync(ctx.configPath, JSON.stringify(raw, null, 2));\n return { success: true, message: \"applied migrations\" };\n },\n });\n }\n\n const result = ConfigSchema.safeParse(raw);\n if (!result.success) {\n for (const issue of result.error.issues) {\n results.push({\n status: \"fail\",\n message: `Validation: ${issue.path.join(\".\")} — ${issue.message}`,\n });\n }\n } else {\n results.push({ status: \"pass\", message: \"Schema valid\" });\n }\n\n return results;\n },\n};\n","import { execFileSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { DoctorCheck, CheckResult } from \"../types.js\";\n\nfunction commandExists(cmd: string): boolean {\n try {\n execFileSync(\"which\", [cmd], { stdio: \"pipe\" });\n return true;\n } catch {\n // not in PATH\n }\n let dir = process.cwd();\n while (true) {\n const binPath = path.join(dir, \"node_modules\", \".bin\", cmd);\n if (fs.existsSync(binPath)) return true;\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return false;\n}\n\nexport const agentsCheck: DoctorCheck = {\n name: \"Agents\",\n order: 2,\n async run(ctx) {\n const results: CheckResult[] = [];\n if (!ctx.config) {\n results.push({ status: \"fail\", message: \"Cannot check agents — config not loaded\" });\n return results;\n }\n\n const agents = ctx.config.agents;\n const defaultAgent = ctx.config.defaultAgent;\n\n if (!agents[defaultAgent]) {\n results.push({\n status: \"fail\",\n message: `Default agent \"${defaultAgent}\" not found in agents config`,\n });\n }\n\n for (const [name, agent] of Object.entries(agents)) {\n const isDefault = name === defaultAgent;\n if (commandExists(agent.command)) {\n results.push({\n status: \"pass\",\n message: `${agent.command} found${isDefault ? \" (default)\" : \"\"}`,\n });\n } else {\n results.push({\n status: isDefault ? \"fail\" : \"warn\",\n message: `${agent.command} not found in PATH${isDefault ? \" (default agent!)\" : \"\"}`,\n });\n }\n }\n\n return results;\n },\n};\n","import type { DoctorCheck, CheckResult } from \"../types.js\";\n\nconst BOT_TOKEN_REGEX = /^\\d+:[A-Za-z0-9_-]{35,}$/;\n\nexport const telegramCheck: DoctorCheck = {\n name: \"Telegram\",\n order: 3,\n async run(ctx) {\n const results: CheckResult[] = [];\n\n if (!ctx.config) {\n results.push({ status: \"fail\", message: \"Cannot check Telegram — config not loaded\" });\n return results;\n }\n\n const tgConfig = ctx.config.channels.telegram as Record<string, unknown> | undefined;\n if (!tgConfig || !tgConfig.enabled) {\n results.push({ status: \"pass\", message: \"Telegram not enabled (skipped)\" });\n return results;\n }\n\n const botToken = tgConfig.botToken as string | undefined;\n const chatId = tgConfig.chatId as number | undefined;\n\n if (!botToken || !BOT_TOKEN_REGEX.test(botToken)) {\n results.push({ status: \"fail\", message: \"Bot token format invalid\" });\n return results;\n }\n results.push({ status: \"pass\", message: \"Bot token format valid\" });\n\n let botId: number | undefined;\n try {\n const res = await fetch(`https://api.telegram.org/bot${botToken}/getMe`);\n const data = (await res.json()) as { ok: boolean; result?: { id: number; username: string }; description?: string };\n if (data.ok && data.result) {\n botId = data.result.id;\n results.push({ status: \"pass\", message: `Bot token valid (@${data.result.username})` });\n } else {\n results.push({ status: \"fail\", message: `Bot token rejected: ${data.description || \"unknown error\"}` });\n return results;\n }\n } catch (err) {\n results.push({ status: \"fail\", message: `Cannot reach Telegram API: ${err instanceof Error ? err.message : String(err)}` });\n return results;\n }\n\n if (!chatId || chatId === 0) {\n results.push({ status: \"fail\", message: \"Chat ID not configured\" });\n return results;\n }\n\n try {\n const res = await fetch(`https://api.telegram.org/bot${botToken}/getChat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ chat_id: chatId }),\n });\n const data = (await res.json()) as {\n ok: boolean;\n result?: { type: string; is_forum?: boolean; title: string };\n description?: string;\n };\n if (!data.ok || !data.result) {\n results.push({ status: \"fail\", message: `Chat ID invalid: ${data.description || \"unknown error\"}` });\n return results;\n }\n if (data.result.type !== \"supergroup\") {\n results.push({ status: \"fail\", message: `Chat is \"${data.result.type}\", must be a supergroup` });\n return results;\n }\n if (!data.result.is_forum) {\n results.push({ status: \"warn\", message: \"Chat does not have topics enabled\" });\n } else {\n results.push({ status: \"pass\", message: `Chat is supergroup with topics (\"${data.result.title}\")` });\n }\n } catch (err) {\n results.push({ status: \"fail\", message: `Cannot validate chat: ${err instanceof Error ? err.message : String(err)}` });\n return results;\n }\n\n try {\n const res = await fetch(`https://api.telegram.org/bot${botToken}/getChatMember`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ chat_id: chatId, user_id: botId }),\n });\n const data = (await res.json()) as { ok: boolean; result?: { status: string }; description?: string };\n if (!data.ok || !data.result) {\n results.push({ status: \"fail\", message: `Cannot check bot membership: ${data.description || \"unknown\"}` });\n } else if (data.result.status === \"administrator\" || data.result.status === \"creator\") {\n results.push({ status: \"pass\", message: \"Bot is admin in group\" });\n } else {\n results.push({\n status: \"fail\",\n message: `Bot is \"${data.result.status}\" — must be admin. Promote bot in group settings.`,\n });\n }\n } catch (err) {\n results.push({ status: \"fail\", message: `Admin check failed: ${err instanceof Error ? err.message : String(err)}` });\n }\n\n return results;\n },\n};\n","import * as fs from \"node:fs\";\nimport type { DoctorCheck, CheckResult } from \"../types.js\";\n\nexport const storageCheck: DoctorCheck = {\n name: \"Storage\",\n order: 4,\n async run(ctx) {\n const results: CheckResult[] = [];\n\n if (!fs.existsSync(ctx.dataDir)) {\n results.push({\n status: \"fail\",\n message: \"Data directory ~/.openacp does not exist\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.mkdirSync(ctx.dataDir, { recursive: true });\n return { success: true, message: \"created directory\" };\n },\n });\n } else {\n try {\n fs.accessSync(ctx.dataDir, fs.constants.W_OK);\n results.push({ status: \"pass\", message: \"Data directory exists and writable\" });\n } catch {\n results.push({ status: \"fail\", message: \"Data directory not writable\" });\n }\n }\n\n if (fs.existsSync(ctx.sessionsPath)) {\n try {\n const content = fs.readFileSync(ctx.sessionsPath, \"utf-8\");\n const data = JSON.parse(content);\n if (typeof data === \"object\" && data !== null && \"sessions\" in data) {\n results.push({ status: \"pass\", message: \"Sessions file valid\" });\n } else {\n results.push({\n status: \"fail\",\n message: \"Sessions file has invalid structure\",\n fixable: true,\n fixRisk: \"risky\",\n fix: async () => {\n fs.writeFileSync(ctx.sessionsPath, JSON.stringify({ version: 1, sessions: {} }, null, 2));\n return { success: true, message: \"reset sessions file\" };\n },\n });\n }\n } catch {\n results.push({\n status: \"fail\",\n message: \"Sessions file corrupt (invalid JSON)\",\n fixable: true,\n fixRisk: \"risky\",\n fix: async () => {\n fs.writeFileSync(ctx.sessionsPath, JSON.stringify({ version: 1, sessions: {} }, null, 2));\n return { success: true, message: \"reset sessions file\" };\n },\n });\n }\n } else {\n results.push({ status: \"pass\", message: \"Sessions file not present yet (created on first session)\" });\n }\n\n if (!fs.existsSync(ctx.logsDir)) {\n results.push({\n status: \"warn\",\n message: \"Log directory does not exist\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.mkdirSync(ctx.logsDir, { recursive: true });\n return { success: true, message: \"created log directory\" };\n },\n });\n } else {\n try {\n fs.accessSync(ctx.logsDir, fs.constants.W_OK);\n results.push({ status: \"pass\", message: \"Log directory exists and writable\" });\n } catch {\n results.push({ status: \"fail\", message: \"Log directory not writable\" });\n }\n }\n\n return results;\n },\n};\n","import * as fs from \"node:fs\";\nimport { expandHome } from \"../../config/config.js\";\nimport type { DoctorCheck, CheckResult } from \"../types.js\";\n\nexport const workspaceCheck: DoctorCheck = {\n name: \"Workspace\",\n order: 5,\n async run(ctx) {\n const results: CheckResult[] = [];\n\n if (!ctx.config) {\n results.push({ status: \"fail\", message: \"Cannot check workspace — config not loaded\" });\n return results;\n }\n\n const baseDir = expandHome(ctx.config.workspace.baseDir);\n\n if (!fs.existsSync(baseDir)) {\n results.push({\n status: \"warn\",\n message: `Workspace directory does not exist: ${baseDir}`,\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.mkdirSync(baseDir, { recursive: true });\n return { success: true, message: \"created directory\" };\n },\n });\n } else {\n try {\n fs.accessSync(baseDir, fs.constants.W_OK);\n results.push({ status: \"pass\", message: `Workspace directory exists: ${baseDir}` });\n } catch {\n results.push({ status: \"fail\", message: `Workspace directory not writable: ${baseDir}` });\n }\n }\n\n return results;\n },\n};\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { DoctorCheck, CheckResult } from \"../types.js\";\n\nexport const pluginsCheck: DoctorCheck = {\n name: \"Plugins\",\n order: 6,\n async run(ctx) {\n const results: CheckResult[] = [];\n\n if (!fs.existsSync(ctx.pluginsDir)) {\n results.push({\n status: \"warn\",\n message: \"Plugins directory does not exist\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.mkdirSync(ctx.pluginsDir, { recursive: true });\n fs.writeFileSync(\n path.join(ctx.pluginsDir, \"package.json\"),\n JSON.stringify({ name: \"openacp-plugins\", private: true, dependencies: {} }, null, 2),\n );\n return { success: true, message: \"initialized plugins directory\" };\n },\n });\n return results;\n }\n results.push({ status: \"pass\", message: \"Plugins directory exists\" });\n\n const pkgPath = path.join(ctx.pluginsDir, \"package.json\");\n if (!fs.existsSync(pkgPath)) {\n results.push({\n status: \"warn\",\n message: \"Plugins package.json missing\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.writeFileSync(\n pkgPath,\n JSON.stringify({ name: \"openacp-plugins\", private: true, dependencies: {} }, null, 2),\n );\n return { success: true, message: \"created package.json\" };\n },\n });\n return results;\n }\n\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n const deps = pkg.dependencies || {};\n const count = Object.keys(deps).length;\n results.push({ status: \"pass\", message: `Plugins package.json valid (${count} plugins)` });\n } catch {\n results.push({\n status: \"fail\",\n message: \"Plugins package.json is invalid JSON\",\n fixable: true,\n fixRisk: \"risky\",\n fix: async () => {\n fs.writeFileSync(\n pkgPath,\n JSON.stringify({ name: \"openacp-plugins\", private: true, dependencies: {} }, null, 2),\n );\n return { success: true, message: \"reset package.json\" };\n },\n });\n }\n\n return results;\n },\n};\n","import * as fs from \"node:fs\";\nimport * as net from \"node:net\";\nimport type { DoctorCheck, CheckResult } from \"../types.js\";\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction checkPortInUse(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = net.createServer();\n server.once(\"error\", () => resolve(true));\n server.once(\"listening\", () => {\n server.close();\n resolve(false);\n });\n server.listen(port, \"127.0.0.1\");\n });\n}\n\nexport const daemonCheck: DoctorCheck = {\n name: \"Daemon\",\n order: 7,\n async run(ctx) {\n const results: CheckResult[] = [];\n\n if (fs.existsSync(ctx.pidPath)) {\n const content = fs.readFileSync(ctx.pidPath, \"utf-8\").trim();\n const pid = parseInt(content, 10);\n if (isNaN(pid)) {\n results.push({\n status: \"warn\",\n message: \"PID file contains invalid data\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.unlinkSync(ctx.pidPath);\n return { success: true, message: \"removed invalid PID file\" };\n },\n });\n } else if (!isProcessAlive(pid)) {\n results.push({\n status: \"warn\",\n message: `Stale PID file (PID ${pid} not running)`,\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.unlinkSync(ctx.pidPath);\n return { success: true, message: \"removed stale PID file\" };\n },\n });\n } else {\n results.push({ status: \"pass\", message: `Daemon running (PID ${pid})` });\n }\n }\n\n if (fs.existsSync(ctx.portFilePath)) {\n const content = fs.readFileSync(ctx.portFilePath, \"utf-8\").trim();\n const port = parseInt(content, 10);\n if (isNaN(port)) {\n results.push({\n status: \"warn\",\n message: \"Port file contains invalid data\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.unlinkSync(ctx.portFilePath);\n return { success: true, message: \"removed invalid port file\" };\n },\n });\n } else {\n results.push({ status: \"pass\", message: `Port file valid (port ${port})` });\n }\n }\n\n if (ctx.config) {\n const apiPort = ctx.config.api.port;\n const inUse = await checkPortInUse(apiPort);\n if (inUse) {\n if (fs.existsSync(ctx.pidPath)) {\n const pid = parseInt(fs.readFileSync(ctx.pidPath, \"utf-8\").trim(), 10);\n if (!isNaN(pid) && isProcessAlive(pid)) {\n results.push({ status: \"pass\", message: `API port ${apiPort} in use by OpenACP daemon` });\n } else {\n results.push({ status: \"warn\", message: `API port ${apiPort} in use by another process` });\n }\n } else {\n results.push({ status: \"warn\", message: `API port ${apiPort} in use by another process` });\n }\n } else {\n results.push({ status: \"pass\", message: `API port ${apiPort} available` });\n }\n }\n\n return results;\n },\n};\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { execFileSync } from \"node:child_process\";\nimport type { DoctorCheck, CheckResult } from \"../types.js\";\n\nconst BIN_DIR = path.join(os.homedir(), \".openacp\", \"bin\");\nconst BIN_NAME = os.platform() === \"win32\" ? \"cloudflared.exe\" : \"cloudflared\";\nconst BIN_PATH = path.join(BIN_DIR, BIN_NAME);\n\nexport const tunnelCheck: DoctorCheck = {\n name: \"Tunnel\",\n order: 8,\n async run(ctx) {\n const results: CheckResult[] = [];\n\n if (!ctx.config) {\n results.push({ status: \"fail\", message: \"Cannot check tunnel — config not loaded\" });\n return results;\n }\n\n if (!ctx.config.tunnel.enabled) {\n results.push({ status: \"pass\", message: \"Tunnel not enabled (skipped)\" });\n return results;\n }\n\n const provider = ctx.config.tunnel.provider;\n results.push({ status: \"pass\", message: `Tunnel provider: ${provider}` });\n\n if (provider === \"cloudflare\") {\n let found = false;\n if (fs.existsSync(BIN_PATH)) {\n found = true;\n } else {\n try {\n execFileSync(\"which\", [\"cloudflared\"], { stdio: \"pipe\" });\n found = true;\n } catch {\n // not found\n }\n }\n\n if (found) {\n results.push({ status: \"pass\", message: \"cloudflared binary found\" });\n } else {\n results.push({\n status: \"warn\",\n message: \"cloudflared binary not found\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n try {\n const { ensureCloudflared } = await import(\"../../../plugins/tunnel/providers/install-cloudflared.js\");\n await ensureCloudflared();\n return { success: true, message: \"installed cloudflared\" };\n } catch (err) {\n return { success: false, message: err instanceof Error ? err.message : String(err) };\n }\n },\n });\n }\n }\n\n const tunnelPort = ctx.config.tunnel.port;\n if (tunnelPort < 1 || tunnelPort > 65535) {\n results.push({ status: \"fail\", message: `Invalid tunnel port: ${tunnelPort}` });\n } else {\n results.push({ status: \"pass\", message: `Tunnel port: ${tunnelPort}` });\n }\n\n return results;\n },\n};\n"],"mappings":"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","names":["fs","path","os","fs","fs","fs","fs","path","fs","fs","path","execFileSync"]}
|
|
@@ -1,3 +1,55 @@
|
|
|
1
|
+
// src/core/adapter-primitives/format-utils.ts
|
|
2
|
+
function progressBar(ratio, length = 10) {
|
|
3
|
+
const filled = Math.round(Math.min(ratio, 1) * length);
|
|
4
|
+
return "\u2593".repeat(filled) + "\u2591".repeat(length - filled);
|
|
5
|
+
}
|
|
6
|
+
function formatTokens(n) {
|
|
7
|
+
return n >= 1e3 ? `${Math.round(n / 1e3)}k` : String(n);
|
|
8
|
+
}
|
|
9
|
+
function stripCodeFences(text) {
|
|
10
|
+
return text.replace(/```\w*\n?/g, "").replace(/```$/gm, "").trim();
|
|
11
|
+
}
|
|
12
|
+
function truncateContent(text, maxLen) {
|
|
13
|
+
if (text.length <= maxLen) return text;
|
|
14
|
+
return text.slice(0, maxLen) + "\n\u2026 (truncated)";
|
|
15
|
+
}
|
|
16
|
+
function splitMessage(text, maxLength) {
|
|
17
|
+
if (text.length <= maxLength) return [text];
|
|
18
|
+
const chunks = [];
|
|
19
|
+
let remaining = text;
|
|
20
|
+
while (remaining.length > 0) {
|
|
21
|
+
if (remaining.length <= maxLength) {
|
|
22
|
+
chunks.push(remaining);
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
const wouldLeaveSmall = remaining.length < maxLength * 1.3;
|
|
26
|
+
const searchLimit = wouldLeaveSmall ? Math.floor(remaining.length / 2) + 300 : maxLength;
|
|
27
|
+
const threshold = maxLength * 0.2;
|
|
28
|
+
let splitAt = remaining.lastIndexOf("\n\n", searchLimit);
|
|
29
|
+
if (splitAt === -1 || splitAt < threshold) {
|
|
30
|
+
splitAt = remaining.lastIndexOf("\n", searchLimit);
|
|
31
|
+
}
|
|
32
|
+
if (splitAt === -1 || splitAt < threshold) {
|
|
33
|
+
splitAt = searchLimit;
|
|
34
|
+
}
|
|
35
|
+
const candidate = remaining.slice(0, splitAt);
|
|
36
|
+
const fences = candidate.match(/```/g);
|
|
37
|
+
if (fences && fences.length % 2 !== 0) {
|
|
38
|
+
const closingFence = remaining.indexOf("```", splitAt);
|
|
39
|
+
if (closingFence !== -1) {
|
|
40
|
+
const afterFence = remaining.indexOf("\n", closingFence + 3);
|
|
41
|
+
const fenceSplit = afterFence !== -1 ? afterFence + 1 : closingFence + 3;
|
|
42
|
+
if (fenceSplit <= maxLength * 2) {
|
|
43
|
+
splitAt = fenceSplit;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
chunks.push(remaining.slice(0, splitAt));
|
|
48
|
+
remaining = remaining.slice(splitAt).replace(/^\n+/, "");
|
|
49
|
+
}
|
|
50
|
+
return chunks;
|
|
51
|
+
}
|
|
52
|
+
|
|
1
53
|
// src/core/adapter-primitives/format-types.ts
|
|
2
54
|
var STATUS_ICONS = {
|
|
3
55
|
pending: "\u23F3",
|
|
@@ -280,58 +332,6 @@ var MessagingAdapter = class {
|
|
|
280
332
|
}
|
|
281
333
|
};
|
|
282
334
|
|
|
283
|
-
// src/core/adapter-primitives/format-utils.ts
|
|
284
|
-
function progressBar(ratio, length = 10) {
|
|
285
|
-
const filled = Math.round(Math.min(ratio, 1) * length);
|
|
286
|
-
return "\u2593".repeat(filled) + "\u2591".repeat(length - filled);
|
|
287
|
-
}
|
|
288
|
-
function formatTokens(n) {
|
|
289
|
-
return n >= 1e3 ? `${Math.round(n / 1e3)}k` : String(n);
|
|
290
|
-
}
|
|
291
|
-
function stripCodeFences(text) {
|
|
292
|
-
return text.replace(/```\w*\n?/g, "").replace(/```$/gm, "").trim();
|
|
293
|
-
}
|
|
294
|
-
function truncateContent(text, maxLen) {
|
|
295
|
-
if (text.length <= maxLen) return text;
|
|
296
|
-
return text.slice(0, maxLen) + "\n\u2026 (truncated)";
|
|
297
|
-
}
|
|
298
|
-
function splitMessage(text, maxLength) {
|
|
299
|
-
if (text.length <= maxLength) return [text];
|
|
300
|
-
const chunks = [];
|
|
301
|
-
let remaining = text;
|
|
302
|
-
while (remaining.length > 0) {
|
|
303
|
-
if (remaining.length <= maxLength) {
|
|
304
|
-
chunks.push(remaining);
|
|
305
|
-
break;
|
|
306
|
-
}
|
|
307
|
-
const wouldLeaveSmall = remaining.length < maxLength * 1.3;
|
|
308
|
-
const searchLimit = wouldLeaveSmall ? Math.floor(remaining.length / 2) + 300 : maxLength;
|
|
309
|
-
const threshold = maxLength * 0.2;
|
|
310
|
-
let splitAt = remaining.lastIndexOf("\n\n", searchLimit);
|
|
311
|
-
if (splitAt === -1 || splitAt < threshold) {
|
|
312
|
-
splitAt = remaining.lastIndexOf("\n", searchLimit);
|
|
313
|
-
}
|
|
314
|
-
if (splitAt === -1 || splitAt < threshold) {
|
|
315
|
-
splitAt = searchLimit;
|
|
316
|
-
}
|
|
317
|
-
const candidate = remaining.slice(0, splitAt);
|
|
318
|
-
const fences = candidate.match(/```/g);
|
|
319
|
-
if (fences && fences.length % 2 !== 0) {
|
|
320
|
-
const closingFence = remaining.indexOf("```", splitAt);
|
|
321
|
-
if (closingFence !== -1) {
|
|
322
|
-
const afterFence = remaining.indexOf("\n", closingFence + 3);
|
|
323
|
-
const fenceSplit = afterFence !== -1 ? afterFence + 1 : closingFence + 3;
|
|
324
|
-
if (fenceSplit <= maxLength * 2) {
|
|
325
|
-
splitAt = fenceSplit;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
chunks.push(remaining.slice(0, splitAt));
|
|
330
|
-
remaining = remaining.slice(splitAt).replace(/^\n+/, "");
|
|
331
|
-
}
|
|
332
|
-
return chunks;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
335
|
// src/core/adapter-primitives/rendering/renderer.ts
|
|
336
336
|
var BaseRenderer = class {
|
|
337
337
|
renderText(content) {
|
|
@@ -435,6 +435,8 @@ export {
|
|
|
435
435
|
stripCodeFences,
|
|
436
436
|
truncateContent,
|
|
437
437
|
splitMessage,
|
|
438
|
+
STATUS_ICONS,
|
|
439
|
+
KIND_ICONS,
|
|
438
440
|
extractContentText,
|
|
439
441
|
formatToolSummary,
|
|
440
442
|
formatToolTitle,
|
|
@@ -442,4 +444,4 @@ export {
|
|
|
442
444
|
MessagingAdapter,
|
|
443
445
|
BaseRenderer
|
|
444
446
|
};
|
|
445
|
-
//# sourceMappingURL=chunk-
|
|
447
|
+
//# sourceMappingURL=chunk-TRXBJEZ5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/adapter-primitives/format-utils.ts","../../src/core/adapter-primitives/format-types.ts","../../src/core/adapter-primitives/message-formatter.ts","../../src/core/adapter-primitives/messaging-adapter.ts","../../src/core/adapter-primitives/rendering/renderer.ts"],"sourcesContent":["export function progressBar(ratio: number, length = 10): string {\n const filled = Math.round(Math.min(ratio, 1) * length);\n return \"▓\".repeat(filled) + \"░\".repeat(length - filled);\n}\n\nexport function formatTokens(n: number): string {\n return n >= 1000 ? `${Math.round(n / 1000)}k` : String(n);\n}\n\nexport function stripCodeFences(text: string): string {\n return text\n .replace(/```\\w*\\n?/g, \"\")\n .replace(/```$/gm, \"\")\n .trim();\n}\n\nexport function truncateContent(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + \"\\n… (truncated)\";\n}\n\nexport function splitMessage(text: string, maxLength: number): string[] {\n if (text.length <= maxLength) return [text];\n const chunks: string[] = [];\n let remaining = text;\n while (remaining.length > 0) {\n if (remaining.length <= maxLength) {\n chunks.push(remaining);\n break;\n }\n\n const wouldLeaveSmall = remaining.length < maxLength * 1.3;\n const searchLimit = wouldLeaveSmall\n ? Math.floor(remaining.length / 2) + 300\n : maxLength;\n\n const threshold = maxLength * 0.2;\n let splitAt = remaining.lastIndexOf(\"\\n\\n\", searchLimit);\n if (splitAt === -1 || splitAt < threshold) {\n splitAt = remaining.lastIndexOf(\"\\n\", searchLimit);\n }\n if (splitAt === -1 || splitAt < threshold) {\n splitAt = searchLimit;\n }\n\n const candidate = remaining.slice(0, splitAt);\n const fences = candidate.match(/```/g);\n if (fences && fences.length % 2 !== 0) {\n const closingFence = remaining.indexOf(\"```\", splitAt);\n if (closingFence !== -1) {\n const afterFence = remaining.indexOf(\"\\n\", closingFence + 3);\n const fenceSplit =\n afterFence !== -1 ? afterFence + 1 : closingFence + 3;\n // Only extend to include the closing fence if it doesn't exceed 2x maxLength\n if (fenceSplit <= maxLength * 2) {\n splitAt = fenceSplit;\n }\n }\n }\n\n chunks.push(remaining.slice(0, splitAt));\n remaining = remaining.slice(splitAt).replace(/^\\n+/, \"\");\n }\n return chunks;\n}\n","// src/adapters/shared/format-types.ts\n\nexport type DisplayVerbosity = \"low\" | \"medium\" | \"high\";\n\nexport type NoiseAction = \"hide\" | \"collapse\";\n\nexport interface NoiseRule {\n match: (name: string, kind: string, rawInput: unknown) => boolean;\n action: NoiseAction;\n}\n\nexport type MessageStyle =\n | \"text\"\n | \"thought\"\n | \"tool\"\n | \"plan\"\n | \"usage\"\n | \"system\"\n | \"error\"\n | \"attachment\";\n\nexport interface MessageMetadata {\n toolName?: string;\n toolStatus?: string;\n toolKind?: string;\n filePath?: string;\n command?: string;\n planEntries?: { content: string; status: string }[];\n tokens?: number;\n contextSize?: number;\n cost?: number;\n viewerLinks?: ViewerLinks;\n viewerFilePath?: string;\n}\n\n/** summary and detail are always plain text (never pre-escaped HTML/markdown) — renderers handle escaping */\nexport interface FormattedMessage {\n summary: string;\n detail?: string;\n viewerLinks?: ViewerLinks;\n icon: string;\n originalType: string;\n style: MessageStyle;\n metadata?: MessageMetadata;\n}\n\nexport const STATUS_ICONS: Record<string, string> = {\n pending: \"⏳\",\n in_progress: \"🔄\",\n completed: \"✅\",\n failed: \"❌\",\n cancelled: \"🚫\",\n running: \"🔄\",\n done: \"✅\",\n error: \"❌\",\n};\n\nexport const KIND_ICONS: Record<string, string> = {\n read: \"📖\",\n edit: \"✏️\",\n write: \"✏️\",\n delete: \"🗑️\",\n execute: \"▶️\",\n command: \"▶️\",\n bash: \"▶️\",\n search: \"🔍\",\n web: \"🌐\",\n fetch: \"🌐\",\n agent: \"🧠\",\n think: \"🧠\",\n install: \"📦\",\n move: \"📦\",\n other: \"🛠️\",\n};\n\nexport interface ViewerLinks {\n file?: string;\n diff?: string;\n}\n\nexport interface ToolCallMeta {\n id: string;\n name: string;\n kind?: string;\n status?: string;\n content?: unknown;\n rawInput?: unknown;\n viewerLinks?: ViewerLinks;\n viewerFilePath?: string;\n displaySummary?: string;\n displayTitle?: string;\n displayKind?: string;\n}\n\nexport interface ToolUpdateMeta extends ToolCallMeta {\n status: string;\n}\n","import type { NoiseAction, NoiseRule } from \"./format-types.js\";\nimport { STATUS_ICONS, KIND_ICONS } from \"./format-types.js\";\n\nexport function extractContentText(content: unknown, depth = 0): string {\n if (!content || depth > 5) return \"\";\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return content\n .map((c) => extractContentText(c, depth + 1))\n .filter(Boolean)\n .join(\"\\n\");\n }\n if (typeof content !== \"object\") return String(content);\n\n const obj = content as Record<string, unknown>;\n if (obj.text && typeof obj.text === \"string\") return obj.text;\n if (obj.content) {\n if (typeof obj.content === \"string\") return obj.content;\n if (Array.isArray(obj.content)) {\n return obj.content\n .map((c) => extractContentText(c, depth + 1))\n .filter(Boolean)\n .join(\"\\n\");\n }\n return extractContentText(obj.content, depth + 1);\n }\n if (obj.input) return extractContentText(obj.input, depth + 1);\n if (obj.output) return extractContentText(obj.output, depth + 1);\n\n // Skip objects with only a 'type' key and no content fields\n const keys = Object.keys(obj).filter((k) => k !== \"type\");\n if (keys.length === 0) return \"\";\n\n // Fallback: serialize unrecognized objects so edge-case agent responses are not silently dropped\n try {\n return JSON.stringify(obj, null, 2);\n } catch {\n return \"\";\n }\n}\n\nfunction parseRawInput(rawInput: unknown): Record<string, unknown> {\n try {\n if (typeof rawInput === \"string\") {\n return JSON.parse(rawInput) as Record<string, unknown>;\n }\n if (typeof rawInput === \"object\" && rawInput !== null) {\n return rawInput as Record<string, unknown>;\n }\n } catch {\n // fall through\n }\n return {};\n}\n\n// --- Step 5: formatToolSummary with displaySummary override ---\n\nexport function formatToolSummary(\n name: string,\n rawInput: unknown,\n displaySummary?: string,\n): string {\n if (displaySummary && typeof displaySummary === \"string\") {\n return displaySummary;\n }\n\n const args = parseRawInput(rawInput);\n const lowerName = name.toLowerCase();\n\n if (lowerName === \"read\") {\n const fp = args.file_path ?? args.filePath ?? \"\";\n const limit = args.limit ? ` (${args.limit} lines)` : \"\";\n return fp ? `📖 Read ${fp}${limit}` : `🔧 ${name}`;\n }\n if (lowerName === \"edit\") {\n const fp = args.file_path ?? args.filePath ?? \"\";\n return fp ? `✏️ Edit ${fp}` : `🔧 ${name}`;\n }\n if (lowerName === \"write\") {\n const fp = args.file_path ?? args.filePath ?? \"\";\n return fp ? `📝 Write ${fp}` : `🔧 ${name}`;\n }\n if (lowerName === \"bash\") {\n const cmd = String(args.command ?? \"\").slice(0, 60);\n return cmd ? `▶️ Run: ${cmd}` : `🔧 ${name}`;\n }\n if (lowerName === \"grep\") {\n const pattern = args.pattern ?? \"\";\n const path = args.path ?? \"\";\n return pattern\n ? `🔍 Grep \"${pattern}\"${path ? ` in ${path}` : \"\"}`\n : `🔧 ${name}`;\n }\n if (lowerName === \"glob\") {\n const pattern = args.pattern ?? \"\";\n return pattern ? `🔍 Glob ${pattern}` : `🔧 ${name}`;\n }\n if (lowerName === \"agent\") {\n const desc = String(args.description ?? \"\").slice(0, 60);\n return desc ? `🧠 Agent: ${desc}` : `🔧 ${name}`;\n }\n if (lowerName === \"webfetch\" || lowerName === \"web_fetch\") {\n const url = String(args.url ?? \"\").slice(0, 60);\n return url ? `🌐 Fetch ${url}` : `🔧 ${name}`;\n }\n if (lowerName === \"websearch\" || lowerName === \"web_search\") {\n const query = String(args.query ?? \"\").slice(0, 60);\n return query ? `🌐 Search \"${query}\"` : `🔧 ${name}`;\n }\n\n return `🔧 ${name}`;\n}\n\n// --- Step 6: formatToolTitle for low verbosity ---\n\nexport function formatToolTitle(\n name: string,\n rawInput: unknown,\n displayTitle?: string,\n): string {\n if (displayTitle && typeof displayTitle === \"string\") {\n return displayTitle;\n }\n\n const args = parseRawInput(rawInput);\n const lowerName = name.toLowerCase();\n\n if ([\"read\", \"edit\", \"write\"].includes(lowerName)) {\n return String(args.file_path ?? args.filePath ?? name);\n }\n if (lowerName === \"bash\") {\n return String(args.command ?? name).slice(0, 60);\n }\n if (lowerName === \"grep\") {\n const pattern = args.pattern ?? \"\";\n const path = args.path ?? \"\";\n return pattern ? `\"${pattern}\"${path ? ` in ${path}` : \"\"}` : name;\n }\n if (lowerName === \"glob\") {\n return String(args.pattern ?? name);\n }\n if (lowerName === \"agent\") {\n return String(args.description ?? name).slice(0, 60);\n }\n if ([\"webfetch\", \"web_fetch\"].includes(lowerName)) {\n return String(args.url ?? name).slice(0, 60);\n }\n if ([\"websearch\", \"web_search\"].includes(lowerName)) {\n return String(args.query ?? name).slice(0, 60);\n }\n\n return name;\n}\n\n// --- Step 7: resolveToolIcon ---\n\nexport function resolveToolIcon(tool: {\n status?: string;\n displayKind?: string;\n kind?: string;\n}): string {\n const statusIcon = STATUS_ICONS[tool.status || \"\"];\n if (statusIcon) return statusIcon;\n const kind = tool.displayKind ?? tool.kind;\n if (kind && KIND_ICONS[kind]) return KIND_ICONS[kind];\n return \"🔧\";\n}\n\n// --- Step 8: Noise filtering ---\n\nconst NOISE_RULES: NoiseRule[] = [\n {\n match: (name) => name.toLowerCase() === \"ls\",\n action: \"hide\",\n },\n {\n match: (_name, kind, rawInput) => {\n if (kind !== \"read\") return false;\n const args = parseRawInput(rawInput);\n const p = String(args.file_path ?? args.filePath ?? args.path ?? \"\");\n return p.endsWith(\"/\");\n },\n action: \"hide\",\n },\n {\n match: (name) => name.toLowerCase() === \"glob\",\n action: \"collapse\",\n },\n];\n\nexport function evaluateNoise(\n name: string,\n kind: string,\n rawInput: unknown,\n): NoiseAction | null {\n for (const rule of NOISE_RULES) {\n if (rule.match(name, kind, rawInput)) return rule.action;\n }\n return null;\n}\n","import type {\n IChannelAdapter,\n ChannelConfig,\n AdapterCapabilities,\n} from '../channel.js'\nimport type {\n OutgoingMessage,\n PermissionRequest,\n NotificationMessage,\n} from '../types.js'\nimport type { DisplayVerbosity, ToolCallMeta } from './format-types.js'\nimport type { IRenderer } from './rendering/renderer.js'\nimport { evaluateNoise } from './message-formatter.js'\n\nexport interface AdapterContext {\n configManager: { get(): Record<string, unknown> }\n fileService?: unknown\n}\n\nexport interface MessagingAdapterConfig extends ChannelConfig {\n maxMessageLength: number\n flushInterval?: number\n sendInterval?: number\n thinkingRefreshInterval?: number\n thinkingDuration?: number\n displayVerbosity?: DisplayVerbosity\n}\n\nexport interface SentMessage {\n messageId: string\n}\n\nconst HIDDEN_ON_LOW = new Set(['thought', 'plan', 'usage'])\n\nexport abstract class MessagingAdapter implements IChannelAdapter {\n abstract readonly name: string\n abstract readonly renderer: IRenderer\n abstract readonly capabilities: AdapterCapabilities\n\n constructor(\n protected context: AdapterContext,\n protected adapterConfig: MessagingAdapterConfig,\n ) {}\n\n // === Message dispatch flow ===\n\n async sendMessage(sessionId: string, content: OutgoingMessage): Promise<void> {\n const verbosity = this.getVerbosity()\n if (!this.shouldDisplay(content, verbosity)) return\n await this.dispatchMessage(sessionId, content, verbosity)\n }\n\n protected async dispatchMessage(\n sessionId: string,\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): Promise<void> {\n switch (content.type) {\n case 'text': return this.handleText(sessionId, content)\n case 'thought': return this.handleThought(sessionId, content, verbosity)\n case 'tool_call': return this.handleToolCall(sessionId, content, verbosity)\n case 'tool_update': return this.handleToolUpdate(sessionId, content, verbosity)\n case 'plan': return this.handlePlan(sessionId, content, verbosity)\n case 'usage': return this.handleUsage(sessionId, content, verbosity)\n case 'error': return this.handleError(sessionId, content)\n case 'attachment': return this.handleAttachment(sessionId, content)\n case 'system_message': return this.handleSystem(sessionId, content)\n case 'session_end': return this.handleSessionEnd(sessionId, content)\n case 'mode_change': return this.handleModeChange(sessionId, content)\n case 'config_update': return this.handleConfigUpdate(sessionId, content)\n case 'model_update': return this.handleModelUpdate(sessionId, content)\n case 'user_replay': return this.handleUserReplay(sessionId, content)\n case 'resource': return this.handleResource(sessionId, content)\n case 'resource_link': return this.handleResourceLink(sessionId, content)\n }\n }\n\n // === Default handlers — all protected, all overridable ===\n\n protected async handleText(_sessionId: string, _content: OutgoingMessage): Promise<void> {}\n protected async handleThought(_sessionId: string, _content: OutgoingMessage, _verbosity: DisplayVerbosity): Promise<void> {}\n protected async handleToolCall(_sessionId: string, _content: OutgoingMessage, _verbosity: DisplayVerbosity): Promise<void> {}\n protected async handleToolUpdate(_sessionId: string, _content: OutgoingMessage, _verbosity: DisplayVerbosity): Promise<void> {}\n protected async handlePlan(_sessionId: string, _content: OutgoingMessage, _verbosity: DisplayVerbosity): Promise<void> {}\n protected async handleUsage(_sessionId: string, _content: OutgoingMessage, _verbosity: DisplayVerbosity): Promise<void> {}\n protected async handleError(_sessionId: string, _content: OutgoingMessage): Promise<void> {}\n protected async handleAttachment(_sessionId: string, _content: OutgoingMessage): Promise<void> {}\n protected async handleSystem(_sessionId: string, _content: OutgoingMessage): Promise<void> {}\n protected async handleSessionEnd(_sessionId: string, _content: OutgoingMessage): Promise<void> {}\n protected async handleModeChange(_sessionId: string, _content: OutgoingMessage): Promise<void> {}\n protected async handleConfigUpdate(_sessionId: string, _content: OutgoingMessage): Promise<void> {}\n protected async handleModelUpdate(_sessionId: string, _content: OutgoingMessage): Promise<void> {}\n protected async handleUserReplay(_sessionId: string, _content: OutgoingMessage): Promise<void> {}\n protected async handleResource(_sessionId: string, _content: OutgoingMessage): Promise<void> {}\n protected async handleResourceLink(_sessionId: string, _content: OutgoingMessage): Promise<void> {}\n\n // === Helpers ===\n\n protected getVerbosity(): DisplayVerbosity {\n const config = this.context.configManager.get()\n const channelConfig = (config as Record<string, unknown>).channels as Record<string, Record<string, unknown>> | undefined\n const v = channelConfig?.[this.name]?.displayVerbosity ?? this.adapterConfig.displayVerbosity\n if (v === 'low' || v === 'high') return v\n return 'medium'\n }\n\n protected shouldDisplay(content: OutgoingMessage, verbosity: DisplayVerbosity): boolean {\n if (verbosity === 'low' && HIDDEN_ON_LOW.has(content.type)) return false\n\n if (content.type === 'tool_call') {\n const meta = (content.metadata ?? {}) as Partial<ToolCallMeta>\n const toolName = meta.name ?? content.text ?? ''\n const toolKind = String(meta.kind ?? 'other')\n const noiseAction = evaluateNoise(toolName, toolKind, meta.rawInput)\n if (noiseAction === 'hide' && verbosity !== 'high') return false\n if (noiseAction === 'collapse' && verbosity === 'low') return false\n }\n\n return true\n }\n\n // === Abstract — adapter MUST implement ===\n\n abstract start(): Promise<void>\n abstract stop(): Promise<void>\n abstract createSessionThread(sessionId: string, name: string): Promise<string>\n abstract renameSessionThread(sessionId: string, newName: string): Promise<void>\n abstract sendPermissionRequest(sessionId: string, request: PermissionRequest): Promise<void>\n abstract sendNotification(notification: NotificationMessage): Promise<void>\n}\n","import type { OutgoingMessage, PermissionRequest, NotificationMessage } from '../../types.js'\nimport type { DisplayVerbosity, ToolCallMeta, ToolUpdateMeta } from '../format-types.js'\nimport {\n formatToolSummary,\n formatToolTitle,\n resolveToolIcon,\n} from '../message-formatter.js'\nimport { progressBar, formatTokens } from '../format-utils.js'\n\nexport interface RenderedMessage<TComponents = unknown> {\n body: string\n format: 'html' | 'markdown' | 'plain' | 'structured'\n attachments?: RenderedAttachment[]\n components?: TComponents\n}\n\nexport interface RenderedPermission<TComponents = unknown> extends RenderedMessage<TComponents> {\n actions: RenderedAction[]\n}\n\nexport interface RenderedAction {\n id: string\n label: string\n isAllow?: boolean\n}\n\nexport interface RenderedAttachment {\n type: 'file' | 'image' | 'audio'\n data: Buffer | string\n mimeType?: string\n filename?: string\n}\n\nexport interface IRenderer {\n renderText(content: OutgoingMessage, verbosity: DisplayVerbosity): RenderedMessage\n renderToolCall(content: OutgoingMessage, verbosity: DisplayVerbosity): RenderedMessage\n renderToolUpdate(content: OutgoingMessage, verbosity: DisplayVerbosity): RenderedMessage\n renderPlan(content: OutgoingMessage, verbosity: DisplayVerbosity): RenderedMessage\n renderUsage(content: OutgoingMessage, verbosity: DisplayVerbosity): RenderedMessage\n renderPermission(request: PermissionRequest): RenderedPermission\n renderError(content: OutgoingMessage): RenderedMessage\n renderNotification(notification: NotificationMessage): RenderedMessage\n renderThought?(content: OutgoingMessage, verbosity: DisplayVerbosity): RenderedMessage\n renderAttachment?(content: OutgoingMessage): RenderedMessage\n renderSessionEnd?(content: OutgoingMessage): RenderedMessage\n renderSystemMessage?(content: OutgoingMessage): RenderedMessage\n renderModeChange?(content: OutgoingMessage, verbosity: DisplayVerbosity): RenderedMessage\n renderConfigUpdate?(content: OutgoingMessage, verbosity: DisplayVerbosity): RenderedMessage\n renderModelUpdate?(content: OutgoingMessage, verbosity: DisplayVerbosity): RenderedMessage\n renderResource?(content: OutgoingMessage): RenderedMessage\n renderResourceLink?(content: OutgoingMessage): RenderedMessage\n}\n\n/**\n * BaseRenderer — plain text defaults. Extend for platform-specific rendering.\n */\nexport class BaseRenderer implements IRenderer {\n renderText(content: OutgoingMessage): RenderedMessage {\n return { body: content.text, format: 'plain' }\n }\n\n renderToolCall(content: OutgoingMessage, verbosity: DisplayVerbosity): RenderedMessage {\n const meta = (content.metadata ?? {}) as Partial<ToolCallMeta>\n const name = meta.name ?? content.text ?? 'Tool'\n const icon = resolveToolIcon(meta)\n const label = verbosity === 'low'\n ? formatToolTitle(name, meta.rawInput, meta.displayTitle as string | undefined)\n : formatToolSummary(name, meta.rawInput, meta.displaySummary as string | undefined)\n return { body: `${icon} ${label}`, format: 'plain' }\n }\n\n renderToolUpdate(content: OutgoingMessage, verbosity: DisplayVerbosity): RenderedMessage {\n const meta = (content.metadata ?? {}) as Partial<ToolUpdateMeta>\n const name = meta.name ?? content.text ?? 'Tool'\n const icon = resolveToolIcon(meta)\n const label = verbosity === 'low'\n ? formatToolTitle(name, meta.rawInput, meta.displayTitle as string | undefined)\n : formatToolSummary(name, meta.rawInput, meta.displaySummary as string | undefined)\n return { body: `${icon} ${label}`, format: 'plain' }\n }\n\n renderPlan(content: OutgoingMessage, verbosity: DisplayVerbosity): RenderedMessage {\n const entries = (content.metadata as { entries?: Array<{ content: string; status: string }> })?.entries ?? []\n const done = entries.filter(e => e.status === 'completed').length\n if (verbosity === 'medium' || verbosity === 'low') {\n return { body: `📋 Plan: ${done}/${entries.length} steps completed`, format: 'plain' }\n }\n const lines = entries.map((e, i) => {\n const icon = e.status === 'completed' ? '✅' : e.status === 'in_progress' ? '🔄' : '⬜'\n return `${icon} ${i + 1}. ${e.content}`\n })\n return { body: `📋 Plan\\n${lines.join('\\n')}`, format: 'plain' }\n }\n\n renderUsage(content: OutgoingMessage, verbosity: DisplayVerbosity): RenderedMessage {\n const meta = content.metadata as { tokensUsed?: number; contextSize?: number; cost?: number } | undefined\n if (!meta?.tokensUsed) return { body: '📊 Usage data unavailable', format: 'plain' }\n const costStr = meta.cost != null ? ` · $${meta.cost.toFixed(2)}` : ''\n if (verbosity === 'medium') {\n return { body: `📊 ${formatTokens(meta.tokensUsed)} tokens${costStr}`, format: 'plain' }\n }\n if (!meta.contextSize) return { body: `📊 ${formatTokens(meta.tokensUsed)} tokens`, format: 'plain' }\n const ratio = meta.tokensUsed / meta.contextSize\n const pct = Math.round(ratio * 100)\n const bar = progressBar(ratio)\n let text = `📊 ${formatTokens(meta.tokensUsed)} / ${formatTokens(meta.contextSize)} tokens\\n${bar} ${pct}%`\n if (meta.cost != null) text += `\\n💰 $${meta.cost.toFixed(2)}`\n return { body: text, format: 'plain' }\n }\n\n renderPermission(request: PermissionRequest): RenderedPermission {\n return {\n body: request.description,\n format: 'plain',\n actions: request.options.map(o => ({ id: o.id, label: o.label, isAllow: o.isAllow })),\n }\n }\n\n renderError(content: OutgoingMessage): RenderedMessage {\n return { body: `❌ Error: ${content.text}`, format: 'plain' }\n }\n\n renderNotification(notification: NotificationMessage): RenderedMessage {\n const emoji: Record<string, string> = {\n completed: '✅', error: '❌', permission: '🔐', input_required: '💬', budget_warning: '⚠️',\n }\n return {\n body: `${emoji[notification.type] || 'ℹ️'} ${notification.sessionName || 'Session'}\\n${notification.summary}`,\n format: 'plain',\n }\n }\n\n renderSystemMessage(content: OutgoingMessage): RenderedMessage {\n return { body: content.text, format: 'plain' }\n }\n\n renderModeChange(content: OutgoingMessage): RenderedMessage {\n const modeId = (content.metadata as Record<string, unknown>)?.modeId ?? ''\n return { body: `🔄 Mode: ${modeId}`, format: 'plain' }\n }\n\n renderConfigUpdate(): RenderedMessage {\n return { body: '⚙️ Config updated', format: 'plain' }\n }\n\n renderModelUpdate(content: OutgoingMessage): RenderedMessage {\n const modelId = (content.metadata as Record<string, unknown>)?.modelId ?? ''\n return { body: `🤖 Model: ${modelId}`, format: 'plain' }\n }\n\n renderResource(content: OutgoingMessage): RenderedMessage {\n const uri = (content.metadata as Record<string, unknown>)?.uri ?? ''\n return { body: `📄 Resource: ${content.text} (${uri})`, format: 'plain' }\n }\n\n renderResourceLink(content: OutgoingMessage): RenderedMessage {\n const uri = (content.metadata as Record<string, unknown>)?.uri ?? ''\n return { body: `🔗 ${content.text}: ${uri}`, format: 'plain' }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
} from "./chunk-QVMEF6FB.js";
|
|
10
10
|
|
|
11
11
|
// src/core/config/config-editor.ts
|
|
12
|
+
import * as os from "os";
|
|
13
|
+
import * as path from "path";
|
|
12
14
|
import * as clack from "@clack/prompts";
|
|
13
15
|
async function select2(opts) {
|
|
14
16
|
const result = await clack.select({
|
|
@@ -147,126 +149,51 @@ async function editTelegram(config, updates) {
|
|
|
147
149
|
}
|
|
148
150
|
}
|
|
149
151
|
}
|
|
150
|
-
|
|
152
|
+
var DISCORD_PACKAGE = "@openacp/adapter-discord";
|
|
153
|
+
async function ensureDiscordPlugin() {
|
|
151
154
|
try {
|
|
152
|
-
|
|
153
|
-
|
|
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
|
+
]
|
|
154
163
|
});
|
|
155
|
-
if (
|
|
156
|
-
|
|
157
|
-
return
|
|
164
|
+
if (shouldInstall === "no") {
|
|
165
|
+
console.log(warn(`Install later with: openacp plugin add ${DISCORD_PACKAGE}`));
|
|
166
|
+
return null;
|
|
158
167
|
}
|
|
159
|
-
|
|
160
|
-
|
|
168
|
+
try {
|
|
169
|
+
console.log(dim(`Installing ${DISCORD_PACKAGE}...`));
|
|
170
|
+
const { installNpmPlugin } = await import("./plugin-installer-GQ2P3Q3E.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;
|
|
161
177
|
}
|
|
162
|
-
return { ok: false, error: `Discord API returned ${res.status}` };
|
|
163
|
-
} catch (err) {
|
|
164
|
-
return { ok: false, error: err.message };
|
|
165
178
|
}
|
|
166
179
|
}
|
|
167
|
-
async function editDiscord(
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (!updates.channels.discord) {
|
|
181
|
-
updates.channels.discord = {};
|
|
182
|
-
}
|
|
183
|
-
return updates.channels.discord;
|
|
184
|
-
};
|
|
185
|
-
while (true) {
|
|
186
|
-
const isEnabled = (() => {
|
|
187
|
-
const ch = updates.channels;
|
|
188
|
-
const dcUp = ch?.discord;
|
|
189
|
-
if (dcUp && "enabled" in dcUp) return dcUp.enabled;
|
|
190
|
-
return currentEnabled;
|
|
191
|
-
})();
|
|
192
|
-
const choice = await select2({
|
|
193
|
-
message: "Discord settings:",
|
|
194
|
-
choices: [
|
|
195
|
-
{ name: isEnabled ? "Disable Discord" : "Enable Discord", value: "toggle" },
|
|
196
|
-
{ name: "Configure Bot Token & Server", value: "setup" },
|
|
197
|
-
{ name: "Back", value: "back" }
|
|
198
|
-
]
|
|
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-MD2U4ZV2.js");
|
|
186
|
+
const { createInstallContext } = await import("./install-context-XPWTFT3J.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
|
|
199
193
|
});
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
dcUp.enabled = !isEnabled;
|
|
204
|
-
console.log(!isEnabled ? ok("Discord enabled") : ok("Discord disabled"));
|
|
205
|
-
}
|
|
206
|
-
if (choice === "setup") {
|
|
207
|
-
const token = await input({
|
|
208
|
-
message: "Bot token:",
|
|
209
|
-
default: currentToken,
|
|
210
|
-
validate: (val) => val.trim().length > 0 || "Token cannot be empty"
|
|
211
|
-
});
|
|
212
|
-
let tokenValid = true;
|
|
213
|
-
try {
|
|
214
|
-
const { validateDiscordToken } = await import("./validators-6CLEZUBD.js");
|
|
215
|
-
const tokenResult = await validateDiscordToken(token.trim());
|
|
216
|
-
if (tokenResult.ok) {
|
|
217
|
-
console.log(ok(`Connected as @${tokenResult.username}`));
|
|
218
|
-
} else {
|
|
219
|
-
console.log(warn(`Token validation failed: ${tokenResult.error}`));
|
|
220
|
-
tokenValid = false;
|
|
221
|
-
}
|
|
222
|
-
} catch {
|
|
223
|
-
console.log(warn("Discord validator not available \u2014 skipping validation"));
|
|
224
|
-
}
|
|
225
|
-
if (!tokenValid) {
|
|
226
|
-
const action = await select2({
|
|
227
|
-
message: "What to do?",
|
|
228
|
-
choices: [
|
|
229
|
-
{ name: "Continue anyway", value: "continue" },
|
|
230
|
-
{ name: "Cancel", value: "cancel" }
|
|
231
|
-
]
|
|
232
|
-
});
|
|
233
|
-
if (action === "cancel") continue;
|
|
234
|
-
}
|
|
235
|
-
const guildIdStr = await input({
|
|
236
|
-
message: "Guild (server) ID:",
|
|
237
|
-
default: currentGuildId,
|
|
238
|
-
validate: (val) => {
|
|
239
|
-
const trimmed = val.trim();
|
|
240
|
-
if (!trimmed) return "Guild ID cannot be empty";
|
|
241
|
-
if (!/^\d{17,20}$/.test(trimmed)) return "Guild ID must be a numeric Discord snowflake (17-20 digits)";
|
|
242
|
-
return true;
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
const validToken = token.trim();
|
|
246
|
-
const validGuildId = guildIdStr.trim();
|
|
247
|
-
const guildResult = await validateDiscordGuild(validToken, validGuildId);
|
|
248
|
-
if (guildResult.ok) {
|
|
249
|
-
console.log(ok(`Server: ${guildResult.name}`));
|
|
250
|
-
} else {
|
|
251
|
-
console.log(warn(`Guild validation failed: ${guildResult.error}`));
|
|
252
|
-
const action = await select2({
|
|
253
|
-
message: "What to do?",
|
|
254
|
-
choices: [
|
|
255
|
-
{ name: "Save anyway", value: "continue" },
|
|
256
|
-
{ name: "Cancel", value: "cancel" }
|
|
257
|
-
]
|
|
258
|
-
});
|
|
259
|
-
if (action === "cancel") continue;
|
|
260
|
-
}
|
|
261
|
-
const dcUp = ensureDiscordUpdates();
|
|
262
|
-
dcUp.botToken = validToken;
|
|
263
|
-
dcUp.guildId = validGuildId;
|
|
264
|
-
dcUp.enabled = true;
|
|
265
|
-
dcUp.forumChannelId = null;
|
|
266
|
-
dcUp.notificationChannelId = null;
|
|
267
|
-
dcUp.assistantThreadId = null;
|
|
268
|
-
console.log(ok("Discord configured and enabled"));
|
|
269
|
-
}
|
|
194
|
+
await plugin.configure(ctx);
|
|
195
|
+
} else {
|
|
196
|
+
console.log(warn("This plugin does not have a configure() method yet."));
|
|
270
197
|
}
|
|
271
198
|
}
|
|
272
199
|
async function editChannels(config, updates) {
|
|
@@ -719,17 +646,17 @@ ${c.cyan}${c.bold}OpenACP Config Editor${c.reset}`);
|
|
|
719
646
|
async function sendConfigViaApi(port, updates) {
|
|
720
647
|
const { apiCall: call } = await import("./api-client-AQPNKXI2.js");
|
|
721
648
|
const paths = flattenToPaths(updates);
|
|
722
|
-
for (const { path, value } of paths) {
|
|
649
|
+
for (const { path: path2, value } of paths) {
|
|
723
650
|
const res = await call(port, "/api/config", {
|
|
724
651
|
method: "PATCH",
|
|
725
652
|
headers: { "Content-Type": "application/json" },
|
|
726
|
-
body: JSON.stringify({ path, value })
|
|
653
|
+
body: JSON.stringify({ path: path2, value })
|
|
727
654
|
});
|
|
728
655
|
const data = await res.json();
|
|
729
656
|
if (!res.ok) {
|
|
730
|
-
console.log(warn(`Failed to update ${
|
|
657
|
+
console.log(warn(`Failed to update ${path2}: ${data.error}`));
|
|
731
658
|
} else if (data.needsRestart) {
|
|
732
|
-
console.log(warn(`${
|
|
659
|
+
console.log(warn(`${path2} updated \u2014 restart required`));
|
|
733
660
|
}
|
|
734
661
|
}
|
|
735
662
|
}
|
|
@@ -749,4 +676,4 @@ function flattenToPaths(obj, prefix = "") {
|
|
|
749
676
|
export {
|
|
750
677
|
runConfigEditor
|
|
751
678
|
};
|
|
752
|
-
//# sourceMappingURL=chunk-
|
|
679
|
+
//# sourceMappingURL=chunk-UMT7RU77.js.map
|