oh-my-opencode 3.6.0 → 3.7.0
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 +6 -6
- package/README.ko.md +6 -6
- package/README.md +6 -6
- package/README.zh-cn.md +6 -6
- package/dist/agents/sisyphus-junior/gpt.d.ts +4 -14
- package/dist/cli/index.js +357 -104
- package/dist/cli/run/event-handlers.d.ts +1 -0
- package/dist/cli/run/opencode-bin-path.d.ts +3 -0
- package/dist/cli/run/opencode-binary-resolver.d.ts +5 -0
- package/dist/cli/run/session-resolver.d.ts +1 -0
- package/dist/cli/run/types.d.ts +29 -0
- package/dist/config/schema/browser-automation.d.ts +2 -0
- package/dist/config/schema/experimental.d.ts +1 -0
- package/dist/config/schema/hooks.d.ts +1 -0
- package/dist/config/schema/oh-my-opencode-config.d.ts +3 -0
- package/dist/create-hooks.d.ts +3 -0
- package/dist/create-managers.d.ts +1 -0
- package/dist/features/background-agent/manager.d.ts +3 -0
- package/dist/features/builtin-skills/skills/index.d.ts +1 -0
- package/dist/features/builtin-skills/skills/playwright-cli.d.ts +10 -0
- package/dist/features/tmux-subagent/action-executor-core.d.ts +21 -0
- package/dist/features/tmux-subagent/action-executor.d.ts +3 -12
- package/dist/features/tmux-subagent/grid-planning.d.ts +2 -2
- package/dist/features/tmux-subagent/pane-split-availability.d.ts +3 -2
- package/dist/features/tmux-subagent/polling-manager.d.ts +1 -0
- package/dist/features/tmux-subagent/spawn-target-finder.d.ts +1 -1
- package/dist/hooks/context-window-monitor.d.ts +5 -1
- package/dist/hooks/directory-agents-injector/hook.d.ts +3 -1
- package/dist/hooks/directory-readme-injector/hook.d.ts +3 -1
- package/dist/hooks/hashline-read-enhancer/hook.d.ts +18 -0
- package/dist/hooks/hashline-read-enhancer/index.d.ts +1 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/preemptive-compaction.d.ts +4 -1
- package/dist/hooks/rules-injector/hook.d.ts +3 -1
- package/dist/hooks/think-mode/switcher.d.ts +7 -0
- package/dist/hooks/tool-output-truncator.d.ts +3 -0
- package/dist/index.js +1758 -830
- package/dist/plugin/hooks/create-core-hooks.d.ts +3 -0
- package/dist/plugin/hooks/create-session-hooks.d.ts +2 -0
- package/dist/plugin/hooks/create-tool-guard-hooks.d.ts +4 -1
- package/dist/shared/dynamic-truncator.d.ts +7 -3
- package/dist/shared/fallback-model-availability.d.ts +9 -2
- package/dist/shared/git-worktree/index.d.ts +2 -0
- package/dist/shared/git-worktree/parse-status-porcelain-line.d.ts +6 -0
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/model-availability.d.ts +0 -5
- package/dist/shared/session-directory-resolver.d.ts +7 -0
- package/dist/shared/tmux/tmux-utils/layout.d.ts +2 -2
- package/dist/tools/call-omo-agent/tools.d.ts +1 -1
- package/dist/tools/delegate-task/sync-prompt-sender.d.ts +7 -1
- package/dist/tools/hashline-edit/constants.d.ts +2 -0
- package/dist/tools/hashline-edit/edit-operations.d.ts +6 -0
- package/dist/tools/hashline-edit/hash-computation.d.ts +3 -0
- package/dist/tools/hashline-edit/index.d.ts +7 -0
- package/dist/tools/hashline-edit/tools.d.ts +2 -0
- package/dist/tools/hashline-edit/types.d.ts +22 -0
- package/dist/tools/hashline-edit/validation.d.ts +6 -0
- package/dist/tools/index.d.ts +1 -0
- package/package.json +8 -8
package/dist/cli/index.js
CHANGED
|
@@ -4930,10 +4930,7 @@ function normalizeSDKResponse(response, fallback, options) {
|
|
|
4930
4930
|
}
|
|
4931
4931
|
|
|
4932
4932
|
// src/shared/dynamic-truncator.ts
|
|
4933
|
-
var
|
|
4934
|
-
var init_dynamic_truncator = __esm(() => {
|
|
4935
|
-
ANTHROPIC_ACTUAL_LIMIT = process.env.ANTHROPIC_1M_CONTEXT === "true" || process.env.VERTEX_ANTHROPIC_1M_CONTEXT === "true" ? 1e6 : 200000;
|
|
4936
|
-
});
|
|
4933
|
+
var init_dynamic_truncator = () => {};
|
|
4937
4934
|
|
|
4938
4935
|
// src/shared/data-path.ts
|
|
4939
4936
|
import * as path2 from "path";
|
|
@@ -7007,6 +7004,18 @@ var init_model_resolver = __esm(() => {
|
|
|
7007
7004
|
init_model_resolution_pipeline();
|
|
7008
7005
|
});
|
|
7009
7006
|
|
|
7007
|
+
// src/shared/model-name-matcher.ts
|
|
7008
|
+
var init_model_name_matcher = __esm(() => {
|
|
7009
|
+
init_logger();
|
|
7010
|
+
});
|
|
7011
|
+
|
|
7012
|
+
// src/shared/fallback-model-availability.ts
|
|
7013
|
+
var init_fallback_model_availability = __esm(() => {
|
|
7014
|
+
init_connected_providers_cache();
|
|
7015
|
+
init_logger();
|
|
7016
|
+
init_model_name_matcher();
|
|
7017
|
+
});
|
|
7018
|
+
|
|
7010
7019
|
// src/features/hook-message-injector/constants.ts
|
|
7011
7020
|
var init_constants = __esm(() => {
|
|
7012
7021
|
init_shared();
|
|
@@ -7045,6 +7054,26 @@ var init_opencode_message_dir = __esm(() => {
|
|
|
7045
7054
|
});
|
|
7046
7055
|
|
|
7047
7056
|
// src/shared/agent-display-names.ts
|
|
7057
|
+
function getAgentDisplayName(configKey) {
|
|
7058
|
+
const exactMatch = AGENT_DISPLAY_NAMES[configKey];
|
|
7059
|
+
if (exactMatch !== undefined)
|
|
7060
|
+
return exactMatch;
|
|
7061
|
+
const lowerKey = configKey.toLowerCase();
|
|
7062
|
+
for (const [k, v] of Object.entries(AGENT_DISPLAY_NAMES)) {
|
|
7063
|
+
if (k.toLowerCase() === lowerKey)
|
|
7064
|
+
return v;
|
|
7065
|
+
}
|
|
7066
|
+
return configKey;
|
|
7067
|
+
}
|
|
7068
|
+
function getAgentConfigKey(agentName) {
|
|
7069
|
+
const lower = agentName.toLowerCase();
|
|
7070
|
+
const reversed = REVERSE_DISPLAY_NAMES[lower];
|
|
7071
|
+
if (reversed !== undefined)
|
|
7072
|
+
return reversed;
|
|
7073
|
+
if (AGENT_DISPLAY_NAMES[lower] !== undefined)
|
|
7074
|
+
return lower;
|
|
7075
|
+
return lower;
|
|
7076
|
+
}
|
|
7048
7077
|
var AGENT_DISPLAY_NAMES, REVERSE_DISPLAY_NAMES;
|
|
7049
7078
|
var init_agent_display_names = __esm(() => {
|
|
7050
7079
|
AGENT_DISPLAY_NAMES = {
|
|
@@ -7166,10 +7195,15 @@ async function getAvailableServerPort(preferredPort = DEFAULT_SERVER_PORT, hostn
|
|
|
7166
7195
|
}
|
|
7167
7196
|
var DEFAULT_SERVER_PORT = 4096, MAX_PORT_ATTEMPTS = 20;
|
|
7168
7197
|
var init_port_utils = () => {};
|
|
7198
|
+
// src/shared/git-worktree/parse-status-porcelain.ts
|
|
7199
|
+
var init_parse_status_porcelain = () => {};
|
|
7169
7200
|
// src/shared/git-worktree/collect-git-diff-stats.ts
|
|
7170
|
-
var init_collect_git_diff_stats = () => {
|
|
7201
|
+
var init_collect_git_diff_stats = __esm(() => {
|
|
7202
|
+
init_parse_status_porcelain();
|
|
7203
|
+
});
|
|
7171
7204
|
// src/shared/git-worktree/index.ts
|
|
7172
7205
|
var init_git_worktree = __esm(() => {
|
|
7206
|
+
init_parse_status_porcelain();
|
|
7173
7207
|
init_collect_git_diff_stats();
|
|
7174
7208
|
});
|
|
7175
7209
|
|
|
@@ -7177,6 +7211,9 @@ var init_git_worktree = __esm(() => {
|
|
|
7177
7211
|
var init_safe_create_hook = __esm(() => {
|
|
7178
7212
|
init_logger();
|
|
7179
7213
|
});
|
|
7214
|
+
// src/shared/session-directory-resolver.ts
|
|
7215
|
+
var init_session_directory_resolver = () => {};
|
|
7216
|
+
|
|
7180
7217
|
// src/shared/index.ts
|
|
7181
7218
|
var init_shared = __esm(() => {
|
|
7182
7219
|
init_model_resolution_pipeline();
|
|
@@ -7207,6 +7244,7 @@ var init_shared = __esm(() => {
|
|
|
7207
7244
|
init_model_requirements();
|
|
7208
7245
|
init_model_resolver();
|
|
7209
7246
|
init_model_availability();
|
|
7247
|
+
init_fallback_model_availability();
|
|
7210
7248
|
init_connected_providers_cache();
|
|
7211
7249
|
init_session_utils();
|
|
7212
7250
|
init_tmux();
|
|
@@ -7218,6 +7256,7 @@ var init_shared = __esm(() => {
|
|
|
7218
7256
|
init_safe_create_hook();
|
|
7219
7257
|
init_opencode_storage_paths();
|
|
7220
7258
|
init_opencode_message_dir();
|
|
7259
|
+
init_session_directory_resolver();
|
|
7221
7260
|
});
|
|
7222
7261
|
|
|
7223
7262
|
// src/cli/config-manager/config-context.ts
|
|
@@ -8868,6 +8907,7 @@ var init_startup_toasts = __esm(() => {
|
|
|
8868
8907
|
// src/hooks/auto-update-checker/hook.ts
|
|
8869
8908
|
function createAutoUpdateCheckerHook(ctx, options = {}) {
|
|
8870
8909
|
const { showStartupToast = true, isSisyphusEnabled = false, autoUpdate = true } = options;
|
|
8910
|
+
const isCliRunMode = process.env.OPENCODE_CLI_RUN_MODE === "true";
|
|
8871
8911
|
const getToastMessage = (isUpdate, latestVersion) => {
|
|
8872
8912
|
if (isSisyphusEnabled) {
|
|
8873
8913
|
return isUpdate ? `Sisyphus on steroids is steering OpenCode.
|
|
@@ -8881,6 +8921,8 @@ v${latestVersion} available. Restart OpenCode to apply.` : "OpenCode is now on S
|
|
|
8881
8921
|
event: ({ event }) => {
|
|
8882
8922
|
if (event.type !== "session.created")
|
|
8883
8923
|
return;
|
|
8924
|
+
if (isCliRunMode)
|
|
8925
|
+
return;
|
|
8884
8926
|
if (hasChecked)
|
|
8885
8927
|
return;
|
|
8886
8928
|
const props = event.properties;
|
|
@@ -8957,7 +8999,7 @@ var {
|
|
|
8957
8999
|
// package.json
|
|
8958
9000
|
var package_default = {
|
|
8959
9001
|
name: "oh-my-opencode",
|
|
8960
|
-
version: "3.
|
|
9002
|
+
version: "3.7.0",
|
|
8961
9003
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
8962
9004
|
main: "dist/index.js",
|
|
8963
9005
|
types: "dist/index.d.ts",
|
|
@@ -9031,13 +9073,13 @@ var package_default = {
|
|
|
9031
9073
|
typescript: "^5.7.3"
|
|
9032
9074
|
},
|
|
9033
9075
|
optionalDependencies: {
|
|
9034
|
-
"oh-my-opencode-darwin-arm64": "3.
|
|
9035
|
-
"oh-my-opencode-darwin-x64": "3.
|
|
9036
|
-
"oh-my-opencode-linux-arm64": "3.
|
|
9037
|
-
"oh-my-opencode-linux-arm64-musl": "3.
|
|
9038
|
-
"oh-my-opencode-linux-x64": "3.
|
|
9039
|
-
"oh-my-opencode-linux-x64-musl": "3.
|
|
9040
|
-
"oh-my-opencode-windows-x64": "3.
|
|
9076
|
+
"oh-my-opencode-darwin-arm64": "3.7.0",
|
|
9077
|
+
"oh-my-opencode-darwin-x64": "3.7.0",
|
|
9078
|
+
"oh-my-opencode-linux-arm64": "3.7.0",
|
|
9079
|
+
"oh-my-opencode-linux-arm64-musl": "3.7.0",
|
|
9080
|
+
"oh-my-opencode-linux-x64": "3.7.0",
|
|
9081
|
+
"oh-my-opencode-linux-x64-musl": "3.7.0",
|
|
9082
|
+
"oh-my-opencode-windows-x64": "3.7.0"
|
|
9041
9083
|
},
|
|
9042
9084
|
trustedDependencies: [
|
|
9043
9085
|
"@ast-grep/cli",
|
|
@@ -10145,7 +10187,8 @@ function serializeError(error) {
|
|
|
10145
10187
|
function getSessionTag(ctx, payload) {
|
|
10146
10188
|
const props = payload.properties;
|
|
10147
10189
|
const info = props?.info;
|
|
10148
|
-
const
|
|
10190
|
+
const part = props?.part;
|
|
10191
|
+
const sessionID = props?.sessionID ?? props?.sessionId ?? info?.sessionID ?? info?.sessionId ?? part?.sessionID ?? part?.sessionId;
|
|
10149
10192
|
const isMainSession = sessionID === ctx.sessionID;
|
|
10150
10193
|
if (isMainSession)
|
|
10151
10194
|
return import_picocolors5.default.green("[MAIN]");
|
|
@@ -10166,9 +10209,9 @@ function logEventVerbose(ctx, payload) {
|
|
|
10166
10209
|
case "message.part.updated": {
|
|
10167
10210
|
const partProps = props;
|
|
10168
10211
|
const part = partProps?.part;
|
|
10169
|
-
if (part?.type === "tool
|
|
10170
|
-
const
|
|
10171
|
-
console.error(import_picocolors5.default.dim(`${sessionTag} message.part (tool): ${
|
|
10212
|
+
if (part?.type === "tool") {
|
|
10213
|
+
const status = part.state?.status ?? "unknown";
|
|
10214
|
+
console.error(import_picocolors5.default.dim(`${sessionTag} message.part (tool): ${part.tool ?? part.name ?? "?"} [${status}]`));
|
|
10172
10215
|
} else if (part?.type === "text" && part.text) {
|
|
10173
10216
|
const preview = part.text.slice(0, 80).replace(/\n/g, "\\n");
|
|
10174
10217
|
console.error(import_picocolors5.default.dim(`${sessionTag} message.part (text): "${preview}${part.text.length > 80 ? "..." : ""}"`));
|
|
@@ -10225,11 +10268,20 @@ var import_picocolors7 = __toESM(require_picocolors(), 1);
|
|
|
10225
10268
|
|
|
10226
10269
|
// src/cli/run/event-handlers.ts
|
|
10227
10270
|
var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
10271
|
+
function getSessionId(props) {
|
|
10272
|
+
return props?.sessionID ?? props?.sessionId;
|
|
10273
|
+
}
|
|
10274
|
+
function getInfoSessionId(props) {
|
|
10275
|
+
return props?.info?.sessionID ?? props?.info?.sessionId;
|
|
10276
|
+
}
|
|
10277
|
+
function getPartSessionId(props) {
|
|
10278
|
+
return props?.part?.sessionID ?? props?.part?.sessionId;
|
|
10279
|
+
}
|
|
10228
10280
|
function handleSessionIdle(ctx, payload, state) {
|
|
10229
10281
|
if (payload.type !== "session.idle")
|
|
10230
10282
|
return;
|
|
10231
10283
|
const props = payload.properties;
|
|
10232
|
-
if (props
|
|
10284
|
+
if (getSessionId(props) === ctx.sessionID) {
|
|
10233
10285
|
state.mainSessionIdle = true;
|
|
10234
10286
|
}
|
|
10235
10287
|
}
|
|
@@ -10237,7 +10289,7 @@ function handleSessionStatus(ctx, payload, state) {
|
|
|
10237
10289
|
if (payload.type !== "session.status")
|
|
10238
10290
|
return;
|
|
10239
10291
|
const props = payload.properties;
|
|
10240
|
-
if (props
|
|
10292
|
+
if (getSessionId(props) !== ctx.sessionID)
|
|
10241
10293
|
return;
|
|
10242
10294
|
if (props?.status?.type === "busy") {
|
|
10243
10295
|
state.mainSessionIdle = false;
|
|
@@ -10251,7 +10303,7 @@ function handleSessionError(ctx, payload, state) {
|
|
|
10251
10303
|
if (payload.type !== "session.error")
|
|
10252
10304
|
return;
|
|
10253
10305
|
const props = payload.properties;
|
|
10254
|
-
if (props
|
|
10306
|
+
if (getSessionId(props) === ctx.sessionID) {
|
|
10255
10307
|
state.mainSessionError = true;
|
|
10256
10308
|
state.lastError = serializeError(props?.error);
|
|
10257
10309
|
console.error(import_picocolors6.default.red(`
|
|
@@ -10262,11 +10314,11 @@ function handleMessagePartUpdated(ctx, payload, state) {
|
|
|
10262
10314
|
if (payload.type !== "message.part.updated")
|
|
10263
10315
|
return;
|
|
10264
10316
|
const props = payload.properties;
|
|
10265
|
-
|
|
10266
|
-
|
|
10267
|
-
if (
|
|
10317
|
+
const partSid = getPartSessionId(props);
|
|
10318
|
+
const infoSid = getInfoSessionId(props);
|
|
10319
|
+
if ((partSid ?? infoSid) !== ctx.sessionID)
|
|
10268
10320
|
return;
|
|
10269
|
-
const part = props
|
|
10321
|
+
const part = props?.part;
|
|
10270
10322
|
if (!part)
|
|
10271
10323
|
return;
|
|
10272
10324
|
if (part.type === "text" && part.text) {
|
|
@@ -10277,12 +10329,53 @@ function handleMessagePartUpdated(ctx, payload, state) {
|
|
|
10277
10329
|
}
|
|
10278
10330
|
state.lastPartText = part.text;
|
|
10279
10331
|
}
|
|
10332
|
+
if (part.type === "tool") {
|
|
10333
|
+
handleToolPart(ctx, part, state);
|
|
10334
|
+
}
|
|
10335
|
+
}
|
|
10336
|
+
function handleToolPart(_ctx, part, state) {
|
|
10337
|
+
const toolName = part.tool || part.name || "unknown";
|
|
10338
|
+
const status = part.state?.status;
|
|
10339
|
+
if (status === "running") {
|
|
10340
|
+
state.currentTool = toolName;
|
|
10341
|
+
let inputPreview = "";
|
|
10342
|
+
const input = part.state?.input;
|
|
10343
|
+
if (input) {
|
|
10344
|
+
if (input.command) {
|
|
10345
|
+
inputPreview = ` ${import_picocolors6.default.dim(String(input.command).slice(0, 60))}`;
|
|
10346
|
+
} else if (input.pattern) {
|
|
10347
|
+
inputPreview = ` ${import_picocolors6.default.dim(String(input.pattern).slice(0, 40))}`;
|
|
10348
|
+
} else if (input.filePath) {
|
|
10349
|
+
inputPreview = ` ${import_picocolors6.default.dim(String(input.filePath))}`;
|
|
10350
|
+
} else if (input.query) {
|
|
10351
|
+
inputPreview = ` ${import_picocolors6.default.dim(String(input.query).slice(0, 40))}`;
|
|
10352
|
+
}
|
|
10353
|
+
}
|
|
10354
|
+
state.hasReceivedMeaningfulWork = true;
|
|
10355
|
+
process.stdout.write(`
|
|
10356
|
+
${import_picocolors6.default.cyan(">")} ${import_picocolors6.default.bold(toolName)}${inputPreview}
|
|
10357
|
+
`);
|
|
10358
|
+
}
|
|
10359
|
+
if (status === "completed" || status === "error") {
|
|
10360
|
+
const output = part.state?.output || "";
|
|
10361
|
+
const maxLen = 200;
|
|
10362
|
+
const preview = output.length > maxLen ? output.slice(0, maxLen) + "..." : output;
|
|
10363
|
+
if (preview.trim()) {
|
|
10364
|
+
const lines = preview.split(`
|
|
10365
|
+
`).slice(0, 3);
|
|
10366
|
+
process.stdout.write(import_picocolors6.default.dim(` \u2514\u2500 ${lines.join(`
|
|
10367
|
+
`)}
|
|
10368
|
+
`));
|
|
10369
|
+
}
|
|
10370
|
+
state.currentTool = null;
|
|
10371
|
+
state.lastPartText = "";
|
|
10372
|
+
}
|
|
10280
10373
|
}
|
|
10281
10374
|
function handleMessageUpdated(ctx, payload, state) {
|
|
10282
10375
|
if (payload.type !== "message.updated")
|
|
10283
10376
|
return;
|
|
10284
10377
|
const props = payload.properties;
|
|
10285
|
-
if (props
|
|
10378
|
+
if (getInfoSessionId(props) !== ctx.sessionID)
|
|
10286
10379
|
return;
|
|
10287
10380
|
if (props?.info?.role !== "assistant")
|
|
10288
10381
|
return;
|
|
@@ -10294,7 +10387,7 @@ function handleToolExecute(ctx, payload, state) {
|
|
|
10294
10387
|
if (payload.type !== "tool.execute")
|
|
10295
10388
|
return;
|
|
10296
10389
|
const props = payload.properties;
|
|
10297
|
-
if (props
|
|
10390
|
+
if (getSessionId(props) !== ctx.sessionID)
|
|
10298
10391
|
return;
|
|
10299
10392
|
const toolName = props?.name || "unknown";
|
|
10300
10393
|
state.currentTool = toolName;
|
|
@@ -10320,7 +10413,7 @@ function handleToolResult(ctx, payload, state) {
|
|
|
10320
10413
|
if (payload.type !== "tool.result")
|
|
10321
10414
|
return;
|
|
10322
10415
|
const props = payload.properties;
|
|
10323
|
-
if (props
|
|
10416
|
+
if (getSessionId(props) !== ctx.sessionID)
|
|
10324
10417
|
return;
|
|
10325
10418
|
const output = props?.output || "";
|
|
10326
10419
|
const maxLen = 200;
|
|
@@ -10335,6 +10428,25 @@ function handleToolResult(ctx, payload, state) {
|
|
|
10335
10428
|
state.currentTool = null;
|
|
10336
10429
|
state.lastPartText = "";
|
|
10337
10430
|
}
|
|
10431
|
+
function handleTuiToast(_ctx, payload, state) {
|
|
10432
|
+
if (payload.type !== "tui.toast.show")
|
|
10433
|
+
return;
|
|
10434
|
+
const props = payload.properties;
|
|
10435
|
+
const title = props?.title ? `${props.title}: ` : "";
|
|
10436
|
+
const message = props?.message?.trim();
|
|
10437
|
+
const variant = props?.variant ?? "info";
|
|
10438
|
+
if (!message)
|
|
10439
|
+
return;
|
|
10440
|
+
if (variant === "error") {
|
|
10441
|
+
state.mainSessionError = true;
|
|
10442
|
+
state.lastError = `${title}${message}`;
|
|
10443
|
+
console.error(import_picocolors6.default.red(`
|
|
10444
|
+
[tui.toast.error] ${state.lastError}`));
|
|
10445
|
+
return;
|
|
10446
|
+
}
|
|
10447
|
+
const colorize = variant === "warning" ? import_picocolors6.default.yellow : import_picocolors6.default.dim;
|
|
10448
|
+
console.log(colorize(`[toast:${variant}] ${title}${message}`));
|
|
10449
|
+
}
|
|
10338
10450
|
|
|
10339
10451
|
// src/cli/run/event-stream-processor.ts
|
|
10340
10452
|
async function processEvents(ctx, stream, state) {
|
|
@@ -10355,6 +10467,7 @@ async function processEvents(ctx, stream, state) {
|
|
|
10355
10467
|
handleMessageUpdated(ctx, payload, state);
|
|
10356
10468
|
handleToolExecute(ctx, payload, state);
|
|
10357
10469
|
handleToolResult(ctx, payload, state);
|
|
10470
|
+
handleTuiToast(ctx, payload, state);
|
|
10358
10471
|
} catch (err) {
|
|
10359
10472
|
console.error(import_picocolors7.default.red(`[event error] ${err}`));
|
|
10360
10473
|
}
|
|
@@ -22787,7 +22900,8 @@ var BackgroundTaskConfigSchema = exports_external.object({
|
|
|
22787
22900
|
var BrowserAutomationProviderSchema = exports_external.enum([
|
|
22788
22901
|
"playwright",
|
|
22789
22902
|
"agent-browser",
|
|
22790
|
-
"dev-browser"
|
|
22903
|
+
"dev-browser",
|
|
22904
|
+
"playwright-cli"
|
|
22791
22905
|
]);
|
|
22792
22906
|
var BrowserAutomationConfigSchema = exports_external.object({
|
|
22793
22907
|
provider: BrowserAutomationProviderSchema.default("playwright")
|
|
@@ -22886,7 +23000,8 @@ var ExperimentalConfigSchema = exports_external.object({
|
|
|
22886
23000
|
dynamic_context_pruning: DynamicContextPruningConfigSchema.optional(),
|
|
22887
23001
|
task_system: exports_external.boolean().optional(),
|
|
22888
23002
|
plugin_load_timeout_ms: exports_external.number().min(1000).optional(),
|
|
22889
|
-
safe_hook_creation: exports_external.boolean().optional()
|
|
23003
|
+
safe_hook_creation: exports_external.boolean().optional(),
|
|
23004
|
+
hashline_edit: exports_external.boolean().optional()
|
|
22890
23005
|
});
|
|
22891
23006
|
// src/config/schema/git-master.ts
|
|
22892
23007
|
var GitMasterConfigSchema = exports_external.object({
|
|
@@ -22936,7 +23051,8 @@ var HookNameSchema = exports_external.enum([
|
|
|
22936
23051
|
"stop-continuation-guard",
|
|
22937
23052
|
"tasks-todowrite-disabler",
|
|
22938
23053
|
"write-existing-file-guard",
|
|
22939
|
-
"anthropic-effort"
|
|
23054
|
+
"anthropic-effort",
|
|
23055
|
+
"hashline-read-enhancer"
|
|
22940
23056
|
]);
|
|
22941
23057
|
// src/config/schema/notification.ts
|
|
22942
23058
|
var NotificationConfigSchema = exports_external.object({
|
|
@@ -24624,7 +24740,99 @@ async function createOpencode(options) {
|
|
|
24624
24740
|
// src/cli/run/server-connection.ts
|
|
24625
24741
|
init_port_utils();
|
|
24626
24742
|
var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
24743
|
+
|
|
24744
|
+
// src/cli/run/opencode-binary-resolver.ts
|
|
24745
|
+
import { delimiter, dirname, join as join8 } from "path";
|
|
24746
|
+
var OPENCODE_COMMANDS = ["opencode", "opencode-desktop"];
|
|
24747
|
+
var WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"];
|
|
24748
|
+
function getCommandCandidates(platform) {
|
|
24749
|
+
if (platform !== "win32")
|
|
24750
|
+
return [...OPENCODE_COMMANDS];
|
|
24751
|
+
return OPENCODE_COMMANDS.flatMap((command) => WINDOWS_SUFFIXES.map((suffix) => `${command}${suffix}`));
|
|
24752
|
+
}
|
|
24753
|
+
function collectCandidateBinaryPaths(pathEnv, which = Bun.which, platform = process.platform) {
|
|
24754
|
+
const seen = new Set;
|
|
24755
|
+
const candidates = [];
|
|
24756
|
+
const commandCandidates = getCommandCandidates(platform);
|
|
24757
|
+
const addCandidate = (binaryPath) => {
|
|
24758
|
+
if (!binaryPath || seen.has(binaryPath))
|
|
24759
|
+
return;
|
|
24760
|
+
seen.add(binaryPath);
|
|
24761
|
+
candidates.push(binaryPath);
|
|
24762
|
+
};
|
|
24763
|
+
for (const command of commandCandidates) {
|
|
24764
|
+
addCandidate(which(command));
|
|
24765
|
+
}
|
|
24766
|
+
for (const entry of (pathEnv ?? "").split(delimiter).filter(Boolean)) {
|
|
24767
|
+
for (const command of commandCandidates) {
|
|
24768
|
+
addCandidate(join8(entry, command));
|
|
24769
|
+
}
|
|
24770
|
+
}
|
|
24771
|
+
return candidates;
|
|
24772
|
+
}
|
|
24773
|
+
async function canExecuteBinary(binaryPath) {
|
|
24774
|
+
try {
|
|
24775
|
+
const proc = Bun.spawn([binaryPath, "--version"], {
|
|
24776
|
+
stdout: "pipe",
|
|
24777
|
+
stderr: "pipe"
|
|
24778
|
+
});
|
|
24779
|
+
await proc.exited;
|
|
24780
|
+
return proc.exitCode === 0;
|
|
24781
|
+
} catch {
|
|
24782
|
+
return false;
|
|
24783
|
+
}
|
|
24784
|
+
}
|
|
24785
|
+
async function findWorkingOpencodeBinary(pathEnv = process.env.PATH, probe = canExecuteBinary, which = Bun.which, platform = process.platform) {
|
|
24786
|
+
const candidates = collectCandidateBinaryPaths(pathEnv, which, platform);
|
|
24787
|
+
for (const candidate of candidates) {
|
|
24788
|
+
if (await probe(candidate)) {
|
|
24789
|
+
return candidate;
|
|
24790
|
+
}
|
|
24791
|
+
}
|
|
24792
|
+
return null;
|
|
24793
|
+
}
|
|
24794
|
+
function buildPathWithBinaryFirst(pathEnv, binaryPath) {
|
|
24795
|
+
const preferredDir = dirname(binaryPath);
|
|
24796
|
+
const existing = (pathEnv ?? "").split(delimiter).filter((entry) => entry.length > 0 && entry !== preferredDir);
|
|
24797
|
+
return [preferredDir, ...existing].join(delimiter);
|
|
24798
|
+
}
|
|
24799
|
+
async function withWorkingOpencodePath(startServer, finder = findWorkingOpencodeBinary) {
|
|
24800
|
+
const originalPath = process.env.PATH;
|
|
24801
|
+
const binaryPath = await finder(originalPath);
|
|
24802
|
+
if (!binaryPath) {
|
|
24803
|
+
return startServer();
|
|
24804
|
+
}
|
|
24805
|
+
process.env.PATH = buildPathWithBinaryFirst(originalPath, binaryPath);
|
|
24806
|
+
try {
|
|
24807
|
+
return await startServer();
|
|
24808
|
+
} finally {
|
|
24809
|
+
process.env.PATH = originalPath;
|
|
24810
|
+
}
|
|
24811
|
+
}
|
|
24812
|
+
|
|
24813
|
+
// src/cli/run/opencode-bin-path.ts
|
|
24814
|
+
import { delimiter as delimiter2, dirname as dirname2 } from "path";
|
|
24815
|
+
import { createRequire } from "module";
|
|
24816
|
+
var resolveFromCurrentModule = createRequire(import.meta.url).resolve;
|
|
24817
|
+
function prependResolvedOpencodeBinToPath(env = process.env, resolve2 = resolveFromCurrentModule) {
|
|
24818
|
+
let resolvedPath;
|
|
24819
|
+
try {
|
|
24820
|
+
resolvedPath = resolve2("opencode-ai/bin/opencode");
|
|
24821
|
+
} catch {
|
|
24822
|
+
return;
|
|
24823
|
+
}
|
|
24824
|
+
const opencodeBinDir = dirname2(resolvedPath);
|
|
24825
|
+
const currentPath = env.PATH ?? "";
|
|
24826
|
+
const pathSegments = currentPath ? currentPath.split(delimiter2) : [];
|
|
24827
|
+
if (pathSegments.includes(opencodeBinDir)) {
|
|
24828
|
+
return;
|
|
24829
|
+
}
|
|
24830
|
+
env.PATH = currentPath ? `${opencodeBinDir}${delimiter2}${currentPath}` : opencodeBinDir;
|
|
24831
|
+
}
|
|
24832
|
+
|
|
24833
|
+
// src/cli/run/server-connection.ts
|
|
24627
24834
|
async function createServerConnection(options) {
|
|
24835
|
+
prependResolvedOpencodeBinToPath();
|
|
24628
24836
|
const { port, attach, signal } = options;
|
|
24629
24837
|
if (attach !== undefined) {
|
|
24630
24838
|
console.log(import_picocolors8.default.dim("Attaching to existing server at"), import_picocolors8.default.cyan(attach));
|
|
@@ -24638,7 +24846,7 @@ async function createServerConnection(options) {
|
|
|
24638
24846
|
const available = await isPortAvailable(port, "127.0.0.1");
|
|
24639
24847
|
if (available) {
|
|
24640
24848
|
console.log(import_picocolors8.default.dim("Starting server on port"), import_picocolors8.default.cyan(port.toString()));
|
|
24641
|
-
const { client: client5, server: server3 } = await createOpencode({ signal, port, hostname: "127.0.0.1" });
|
|
24849
|
+
const { client: client5, server: server3 } = await withWorkingOpencodePath(() => createOpencode({ signal, port, hostname: "127.0.0.1" }));
|
|
24642
24850
|
console.log(import_picocolors8.default.dim("Server listening at"), import_picocolors8.default.cyan(server3.url));
|
|
24643
24851
|
return { client: client5, cleanup: () => server3.close() };
|
|
24644
24852
|
}
|
|
@@ -24652,7 +24860,7 @@ async function createServerConnection(options) {
|
|
|
24652
24860
|
} else {
|
|
24653
24861
|
console.log(import_picocolors8.default.dim("Starting server on port"), import_picocolors8.default.cyan(selectedPort.toString()));
|
|
24654
24862
|
}
|
|
24655
|
-
const { client: client3, server: server2 } = await createOpencode({ signal, port: selectedPort, hostname: "127.0.0.1" });
|
|
24863
|
+
const { client: client3, server: server2 } = await withWorkingOpencodePath(() => createOpencode({ signal, port: selectedPort, hostname: "127.0.0.1" }));
|
|
24656
24864
|
console.log(import_picocolors8.default.dim("Server listening at"), import_picocolors8.default.cyan(server2.url));
|
|
24657
24865
|
return { client: client3, cleanup: () => server2.close() };
|
|
24658
24866
|
}
|
|
@@ -24662,9 +24870,12 @@ var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
|
24662
24870
|
var SESSION_CREATE_MAX_RETRIES = 3;
|
|
24663
24871
|
var SESSION_CREATE_RETRY_DELAY_MS = 1000;
|
|
24664
24872
|
async function resolveSession(options) {
|
|
24665
|
-
const { client: client3, sessionId } = options;
|
|
24873
|
+
const { client: client3, sessionId, directory } = options;
|
|
24666
24874
|
if (sessionId) {
|
|
24667
|
-
const res = await client3.session.get({
|
|
24875
|
+
const res = await client3.session.get({
|
|
24876
|
+
path: { id: sessionId },
|
|
24877
|
+
query: { directory }
|
|
24878
|
+
});
|
|
24668
24879
|
if (res.error || !res.data) {
|
|
24669
24880
|
throw new Error(`Session not found: ${sessionId}`);
|
|
24670
24881
|
}
|
|
@@ -24677,7 +24888,8 @@ async function resolveSession(options) {
|
|
|
24677
24888
|
permission: [
|
|
24678
24889
|
{ permission: "question", action: "deny", pattern: "*" }
|
|
24679
24890
|
]
|
|
24680
|
-
}
|
|
24891
|
+
},
|
|
24892
|
+
query: { directory }
|
|
24681
24893
|
});
|
|
24682
24894
|
if (res.error) {
|
|
24683
24895
|
console.error(import_picocolors9.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES} failed:`));
|
|
@@ -24764,6 +24976,7 @@ async function executeOnCompleteHook(options) {
|
|
|
24764
24976
|
}
|
|
24765
24977
|
|
|
24766
24978
|
// src/cli/run/agent-resolver.ts
|
|
24979
|
+
init_agent_display_names();
|
|
24767
24980
|
var import_picocolors11 = __toESM(require_picocolors(), 1);
|
|
24768
24981
|
var CORE_AGENT_ORDER = ["sisyphus", "hephaestus", "prometheus", "atlas"];
|
|
24769
24982
|
var DEFAULT_AGENT = "sisyphus";
|
|
@@ -24771,18 +24984,22 @@ var normalizeAgentName = (agent) => {
|
|
|
24771
24984
|
if (!agent)
|
|
24772
24985
|
return;
|
|
24773
24986
|
const trimmed = agent.trim();
|
|
24774
|
-
if (
|
|
24987
|
+
if (trimmed.length === 0)
|
|
24775
24988
|
return;
|
|
24776
|
-
const
|
|
24777
|
-
const
|
|
24778
|
-
|
|
24989
|
+
const configKey = getAgentConfigKey(trimmed);
|
|
24990
|
+
const displayName = getAgentDisplayName(configKey);
|
|
24991
|
+
const isKnownAgent = displayName !== configKey;
|
|
24992
|
+
return {
|
|
24993
|
+
configKey,
|
|
24994
|
+
resolvedName: isKnownAgent ? displayName : trimmed
|
|
24995
|
+
};
|
|
24779
24996
|
};
|
|
24780
|
-
var isAgentDisabled = (
|
|
24781
|
-
const lowered =
|
|
24782
|
-
if (lowered ===
|
|
24997
|
+
var isAgentDisabled = (agentConfigKey, config2) => {
|
|
24998
|
+
const lowered = agentConfigKey.toLowerCase();
|
|
24999
|
+
if (lowered === DEFAULT_AGENT && config2.sisyphus_agent?.disabled === true) {
|
|
24783
25000
|
return true;
|
|
24784
25001
|
}
|
|
24785
|
-
return (config2.disabled_agents ?? []).some((disabled) => disabled
|
|
25002
|
+
return (config2.disabled_agents ?? []).some((disabled) => getAgentConfigKey(disabled) === lowered);
|
|
24786
25003
|
};
|
|
24787
25004
|
var pickFallbackAgent = (config2) => {
|
|
24788
25005
|
for (const agent of CORE_AGENT_ORDER) {
|
|
@@ -24796,19 +25013,22 @@ var resolveRunAgent = (options, pluginConfig, env = process.env) => {
|
|
|
24796
25013
|
const cliAgent = normalizeAgentName(options.agent);
|
|
24797
25014
|
const envAgent = normalizeAgentName(env.OPENCODE_DEFAULT_AGENT);
|
|
24798
25015
|
const configAgent = normalizeAgentName(pluginConfig.default_run_agent);
|
|
24799
|
-
const resolved = cliAgent ?? envAgent ?? configAgent ??
|
|
24800
|
-
|
|
24801
|
-
|
|
25016
|
+
const resolved = cliAgent ?? envAgent ?? configAgent ?? {
|
|
25017
|
+
configKey: DEFAULT_AGENT,
|
|
25018
|
+
resolvedName: getAgentDisplayName(DEFAULT_AGENT)
|
|
25019
|
+
};
|
|
25020
|
+
if (isAgentDisabled(resolved.configKey, pluginConfig)) {
|
|
24802
25021
|
const fallback = pickFallbackAgent(pluginConfig);
|
|
25022
|
+
const fallbackName = getAgentDisplayName(fallback);
|
|
24803
25023
|
const fallbackDisabled = isAgentDisabled(fallback, pluginConfig);
|
|
24804
25024
|
if (fallbackDisabled) {
|
|
24805
|
-
console.log(import_picocolors11.default.yellow(`Requested agent "${
|
|
24806
|
-
return
|
|
25025
|
+
console.log(import_picocolors11.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled and no enabled core agent was found. Proceeding with "${fallbackName}".`));
|
|
25026
|
+
return fallbackName;
|
|
24807
25027
|
}
|
|
24808
|
-
console.log(import_picocolors11.default.yellow(`Requested agent "${
|
|
24809
|
-
return
|
|
25028
|
+
console.log(import_picocolors11.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled. Falling back to "${fallbackName}".`));
|
|
25029
|
+
return fallbackName;
|
|
24810
25030
|
}
|
|
24811
|
-
return
|
|
25031
|
+
return resolved.resolvedName;
|
|
24812
25032
|
};
|
|
24813
25033
|
|
|
24814
25034
|
// src/cli/run/poll-for-completion.ts
|
|
@@ -24832,7 +25052,10 @@ async function checkCompletionConditions(ctx) {
|
|
|
24832
25052
|
}
|
|
24833
25053
|
}
|
|
24834
25054
|
async function areAllTodosComplete(ctx) {
|
|
24835
|
-
const todosRes = await ctx.client.session.todo({
|
|
25055
|
+
const todosRes = await ctx.client.session.todo({
|
|
25056
|
+
path: { id: ctx.sessionID },
|
|
25057
|
+
query: { directory: ctx.directory }
|
|
25058
|
+
});
|
|
24836
25059
|
const todos = normalizeSDKResponse(todosRes, []);
|
|
24837
25060
|
const incompleteTodos = todos.filter((t) => t.status !== "completed" && t.status !== "cancelled");
|
|
24838
25061
|
if (incompleteTodos.length > 0) {
|
|
@@ -24846,12 +25069,15 @@ async function areAllChildrenIdle(ctx) {
|
|
|
24846
25069
|
return areAllDescendantsIdle(ctx, ctx.sessionID, allStatuses);
|
|
24847
25070
|
}
|
|
24848
25071
|
async function fetchAllStatuses(ctx) {
|
|
24849
|
-
const statusRes = await ctx.client.session.status(
|
|
25072
|
+
const statusRes = await ctx.client.session.status({
|
|
25073
|
+
query: { directory: ctx.directory }
|
|
25074
|
+
});
|
|
24850
25075
|
return normalizeSDKResponse(statusRes, {});
|
|
24851
25076
|
}
|
|
24852
25077
|
async function areAllDescendantsIdle(ctx, sessionID, allStatuses) {
|
|
24853
25078
|
const childrenRes = await ctx.client.session.children({
|
|
24854
|
-
path: { id: sessionID }
|
|
25079
|
+
path: { id: sessionID },
|
|
25080
|
+
query: { directory: ctx.directory }
|
|
24855
25081
|
});
|
|
24856
25082
|
const children = normalizeSDKResponse(childrenRes, []);
|
|
24857
25083
|
for (const child of children) {
|
|
@@ -24869,6 +25095,7 @@ async function areAllDescendantsIdle(ctx, sessionID, allStatuses) {
|
|
|
24869
25095
|
}
|
|
24870
25096
|
|
|
24871
25097
|
// src/cli/run/poll-for-completion.ts
|
|
25098
|
+
init_shared();
|
|
24872
25099
|
var DEFAULT_POLL_INTERVAL_MS = 500;
|
|
24873
25100
|
var DEFAULT_REQUIRED_CONSECUTIVE = 3;
|
|
24874
25101
|
var ERROR_GRACE_CYCLES = 3;
|
|
@@ -24880,6 +25107,7 @@ async function pollForCompletion(ctx, eventState, abortController, options = {})
|
|
|
24880
25107
|
let consecutiveCompleteChecks = 0;
|
|
24881
25108
|
let errorCycleCount = 0;
|
|
24882
25109
|
let firstWorkTimestamp = null;
|
|
25110
|
+
const pollStartTimestamp = Date.now();
|
|
24883
25111
|
while (!abortController.signal.aborted) {
|
|
24884
25112
|
await new Promise((resolve2) => setTimeout(resolve2, pollIntervalMs));
|
|
24885
25113
|
if (eventState.mainSessionError) {
|
|
@@ -24895,6 +25123,12 @@ Session ended with error: ${eventState.lastError}`));
|
|
|
24895
25123
|
} else {
|
|
24896
25124
|
errorCycleCount = 0;
|
|
24897
25125
|
}
|
|
25126
|
+
const mainSessionStatus = await getMainSessionStatus(ctx);
|
|
25127
|
+
if (mainSessionStatus === "busy" || mainSessionStatus === "retry") {
|
|
25128
|
+
eventState.mainSessionIdle = false;
|
|
25129
|
+
} else if (mainSessionStatus === "idle") {
|
|
25130
|
+
eventState.mainSessionIdle = true;
|
|
25131
|
+
}
|
|
24898
25132
|
if (!eventState.mainSessionIdle) {
|
|
24899
25133
|
consecutiveCompleteChecks = 0;
|
|
24900
25134
|
continue;
|
|
@@ -24904,8 +25138,11 @@ Session ended with error: ${eventState.lastError}`));
|
|
|
24904
25138
|
continue;
|
|
24905
25139
|
}
|
|
24906
25140
|
if (!eventState.hasReceivedMeaningfulWork) {
|
|
25141
|
+
if (Date.now() - pollStartTimestamp < minStabilizationMs) {
|
|
25142
|
+
consecutiveCompleteChecks = 0;
|
|
25143
|
+
continue;
|
|
25144
|
+
}
|
|
24907
25145
|
consecutiveCompleteChecks = 0;
|
|
24908
|
-
continue;
|
|
24909
25146
|
}
|
|
24910
25147
|
if (firstWorkTimestamp === null) {
|
|
24911
25148
|
firstWorkTimestamp = Date.now();
|
|
@@ -24929,6 +25166,21 @@ All tasks completed.`));
|
|
|
24929
25166
|
}
|
|
24930
25167
|
return 130;
|
|
24931
25168
|
}
|
|
25169
|
+
async function getMainSessionStatus(ctx) {
|
|
25170
|
+
try {
|
|
25171
|
+
const statusesRes = await ctx.client.session.status({
|
|
25172
|
+
query: { directory: ctx.directory }
|
|
25173
|
+
});
|
|
25174
|
+
const statuses = normalizeSDKResponse(statusesRes, {});
|
|
25175
|
+
const status = statuses[ctx.sessionID]?.type;
|
|
25176
|
+
if (status === "idle" || status === "busy" || status === "retry") {
|
|
25177
|
+
return status;
|
|
25178
|
+
}
|
|
25179
|
+
return null;
|
|
25180
|
+
} catch {
|
|
25181
|
+
return null;
|
|
25182
|
+
}
|
|
25183
|
+
}
|
|
24932
25184
|
|
|
24933
25185
|
// src/cli/run/runner.ts
|
|
24934
25186
|
var DEFAULT_TIMEOUT_MS = 600000;
|
|
@@ -24984,7 +25236,8 @@ Interrupted. Shutting down...`));
|
|
|
24984
25236
|
try {
|
|
24985
25237
|
const sessionID = await resolveSession({
|
|
24986
25238
|
client: client3,
|
|
24987
|
-
sessionId: options.sessionId
|
|
25239
|
+
sessionId: options.sessionId,
|
|
25240
|
+
directory
|
|
24988
25241
|
});
|
|
24989
25242
|
console.log(import_picocolors14.default.dim(`Session: ${sessionID}`));
|
|
24990
25243
|
const ctx = { client: client3, sessionID, directory, abortController };
|
|
@@ -25235,24 +25488,24 @@ import { existsSync as existsSync19, readFileSync as readFileSync20 } from "fs";
|
|
|
25235
25488
|
// src/cli/doctor/checks/system-binary.ts
|
|
25236
25489
|
import { existsSync as existsSync16 } from "fs";
|
|
25237
25490
|
import { homedir as homedir5 } from "os";
|
|
25238
|
-
import { join as
|
|
25491
|
+
import { join as join13 } from "path";
|
|
25239
25492
|
function getDesktopAppPaths(platform) {
|
|
25240
25493
|
const home = homedir5();
|
|
25241
25494
|
switch (platform) {
|
|
25242
25495
|
case "darwin":
|
|
25243
25496
|
return [
|
|
25244
25497
|
"/Applications/OpenCode.app/Contents/MacOS/OpenCode",
|
|
25245
|
-
|
|
25498
|
+
join13(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
|
|
25246
25499
|
];
|
|
25247
25500
|
case "win32": {
|
|
25248
25501
|
const programFiles = process.env.ProgramFiles;
|
|
25249
25502
|
const localAppData = process.env.LOCALAPPDATA;
|
|
25250
25503
|
const paths = [];
|
|
25251
25504
|
if (programFiles) {
|
|
25252
|
-
paths.push(
|
|
25505
|
+
paths.push(join13(programFiles, "OpenCode", "OpenCode.exe"));
|
|
25253
25506
|
}
|
|
25254
25507
|
if (localAppData) {
|
|
25255
|
-
paths.push(
|
|
25508
|
+
paths.push(join13(localAppData, "OpenCode", "OpenCode.exe"));
|
|
25256
25509
|
}
|
|
25257
25510
|
return paths;
|
|
25258
25511
|
}
|
|
@@ -25260,8 +25513,8 @@ function getDesktopAppPaths(platform) {
|
|
|
25260
25513
|
return [
|
|
25261
25514
|
"/usr/bin/opencode",
|
|
25262
25515
|
"/usr/lib/opencode/opencode",
|
|
25263
|
-
|
|
25264
|
-
|
|
25516
|
+
join13(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
|
|
25517
|
+
join13(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
|
|
25265
25518
|
];
|
|
25266
25519
|
default:
|
|
25267
25520
|
return [];
|
|
@@ -25401,21 +25654,21 @@ init_checker();
|
|
|
25401
25654
|
init_auto_update_checker();
|
|
25402
25655
|
import { existsSync as existsSync18, readFileSync as readFileSync19 } from "fs";
|
|
25403
25656
|
import { homedir as homedir6 } from "os";
|
|
25404
|
-
import { join as
|
|
25657
|
+
import { join as join14 } from "path";
|
|
25405
25658
|
init_shared();
|
|
25406
25659
|
function getPlatformDefaultCacheDir(platform = process.platform) {
|
|
25407
25660
|
if (platform === "darwin")
|
|
25408
|
-
return
|
|
25661
|
+
return join14(homedir6(), "Library", "Caches");
|
|
25409
25662
|
if (platform === "win32")
|
|
25410
|
-
return process.env.LOCALAPPDATA ??
|
|
25411
|
-
return
|
|
25663
|
+
return process.env.LOCALAPPDATA ?? join14(homedir6(), "AppData", "Local");
|
|
25664
|
+
return join14(homedir6(), ".cache");
|
|
25412
25665
|
}
|
|
25413
25666
|
function resolveOpenCodeCacheDir() {
|
|
25414
25667
|
const xdgCacheHome = process.env.XDG_CACHE_HOME;
|
|
25415
25668
|
if (xdgCacheHome)
|
|
25416
|
-
return
|
|
25669
|
+
return join14(xdgCacheHome, "opencode");
|
|
25417
25670
|
const fromShared = getOpenCodeCacheDir();
|
|
25418
|
-
const platformDefault =
|
|
25671
|
+
const platformDefault = join14(getPlatformDefaultCacheDir(), "opencode");
|
|
25419
25672
|
if (existsSync18(fromShared) || !existsSync18(platformDefault))
|
|
25420
25673
|
return fromShared;
|
|
25421
25674
|
return platformDefault;
|
|
@@ -25438,8 +25691,8 @@ function normalizeVersion(value) {
|
|
|
25438
25691
|
}
|
|
25439
25692
|
function getLoadedPluginVersion() {
|
|
25440
25693
|
const cacheDir = resolveOpenCodeCacheDir();
|
|
25441
|
-
const cachePackagePath =
|
|
25442
|
-
const installedPackagePath =
|
|
25694
|
+
const cachePackagePath = join14(cacheDir, "package.json");
|
|
25695
|
+
const installedPackagePath = join14(cacheDir, "node_modules", PACKAGE_NAME4, "package.json");
|
|
25443
25696
|
const cachePackage = readPackageJson(cachePackagePath);
|
|
25444
25697
|
const installedPackage = readPackageJson(installedPackagePath);
|
|
25445
25698
|
const expectedVersion = normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME4]);
|
|
@@ -25568,22 +25821,22 @@ async function checkSystem() {
|
|
|
25568
25821
|
|
|
25569
25822
|
// src/cli/doctor/checks/config.ts
|
|
25570
25823
|
import { readFileSync as readFileSync23 } from "fs";
|
|
25571
|
-
import { join as
|
|
25824
|
+
import { join as join18 } from "path";
|
|
25572
25825
|
init_shared();
|
|
25573
25826
|
|
|
25574
25827
|
// src/cli/doctor/checks/model-resolution-cache.ts
|
|
25575
25828
|
init_shared();
|
|
25576
25829
|
import { existsSync as existsSync20, readFileSync as readFileSync21 } from "fs";
|
|
25577
25830
|
import { homedir as homedir7 } from "os";
|
|
25578
|
-
import { join as
|
|
25831
|
+
import { join as join15 } from "path";
|
|
25579
25832
|
function getOpenCodeCacheDir2() {
|
|
25580
25833
|
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
25581
25834
|
if (xdgCache)
|
|
25582
|
-
return
|
|
25583
|
-
return
|
|
25835
|
+
return join15(xdgCache, "opencode");
|
|
25836
|
+
return join15(homedir7(), ".cache", "opencode");
|
|
25584
25837
|
}
|
|
25585
25838
|
function loadAvailableModelsFromCache() {
|
|
25586
|
-
const cacheFile =
|
|
25839
|
+
const cacheFile = join15(getOpenCodeCacheDir2(), "models.json");
|
|
25587
25840
|
if (!existsSync20(cacheFile)) {
|
|
25588
25841
|
return { providers: [], modelCount: 0, cacheExists: false };
|
|
25589
25842
|
}
|
|
@@ -25610,10 +25863,10 @@ init_model_requirements();
|
|
|
25610
25863
|
// src/cli/doctor/checks/model-resolution-config.ts
|
|
25611
25864
|
init_shared();
|
|
25612
25865
|
import { readFileSync as readFileSync22 } from "fs";
|
|
25613
|
-
import { join as
|
|
25866
|
+
import { join as join16 } from "path";
|
|
25614
25867
|
var PACKAGE_NAME5 = "oh-my-opencode";
|
|
25615
|
-
var USER_CONFIG_BASE =
|
|
25616
|
-
var PROJECT_CONFIG_BASE =
|
|
25868
|
+
var USER_CONFIG_BASE = join16(getOpenCodeConfigPaths({ binary: "opencode", version: null }).configDir, PACKAGE_NAME5);
|
|
25869
|
+
var PROJECT_CONFIG_BASE = join16(process.cwd(), ".opencode", PACKAGE_NAME5);
|
|
25617
25870
|
function loadOmoConfig() {
|
|
25618
25871
|
const projectDetected = detectConfigFile(PROJECT_CONFIG_BASE);
|
|
25619
25872
|
if (projectDetected.format !== "none") {
|
|
@@ -25638,7 +25891,7 @@ function loadOmoConfig() {
|
|
|
25638
25891
|
|
|
25639
25892
|
// src/cli/doctor/checks/model-resolution-details.ts
|
|
25640
25893
|
init_shared();
|
|
25641
|
-
import { join as
|
|
25894
|
+
import { join as join17 } from "path";
|
|
25642
25895
|
|
|
25643
25896
|
// src/cli/doctor/checks/model-resolution-variant.ts
|
|
25644
25897
|
function formatModelWithVariant(model, variant) {
|
|
@@ -25677,7 +25930,7 @@ function getCategoryEffectiveVariant(categoryName, requirement, config2) {
|
|
|
25677
25930
|
// src/cli/doctor/checks/model-resolution-details.ts
|
|
25678
25931
|
function buildModelResolutionDetails(options) {
|
|
25679
25932
|
const details = [];
|
|
25680
|
-
const cacheFile =
|
|
25933
|
+
const cacheFile = join17(getOpenCodeCacheDir(), "models.json");
|
|
25681
25934
|
details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
|
|
25682
25935
|
details.push("");
|
|
25683
25936
|
if (options.available.cacheExists) {
|
|
@@ -25789,8 +26042,8 @@ async function checkModels() {
|
|
|
25789
26042
|
}
|
|
25790
26043
|
|
|
25791
26044
|
// src/cli/doctor/checks/config.ts
|
|
25792
|
-
var USER_CONFIG_BASE2 =
|
|
25793
|
-
var PROJECT_CONFIG_BASE2 =
|
|
26045
|
+
var USER_CONFIG_BASE2 = join18(getOpenCodeConfigDir({ binary: "opencode" }), PACKAGE_NAME4);
|
|
26046
|
+
var PROJECT_CONFIG_BASE2 = join18(process.cwd(), ".opencode", PACKAGE_NAME4);
|
|
25794
26047
|
function findConfigPath() {
|
|
25795
26048
|
const projectConfig = detectConfigFile(PROJECT_CONFIG_BASE2);
|
|
25796
26049
|
if (projectConfig.format !== "none")
|
|
@@ -25910,8 +26163,8 @@ async function checkConfig() {
|
|
|
25910
26163
|
|
|
25911
26164
|
// src/cli/doctor/checks/dependencies.ts
|
|
25912
26165
|
import { existsSync as existsSync21 } from "fs";
|
|
25913
|
-
import { createRequire } from "module";
|
|
25914
|
-
import { dirname as
|
|
26166
|
+
import { createRequire as createRequire2 } from "module";
|
|
26167
|
+
import { dirname as dirname5, join as join19 } from "path";
|
|
25915
26168
|
async function checkBinaryExists(binary2) {
|
|
25916
26169
|
try {
|
|
25917
26170
|
const path9 = Bun.which(binary2);
|
|
@@ -25968,11 +26221,11 @@ async function checkAstGrepNapi() {
|
|
|
25968
26221
|
};
|
|
25969
26222
|
} catch {
|
|
25970
26223
|
const { existsSync: existsSync22 } = await import("fs");
|
|
25971
|
-
const { join:
|
|
26224
|
+
const { join: join20 } = await import("path");
|
|
25972
26225
|
const { homedir: homedir8 } = await import("os");
|
|
25973
26226
|
const pathsToCheck = [
|
|
25974
|
-
|
|
25975
|
-
|
|
26227
|
+
join20(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
|
|
26228
|
+
join20(process.cwd(), "node_modules", "@ast-grep", "napi")
|
|
25976
26229
|
];
|
|
25977
26230
|
for (const napiPath of pathsToCheck) {
|
|
25978
26231
|
if (existsSync22(napiPath)) {
|
|
@@ -25998,9 +26251,9 @@ async function checkAstGrepNapi() {
|
|
|
25998
26251
|
function findCommentCheckerPackageBinary() {
|
|
25999
26252
|
const binaryName = process.platform === "win32" ? "comment-checker.exe" : "comment-checker";
|
|
26000
26253
|
try {
|
|
26001
|
-
const require2 =
|
|
26254
|
+
const require2 = createRequire2(import.meta.url);
|
|
26002
26255
|
const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
|
|
26003
|
-
const binaryPath =
|
|
26256
|
+
const binaryPath = join19(dirname5(pkgPath), "bin", binaryName);
|
|
26004
26257
|
if (existsSync21(binaryPath))
|
|
26005
26258
|
return binaryPath;
|
|
26006
26259
|
} catch {}
|
|
@@ -26120,7 +26373,7 @@ init_jsonc_parser();
|
|
|
26120
26373
|
// src/tools/lsp/server-installation.ts
|
|
26121
26374
|
init_shared();
|
|
26122
26375
|
import { existsSync as existsSync22 } from "fs";
|
|
26123
|
-
import { join as
|
|
26376
|
+
import { join as join20 } from "path";
|
|
26124
26377
|
function isServerInstalled(command) {
|
|
26125
26378
|
if (command.length === 0)
|
|
26126
26379
|
return false;
|
|
@@ -26148,23 +26401,23 @@ function isServerInstalled(command) {
|
|
|
26148
26401
|
const paths = pathEnv.split(pathSeparator);
|
|
26149
26402
|
for (const p2 of paths) {
|
|
26150
26403
|
for (const suffix of exts) {
|
|
26151
|
-
if (existsSync22(
|
|
26404
|
+
if (existsSync22(join20(p2, cmd + suffix))) {
|
|
26152
26405
|
return true;
|
|
26153
26406
|
}
|
|
26154
26407
|
}
|
|
26155
26408
|
}
|
|
26156
26409
|
const cwd = process.cwd();
|
|
26157
26410
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
26158
|
-
const dataDir =
|
|
26411
|
+
const dataDir = join20(getDataDir(), "opencode");
|
|
26159
26412
|
const additionalBases = [
|
|
26160
|
-
|
|
26161
|
-
|
|
26162
|
-
|
|
26163
|
-
|
|
26413
|
+
join20(cwd, "node_modules", ".bin"),
|
|
26414
|
+
join20(configDir, "bin"),
|
|
26415
|
+
join20(configDir, "node_modules", ".bin"),
|
|
26416
|
+
join20(dataDir, "bin")
|
|
26164
26417
|
];
|
|
26165
26418
|
for (const base of additionalBases) {
|
|
26166
26419
|
for (const suffix of exts) {
|
|
26167
|
-
if (existsSync22(
|
|
26420
|
+
if (existsSync22(join20(base, cmd + suffix))) {
|
|
26168
26421
|
return true;
|
|
26169
26422
|
}
|
|
26170
26423
|
}
|
|
@@ -26200,13 +26453,13 @@ function getLspServerStats(servers) {
|
|
|
26200
26453
|
init_shared();
|
|
26201
26454
|
import { existsSync as existsSync23, readFileSync as readFileSync24 } from "fs";
|
|
26202
26455
|
import { homedir as homedir8 } from "os";
|
|
26203
|
-
import { join as
|
|
26456
|
+
import { join as join21 } from "path";
|
|
26204
26457
|
var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
|
|
26205
26458
|
function getMcpConfigPaths() {
|
|
26206
26459
|
return [
|
|
26207
|
-
|
|
26208
|
-
|
|
26209
|
-
|
|
26460
|
+
join21(homedir8(), ".claude", ".mcp.json"),
|
|
26461
|
+
join21(process.cwd(), ".mcp.json"),
|
|
26462
|
+
join21(process.cwd(), ".claude", ".mcp.json")
|
|
26210
26463
|
];
|
|
26211
26464
|
}
|
|
26212
26465
|
function loadUserMcpConfig() {
|
|
@@ -26618,10 +26871,10 @@ async function doctor(options = { mode: "default" }) {
|
|
|
26618
26871
|
// src/features/mcp-oauth/storage.ts
|
|
26619
26872
|
init_shared();
|
|
26620
26873
|
import { chmodSync, existsSync as existsSync24, mkdirSync as mkdirSync3, readFileSync as readFileSync25, unlinkSync, writeFileSync as writeFileSync9 } from "fs";
|
|
26621
|
-
import { dirname as
|
|
26874
|
+
import { dirname as dirname6, join as join22 } from "path";
|
|
26622
26875
|
var STORAGE_FILE_NAME = "mcp-oauth.json";
|
|
26623
26876
|
function getMcpOauthStoragePath() {
|
|
26624
|
-
return
|
|
26877
|
+
return join22(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
|
|
26625
26878
|
}
|
|
26626
26879
|
function normalizeHost(serverHost) {
|
|
26627
26880
|
let host = serverHost.trim();
|
|
@@ -26671,7 +26924,7 @@ function readStore() {
|
|
|
26671
26924
|
function writeStore(store) {
|
|
26672
26925
|
const filePath = getMcpOauthStoragePath();
|
|
26673
26926
|
try {
|
|
26674
|
-
const dir =
|
|
26927
|
+
const dir = dirname6(filePath);
|
|
26675
26928
|
if (!existsSync24(dir)) {
|
|
26676
26929
|
mkdirSync3(dir, { recursive: true });
|
|
26677
26930
|
}
|