opencode-tbot 0.1.32 → 0.1.34
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.ja.md +139 -43
- package/README.md +96 -43
- package/README.zh-CN.md +117 -61
- package/dist/assets/{plugin-config-jkAZYbFW.js → plugin-config-LIr8LS0-.js} +25 -2
- package/dist/assets/plugin-config-LIr8LS0-.js.map +1 -0
- package/dist/cli.js +5 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/plugin.js +111 -83
- package/dist/plugin.js.map +1 -1
- package/package.json +1 -1
- package/dist/assets/plugin-config-jkAZYbFW.js.map +0 -1
package/dist/plugin.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { i as OPENCODE_TBOT_VERSION, n as preparePluginConfiguration, o as loadAppConfig } from "./assets/plugin-config-
|
|
1
|
+
import { i as OPENCODE_TBOT_VERSION, n as preparePluginConfiguration, o as loadAppConfig } from "./assets/plugin-config-LIr8LS0-.js";
|
|
2
2
|
import { appendFile, mkdir, readFile, readdir, rename, stat, unlink, writeFile } from "node:fs/promises";
|
|
3
3
|
import { dirname, isAbsolute, join } from "node:path";
|
|
4
|
-
import { parse, printParseErrorCode } from "jsonc-parser";
|
|
5
4
|
import { randomUUID } from "node:crypto";
|
|
6
5
|
import { createOpencodeClient } from "@opencode-ai/sdk";
|
|
7
6
|
import { run } from "@grammyjs/runner";
|
|
@@ -919,6 +918,9 @@ var OpenCodeClient = class {
|
|
|
919
918
|
this.modelCache.promise = refreshPromise;
|
|
920
919
|
return refreshPromise;
|
|
921
920
|
}
|
|
921
|
+
async listConfiguredPlugins() {
|
|
922
|
+
return normalizeConfiguredPluginSpecs((await this.loadConfig()).plugin);
|
|
923
|
+
}
|
|
922
924
|
async promptSession(input) {
|
|
923
925
|
const startedAt = Date.now();
|
|
924
926
|
const promptText = input.prompt?.trim() ?? "";
|
|
@@ -1539,6 +1541,19 @@ function normalizePermissionRequest(permission) {
|
|
|
1539
1541
|
sessionID
|
|
1540
1542
|
};
|
|
1541
1543
|
}
|
|
1544
|
+
function normalizeConfiguredPluginSpecs(value) {
|
|
1545
|
+
if (!Array.isArray(value)) return [];
|
|
1546
|
+
const normalizedPlugins = [];
|
|
1547
|
+
const seenPlugins = /* @__PURE__ */ new Set();
|
|
1548
|
+
for (const item of value) {
|
|
1549
|
+
if (typeof item !== "string") continue;
|
|
1550
|
+
const normalizedItem = item.trim();
|
|
1551
|
+
if (normalizedItem.length === 0 || seenPlugins.has(normalizedItem)) continue;
|
|
1552
|
+
seenPlugins.add(normalizedItem);
|
|
1553
|
+
normalizedPlugins.push(normalizedItem);
|
|
1554
|
+
}
|
|
1555
|
+
return normalizedPlugins;
|
|
1556
|
+
}
|
|
1542
1557
|
function normalizePermissionPatterns$1(permission) {
|
|
1543
1558
|
if (Array.isArray(permission.patterns)) return permission.patterns.filter((value) => typeof value === "string");
|
|
1544
1559
|
if (typeof permission.pattern === "string" && permission.pattern.trim().length > 0) return [permission.pattern];
|
|
@@ -1739,7 +1754,7 @@ async function readStateFile(filePath, createDefaultState) {
|
|
|
1739
1754
|
const content = await readFile(filePath, "utf8");
|
|
1740
1755
|
return JSON.parse(content);
|
|
1741
1756
|
} catch (error) {
|
|
1742
|
-
if (isMissingFileError
|
|
1757
|
+
if (isMissingFileError(error)) return createDefaultState();
|
|
1743
1758
|
throw error;
|
|
1744
1759
|
}
|
|
1745
1760
|
}
|
|
@@ -1752,7 +1767,7 @@ async function writeStateFile(filePath, state) {
|
|
|
1752
1767
|
function cloneState(state) {
|
|
1753
1768
|
return JSON.parse(JSON.stringify(state));
|
|
1754
1769
|
}
|
|
1755
|
-
function isMissingFileError
|
|
1770
|
+
function isMissingFileError(error) {
|
|
1756
1771
|
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
1757
1772
|
}
|
|
1758
1773
|
//#endregion
|
|
@@ -2056,27 +2071,30 @@ var GetPathUseCase = class {
|
|
|
2056
2071
|
//#endregion
|
|
2057
2072
|
//#region src/use-cases/get-status.usecase.ts
|
|
2058
2073
|
var GetStatusUseCase = class {
|
|
2059
|
-
constructor(getHealthUseCase, getPathUseCase, listLspUseCase, listMcpUseCase, listSessionsUseCase, sessionRepo) {
|
|
2074
|
+
constructor(getHealthUseCase, getPathUseCase, listLspUseCase, listMcpUseCase, listSessionsUseCase, sessionRepo, configuredPluginReader) {
|
|
2060
2075
|
this.getHealthUseCase = getHealthUseCase;
|
|
2061
2076
|
this.getPathUseCase = getPathUseCase;
|
|
2062
2077
|
this.listLspUseCase = listLspUseCase;
|
|
2063
2078
|
this.listMcpUseCase = listMcpUseCase;
|
|
2064
2079
|
this.listSessionsUseCase = listSessionsUseCase;
|
|
2065
2080
|
this.sessionRepo = sessionRepo;
|
|
2081
|
+
this.configuredPluginReader = configuredPluginReader;
|
|
2066
2082
|
}
|
|
2067
2083
|
async execute(input) {
|
|
2068
|
-
const [health, path, lsp, mcp] = await Promise.allSettled([
|
|
2084
|
+
const [health, path, lsp, mcp, plugins] = await Promise.allSettled([
|
|
2069
2085
|
this.getHealthUseCase.execute(),
|
|
2070
2086
|
this.getPathUseCase.execute(),
|
|
2071
2087
|
this.listLspUseCase.execute({ chatId: input.chatId }),
|
|
2072
|
-
this.listMcpUseCase.execute({ chatId: input.chatId })
|
|
2088
|
+
this.listMcpUseCase.execute({ chatId: input.chatId }),
|
|
2089
|
+
this.configuredPluginReader.listConfiguredPlugins()
|
|
2073
2090
|
]);
|
|
2074
2091
|
const pathResult = mapSettledResult(path);
|
|
2075
|
-
const
|
|
2092
|
+
const pluginResult = loadConfiguredPluginsResult(plugins);
|
|
2093
|
+
const workspace = await loadWorkspaceStatusResult(input.chatId, pathResult, this.listSessionsUseCase, this.sessionRepo);
|
|
2076
2094
|
return {
|
|
2077
2095
|
health: mapSettledResult(health),
|
|
2078
2096
|
path: pathResult,
|
|
2079
|
-
plugins,
|
|
2097
|
+
plugins: pluginResult,
|
|
2080
2098
|
workspace,
|
|
2081
2099
|
lsp: mapSettledResult(lsp),
|
|
2082
2100
|
mcp: mapSettledResult(mcp)
|
|
@@ -2093,49 +2111,14 @@ function mapSettledResult(result) {
|
|
|
2093
2111
|
status: "error"
|
|
2094
2112
|
};
|
|
2095
2113
|
}
|
|
2096
|
-
|
|
2097
|
-
if (
|
|
2098
|
-
error:
|
|
2114
|
+
function loadConfiguredPluginsResult(result) {
|
|
2115
|
+
if (result.status === "rejected") return {
|
|
2116
|
+
error: result.reason,
|
|
2099
2117
|
status: "error"
|
|
2100
2118
|
};
|
|
2101
|
-
try {
|
|
2102
|
-
return {
|
|
2103
|
-
data: await loadConfiguredPlugins(path.data.config),
|
|
2104
|
-
status: "ok"
|
|
2105
|
-
};
|
|
2106
|
-
} catch (error) {
|
|
2107
|
-
return {
|
|
2108
|
-
error,
|
|
2109
|
-
status: "error"
|
|
2110
|
-
};
|
|
2111
|
-
}
|
|
2112
|
-
}
|
|
2113
|
-
async function loadConfiguredPlugins(configFilePath) {
|
|
2114
|
-
const resolvedConfigFilePath = await resolveOpenCodeConfigFilePath(configFilePath);
|
|
2115
|
-
let content;
|
|
2116
|
-
try {
|
|
2117
|
-
content = await readFile(resolvedConfigFilePath, "utf8");
|
|
2118
|
-
} catch (error) {
|
|
2119
|
-
if (isMissingFileError(error)) return {
|
|
2120
|
-
configFilePath: resolvedConfigFilePath,
|
|
2121
|
-
plugins: []
|
|
2122
|
-
};
|
|
2123
|
-
throw error;
|
|
2124
|
-
}
|
|
2125
|
-
const parseErrors = [];
|
|
2126
|
-
const parsed = parse(content, parseErrors, { allowTrailingComma: true });
|
|
2127
|
-
if (parseErrors.length > 0) {
|
|
2128
|
-
const errorSummary = parseErrors.map((error) => printParseErrorCode(error.error)).join(", ");
|
|
2129
|
-
throw new Error(`Failed to parse ${resolvedConfigFilePath}: ${errorSummary}`);
|
|
2130
|
-
}
|
|
2131
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {
|
|
2132
|
-
configFilePath: resolvedConfigFilePath,
|
|
2133
|
-
plugins: []
|
|
2134
|
-
};
|
|
2135
|
-
const pluginSpecs = Array.isArray(parsed.plugin) ? parsed.plugin : [];
|
|
2136
2119
|
return {
|
|
2137
|
-
|
|
2138
|
-
|
|
2120
|
+
data: { plugins: normalizeConfiguredPluginLabels(result.value) },
|
|
2121
|
+
status: "ok"
|
|
2139
2122
|
};
|
|
2140
2123
|
}
|
|
2141
2124
|
async function loadWorkspaceStatusResult(chatId, path, listSessionsUseCase, sessionRepo) {
|
|
@@ -2178,17 +2161,43 @@ function isUsableWorkspacePath(value) {
|
|
|
2178
2161
|
const normalized = value.trim();
|
|
2179
2162
|
return normalized.length > 0 && normalized !== "/" && normalized !== "\\" && isAbsolute(normalized);
|
|
2180
2163
|
}
|
|
2181
|
-
|
|
2164
|
+
function normalizeConfiguredPluginLabels(plugins) {
|
|
2165
|
+
const normalizedPlugins = [];
|
|
2166
|
+
const seenPlugins = /* @__PURE__ */ new Set();
|
|
2167
|
+
for (const plugin of plugins) {
|
|
2168
|
+
const normalizedPlugin = normalizeConfiguredPluginLabel(plugin);
|
|
2169
|
+
if (normalizedPlugin.length === 0 || seenPlugins.has(normalizedPlugin)) continue;
|
|
2170
|
+
seenPlugins.add(normalizedPlugin);
|
|
2171
|
+
normalizedPlugins.push(normalizedPlugin);
|
|
2172
|
+
}
|
|
2173
|
+
return normalizedPlugins;
|
|
2174
|
+
}
|
|
2175
|
+
function normalizeConfiguredPluginLabel(plugin) {
|
|
2176
|
+
const normalizedPlugin = plugin.trim();
|
|
2177
|
+
const localPluginName = extractLocalPluginName(normalizedPlugin);
|
|
2178
|
+
return localPluginName ? `${localPluginName} (local plugin)` : normalizedPlugin;
|
|
2179
|
+
}
|
|
2180
|
+
function extractLocalPluginName(plugin) {
|
|
2181
|
+
const filePath = parseFilePluginPath(plugin);
|
|
2182
|
+
if (!filePath) return null;
|
|
2183
|
+
const pathSegments = filePath.split("/").filter((segment) => segment.length > 0);
|
|
2184
|
+
const fileName = pathSegments.at(-1);
|
|
2185
|
+
const parentDirectoryName = pathSegments.at(-2);
|
|
2186
|
+
if (!fileName || parentDirectoryName !== "plugins") return null;
|
|
2187
|
+
const pluginName = fileName.replace(/\.(?:[cm]?js|[cm]?ts)$/iu, "");
|
|
2188
|
+
return pluginName.trim().length > 0 ? pluginName.trim() : null;
|
|
2189
|
+
}
|
|
2190
|
+
function parseFilePluginPath(plugin) {
|
|
2191
|
+
if (!plugin.startsWith("file://")) return null;
|
|
2182
2192
|
try {
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2193
|
+
const fileUrl = new URL(plugin);
|
|
2194
|
+
if (fileUrl.protocol !== "file:") return null;
|
|
2195
|
+
const normalizedPath = decodeURIComponent(fileUrl.pathname).replace(/^\/([A-Za-z]:)/u, "$1").replace(/\\/gu, "/");
|
|
2196
|
+
return normalizedPath.length > 0 ? normalizedPath : null;
|
|
2197
|
+
} catch {
|
|
2198
|
+
return null;
|
|
2187
2199
|
}
|
|
2188
2200
|
}
|
|
2189
|
-
function isMissingFileError(error) {
|
|
2190
|
-
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
2191
|
-
}
|
|
2192
2201
|
function isSelectableAgent(agent) {
|
|
2193
2202
|
return !agent.hidden && agent.mode !== "subagent";
|
|
2194
2203
|
}
|
|
@@ -2798,7 +2807,7 @@ function createContainer(config, opencodeClient, logger) {
|
|
|
2798
2807
|
const listLspUseCase = new ListLspUseCase(sessionRepo, opencodeClient);
|
|
2799
2808
|
const listMcpUseCase = new ListMcpUseCase(sessionRepo, opencodeClient);
|
|
2800
2809
|
const listSessionsUseCase = new ListSessionsUseCase(sessionRepo, opencodeClient);
|
|
2801
|
-
const getStatusUseCase = new GetStatusUseCase(getHealthUseCase, getPathUseCase, listLspUseCase, listMcpUseCase, listSessionsUseCase, sessionRepo);
|
|
2810
|
+
const getStatusUseCase = new GetStatusUseCase(getHealthUseCase, getPathUseCase, listLspUseCase, listMcpUseCase, listSessionsUseCase, sessionRepo, opencodeClient);
|
|
2802
2811
|
const listModelsUseCase = new ListModelsUseCase(sessionRepo, opencodeClient);
|
|
2803
2812
|
const renameSessionUseCase = new RenameSessionUseCase(sessionRepo, opencodeClient, opencodeLogger);
|
|
2804
2813
|
const sendPromptUseCase = new SendPromptUseCase(sessionRepo, opencodeClient, promptLogger);
|
|
@@ -3015,11 +3024,7 @@ async function handleSessionIdle(runtime, event) {
|
|
|
3015
3024
|
component: "plugin-event",
|
|
3016
3025
|
sessionId: event.sessionId
|
|
3017
3026
|
});
|
|
3018
|
-
if (runtime.container.foregroundSessionTracker.clear(event.sessionId)) {
|
|
3019
|
-
logPluginEvent(logger, { event: "plugin-event.session.idle.foreground_suppressed" }, "session idle notification suppressed for foreground Telegram session");
|
|
3020
|
-
return;
|
|
3021
|
-
}
|
|
3022
|
-
await notifyBoundChats(runtime, event.sessionId, `Session finished.\n\nSession: ${event.sessionId}`);
|
|
3027
|
+
if (runtime.container.foregroundSessionTracker.clear(event.sessionId)) logPluginEvent(logger, { event: "plugin-event.session.idle.foreground_suppressed" }, "session idle notification suppressed for foreground Telegram session");
|
|
3023
3028
|
}
|
|
3024
3029
|
async function handleSessionStatus(runtime, event) {
|
|
3025
3030
|
if (event.statusType !== "idle") return;
|
|
@@ -3115,14 +3120,16 @@ function normalizePermissionReply(value) {
|
|
|
3115
3120
|
function extractSessionErrorMessage(error) {
|
|
3116
3121
|
if (error instanceof Error && error.message.trim().length > 0) return error.message.trim();
|
|
3117
3122
|
if (!isPlainRecord(error)) return null;
|
|
3123
|
+
if (typeof error.message === "string" && error.message.trim().length > 0) return error.message.trim();
|
|
3118
3124
|
if (isPlainRecord(error.data) && typeof error.data.message === "string" && error.data.message.trim().length > 0) return error.data.message.trim();
|
|
3119
3125
|
return asNonEmptyString(error.name);
|
|
3120
3126
|
}
|
|
3121
3127
|
function normalizeForegroundSessionError(error) {
|
|
3122
3128
|
if (error instanceof Error) return error;
|
|
3123
|
-
if (isPlainRecord(error)
|
|
3129
|
+
if (isPlainRecord(error)) {
|
|
3124
3130
|
const normalized = new Error(extractSessionErrorMessage(error) ?? "Unknown session error.");
|
|
3125
|
-
|
|
3131
|
+
const normalizedName = asNonEmptyString(error.name);
|
|
3132
|
+
if (normalizedName) normalized.name = normalizedName;
|
|
3126
3133
|
if (isPlainRecord(error.data)) normalized.data = error.data;
|
|
3127
3134
|
return normalized;
|
|
3128
3135
|
}
|
|
@@ -3915,14 +3922,18 @@ function normalizeError(error, copy) {
|
|
|
3915
3922
|
message: copy.errors.contextOverflow,
|
|
3916
3923
|
cause: extractMessage(error.data) ?? null
|
|
3917
3924
|
};
|
|
3918
|
-
if (isNamedError(error, "APIError"))
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3925
|
+
if (isNamedError(error, "APIError")) {
|
|
3926
|
+
const providerMessage = extractMessage(error.data);
|
|
3927
|
+
return {
|
|
3928
|
+
message: copy.errors.providerRequest,
|
|
3929
|
+
cause: joinNonEmptyParts([
|
|
3930
|
+
getProviderCompatibilityHint(providerMessage),
|
|
3931
|
+
providerMessage,
|
|
3932
|
+
extractStatusCode(error.data, copy),
|
|
3933
|
+
extractRetryable(error.data, copy)
|
|
3934
|
+
])
|
|
3935
|
+
};
|
|
3936
|
+
}
|
|
3926
3937
|
if (isNamedError(error, "NotFoundError")) return {
|
|
3927
3938
|
message: copy.errors.notFound,
|
|
3928
3939
|
cause: extractMessage(error.data) ?? null
|
|
@@ -3940,6 +3951,10 @@ function normalizeError(error, copy) {
|
|
|
3940
3951
|
cause: extractMessage(error) ?? stringifyUnknown(error)
|
|
3941
3952
|
};
|
|
3942
3953
|
}
|
|
3954
|
+
function getProviderCompatibilityHint(message) {
|
|
3955
|
+
if (!message) return null;
|
|
3956
|
+
return /tool_choice parameter does not support being set to required or object in thinking mode/iu.test(message) ? "Current model/reasoning mode is incompatible with tool calling. Switch to a compatible model or disable thinking mode." : null;
|
|
3957
|
+
}
|
|
3943
3958
|
function isBadRequestError(error) {
|
|
3944
3959
|
return !!error && typeof error === "object" && "success" in error && error.success === false;
|
|
3945
3960
|
}
|
|
@@ -4369,7 +4384,7 @@ function getStatusLayoutCopy(copy) {
|
|
|
4369
4384
|
mcpNotesLabel: "Notes",
|
|
4370
4385
|
mcpRegistrationRequiredStatus: "🟡",
|
|
4371
4386
|
mcpTitle: "🔌 MCP",
|
|
4372
|
-
noPluginsMessage: "No plugins
|
|
4387
|
+
noPluginsMessage: "No plugins detected in the current OpenCode setup.",
|
|
4373
4388
|
noneStatus: "⚪",
|
|
4374
4389
|
openCodeVersionLabel: "OpenCode Version",
|
|
4375
4390
|
overviewTitle: "🖥️ Overview",
|
|
@@ -4390,7 +4405,7 @@ function getStatusLayoutCopy(copy) {
|
|
|
4390
4405
|
mcpNotesLabel: "補足",
|
|
4391
4406
|
mcpRegistrationRequiredStatus: "🟡",
|
|
4392
4407
|
mcpTitle: "🔌 MCP",
|
|
4393
|
-
noPluginsMessage: "現在の OpenCode
|
|
4408
|
+
noPluginsMessage: "現在の OpenCode 構成ではプラグインが検出されていません。",
|
|
4394
4409
|
noneStatus: "⚪",
|
|
4395
4410
|
openCodeVersionLabel: "OpenCode バージョン",
|
|
4396
4411
|
overviewTitle: "🖥️ 概要",
|
|
@@ -4411,7 +4426,7 @@ function getStatusLayoutCopy(copy) {
|
|
|
4411
4426
|
mcpNotesLabel: "说明",
|
|
4412
4427
|
mcpRegistrationRequiredStatus: "🟡",
|
|
4413
4428
|
mcpTitle: "🔌 MCP",
|
|
4414
|
-
noPluginsMessage: "当前 OpenCode
|
|
4429
|
+
noPluginsMessage: "当前 OpenCode 环境中未检测到插件。",
|
|
4415
4430
|
noneStatus: "⚪",
|
|
4416
4431
|
openCodeVersionLabel: "OpenCode版本",
|
|
4417
4432
|
overviewTitle: "🖥️ 概览",
|
|
@@ -5832,14 +5847,15 @@ function getTelegramBotRuntimeRegistry() {
|
|
|
5832
5847
|
//#region src/plugin.ts
|
|
5833
5848
|
async function ensureTelegramBotPluginRuntime(options) {
|
|
5834
5849
|
const runtimeStateHolder = getTelegramBotPluginRuntimeStateHolder();
|
|
5835
|
-
const
|
|
5836
|
-
if (runtimeStateHolder.state && runtimeStateHolder.state.
|
|
5850
|
+
const explicitCwd = resolveExplicitPluginRuntimeCwd(options.context);
|
|
5851
|
+
if (runtimeStateHolder.state && explicitCwd === null) return runtimeStateHolder.state.runtimePromise;
|
|
5852
|
+
if (runtimeStateHolder.state && explicitCwd !== null && runtimeStateHolder.state.cwd !== explicitCwd) {
|
|
5837
5853
|
const activeState = runtimeStateHolder.state;
|
|
5838
5854
|
runtimeStateHolder.state = null;
|
|
5839
5855
|
await disposeTelegramBotPluginRuntimeState(activeState);
|
|
5840
5856
|
}
|
|
5841
5857
|
if (!runtimeStateHolder.state) {
|
|
5842
|
-
const runtimePromise = startPluginRuntime(options,
|
|
5858
|
+
const runtimePromise = startPluginRuntime(options, resolvePluginRuntimeCwd(options.context), requirePluginClient(options.context)).then((runtime) => {
|
|
5843
5859
|
if (runtimeStateHolder.state?.runtimePromise === runtimePromise) runtimeStateHolder.state.runtime = runtime;
|
|
5844
5860
|
return runtime;
|
|
5845
5861
|
}).catch((error) => {
|
|
@@ -5847,7 +5863,7 @@ async function ensureTelegramBotPluginRuntime(options) {
|
|
|
5847
5863
|
throw error;
|
|
5848
5864
|
});
|
|
5849
5865
|
runtimeStateHolder.state = {
|
|
5850
|
-
cwd,
|
|
5866
|
+
cwd: explicitCwd ?? resolvePluginRuntimeCwd(options.context),
|
|
5851
5867
|
runtime: null,
|
|
5852
5868
|
runtimePromise
|
|
5853
5869
|
};
|
|
@@ -5864,7 +5880,7 @@ async function resetTelegramBotPluginRuntimeForTests() {
|
|
|
5864
5880
|
runtimeStateHolder.state = null;
|
|
5865
5881
|
await disposeTelegramBotPluginRuntimeState(activeState);
|
|
5866
5882
|
}
|
|
5867
|
-
async function startPluginRuntime(options, cwd) {
|
|
5883
|
+
async function startPluginRuntime(options, cwd, client) {
|
|
5868
5884
|
const bootstrapApp = options.bootstrapApp ?? bootstrapPluginApp;
|
|
5869
5885
|
const prepareConfiguration = options.prepareConfiguration ?? preparePluginConfiguration;
|
|
5870
5886
|
const startRuntime = options.startRuntime ?? startTelegramBotRuntime;
|
|
@@ -5872,7 +5888,7 @@ async function startPluginRuntime(options, cwd) {
|
|
|
5872
5888
|
cwd,
|
|
5873
5889
|
config: options.config
|
|
5874
5890
|
});
|
|
5875
|
-
const { config, container } = bootstrapApp(
|
|
5891
|
+
const { config, container } = bootstrapApp(client, preparedConfiguration.config, { cwd: preparedConfiguration.cwd });
|
|
5876
5892
|
try {
|
|
5877
5893
|
if (preparedConfiguration.ignoredProjectConfigFilePath) container.logger.child({ component: "runtime" }).warn({
|
|
5878
5894
|
cwd: preparedConfiguration.cwd,
|
|
@@ -5899,7 +5915,19 @@ async function startPluginRuntime(options, cwd) {
|
|
|
5899
5915
|
}
|
|
5900
5916
|
}
|
|
5901
5917
|
function resolvePluginRuntimeCwd(context) {
|
|
5902
|
-
return context
|
|
5918
|
+
return resolveExplicitPluginRuntimeCwd(context) ?? process.cwd();
|
|
5919
|
+
}
|
|
5920
|
+
function resolveExplicitPluginRuntimeCwd(context) {
|
|
5921
|
+
return normalizePluginRuntimePath(context?.worktree) ?? normalizePluginRuntimePath(context?.directory);
|
|
5922
|
+
}
|
|
5923
|
+
function requirePluginClient(context) {
|
|
5924
|
+
if (context?.client) return context.client;
|
|
5925
|
+
throw new Error("OpenCode plugin context.client is required.");
|
|
5926
|
+
}
|
|
5927
|
+
function normalizePluginRuntimePath(value) {
|
|
5928
|
+
if (typeof value !== "string") return null;
|
|
5929
|
+
const normalized = value.trim();
|
|
5930
|
+
return normalized.length > 0 ? normalized : null;
|
|
5903
5931
|
}
|
|
5904
5932
|
async function disposeTelegramBotPluginRuntimeState(state) {
|
|
5905
5933
|
await (state.runtime ?? await state.runtimePromise.catch(() => null))?.dispose();
|