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 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: await loadConfiguredPluginsResult(pathResult),
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(configFilePath, "utf8");
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 ${configFilePath}: ${errorSummary}`);
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.serverTitle, presentStatusPlainServerLines(input, copy, 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.serverTitle, presentStatusMarkdownServerLines(input, copy, 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 presentStatusPlainServerLines(input, copy, layout) {
2617
- if (input.health.status === "error") return presentStatusPlainErrorLines(input.health.error, copy, layout);
2618
- return [presentPlainStatusBullet(layout.statusLabel, formatHealthBadge(input.health.data.healthy, layout)), presentPlainStatusBullet(layout.versionLabel, input.health.data.version)];
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 presentStatusMarkdownServerLines(input, copy, layout) {
2621
- if (input.health.status === "error") return presentStatusMarkdownErrorLines(input.health.error, copy, layout);
2622
- return [presentMarkdownStatusBullet(layout.statusLabel, formatHealthBadge(input.health.data.healthy, layout)), presentMarkdownStatusBullet(layout.versionLabel, input.health.data.version)];
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.path.status === "error") return presentStatusPlainErrorLines(input.path.error, copy, layout);
2626
- return [presentPlainStatusBullet(layout.currentDirectoryLabel, input.path.data.directory)];
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.path.status === "error") return presentStatusMarkdownErrorLines(input.path.error, copy, layout);
2630
- return [presentMarkdownStatusBullet(layout.currentDirectoryLabel, input.path.data.directory, { codeValue: true })];
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
- const lines = [presentPlainStatusBullet(layout.configFileLabel, input.plugins.data.configFilePath)];
2635
- if (input.plugins.data.plugins.length === 0) return [...lines, ...presentPlainEmptyStatusLines(layout.noPluginsMessage, layout)];
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
- const lines = [presentMarkdownStatusBullet(layout.configFileLabel, input.plugins.data.configFilePath, { codeValue: true })];
2645
- if (input.plugins.data.plugins.length === 0) return [...lines, ...presentMarkdownEmptyStatusLines(layout.noPluginsMessage, layout)];
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, copy)
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, copy)
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, copy, layout)
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, copy, layout)
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
- const detailLines = splitStatusLines(presentError(error, copy));
2700
- return [presentPlainStatusBullet(layout.statusLabel, layout.errorStatus), ...detailLines.map((line) => presentPlainStatusBullet(layout.detailsLabel, line))];
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
- const detailLines = splitStatusLines(presentError(error, copy));
2704
- return [presentMarkdownStatusBullet(layout.statusLabel, layout.errorStatus), ...detailLines.map((line) => presentMarkdownStatusBullet(layout.detailsLabel, line))];
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 ? layout.healthyStatus : layout.errorStatus;
2794
+ return healthy ? "🟢" : layout.errorStatus;
2729
2795
  }
2730
- function formatLspStatusBadge(status, copy) {
2796
+ function formatLspStatusBadge(status) {
2731
2797
  switch (status.status) {
2732
- case "connected": return `\uD83D\uDFE2 ${copy.lsp.connected}`;
2733
- case "error": return `\uD83D\uDD34 ${copy.lsp.error}`;
2798
+ case "connected": return "🟢";
2799
+ case "error": return "🔴";
2734
2800
  }
2735
2801
  return status.status;
2736
2802
  }
2737
- function formatMcpStatusBadge(status, copy, layout) {
2803
+ function formatMcpStatusBadge(status, layout) {
2738
2804
  switch (status.status) {
2739
- case "connected": return `\uD83D\uDFE2 ${copy.mcp.connected}`;
2740
- case "disabled": return `\u26AA ${copy.mcp.disabled}`;
2741
- case "needs_auth": return `\uD83D\uDFE1 ${copy.mcp.needsAuth}`;
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
- configFileLabel: "Config File",
2832
+ connectivityLabel: "Connectivity",
2770
2833
  configuredPluginsLabel: "Configured Plugins",
2771
- currentDirectoryLabel: "Current Directory",
2834
+ currentProjectLabel: "Current Project",
2835
+ currentSessionLabel: "Current Session",
2772
2836
  detailsLabel: "Details",
2773
- divider: "----------------",
2774
- errorStatus: "🔴 Unhealthy",
2775
- healthyStatus: "🟢 Healthy",
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: "🟡 Registration Required",
2781
- mcpTitle: "🔌 MCP (Model Context Protocol)",
2841
+ mcpRegistrationRequiredStatus: "🟡",
2842
+ mcpTitle: "🔌 MCP",
2782
2843
  noPluginsMessage: "No plugins configured in the OpenCode config.",
2783
- noneStatus: "⚪ None",
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
- versionLabel: "Version",
2852
+ tbotVersionLabel: "opencode-tbot Version",
2791
2853
  workspaceTitle: "📁 Workspace"
2792
2854
  };
2793
2855
  return {
2794
- configFileLabel: "配置文件",
2856
+ connectivityLabel: "连通性",
2795
2857
  configuredPluginsLabel: "已配置插件",
2796
- currentDirectoryLabel: "当前目录",
2858
+ currentProjectLabel: "当前项目",
2859
+ currentSessionLabel: "当前会话",
2797
2860
  detailsLabel: "详情",
2798
- divider: "----------------",
2799
- errorStatus: "🔴 异常",
2800
- healthyStatus: "🟢 健康",
2801
- lastUpdatedLabel: "最后更新",
2802
- lspTitle: "🧠 LSP (Language Server)",
2803
- mcpFailedStatus: "🔴 失败",
2861
+ errorStatus: "🔴",
2862
+ lspTitle: "🧠 LSP",
2863
+ mcpFailedStatus: "🔴",
2804
2864
  mcpNotesLabel: "说明",
2805
- mcpRegistrationRequiredStatus: "🟡 需要注册",
2806
- mcpTitle: "🔌 MCP (Model Context Protocol)",
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
- versionLabel: "版本",
2876
+ tbotVersionLabel: "opencode-tbot版本",
2816
2877
  workspaceTitle: "📁 工作区"
2817
2878
  };
2818
2879
  }