opencode-tbot 0.1.1 → 0.1.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/dist/plugin.js +154 -93
- package/dist/plugin.js.map +1 -1
- package/package.json +1 -1
package/dist/plugin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as preparePluginConfiguration, s as loadAppConfig } from "./assets/plugin-config-BYsYAzvx.js";
|
|
2
|
-
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
3
|
-
import { basename, dirname, extname } from "node:path";
|
|
2
|
+
import { mkdir, readFile, rename, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import { basename, dirname, extname, join } from "node:path";
|
|
4
4
|
import { parse, printParseErrorCode } from "jsonc-parser";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { OpenRouter } from "@openrouter/sdk";
|
|
@@ -8,6 +8,8 @@ import { createOpencodeClient } from "@opencode-ai/sdk/v2/client";
|
|
|
8
8
|
import { randomUUID } from "node:crypto";
|
|
9
9
|
import { run } from "@grammyjs/runner";
|
|
10
10
|
import { Bot, InlineKeyboard } from "grammy";
|
|
11
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
11
13
|
//#region src/infra/utils/redact.ts
|
|
12
14
|
var REDACTED = "[REDACTED]";
|
|
13
15
|
var DEFAULT_PREVIEW_LENGTH = 160;
|
|
@@ -960,11 +962,13 @@ var GetPathUseCase = class {
|
|
|
960
962
|
//#endregion
|
|
961
963
|
//#region src/use-cases/get-status.usecase.ts
|
|
962
964
|
var GetStatusUseCase = class {
|
|
963
|
-
constructor(getHealthUseCase, getPathUseCase, listLspUseCase, listMcpUseCase) {
|
|
965
|
+
constructor(getHealthUseCase, getPathUseCase, listLspUseCase, listMcpUseCase, listSessionsUseCase, sessionRepo) {
|
|
964
966
|
this.getHealthUseCase = getHealthUseCase;
|
|
965
967
|
this.getPathUseCase = getPathUseCase;
|
|
966
968
|
this.listLspUseCase = listLspUseCase;
|
|
967
969
|
this.listMcpUseCase = listMcpUseCase;
|
|
970
|
+
this.listSessionsUseCase = listSessionsUseCase;
|
|
971
|
+
this.sessionRepo = sessionRepo;
|
|
968
972
|
}
|
|
969
973
|
async execute(input) {
|
|
970
974
|
const [health, path, lsp, mcp] = await Promise.allSettled([
|
|
@@ -974,10 +978,12 @@ var GetStatusUseCase = class {
|
|
|
974
978
|
this.listMcpUseCase.execute({ chatId: input.chatId })
|
|
975
979
|
]);
|
|
976
980
|
const pathResult = mapSettledResult(path);
|
|
981
|
+
const [plugins, workspace] = await Promise.all([loadConfiguredPluginsResult(pathResult), loadWorkspaceStatusResult(input.chatId, pathResult, this.listSessionsUseCase, this.sessionRepo)]);
|
|
977
982
|
return {
|
|
978
983
|
health: mapSettledResult(health),
|
|
979
984
|
path: pathResult,
|
|
980
|
-
plugins
|
|
985
|
+
plugins,
|
|
986
|
+
workspace,
|
|
981
987
|
lsp: mapSettledResult(lsp),
|
|
982
988
|
mcp: mapSettledResult(mcp)
|
|
983
989
|
};
|
|
@@ -1011,12 +1017,13 @@ async function loadConfiguredPluginsResult(path) {
|
|
|
1011
1017
|
}
|
|
1012
1018
|
}
|
|
1013
1019
|
async function loadConfiguredPlugins(configFilePath) {
|
|
1020
|
+
const resolvedConfigFilePath = await resolveOpenCodeConfigFilePath(configFilePath);
|
|
1014
1021
|
let content;
|
|
1015
1022
|
try {
|
|
1016
|
-
content = await readFile(
|
|
1023
|
+
content = await readFile(resolvedConfigFilePath, "utf8");
|
|
1017
1024
|
} catch (error) {
|
|
1018
1025
|
if (isMissingFileError(error)) return {
|
|
1019
|
-
configFilePath,
|
|
1026
|
+
configFilePath: resolvedConfigFilePath,
|
|
1020
1027
|
plugins: []
|
|
1021
1028
|
};
|
|
1022
1029
|
throw error;
|
|
@@ -1025,18 +1032,52 @@ async function loadConfiguredPlugins(configFilePath) {
|
|
|
1025
1032
|
const parsed = parse(content, parseErrors, { allowTrailingComma: true });
|
|
1026
1033
|
if (parseErrors.length > 0) {
|
|
1027
1034
|
const errorSummary = parseErrors.map((error) => printParseErrorCode(error.error)).join(", ");
|
|
1028
|
-
throw new Error(`Failed to parse ${
|
|
1035
|
+
throw new Error(`Failed to parse ${resolvedConfigFilePath}: ${errorSummary}`);
|
|
1029
1036
|
}
|
|
1030
1037
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {
|
|
1031
|
-
configFilePath,
|
|
1038
|
+
configFilePath: resolvedConfigFilePath,
|
|
1032
1039
|
plugins: []
|
|
1033
1040
|
};
|
|
1034
1041
|
const pluginSpecs = Array.isArray(parsed.plugin) ? parsed.plugin : [];
|
|
1035
1042
|
return {
|
|
1036
|
-
configFilePath,
|
|
1043
|
+
configFilePath: resolvedConfigFilePath,
|
|
1037
1044
|
plugins: [...new Set(pluginSpecs.filter((value) => typeof value === "string").map((value) => value.trim()).filter((value) => value.length > 0))]
|
|
1038
1045
|
};
|
|
1039
1046
|
}
|
|
1047
|
+
async function loadWorkspaceStatusResult(chatId, path, listSessionsUseCase, sessionRepo) {
|
|
1048
|
+
if (path.status === "error") return {
|
|
1049
|
+
error: path.error,
|
|
1050
|
+
status: "error"
|
|
1051
|
+
};
|
|
1052
|
+
const binding = await sessionRepo.getByChatId(chatId);
|
|
1053
|
+
let currentProject = path.data.directory;
|
|
1054
|
+
let currentSession = binding?.sessionId ?? null;
|
|
1055
|
+
try {
|
|
1056
|
+
const sessions = await listSessionsUseCase.execute({ chatId });
|
|
1057
|
+
currentProject = sessions.currentDirectory;
|
|
1058
|
+
currentSession = sessions.currentSessionId ? formatSessionStatusLabel(sessions.sessions.find((session) => session.id === sessions.currentSessionId) ?? null, sessions.currentSessionId) : null;
|
|
1059
|
+
} catch {}
|
|
1060
|
+
return {
|
|
1061
|
+
data: {
|
|
1062
|
+
currentProject,
|
|
1063
|
+
currentSession
|
|
1064
|
+
},
|
|
1065
|
+
status: "ok"
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
function formatSessionStatusLabel(session, fallbackId) {
|
|
1069
|
+
if (!session) return fallbackId;
|
|
1070
|
+
const title = session.title.trim() || session.slug || session.id;
|
|
1071
|
+
return title === session.slug ? title : `${title} (${session.slug})`;
|
|
1072
|
+
}
|
|
1073
|
+
async function resolveOpenCodeConfigFilePath(configPath) {
|
|
1074
|
+
try {
|
|
1075
|
+
return (await stat(configPath)).isDirectory() ? join(configPath, "opencode.json") : configPath;
|
|
1076
|
+
} catch (error) {
|
|
1077
|
+
if (isMissingFileError(error)) return configPath;
|
|
1078
|
+
throw error;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1040
1081
|
function isMissingFileError(error) {
|
|
1041
1082
|
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
1042
1083
|
}
|
|
@@ -1559,9 +1600,9 @@ function createContainer(config, opencodeClient, logger) {
|
|
|
1559
1600
|
const listAgentsUseCase = new ListAgentsUseCase(sessionRepo, opencodeClient);
|
|
1560
1601
|
const listLspUseCase = new ListLspUseCase(sessionRepo, opencodeClient);
|
|
1561
1602
|
const listMcpUseCase = new ListMcpUseCase(sessionRepo, opencodeClient);
|
|
1562
|
-
const getStatusUseCase = new GetStatusUseCase(getHealthUseCase, getPathUseCase, listLspUseCase, listMcpUseCase);
|
|
1563
|
-
const listModelsUseCase = new ListModelsUseCase(sessionRepo, opencodeClient);
|
|
1564
1603
|
const listSessionsUseCase = new ListSessionsUseCase(sessionRepo, opencodeClient);
|
|
1604
|
+
const getStatusUseCase = new GetStatusUseCase(getHealthUseCase, getPathUseCase, listLspUseCase, listMcpUseCase, listSessionsUseCase, sessionRepo);
|
|
1605
|
+
const listModelsUseCase = new ListModelsUseCase(sessionRepo, opencodeClient);
|
|
1565
1606
|
const renameSessionUseCase = new RenameSessionUseCase(sessionRepo, opencodeClient, logger);
|
|
1566
1607
|
const sendPromptUseCase = new SendPromptUseCase(sessionRepo, opencodeClient, logger, foregroundSessionTracker);
|
|
1567
1608
|
const switchAgentUseCase = new SwitchAgentUseCase(sessionRepo, opencodeClient, logger);
|
|
@@ -2564,6 +2605,23 @@ function stringifyUnknown(value) {
|
|
|
2564
2605
|
}
|
|
2565
2606
|
}
|
|
2566
2607
|
//#endregion
|
|
2608
|
+
//#region src/app/package-info.ts
|
|
2609
|
+
var OPENCODE_TBOT_VERSION = resolvePackageVersion();
|
|
2610
|
+
function resolvePackageVersion() {
|
|
2611
|
+
let directory = dirname(fileURLToPath(import.meta.url));
|
|
2612
|
+
while (true) {
|
|
2613
|
+
const packageFilePath = join(directory, "package.json");
|
|
2614
|
+
if (existsSync(packageFilePath)) try {
|
|
2615
|
+
const parsed = JSON.parse(readFileSync(packageFilePath, "utf8"));
|
|
2616
|
+
if (typeof parsed.version === "string" && parsed.version.trim().length > 0) return parsed.version;
|
|
2617
|
+
} catch {}
|
|
2618
|
+
const parentDirectory = dirname(directory);
|
|
2619
|
+
if (parentDirectory === directory) break;
|
|
2620
|
+
directory = parentDirectory;
|
|
2621
|
+
}
|
|
2622
|
+
return "unknown";
|
|
2623
|
+
}
|
|
2624
|
+
//#endregion
|
|
2567
2625
|
//#region src/bot/presenters/message.presenter.ts
|
|
2568
2626
|
var VARIANT_ORDER = [
|
|
2569
2627
|
"minimal",
|
|
@@ -2577,26 +2635,22 @@ var VARIANT_ORDER = [
|
|
|
2577
2635
|
function presentStatusMessage(input, copy = BOT_COPY) {
|
|
2578
2636
|
const layout = getStatusLayoutCopy(copy);
|
|
2579
2637
|
const sections = [
|
|
2580
|
-
presentStatusPlainSection(layout.
|
|
2638
|
+
presentStatusPlainSection(layout.overviewTitle, presentStatusPlainOverviewLines(input, copy, layout)),
|
|
2581
2639
|
presentStatusPlainSection(layout.workspaceTitle, presentStatusPlainWorkspaceLines(input, copy, layout)),
|
|
2582
2640
|
presentStatusPlainSection(layout.pluginsTitle, presentStatusPlainPluginLines(input, copy, layout)),
|
|
2583
2641
|
presentStatusPlainSection(layout.mcpTitle, presentStatusPlainMcpLines(input, copy, layout)),
|
|
2584
|
-
presentStatusPlainSection(layout.lspTitle, presentStatusPlainLspLines(input, copy, layout))
|
|
2585
|
-
layout.divider,
|
|
2586
|
-
`${layout.lastUpdatedLabel}: ${formatStatusDate(/* @__PURE__ */ new Date())}`
|
|
2642
|
+
presentStatusPlainSection(layout.lspTitle, presentStatusPlainLspLines(input, copy, layout))
|
|
2587
2643
|
];
|
|
2588
2644
|
return presentStatusSections(layout.pageTitle, sections);
|
|
2589
2645
|
}
|
|
2590
2646
|
function presentStatusMarkdownMessage(input, copy = BOT_COPY) {
|
|
2591
2647
|
const layout = getStatusLayoutCopy(copy);
|
|
2592
2648
|
const sections = [
|
|
2593
|
-
presentStatusMarkdownSection(layout.
|
|
2649
|
+
presentStatusMarkdownSection(layout.overviewTitle, presentStatusMarkdownOverviewLines(input, copy, layout)),
|
|
2594
2650
|
presentStatusMarkdownSection(layout.workspaceTitle, presentStatusMarkdownWorkspaceLines(input, copy, layout)),
|
|
2595
2651
|
presentStatusMarkdownSection(layout.pluginsTitle, presentStatusMarkdownPluginLines(input, copy, layout)),
|
|
2596
2652
|
presentStatusMarkdownSection(layout.mcpTitle, presentStatusMarkdownMcpLines(input, copy, layout)),
|
|
2597
|
-
presentStatusMarkdownSection(layout.lspTitle, presentStatusMarkdownLspLines(input, copy, layout))
|
|
2598
|
-
layout.divider,
|
|
2599
|
-
`_${layout.lastUpdatedLabel}: ${formatStatusDate(/* @__PURE__ */ new Date())}_`
|
|
2653
|
+
presentStatusMarkdownSection(layout.lspTitle, presentStatusMarkdownLspLines(input, copy, layout))
|
|
2600
2654
|
];
|
|
2601
2655
|
return presentStatusSections(`# ${layout.pageTitle}`, sections);
|
|
2602
2656
|
}
|
|
@@ -2613,48 +2667,56 @@ function presentStatusPlainSection(title, lines) {
|
|
|
2613
2667
|
function presentStatusMarkdownSection(title, lines) {
|
|
2614
2668
|
return [`## ${title}`, ...lines].join("\n");
|
|
2615
2669
|
}
|
|
2616
|
-
function
|
|
2617
|
-
|
|
2618
|
-
|
|
2670
|
+
function presentStatusPlainOverviewLines(input, copy, layout) {
|
|
2671
|
+
const lines = [presentPlainStatusBullet(layout.connectivityLabel, input.health.status === "error" ? layout.errorStatus : formatHealthBadge(input.health.data.healthy, layout))];
|
|
2672
|
+
if (input.health.status === "error") return [
|
|
2673
|
+
...lines,
|
|
2674
|
+
...presentStatusPlainErrorDetailLines(input.health.error, copy, layout),
|
|
2675
|
+
presentPlainStatusBullet(layout.tbotVersionLabel, OPENCODE_TBOT_VERSION)
|
|
2676
|
+
];
|
|
2677
|
+
return [
|
|
2678
|
+
...lines,
|
|
2679
|
+
presentPlainStatusBullet(layout.openCodeVersionLabel, input.health.data.version),
|
|
2680
|
+
presentPlainStatusBullet(layout.tbotVersionLabel, OPENCODE_TBOT_VERSION)
|
|
2681
|
+
];
|
|
2619
2682
|
}
|
|
2620
|
-
function
|
|
2621
|
-
|
|
2622
|
-
|
|
2683
|
+
function presentStatusMarkdownOverviewLines(input, copy, layout) {
|
|
2684
|
+
const lines = [presentMarkdownStatusBullet(layout.connectivityLabel, input.health.status === "error" ? layout.errorStatus : formatHealthBadge(input.health.data.healthy, layout))];
|
|
2685
|
+
if (input.health.status === "error") return [
|
|
2686
|
+
...lines,
|
|
2687
|
+
...presentStatusMarkdownErrorDetailLines(input.health.error, copy, layout),
|
|
2688
|
+
presentMarkdownStatusBullet(layout.tbotVersionLabel, OPENCODE_TBOT_VERSION)
|
|
2689
|
+
];
|
|
2690
|
+
return [
|
|
2691
|
+
...lines,
|
|
2692
|
+
presentMarkdownStatusBullet(layout.openCodeVersionLabel, input.health.data.version),
|
|
2693
|
+
presentMarkdownStatusBullet(layout.tbotVersionLabel, OPENCODE_TBOT_VERSION)
|
|
2694
|
+
];
|
|
2623
2695
|
}
|
|
2624
2696
|
function presentStatusPlainWorkspaceLines(input, copy, layout) {
|
|
2625
|
-
if (input.
|
|
2626
|
-
return [presentPlainStatusBullet(layout.
|
|
2697
|
+
if (input.workspace.status === "error") return presentStatusPlainErrorLines(input.workspace.error, copy, layout);
|
|
2698
|
+
return [presentPlainStatusBullet(layout.currentProjectLabel, input.workspace.data.currentProject), presentPlainStatusBullet(layout.currentSessionLabel, input.workspace.data.currentSession ?? copy.common.notSelected)];
|
|
2627
2699
|
}
|
|
2628
2700
|
function presentStatusMarkdownWorkspaceLines(input, copy, layout) {
|
|
2629
|
-
if (input.
|
|
2630
|
-
return [presentMarkdownStatusBullet(layout.
|
|
2701
|
+
if (input.workspace.status === "error") return presentStatusMarkdownErrorLines(input.workspace.error, copy, layout);
|
|
2702
|
+
return [presentMarkdownStatusBullet(layout.currentProjectLabel, input.workspace.data.currentProject, { codeValue: true }), presentMarkdownStatusBullet(layout.currentSessionLabel, input.workspace.data.currentSession ?? copy.common.notSelected)];
|
|
2631
2703
|
}
|
|
2632
2704
|
function presentStatusPlainPluginLines(input, copy, layout) {
|
|
2633
2705
|
if (input.plugins.status === "error") return presentStatusPlainErrorLines(input.plugins.error, copy, layout);
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
return [
|
|
2637
|
-
...lines,
|
|
2638
|
-
`- ${layout.configuredPluginsLabel}:`,
|
|
2639
|
-
...input.plugins.data.plugins.map((plugin) => ` - ${plugin}`)
|
|
2640
|
-
];
|
|
2706
|
+
if (input.plugins.data.plugins.length === 0) return [...presentPlainEmptyStatusLines(layout.noPluginsMessage, layout)];
|
|
2707
|
+
return [`- ${layout.configuredPluginsLabel}:`, ...input.plugins.data.plugins.map((plugin) => ` - ${plugin}`)];
|
|
2641
2708
|
}
|
|
2642
2709
|
function presentStatusMarkdownPluginLines(input, copy, layout) {
|
|
2643
2710
|
if (input.plugins.status === "error") return presentStatusMarkdownErrorLines(input.plugins.error, copy, layout);
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
return [
|
|
2647
|
-
...lines,
|
|
2648
|
-
`- **${layout.configuredPluginsLabel}:**`,
|
|
2649
|
-
...input.plugins.data.plugins.map((plugin) => ` - \`${plugin}\``)
|
|
2650
|
-
];
|
|
2711
|
+
if (input.plugins.data.plugins.length === 0) return [...presentMarkdownEmptyStatusLines(layout.noPluginsMessage, layout)];
|
|
2712
|
+
return [`- **${layout.configuredPluginsLabel}:**`, ...input.plugins.data.plugins.map((plugin) => ` - \`${plugin}\``)];
|
|
2651
2713
|
}
|
|
2652
2714
|
function presentStatusPlainLspLines(input, copy, layout) {
|
|
2653
2715
|
if (input.lsp.status === "error") return presentStatusPlainErrorLines(input.lsp.error, copy, layout);
|
|
2654
2716
|
if (input.lsp.data.statuses.length === 0) return presentPlainEmptyStatusLines(copy.lsp.none, layout);
|
|
2655
2717
|
return input.lsp.data.statuses.flatMap((status) => presentPlainStatusGroup(status.name, [{
|
|
2656
2718
|
label: layout.statusLabel,
|
|
2657
|
-
value: formatLspStatusBadge(status
|
|
2719
|
+
value: formatLspStatusBadge(status)
|
|
2658
2720
|
}, {
|
|
2659
2721
|
codeValue: !!status.root,
|
|
2660
2722
|
label: layout.rootLabel,
|
|
@@ -2666,7 +2728,7 @@ function presentStatusMarkdownLspLines(input, copy, layout) {
|
|
|
2666
2728
|
if (input.lsp.data.statuses.length === 0) return presentMarkdownEmptyStatusLines(copy.lsp.none, layout);
|
|
2667
2729
|
return input.lsp.data.statuses.flatMap((status) => presentMarkdownStatusGroup(status.name, [{
|
|
2668
2730
|
label: layout.statusLabel,
|
|
2669
|
-
value: formatLspStatusBadge(status
|
|
2731
|
+
value: formatLspStatusBadge(status)
|
|
2670
2732
|
}, {
|
|
2671
2733
|
codeValue: !!status.root,
|
|
2672
2734
|
label: layout.rootLabel,
|
|
@@ -2678,10 +2740,10 @@ function presentStatusPlainMcpLines(input, copy, layout) {
|
|
|
2678
2740
|
if (input.mcp.data.statuses.length === 0) return presentPlainEmptyStatusLines(copy.mcp.none, layout);
|
|
2679
2741
|
return input.mcp.data.statuses.flatMap(({ name, status }) => presentPlainStatusGroup(name, [{
|
|
2680
2742
|
label: layout.statusLabel,
|
|
2681
|
-
value: formatMcpStatusBadge(status,
|
|
2743
|
+
value: formatMcpStatusBadge(status, layout)
|
|
2682
2744
|
}, {
|
|
2683
2745
|
label: layout.mcpNotesLabel,
|
|
2684
|
-
value: formatMcpStatusNotes(status, layout)
|
|
2746
|
+
value: formatMcpStatusNotes(status, copy, layout)
|
|
2685
2747
|
}]));
|
|
2686
2748
|
}
|
|
2687
2749
|
function presentStatusMarkdownMcpLines(input, copy, layout) {
|
|
@@ -2689,19 +2751,23 @@ function presentStatusMarkdownMcpLines(input, copy, layout) {
|
|
|
2689
2751
|
if (input.mcp.data.statuses.length === 0) return presentMarkdownEmptyStatusLines(copy.mcp.none, layout);
|
|
2690
2752
|
return input.mcp.data.statuses.flatMap(({ name, status }) => presentMarkdownStatusGroup(name, [{
|
|
2691
2753
|
label: layout.statusLabel,
|
|
2692
|
-
value: formatMcpStatusBadge(status,
|
|
2754
|
+
value: formatMcpStatusBadge(status, layout)
|
|
2693
2755
|
}, {
|
|
2694
2756
|
label: layout.mcpNotesLabel,
|
|
2695
|
-
value: formatMcpStatusNotes(status, layout)
|
|
2757
|
+
value: formatMcpStatusNotes(status, copy, layout)
|
|
2696
2758
|
}], { codeName: true }));
|
|
2697
2759
|
}
|
|
2698
2760
|
function presentStatusPlainErrorLines(error, copy, layout) {
|
|
2699
|
-
|
|
2700
|
-
|
|
2761
|
+
return [presentPlainStatusBullet(layout.statusLabel, layout.errorStatus), ...presentStatusPlainErrorDetailLines(error, copy, layout)];
|
|
2762
|
+
}
|
|
2763
|
+
function presentStatusPlainErrorDetailLines(error, copy, layout) {
|
|
2764
|
+
return splitStatusLines(presentError(error, copy)).map((line) => presentPlainStatusBullet(layout.detailsLabel, line));
|
|
2701
2765
|
}
|
|
2702
2766
|
function presentStatusMarkdownErrorLines(error, copy, layout) {
|
|
2703
|
-
|
|
2704
|
-
|
|
2767
|
+
return [presentMarkdownStatusBullet(layout.statusLabel, layout.errorStatus), ...presentStatusMarkdownErrorDetailLines(error, copy, layout)];
|
|
2768
|
+
}
|
|
2769
|
+
function presentStatusMarkdownErrorDetailLines(error, copy, layout) {
|
|
2770
|
+
return splitStatusLines(presentError(error, copy)).map((line) => presentMarkdownStatusBullet(layout.detailsLabel, line));
|
|
2705
2771
|
}
|
|
2706
2772
|
function presentPlainEmptyStatusLines(message, layout) {
|
|
2707
2773
|
return [presentPlainStatusBullet(layout.statusLabel, layout.noneStatus), presentPlainStatusBullet(layout.detailsLabel, message)];
|
|
@@ -2725,38 +2791,35 @@ function splitStatusLines(text) {
|
|
|
2725
2791
|
return text.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
2726
2792
|
}
|
|
2727
2793
|
function formatHealthBadge(healthy, layout) {
|
|
2728
|
-
return healthy ?
|
|
2794
|
+
return healthy ? "🟢" : layout.errorStatus;
|
|
2729
2795
|
}
|
|
2730
|
-
function formatLspStatusBadge(status
|
|
2796
|
+
function formatLspStatusBadge(status) {
|
|
2731
2797
|
switch (status.status) {
|
|
2732
|
-
case "connected": return
|
|
2733
|
-
case "error": return
|
|
2798
|
+
case "connected": return "🟢";
|
|
2799
|
+
case "error": return "🔴";
|
|
2734
2800
|
}
|
|
2735
2801
|
return status.status;
|
|
2736
2802
|
}
|
|
2737
|
-
function formatMcpStatusBadge(status,
|
|
2803
|
+
function formatMcpStatusBadge(status, layout) {
|
|
2738
2804
|
switch (status.status) {
|
|
2739
|
-
case "connected": return
|
|
2740
|
-
case "disabled": return
|
|
2741
|
-
case "needs_auth": return
|
|
2805
|
+
case "connected": return "🟢";
|
|
2806
|
+
case "disabled": return "⚪";
|
|
2807
|
+
case "needs_auth": return "🟡";
|
|
2742
2808
|
case "failed": return layout.mcpFailedStatus;
|
|
2743
2809
|
case "needs_client_registration": return layout.mcpRegistrationRequiredStatus;
|
|
2744
2810
|
}
|
|
2745
2811
|
return status;
|
|
2746
2812
|
}
|
|
2747
|
-
function formatMcpStatusNotes(status, layout) {
|
|
2813
|
+
function formatMcpStatusNotes(status, copy, layout) {
|
|
2748
2814
|
switch (status.status) {
|
|
2749
2815
|
case "connected": return layout.okLabel;
|
|
2750
|
-
case "disabled": return
|
|
2751
|
-
case "needs_auth": return
|
|
2816
|
+
case "disabled": return copy.mcp.disabled;
|
|
2817
|
+
case "needs_auth": return copy.mcp.needsAuth;
|
|
2752
2818
|
case "failed": return status.error;
|
|
2753
2819
|
case "needs_client_registration": return status.error;
|
|
2754
2820
|
}
|
|
2755
2821
|
return status;
|
|
2756
2822
|
}
|
|
2757
|
-
function formatStatusDate(value) {
|
|
2758
|
-
return value.toISOString().slice(0, 10);
|
|
2759
|
-
}
|
|
2760
2823
|
function formatStatusValue(value) {
|
|
2761
2824
|
const normalized = value.replace(/\r\n?/g, "\n").split("\n").map((line) => line.trim()).filter((line) => line.length > 0).join(" / ");
|
|
2762
2825
|
return normalized.length > 0 ? normalized : "-";
|
|
@@ -2766,53 +2829,51 @@ function normalizeStatusInlineValue(value) {
|
|
|
2766
2829
|
}
|
|
2767
2830
|
function getStatusLayoutCopy(copy) {
|
|
2768
2831
|
if (copy.systemStatus.title === BOT_COPY.systemStatus.title) return {
|
|
2769
|
-
|
|
2832
|
+
connectivityLabel: "Connectivity",
|
|
2770
2833
|
configuredPluginsLabel: "Configured Plugins",
|
|
2771
|
-
|
|
2834
|
+
currentProjectLabel: "Current Project",
|
|
2835
|
+
currentSessionLabel: "Current Session",
|
|
2772
2836
|
detailsLabel: "Details",
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
lastUpdatedLabel: "Last updated",
|
|
2777
|
-
lspTitle: "🧠 LSP (Language Server)",
|
|
2778
|
-
mcpFailedStatus: "🔴 Failed",
|
|
2837
|
+
errorStatus: "🔴",
|
|
2838
|
+
lspTitle: "🧠 LSP",
|
|
2839
|
+
mcpFailedStatus: "🔴",
|
|
2779
2840
|
mcpNotesLabel: "Notes",
|
|
2780
|
-
mcpRegistrationRequiredStatus: "🟡
|
|
2781
|
-
mcpTitle: "🔌 MCP
|
|
2841
|
+
mcpRegistrationRequiredStatus: "🟡",
|
|
2842
|
+
mcpTitle: "🔌 MCP",
|
|
2782
2843
|
noPluginsMessage: "No plugins configured in the OpenCode config.",
|
|
2783
|
-
noneStatus: "⚪
|
|
2844
|
+
noneStatus: "⚪",
|
|
2845
|
+
openCodeVersionLabel: "OpenCode Version",
|
|
2784
2846
|
okLabel: "OK",
|
|
2847
|
+
overviewTitle: "🖥️ Overview",
|
|
2785
2848
|
pageTitle: "📊 Service Status",
|
|
2786
2849
|
pluginsTitle: "🧩 Plugins",
|
|
2787
2850
|
rootLabel: "Root",
|
|
2788
|
-
serverTitle: "🖥️ Server",
|
|
2789
2851
|
statusLabel: "Status",
|
|
2790
|
-
|
|
2852
|
+
tbotVersionLabel: "opencode-tbot Version",
|
|
2791
2853
|
workspaceTitle: "📁 Workspace"
|
|
2792
2854
|
};
|
|
2793
2855
|
return {
|
|
2794
|
-
|
|
2856
|
+
connectivityLabel: "连通性",
|
|
2795
2857
|
configuredPluginsLabel: "已配置插件",
|
|
2796
|
-
|
|
2858
|
+
currentProjectLabel: "当前项目",
|
|
2859
|
+
currentSessionLabel: "当前会话",
|
|
2797
2860
|
detailsLabel: "详情",
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
lastUpdatedLabel: "最后更新",
|
|
2802
|
-
lspTitle: "🧠 LSP (Language Server)",
|
|
2803
|
-
mcpFailedStatus: "🔴 失败",
|
|
2861
|
+
errorStatus: "🔴",
|
|
2862
|
+
lspTitle: "🧠 LSP",
|
|
2863
|
+
mcpFailedStatus: "🔴",
|
|
2804
2864
|
mcpNotesLabel: "说明",
|
|
2805
|
-
mcpRegistrationRequiredStatus: "🟡
|
|
2806
|
-
mcpTitle: "🔌 MCP
|
|
2865
|
+
mcpRegistrationRequiredStatus: "🟡",
|
|
2866
|
+
mcpTitle: "🔌 MCP",
|
|
2807
2867
|
noPluginsMessage: "当前 OpenCode 配置中未配置插件。",
|
|
2808
|
-
noneStatus: "⚪
|
|
2868
|
+
noneStatus: "⚪",
|
|
2869
|
+
openCodeVersionLabel: "OpenCode版本",
|
|
2809
2870
|
okLabel: "正常",
|
|
2871
|
+
overviewTitle: "🖥️ 概览",
|
|
2810
2872
|
pageTitle: "📊 服务状态",
|
|
2811
2873
|
pluginsTitle: "🧩 插件",
|
|
2812
2874
|
rootLabel: "根目录",
|
|
2813
|
-
serverTitle: "🖥️ 服务端",
|
|
2814
2875
|
statusLabel: "状态",
|
|
2815
|
-
|
|
2876
|
+
tbotVersionLabel: "opencode-tbot版本",
|
|
2816
2877
|
workspaceTitle: "📁 工作区"
|
|
2817
2878
|
};
|
|
2818
2879
|
}
|