opencode-tbot 0.1.2 → 0.1.4

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
2
  import { mkdir, readFile, rename, stat, writeFile } from "node:fs/promises";
3
- import { basename, dirname, extname, join } from "node:path";
3
+ import { basename, dirname, extname, isAbsolute, 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";
@@ -962,13 +962,14 @@ var GetPathUseCase = class {
962
962
  //#endregion
963
963
  //#region src/use-cases/get-status.usecase.ts
964
964
  var GetStatusUseCase = class {
965
- constructor(getHealthUseCase, getPathUseCase, listLspUseCase, listMcpUseCase, listSessionsUseCase, sessionRepo) {
965
+ constructor(getHealthUseCase, getPathUseCase, listLspUseCase, listMcpUseCase, listSessionsUseCase, sessionRepo, voiceTranscriptionEnabled) {
966
966
  this.getHealthUseCase = getHealthUseCase;
967
967
  this.getPathUseCase = getPathUseCase;
968
968
  this.listLspUseCase = listLspUseCase;
969
969
  this.listMcpUseCase = listMcpUseCase;
970
970
  this.listSessionsUseCase = listSessionsUseCase;
971
971
  this.sessionRepo = sessionRepo;
972
+ this.voiceTranscriptionEnabled = voiceTranscriptionEnabled;
972
973
  }
973
974
  async execute(input) {
974
975
  const [health, path, lsp, mcp] = await Promise.allSettled([
@@ -983,6 +984,7 @@ var GetStatusUseCase = class {
983
984
  health: mapSettledResult(health),
984
985
  path: pathResult,
985
986
  plugins,
987
+ voiceRecognition: { enabled: this.voiceTranscriptionEnabled },
986
988
  workspace,
987
989
  lsp: mapSettledResult(lsp),
988
990
  mcp: mapSettledResult(mcp)
@@ -1050,11 +1052,11 @@ async function loadWorkspaceStatusResult(chatId, path, listSessionsUseCase, sess
1050
1052
  status: "error"
1051
1053
  };
1052
1054
  const binding = await sessionRepo.getByChatId(chatId);
1053
- let currentProject = path.data.directory;
1055
+ let currentProject = resolveWorkspaceProjectPath(path.data);
1054
1056
  let currentSession = binding?.sessionId ?? null;
1055
1057
  try {
1056
1058
  const sessions = await listSessionsUseCase.execute({ chatId });
1057
- currentProject = sessions.currentDirectory;
1059
+ currentProject = resolveWorkspaceProjectPath(path.data, sessions.currentDirectory);
1058
1060
  currentSession = sessions.currentSessionId ? formatSessionStatusLabel(sessions.sessions.find((session) => session.id === sessions.currentSessionId) ?? null, sessions.currentSessionId) : null;
1059
1061
  } catch {}
1060
1062
  return {
@@ -1070,6 +1072,20 @@ function formatSessionStatusLabel(session, fallbackId) {
1070
1072
  const title = session.title.trim() || session.slug || session.id;
1071
1073
  return title === session.slug ? title : `${title} (${session.slug})`;
1072
1074
  }
1075
+ function resolveWorkspaceProjectPath(path, preferredPath) {
1076
+ const candidates = [
1077
+ preferredPath,
1078
+ path.worktree,
1079
+ path.directory
1080
+ ];
1081
+ for (const candidate of candidates) if (isUsableWorkspacePath(candidate)) return candidate;
1082
+ return preferredPath ?? path.worktree ?? path.directory;
1083
+ }
1084
+ function isUsableWorkspacePath(value) {
1085
+ if (typeof value !== "string") return false;
1086
+ const normalized = value.trim();
1087
+ return normalized.length > 0 && normalized !== "/" && normalized !== "\\" && isAbsolute(normalized);
1088
+ }
1073
1089
  async function resolveOpenCodeConfigFilePath(configPath) {
1074
1090
  try {
1075
1091
  return (await stat(configPath)).isDirectory() ? join(configPath, "opencode.json") : configPath;
@@ -1601,7 +1617,7 @@ function createContainer(config, opencodeClient, logger) {
1601
1617
  const listLspUseCase = new ListLspUseCase(sessionRepo, opencodeClient);
1602
1618
  const listMcpUseCase = new ListMcpUseCase(sessionRepo, opencodeClient);
1603
1619
  const listSessionsUseCase = new ListSessionsUseCase(sessionRepo, opencodeClient);
1604
- const getStatusUseCase = new GetStatusUseCase(getHealthUseCase, getPathUseCase, listLspUseCase, listMcpUseCase, listSessionsUseCase, sessionRepo);
1620
+ const getStatusUseCase = new GetStatusUseCase(getHealthUseCase, getPathUseCase, listLspUseCase, listMcpUseCase, listSessionsUseCase, sessionRepo, config.openrouter.configured);
1605
1621
  const listModelsUseCase = new ListModelsUseCase(sessionRepo, opencodeClient);
1606
1622
  const renameSessionUseCase = new RenameSessionUseCase(sessionRepo, opencodeClient, logger);
1607
1623
  const sendPromptUseCase = new SendPromptUseCase(sessionRepo, opencodeClient, logger, foregroundSessionTracker);
@@ -2634,32 +2650,26 @@ var VARIANT_ORDER = [
2634
2650
  ];
2635
2651
  function presentStatusMessage(input, copy = BOT_COPY) {
2636
2652
  const layout = getStatusLayoutCopy(copy);
2637
- const sections = [
2653
+ return presentStatusSections([
2638
2654
  presentStatusPlainSection(layout.overviewTitle, presentStatusPlainOverviewLines(input, copy, layout)),
2639
2655
  presentStatusPlainSection(layout.workspaceTitle, presentStatusPlainWorkspaceLines(input, copy, layout)),
2640
2656
  presentStatusPlainSection(layout.pluginsTitle, presentStatusPlainPluginLines(input, copy, layout)),
2641
2657
  presentStatusPlainSection(layout.mcpTitle, presentStatusPlainMcpLines(input, copy, layout)),
2642
2658
  presentStatusPlainSection(layout.lspTitle, presentStatusPlainLspLines(input, copy, layout))
2643
- ];
2644
- return presentStatusSections(layout.pageTitle, sections);
2659
+ ]);
2645
2660
  }
2646
2661
  function presentStatusMarkdownMessage(input, copy = BOT_COPY) {
2647
2662
  const layout = getStatusLayoutCopy(copy);
2648
- const sections = [
2663
+ return presentStatusSections([
2649
2664
  presentStatusMarkdownSection(layout.overviewTitle, presentStatusMarkdownOverviewLines(input, copy, layout)),
2650
2665
  presentStatusMarkdownSection(layout.workspaceTitle, presentStatusMarkdownWorkspaceLines(input, copy, layout)),
2651
2666
  presentStatusMarkdownSection(layout.pluginsTitle, presentStatusMarkdownPluginLines(input, copy, layout)),
2652
2667
  presentStatusMarkdownSection(layout.mcpTitle, presentStatusMarkdownMcpLines(input, copy, layout)),
2653
2668
  presentStatusMarkdownSection(layout.lspTitle, presentStatusMarkdownLspLines(input, copy, layout))
2654
- ];
2655
- return presentStatusSections(`# ${layout.pageTitle}`, sections);
2669
+ ]);
2656
2670
  }
2657
- function presentStatusSections(title, sections) {
2658
- return [
2659
- title,
2660
- "",
2661
- ...sections.flatMap((section, index) => index === 0 ? [section] : ["", section])
2662
- ].join("\n");
2671
+ function presentStatusSections(sections) {
2672
+ return sections.flatMap((section, index) => index === 0 ? [section] : ["", section]).join("\n");
2663
2673
  }
2664
2674
  function presentStatusPlainSection(title, lines) {
2665
2675
  return [title, ...lines].join("\n");
@@ -2668,7 +2678,7 @@ function presentStatusMarkdownSection(title, lines) {
2668
2678
  return [`## ${title}`, ...lines].join("\n");
2669
2679
  }
2670
2680
  function presentStatusPlainOverviewLines(input, copy, layout) {
2671
- const lines = [presentPlainStatusBullet(layout.connectivityLabel, input.health.status === "error" ? layout.errorStatus : formatHealthBadge(input.health.data.healthy, layout))];
2681
+ const lines = [presentPlainStatusBullet(layout.connectivityLabel, input.health.status === "error" ? layout.errorStatus : formatHealthBadge(input.health.data.healthy, layout)), presentPlainStatusBullet(layout.voiceRecognitionLabel, formatVoiceRecognitionBadge(input.voiceRecognition.enabled))];
2672
2682
  if (input.health.status === "error") return [
2673
2683
  ...lines,
2674
2684
  ...presentStatusPlainErrorDetailLines(input.health.error, copy, layout),
@@ -2681,7 +2691,7 @@ function presentStatusPlainOverviewLines(input, copy, layout) {
2681
2691
  ];
2682
2692
  }
2683
2693
  function presentStatusMarkdownOverviewLines(input, copy, layout) {
2684
- const lines = [presentMarkdownStatusBullet(layout.connectivityLabel, input.health.status === "error" ? layout.errorStatus : formatHealthBadge(input.health.data.healthy, layout))];
2694
+ const lines = [presentMarkdownStatusBullet(layout.connectivityLabel, input.health.status === "error" ? layout.errorStatus : formatHealthBadge(input.health.data.healthy, layout)), presentMarkdownStatusBullet(layout.voiceRecognitionLabel, formatVoiceRecognitionBadge(input.voiceRecognition.enabled))];
2685
2695
  if (input.health.status === "error") return [
2686
2696
  ...lines,
2687
2697
  ...presentStatusMarkdownErrorDetailLines(input.health.error, copy, layout),
@@ -2695,21 +2705,21 @@ function presentStatusMarkdownOverviewLines(input, copy, layout) {
2695
2705
  }
2696
2706
  function presentStatusPlainWorkspaceLines(input, copy, layout) {
2697
2707
  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)];
2708
+ return [presentPlainStatusBullet(layout.currentProjectLabel, input.workspace.data.currentProject), presentPlainStatusBullet(layout.currentSessionLabel, input.workspace.data.currentSession ?? layout.defaultSessionValue)];
2699
2709
  }
2700
2710
  function presentStatusMarkdownWorkspaceLines(input, copy, layout) {
2701
2711
  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)];
2712
+ return [presentMarkdownStatusBullet(layout.currentProjectLabel, input.workspace.data.currentProject, { codeValue: true }), presentMarkdownStatusBullet(layout.currentSessionLabel, input.workspace.data.currentSession ?? layout.defaultSessionValue)];
2703
2713
  }
2704
2714
  function presentStatusPlainPluginLines(input, copy, layout) {
2705
2715
  if (input.plugins.status === "error") return presentStatusPlainErrorLines(input.plugins.error, copy, layout);
2706
2716
  if (input.plugins.data.plugins.length === 0) return [...presentPlainEmptyStatusLines(layout.noPluginsMessage, layout)];
2707
- return [`- ${layout.configuredPluginsLabel}:`, ...input.plugins.data.plugins.map((plugin) => ` - ${plugin}`)];
2717
+ return input.plugins.data.plugins.map((plugin) => `- ${plugin}`);
2708
2718
  }
2709
2719
  function presentStatusMarkdownPluginLines(input, copy, layout) {
2710
2720
  if (input.plugins.status === "error") return presentStatusMarkdownErrorLines(input.plugins.error, copy, layout);
2711
2721
  if (input.plugins.data.plugins.length === 0) return [...presentMarkdownEmptyStatusLines(layout.noPluginsMessage, layout)];
2712
- return [`- **${layout.configuredPluginsLabel}:**`, ...input.plugins.data.plugins.map((plugin) => ` - \`${plugin}\``)];
2722
+ return input.plugins.data.plugins.map((plugin) => `- \`${plugin}\``);
2713
2723
  }
2714
2724
  function presentStatusPlainLspLines(input, copy, layout) {
2715
2725
  if (input.lsp.status === "error") return presentStatusPlainErrorLines(input.lsp.error, copy, layout);
@@ -2738,24 +2748,12 @@ function presentStatusMarkdownLspLines(input, copy, layout) {
2738
2748
  function presentStatusPlainMcpLines(input, copy, layout) {
2739
2749
  if (input.mcp.status === "error") return presentStatusPlainErrorLines(input.mcp.error, copy, layout);
2740
2750
  if (input.mcp.data.statuses.length === 0) return presentPlainEmptyStatusLines(copy.mcp.none, layout);
2741
- return input.mcp.data.statuses.flatMap(({ name, status }) => presentPlainStatusGroup(name, [{
2742
- label: layout.statusLabel,
2743
- value: formatMcpStatusBadge(status, layout)
2744
- }, {
2745
- label: layout.mcpNotesLabel,
2746
- value: formatMcpStatusNotes(status, copy, layout)
2747
- }]));
2751
+ return input.mcp.data.statuses.flatMap(({ name, status }) => presentPlainStatusGroup(name, getMcpStatusDetailLines(status, copy, layout)));
2748
2752
  }
2749
2753
  function presentStatusMarkdownMcpLines(input, copy, layout) {
2750
2754
  if (input.mcp.status === "error") return presentStatusMarkdownErrorLines(input.mcp.error, copy, layout);
2751
2755
  if (input.mcp.data.statuses.length === 0) return presentMarkdownEmptyStatusLines(copy.mcp.none, layout);
2752
- return input.mcp.data.statuses.flatMap(({ name, status }) => presentMarkdownStatusGroup(name, [{
2753
- label: layout.statusLabel,
2754
- value: formatMcpStatusBadge(status, layout)
2755
- }, {
2756
- label: layout.mcpNotesLabel,
2757
- value: formatMcpStatusNotes(status, copy, layout)
2758
- }], { codeName: true }));
2756
+ return input.mcp.data.statuses.flatMap(({ name, status }) => presentMarkdownStatusGroup(name, getMcpStatusDetailLines(status, copy, layout), { codeName: true }));
2759
2757
  }
2760
2758
  function presentStatusPlainErrorLines(error, copy, layout) {
2761
2759
  return [presentPlainStatusBullet(layout.statusLabel, layout.errorStatus), ...presentStatusPlainErrorDetailLines(error, copy, layout)];
@@ -2793,6 +2791,9 @@ function splitStatusLines(text) {
2793
2791
  function formatHealthBadge(healthy, layout) {
2794
2792
  return healthy ? "🟢" : layout.errorStatus;
2795
2793
  }
2794
+ function formatVoiceRecognitionBadge(enabled) {
2795
+ return enabled ? "🟢" : "⚪";
2796
+ }
2796
2797
  function formatLspStatusBadge(status) {
2797
2798
  switch (status.status) {
2798
2799
  case "connected": return "🟢";
@@ -2810,10 +2811,23 @@ function formatMcpStatusBadge(status, layout) {
2810
2811
  }
2811
2812
  return status;
2812
2813
  }
2814
+ function getMcpStatusDetailLines(status, copy, layout) {
2815
+ const notes = formatMcpStatusNotes(status, copy, layout);
2816
+ return notes ? [{
2817
+ label: layout.statusLabel,
2818
+ value: formatMcpStatusBadge(status, layout)
2819
+ }, {
2820
+ label: layout.mcpNotesLabel,
2821
+ value: notes
2822
+ }] : [{
2823
+ label: layout.statusLabel,
2824
+ value: formatMcpStatusBadge(status, layout)
2825
+ }];
2826
+ }
2813
2827
  function formatMcpStatusNotes(status, copy, layout) {
2814
2828
  switch (status.status) {
2815
- case "connected": return layout.okLabel;
2816
- case "disabled": return copy.mcp.disabled;
2829
+ case "connected": return null;
2830
+ case "disabled": return null;
2817
2831
  case "needs_auth": return copy.mcp.needsAuth;
2818
2832
  case "failed": return status.error;
2819
2833
  case "needs_client_registration": return status.error;
@@ -2830,9 +2844,9 @@ function normalizeStatusInlineValue(value) {
2830
2844
  function getStatusLayoutCopy(copy) {
2831
2845
  if (copy.systemStatus.title === BOT_COPY.systemStatus.title) return {
2832
2846
  connectivityLabel: "Connectivity",
2833
- configuredPluginsLabel: "Configured Plugins",
2834
2847
  currentProjectLabel: "Current Project",
2835
2848
  currentSessionLabel: "Current Session",
2849
+ defaultSessionValue: "OpenCode Default",
2836
2850
  detailsLabel: "Details",
2837
2851
  errorStatus: "🔴",
2838
2852
  lspTitle: "🧠 LSP",
@@ -2843,20 +2857,19 @@ function getStatusLayoutCopy(copy) {
2843
2857
  noPluginsMessage: "No plugins configured in the OpenCode config.",
2844
2858
  noneStatus: "⚪",
2845
2859
  openCodeVersionLabel: "OpenCode Version",
2846
- okLabel: "OK",
2847
2860
  overviewTitle: "🖥️ Overview",
2848
- pageTitle: "📊 Service Status",
2849
2861
  pluginsTitle: "🧩 Plugins",
2850
2862
  rootLabel: "Root",
2851
2863
  statusLabel: "Status",
2852
2864
  tbotVersionLabel: "opencode-tbot Version",
2865
+ voiceRecognitionLabel: "Voice Recognition",
2853
2866
  workspaceTitle: "📁 Workspace"
2854
2867
  };
2855
2868
  return {
2856
2869
  connectivityLabel: "连通性",
2857
- configuredPluginsLabel: "已配置插件",
2858
2870
  currentProjectLabel: "当前项目",
2859
2871
  currentSessionLabel: "当前会话",
2872
+ defaultSessionValue: "OpenCode 默认",
2860
2873
  detailsLabel: "详情",
2861
2874
  errorStatus: "🔴",
2862
2875
  lspTitle: "🧠 LSP",
@@ -2867,13 +2880,12 @@ function getStatusLayoutCopy(copy) {
2867
2880
  noPluginsMessage: "当前 OpenCode 配置中未配置插件。",
2868
2881
  noneStatus: "⚪",
2869
2882
  openCodeVersionLabel: "OpenCode版本",
2870
- okLabel: "正常",
2871
2883
  overviewTitle: "🖥️ 概览",
2872
- pageTitle: "📊 服务状态",
2873
2884
  pluginsTitle: "🧩 插件",
2874
2885
  rootLabel: "根目录",
2875
2886
  statusLabel: "状态",
2876
2887
  tbotVersionLabel: "opencode-tbot版本",
2888
+ voiceRecognitionLabel: "语音识别",
2877
2889
  workspaceTitle: "📁 工作区"
2878
2890
  };
2879
2891
  }