oh-my-opencode 3.7.2 → 3.7.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/README.ja.md +8 -8
- package/README.ko.md +8 -8
- package/README.md +8 -8
- package/README.zh-cn.md +8 -8
- package/dist/agents/atlas/default.d.ts +1 -1
- package/dist/agents/atlas/gpt.d.ts +1 -1
- package/dist/agents/metis.d.ts +1 -1
- package/dist/agents/prometheus/behavioral-summary.d.ts +1 -1
- package/dist/agents/prometheus/identity-constraints.d.ts +1 -1
- package/dist/agents/prometheus/interview-mode.d.ts +1 -1
- package/dist/agents/prometheus/plan-generation.d.ts +1 -1
- package/dist/agents/prometheus/plan-template.d.ts +1 -1
- package/dist/agents/prometheus/system-prompt.d.ts +1 -1
- package/dist/agents/sisyphus-junior/agent.d.ts +1 -1
- package/dist/cli/config-manager/antigravity-provider-configuration.d.ts +2 -2
- package/dist/cli/index.js +225 -91
- package/dist/cli/model-fallback-types.d.ts +5 -0
- package/dist/cli/run/event-state.d.ts +4 -0
- package/dist/cli/run/stdin-suppression.d.ts +12 -0
- package/dist/config/schema/agent-overrides.d.ts +60 -0
- package/dist/config/schema/hooks.d.ts +2 -1
- package/dist/config/schema/oh-my-opencode-config.d.ts +58 -1
- package/dist/create-hooks.d.ts +2 -1
- package/dist/features/background-agent/parent-session-context-resolver.d.ts +1 -0
- package/dist/hooks/atlas/recent-model-resolver.d.ts +6 -0
- package/dist/hooks/atlas/system-reminder-templates.d.ts +1 -1
- package/dist/hooks/index.d.ts +2 -1
- package/dist/hooks/{sisyphus-gpt-hephaestus-reminder → no-sisyphus-gpt}/hook.d.ts +6 -1
- package/dist/hooks/no-sisyphus-gpt/index.d.ts +1 -0
- package/dist/hooks/session-recovery/types.d.ts +1 -0
- package/dist/hooks/ultrawork-model-override/hook.d.ts +6 -0
- package/dist/hooks/ultrawork-model-override/index.d.ts +1 -0
- package/dist/hooks/unstable-agent-babysitter/task-message-analyzer.d.ts +1 -0
- package/dist/hooks/unstable-agent-babysitter/unstable-agent-babysitter-hook.d.ts +2 -0
- package/dist/index.js +559 -453
- package/dist/plugin/hooks/create-core-hooks.d.ts +2 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +4 -2
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/prompt-tools.d.ts +3 -0
- package/dist/tools/delegate-task/constants.d.ts +1 -1
- package/package.json +8 -8
- package/dist/cli/run/opencode-bin-path.d.ts +0 -3
- package/dist/hooks/sisyphus-gpt-hephaestus-reminder/index.d.ts +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -6513,6 +6513,7 @@ var init_hook_names = __esm(() => {
|
|
|
6513
6513
|
HOOK_NAME_MAP = {
|
|
6514
6514
|
"anthropic-auto-compact": "anthropic-context-window-limit-recovery",
|
|
6515
6515
|
"sisyphus-orchestrator": "atlas",
|
|
6516
|
+
"sisyphus-gpt-hephaestus-reminder": "no-sisyphus-gpt",
|
|
6516
6517
|
"empty-message-sanitizer": null
|
|
6517
6518
|
};
|
|
6518
6519
|
});
|
|
@@ -6550,7 +6551,8 @@ var MODEL_VERSION_MAP;
|
|
|
6550
6551
|
var init_model_versions = __esm(() => {
|
|
6551
6552
|
MODEL_VERSION_MAP = {
|
|
6552
6553
|
"openai/gpt-5.2-codex": "openai/gpt-5.3-codex",
|
|
6553
|
-
"anthropic/claude-opus-4-5": "anthropic/claude-opus-4-6"
|
|
6554
|
+
"anthropic/claude-opus-4-5": "anthropic/claude-opus-4-6",
|
|
6555
|
+
"anthropic/claude-sonnet-4-5": "anthropic/claude-sonnet-4-6"
|
|
6554
6556
|
};
|
|
6555
6557
|
});
|
|
6556
6558
|
|
|
@@ -6786,7 +6788,7 @@ var init_model_requirements = __esm(() => {
|
|
|
6786
6788
|
{ providers: ["kimi-for-coding"], model: "k2p5" },
|
|
6787
6789
|
{ providers: ["opencode"], model: "kimi-k2.5-free" },
|
|
6788
6790
|
{ providers: ["zai-coding-plan"], model: "glm-4.7" },
|
|
6789
|
-
{ providers: ["opencode"], model: "
|
|
6791
|
+
{ providers: ["opencode"], model: "big-pickle" }
|
|
6790
6792
|
],
|
|
6791
6793
|
requiresAnyModel: true
|
|
6792
6794
|
},
|
|
@@ -6806,8 +6808,8 @@ var init_model_requirements = __esm(() => {
|
|
|
6806
6808
|
librarian: {
|
|
6807
6809
|
fallbackChain: [
|
|
6808
6810
|
{ providers: ["zai-coding-plan"], model: "glm-4.7" },
|
|
6809
|
-
{ providers: ["opencode"], model: "
|
|
6810
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-
|
|
6811
|
+
{ providers: ["opencode"], model: "big-pickle" },
|
|
6812
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-6" }
|
|
6811
6813
|
]
|
|
6812
6814
|
},
|
|
6813
6815
|
explore: {
|
|
@@ -6857,7 +6859,7 @@ var init_model_requirements = __esm(() => {
|
|
|
6857
6859
|
fallbackChain: [
|
|
6858
6860
|
{ providers: ["kimi-for-coding"], model: "k2p5" },
|
|
6859
6861
|
{ providers: ["opencode"], model: "kimi-k2.5-free" },
|
|
6860
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-
|
|
6862
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-6" },
|
|
6861
6863
|
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" },
|
|
6862
6864
|
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
6863
6865
|
]
|
|
@@ -6904,7 +6906,7 @@ var init_model_requirements = __esm(() => {
|
|
|
6904
6906
|
},
|
|
6905
6907
|
"unspecified-low": {
|
|
6906
6908
|
fallbackChain: [
|
|
6907
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-
|
|
6909
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-6" },
|
|
6908
6910
|
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.3-codex", variant: "medium" },
|
|
6909
6911
|
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" }
|
|
6910
6912
|
]
|
|
@@ -6920,7 +6922,7 @@ var init_model_requirements = __esm(() => {
|
|
|
6920
6922
|
fallbackChain: [
|
|
6921
6923
|
{ providers: ["kimi-for-coding"], model: "k2p5" },
|
|
6922
6924
|
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
|
|
6923
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-
|
|
6925
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-6" }
|
|
6924
6926
|
]
|
|
6925
6927
|
}
|
|
6926
6928
|
};
|
|
@@ -7268,6 +7270,17 @@ var init_safe_create_hook = __esm(() => {
|
|
|
7268
7270
|
// src/shared/session-directory-resolver.ts
|
|
7269
7271
|
var init_session_directory_resolver = () => {};
|
|
7270
7272
|
|
|
7273
|
+
// src/shared/session-tools-store.ts
|
|
7274
|
+
var store;
|
|
7275
|
+
var init_session_tools_store = __esm(() => {
|
|
7276
|
+
store = new Map;
|
|
7277
|
+
});
|
|
7278
|
+
|
|
7279
|
+
// src/shared/prompt-tools.ts
|
|
7280
|
+
var init_prompt_tools = __esm(() => {
|
|
7281
|
+
init_session_tools_store();
|
|
7282
|
+
});
|
|
7283
|
+
|
|
7271
7284
|
// src/shared/index.ts
|
|
7272
7285
|
var init_shared = __esm(() => {
|
|
7273
7286
|
init_model_resolution_pipeline();
|
|
@@ -7311,6 +7324,7 @@ var init_shared = __esm(() => {
|
|
|
7311
7324
|
init_opencode_storage_paths();
|
|
7312
7325
|
init_opencode_message_dir();
|
|
7313
7326
|
init_session_directory_resolver();
|
|
7327
|
+
init_prompt_tools();
|
|
7314
7328
|
});
|
|
7315
7329
|
|
|
7316
7330
|
// src/cli/config-manager/config-context.ts
|
|
@@ -7581,7 +7595,7 @@ function isProviderAvailable(provider, availability) {
|
|
|
7581
7595
|
// src/cli/provider-model-id-transform.ts
|
|
7582
7596
|
function transformModelForProvider(provider, model) {
|
|
7583
7597
|
if (provider === "github-copilot") {
|
|
7584
|
-
return model.replace("claude-opus-4-6", "claude-opus-4.6").replace("claude-sonnet-4-
|
|
7598
|
+
return model.replace("claude-opus-4-6", "claude-opus-4.6").replace("claude-sonnet-4-6", "claude-sonnet-4.6").replace("claude-haiku-4-5", "claude-haiku-4.5").replace("claude-sonnet-4", "claude-sonnet-4").replace("gemini-3-pro", "gemini-3-pro-preview").replace("gemini-3-flash", "gemini-3-flash-preview");
|
|
7585
7599
|
}
|
|
7586
7600
|
return model;
|
|
7587
7601
|
}
|
|
@@ -7655,6 +7669,14 @@ function generateModelConfig(config) {
|
|
|
7655
7669
|
if (req.requiresAnyModel && !isAnyFallbackEntryAvailable(fallbackChain, avail)) {
|
|
7656
7670
|
continue;
|
|
7657
7671
|
}
|
|
7672
|
+
if (avail.native.claude && !avail.isMaxPlan) {
|
|
7673
|
+
agents[role] = {
|
|
7674
|
+
model: "anthropic/claude-sonnet-4-6",
|
|
7675
|
+
variant: "max",
|
|
7676
|
+
ultrawork: { model: "anthropic/claude-opus-4-6", variant: "max" }
|
|
7677
|
+
};
|
|
7678
|
+
continue;
|
|
7679
|
+
}
|
|
7658
7680
|
const resolved2 = resolveModelFromChain(fallbackChain, avail);
|
|
7659
7681
|
if (resolved2) {
|
|
7660
7682
|
const variant = resolved2.variant ?? req.variant;
|
|
@@ -7698,7 +7720,7 @@ function generateModelConfig(config) {
|
|
|
7698
7720
|
categories
|
|
7699
7721
|
};
|
|
7700
7722
|
}
|
|
7701
|
-
var ZAI_MODEL = "zai-coding-plan/glm-4.7", ULTIMATE_FALLBACK = "opencode/
|
|
7723
|
+
var ZAI_MODEL = "zai-coding-plan/glm-4.7", ULTIMATE_FALLBACK = "opencode/big-pickle", SCHEMA_URL = "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json";
|
|
7702
7724
|
var init_model_fallback = __esm(() => {
|
|
7703
7725
|
init_model_requirements();
|
|
7704
7726
|
init_fallback_chain_resolution();
|
|
@@ -7983,13 +8005,13 @@ var init_antigravity_provider_configuration = __esm(() => {
|
|
|
7983
8005
|
high: { thinkingLevel: "high" }
|
|
7984
8006
|
}
|
|
7985
8007
|
},
|
|
7986
|
-
"antigravity-claude-sonnet-4-
|
|
7987
|
-
name: "Claude Sonnet 4.
|
|
8008
|
+
"antigravity-claude-sonnet-4-6": {
|
|
8009
|
+
name: "Claude Sonnet 4.6 (Antigravity)",
|
|
7988
8010
|
limit: { context: 200000, output: 64000 },
|
|
7989
8011
|
modalities: { input: ["text", "image", "pdf"], output: ["text"] }
|
|
7990
8012
|
},
|
|
7991
|
-
"antigravity-claude-sonnet-4-
|
|
7992
|
-
name: "Claude Sonnet 4.
|
|
8013
|
+
"antigravity-claude-sonnet-4-6-thinking": {
|
|
8014
|
+
name: "Claude Sonnet 4.6 Thinking (Antigravity)",
|
|
7993
8015
|
limit: { context: 200000, output: 64000 },
|
|
7994
8016
|
modalities: { input: ["text", "image", "pdf"], output: ["text"] },
|
|
7995
8017
|
variants: {
|
|
@@ -9053,7 +9075,7 @@ var {
|
|
|
9053
9075
|
// package.json
|
|
9054
9076
|
var package_default = {
|
|
9055
9077
|
name: "oh-my-opencode",
|
|
9056
|
-
version: "3.7.
|
|
9078
|
+
version: "3.7.4",
|
|
9057
9079
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
9058
9080
|
main: "dist/index.js",
|
|
9059
9081
|
types: "dist/index.d.ts",
|
|
@@ -9127,13 +9149,13 @@ var package_default = {
|
|
|
9127
9149
|
typescript: "^5.7.3"
|
|
9128
9150
|
},
|
|
9129
9151
|
optionalDependencies: {
|
|
9130
|
-
"oh-my-opencode-darwin-arm64": "3.7.
|
|
9131
|
-
"oh-my-opencode-darwin-x64": "3.7.
|
|
9132
|
-
"oh-my-opencode-linux-arm64": "3.7.
|
|
9133
|
-
"oh-my-opencode-linux-arm64-musl": "3.7.
|
|
9134
|
-
"oh-my-opencode-linux-x64": "3.7.
|
|
9135
|
-
"oh-my-opencode-linux-x64-musl": "3.7.
|
|
9136
|
-
"oh-my-opencode-windows-x64": "3.7.
|
|
9152
|
+
"oh-my-opencode-darwin-arm64": "3.7.4",
|
|
9153
|
+
"oh-my-opencode-darwin-x64": "3.7.4",
|
|
9154
|
+
"oh-my-opencode-linux-arm64": "3.7.4",
|
|
9155
|
+
"oh-my-opencode-linux-arm64-musl": "3.7.4",
|
|
9156
|
+
"oh-my-opencode-linux-x64": "3.7.4",
|
|
9157
|
+
"oh-my-opencode-linux-x64-musl": "3.7.4",
|
|
9158
|
+
"oh-my-opencode-windows-x64": "3.7.4"
|
|
9137
9159
|
},
|
|
9138
9160
|
trustedDependencies: [
|
|
9139
9161
|
"@ast-grep/cli",
|
|
@@ -9366,7 +9388,7 @@ async function runCliInstaller(args, version) {
|
|
|
9366
9388
|
console.log();
|
|
9367
9389
|
}
|
|
9368
9390
|
if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen) {
|
|
9369
|
-
printWarning("No model providers configured. Using opencode/
|
|
9391
|
+
printWarning("No model providers configured. Using opencode/big-pickle as fallback.");
|
|
9370
9392
|
}
|
|
9371
9393
|
console.log(`${SYMBOLS.star} ${import_picocolors2.default.bold(import_picocolors2.default.green(isUpdate ? "Configuration updated!" : "Installation complete!"))}`);
|
|
9372
9394
|
console.log(` Run ${import_picocolors2.default.cyan("opencode")} to start!`);
|
|
@@ -9992,9 +10014,9 @@ async function promptInstallConfig(detected) {
|
|
|
9992
10014
|
const claude = await selectOrCancel({
|
|
9993
10015
|
message: "Do you have a Claude Pro/Max subscription?",
|
|
9994
10016
|
options: [
|
|
9995
|
-
{ value: "no", label: "No", hint: "Will use opencode/
|
|
10017
|
+
{ value: "no", label: "No", hint: "Will use opencode/big-pickle as fallback" },
|
|
9996
10018
|
{ value: "yes", label: "Yes (standard)", hint: "Claude Opus 4.5 for orchestration" },
|
|
9997
|
-
{ value: "max20", label: "Yes (max20 mode)", hint: "Full power with Claude Sonnet 4.
|
|
10019
|
+
{ value: "max20", label: "Yes (max20 mode)", hint: "Full power with Claude Sonnet 4.6 for Librarian" }
|
|
9998
10020
|
],
|
|
9999
10021
|
initialValue: initial.claude
|
|
10000
10022
|
});
|
|
@@ -10147,7 +10169,7 @@ async function runTuiInstaller(args, version) {
|
|
|
10147
10169
|
console.log();
|
|
10148
10170
|
}
|
|
10149
10171
|
if (!config.hasClaude && !config.hasOpenAI && !config.hasGemini && !config.hasCopilot && !config.hasOpencodeZen) {
|
|
10150
|
-
M2.warn("No model providers configured. Using opencode/
|
|
10172
|
+
M2.warn("No model providers configured. Using opencode/big-pickle as fallback.");
|
|
10151
10173
|
}
|
|
10152
10174
|
Me(formatConfigSummary(config), isUpdate ? "Updated Configuration" : "Installation Complete");
|
|
10153
10175
|
M2.success(import_picocolors4.default.bold(isUpdate ? "Configuration updated!" : "Installation complete!"));
|
|
@@ -10212,7 +10234,9 @@ function createEventState() {
|
|
|
10212
10234
|
lastThinkingSummary: "",
|
|
10213
10235
|
textAtLineStart: true,
|
|
10214
10236
|
thinkingAtLineStart: false,
|
|
10215
|
-
currentMessageId: null
|
|
10237
|
+
currentMessageId: null,
|
|
10238
|
+
messageStartedAtById: {},
|
|
10239
|
+
completionMetaPrintedByMessageId: {}
|
|
10216
10240
|
};
|
|
10217
10241
|
}
|
|
10218
10242
|
// src/cli/run/event-formatting.ts
|
|
@@ -10572,6 +10596,19 @@ function getPartMessageId(props) {
|
|
|
10572
10596
|
function getDeltaMessageId(props) {
|
|
10573
10597
|
return props?.messageID;
|
|
10574
10598
|
}
|
|
10599
|
+
function renderCompletionMetaLine(state, messageID) {
|
|
10600
|
+
if (state.completionMetaPrintedByMessageId[messageID])
|
|
10601
|
+
return;
|
|
10602
|
+
const startedAt = state.messageStartedAtById[messageID];
|
|
10603
|
+
const elapsedSec = startedAt ? ((Date.now() - startedAt) / 1000).toFixed(1) : "0.0";
|
|
10604
|
+
const agent = state.currentAgent ?? "assistant";
|
|
10605
|
+
const model = state.currentModel ?? "unknown-model";
|
|
10606
|
+
const variant = state.currentVariant ? ` (${state.currentVariant})` : "";
|
|
10607
|
+
process.stdout.write(import_picocolors7.default.dim(`
|
|
10608
|
+
${displayChars.treeEnd} ${agent} \xB7 ${model}${variant} \xB7 ${elapsedSec}s
|
|
10609
|
+
`));
|
|
10610
|
+
state.completionMetaPrintedByMessageId[messageID] = true;
|
|
10611
|
+
}
|
|
10575
10612
|
function handleSessionIdle(ctx, payload, state) {
|
|
10576
10613
|
if (payload.type !== "session.idle")
|
|
10577
10614
|
return;
|
|
@@ -10646,6 +10683,12 @@ function handleMessagePartUpdated(ctx, payload, state) {
|
|
|
10646
10683
|
state.hasReceivedMeaningfulWork = true;
|
|
10647
10684
|
}
|
|
10648
10685
|
state.lastPartText = part.text;
|
|
10686
|
+
if (part.time?.end) {
|
|
10687
|
+
const messageID = part.messageID ?? state.currentMessageId;
|
|
10688
|
+
if (messageID) {
|
|
10689
|
+
renderCompletionMetaLine(state, messageID);
|
|
10690
|
+
}
|
|
10691
|
+
}
|
|
10649
10692
|
}
|
|
10650
10693
|
if (part.type === "tool") {
|
|
10651
10694
|
handleToolPart(ctx, part, state);
|
|
@@ -10740,6 +10783,10 @@ function handleMessageUpdated(ctx, payload, state) {
|
|
|
10740
10783
|
state.textAtLineStart = true;
|
|
10741
10784
|
state.thinkingAtLineStart = false;
|
|
10742
10785
|
closeThinkBlockIfNeeded(state);
|
|
10786
|
+
if (messageID) {
|
|
10787
|
+
state.messageStartedAtById[messageID] = Date.now();
|
|
10788
|
+
state.completionMetaPrintedByMessageId[messageID] = false;
|
|
10789
|
+
}
|
|
10743
10790
|
}
|
|
10744
10791
|
const agent = props?.info?.agent ?? null;
|
|
10745
10792
|
const model = props?.info?.modelID ?? null;
|
|
@@ -23244,6 +23291,10 @@ var AgentOverrideConfigSchema = exports_external.object({
|
|
|
23244
23291
|
type: exports_external.enum(["enabled", "disabled"]),
|
|
23245
23292
|
budgetTokens: exports_external.number().optional()
|
|
23246
23293
|
}).optional(),
|
|
23294
|
+
ultrawork: exports_external.object({
|
|
23295
|
+
model: exports_external.string(),
|
|
23296
|
+
variant: exports_external.string().optional()
|
|
23297
|
+
}).optional(),
|
|
23247
23298
|
reasoningEffort: exports_external.enum(["low", "medium", "high", "xhigh"]).optional(),
|
|
23248
23299
|
textVerbosity: exports_external.enum(["low", "medium", "high"]).optional(),
|
|
23249
23300
|
providerOptions: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
@@ -23413,6 +23464,7 @@ var HookNameSchema = exports_external.enum([
|
|
|
23413
23464
|
"non-interactive-env",
|
|
23414
23465
|
"interactive-bash-session",
|
|
23415
23466
|
"thinking-block-validator",
|
|
23467
|
+
"ultrawork-model-override",
|
|
23416
23468
|
"ralph-loop",
|
|
23417
23469
|
"category-skill-reminder",
|
|
23418
23470
|
"compaction-context-injector",
|
|
@@ -23424,7 +23476,7 @@ var HookNameSchema = exports_external.enum([
|
|
|
23424
23476
|
"delegate-task-retry",
|
|
23425
23477
|
"prometheus-md-only",
|
|
23426
23478
|
"sisyphus-junior-notepad",
|
|
23427
|
-
"sisyphus-gpt
|
|
23479
|
+
"no-sisyphus-gpt",
|
|
23428
23480
|
"start-work",
|
|
23429
23481
|
"atlas",
|
|
23430
23482
|
"unstable-agent-babysitter",
|
|
@@ -25192,34 +25244,31 @@ async function withWorkingOpencodePath(startServer, finder = findWorkingOpencode
|
|
|
25192
25244
|
}
|
|
25193
25245
|
}
|
|
25194
25246
|
|
|
25195
|
-
// src/cli/run/
|
|
25196
|
-
|
|
25197
|
-
|
|
25198
|
-
|
|
25199
|
-
function prependResolvedOpencodeBinToPath(env = process.env, resolve2 = resolveFromCurrentModule) {
|
|
25200
|
-
let resolvedPath;
|
|
25201
|
-
try {
|
|
25202
|
-
resolvedPath = resolve2("opencode-ai/bin/opencode");
|
|
25203
|
-
} catch {
|
|
25204
|
-
return;
|
|
25247
|
+
// src/cli/run/server-connection.ts
|
|
25248
|
+
function isPortStartFailure(error45, port) {
|
|
25249
|
+
if (!(error45 instanceof Error)) {
|
|
25250
|
+
return false;
|
|
25205
25251
|
}
|
|
25206
|
-
|
|
25207
|
-
|
|
25208
|
-
|
|
25209
|
-
if (
|
|
25210
|
-
return;
|
|
25252
|
+
return error45.message.includes(`Failed to start server on port ${port}`);
|
|
25253
|
+
}
|
|
25254
|
+
function isPortRangeExhausted(error45) {
|
|
25255
|
+
if (!(error45 instanceof Error)) {
|
|
25256
|
+
return false;
|
|
25211
25257
|
}
|
|
25212
|
-
|
|
25258
|
+
return error45.message.includes("No available port found in range");
|
|
25259
|
+
}
|
|
25260
|
+
async function startServer(options) {
|
|
25261
|
+
const { signal, port } = options;
|
|
25262
|
+
const { client: client3, server: server2 } = await withWorkingOpencodePath(() => createOpencode({ signal, port, hostname: "127.0.0.1" }));
|
|
25263
|
+
console.log(import_picocolors9.default.dim("Server listening at"), import_picocolors9.default.cyan(server2.url));
|
|
25264
|
+
return { client: client3, cleanup: () => server2.close() };
|
|
25213
25265
|
}
|
|
25214
|
-
|
|
25215
|
-
// src/cli/run/server-connection.ts
|
|
25216
25266
|
async function createServerConnection(options) {
|
|
25217
|
-
prependResolvedOpencodeBinToPath();
|
|
25218
25267
|
const { port, attach, signal } = options;
|
|
25219
25268
|
if (attach !== undefined) {
|
|
25220
25269
|
console.log(import_picocolors9.default.dim("Attaching to existing server at"), import_picocolors9.default.cyan(attach));
|
|
25221
|
-
const
|
|
25222
|
-
return { client:
|
|
25270
|
+
const client3 = createOpencodeClient({ baseUrl: attach });
|
|
25271
|
+
return { client: client3, cleanup: () => {} };
|
|
25223
25272
|
}
|
|
25224
25273
|
if (port !== undefined) {
|
|
25225
25274
|
if (port < 1 || port > 65535) {
|
|
@@ -25228,23 +25277,58 @@ async function createServerConnection(options) {
|
|
|
25228
25277
|
const available = await isPortAvailable(port, "127.0.0.1");
|
|
25229
25278
|
if (available) {
|
|
25230
25279
|
console.log(import_picocolors9.default.dim("Starting server on port"), import_picocolors9.default.cyan(port.toString()));
|
|
25231
|
-
|
|
25232
|
-
|
|
25233
|
-
|
|
25280
|
+
try {
|
|
25281
|
+
return await startServer({ signal, port });
|
|
25282
|
+
} catch (error45) {
|
|
25283
|
+
if (!isPortStartFailure(error45, port)) {
|
|
25284
|
+
throw error45;
|
|
25285
|
+
}
|
|
25286
|
+
const stillAvailable = await isPortAvailable(port, "127.0.0.1");
|
|
25287
|
+
if (stillAvailable) {
|
|
25288
|
+
throw error45;
|
|
25289
|
+
}
|
|
25290
|
+
console.log(import_picocolors9.default.dim("Port"), import_picocolors9.default.cyan(port.toString()), import_picocolors9.default.dim("became occupied, attaching to existing server"));
|
|
25291
|
+
const client4 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
|
|
25292
|
+
return { client: client4, cleanup: () => {} };
|
|
25293
|
+
}
|
|
25234
25294
|
}
|
|
25235
25295
|
console.log(import_picocolors9.default.dim("Port"), import_picocolors9.default.cyan(port.toString()), import_picocolors9.default.dim("is occupied, attaching to existing server"));
|
|
25236
|
-
const
|
|
25237
|
-
return { client:
|
|
25296
|
+
const client3 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
|
|
25297
|
+
return { client: client3, cleanup: () => {} };
|
|
25298
|
+
}
|
|
25299
|
+
let selectedPort;
|
|
25300
|
+
let wasAutoSelected;
|
|
25301
|
+
try {
|
|
25302
|
+
const selected = await getAvailableServerPort(DEFAULT_SERVER_PORT, "127.0.0.1");
|
|
25303
|
+
selectedPort = selected.port;
|
|
25304
|
+
wasAutoSelected = selected.wasAutoSelected;
|
|
25305
|
+
} catch (error45) {
|
|
25306
|
+
if (!isPortRangeExhausted(error45)) {
|
|
25307
|
+
throw error45;
|
|
25308
|
+
}
|
|
25309
|
+
const defaultPortIsAvailable = await isPortAvailable(DEFAULT_SERVER_PORT, "127.0.0.1");
|
|
25310
|
+
if (defaultPortIsAvailable) {
|
|
25311
|
+
throw error45;
|
|
25312
|
+
}
|
|
25313
|
+
console.log(import_picocolors9.default.dim("Port range exhausted, attaching to existing server on"), import_picocolors9.default.cyan(DEFAULT_SERVER_PORT.toString()));
|
|
25314
|
+
const client3 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${DEFAULT_SERVER_PORT}` });
|
|
25315
|
+
return { client: client3, cleanup: () => {} };
|
|
25238
25316
|
}
|
|
25239
|
-
const { port: selectedPort, wasAutoSelected } = await getAvailableServerPort(DEFAULT_SERVER_PORT, "127.0.0.1");
|
|
25240
25317
|
if (wasAutoSelected) {
|
|
25241
25318
|
console.log(import_picocolors9.default.dim("Auto-selected port"), import_picocolors9.default.cyan(selectedPort.toString()));
|
|
25242
25319
|
} else {
|
|
25243
25320
|
console.log(import_picocolors9.default.dim("Starting server on port"), import_picocolors9.default.cyan(selectedPort.toString()));
|
|
25244
25321
|
}
|
|
25245
|
-
|
|
25246
|
-
|
|
25247
|
-
|
|
25322
|
+
try {
|
|
25323
|
+
return await startServer({ signal, port: selectedPort });
|
|
25324
|
+
} catch (error45) {
|
|
25325
|
+
if (!isPortStartFailure(error45, selectedPort)) {
|
|
25326
|
+
throw error45;
|
|
25327
|
+
}
|
|
25328
|
+
const { port: retryPort } = await getAvailableServerPort(selectedPort + 1, "127.0.0.1");
|
|
25329
|
+
console.log(import_picocolors9.default.dim("Retrying server start on port"), import_picocolors9.default.cyan(retryPort.toString()));
|
|
25330
|
+
return await startServer({ signal, port: retryPort });
|
|
25331
|
+
}
|
|
25248
25332
|
}
|
|
25249
25333
|
|
|
25250
25334
|
// src/cli/run/session-resolver.ts
|
|
@@ -25427,7 +25511,7 @@ var NOTEPAD_DIR = "notepads";
|
|
|
25427
25511
|
var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
|
|
25428
25512
|
// src/features/boulder-state/storage.ts
|
|
25429
25513
|
import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync3, readdirSync } from "fs";
|
|
25430
|
-
import { dirname as
|
|
25514
|
+
import { dirname as dirname2, join as join9, basename } from "path";
|
|
25431
25515
|
function getBoulderFilePath(directory) {
|
|
25432
25516
|
return join9(directory, BOULDER_DIR, BOULDER_FILE);
|
|
25433
25517
|
}
|
|
@@ -25508,7 +25592,7 @@ function getActiveContinuationMarkerReason(marker) {
|
|
|
25508
25592
|
// src/hooks/ralph-loop/storage.ts
|
|
25509
25593
|
init_frontmatter();
|
|
25510
25594
|
import { existsSync as existsSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync9, unlinkSync, mkdirSync as mkdirSync5 } from "fs";
|
|
25511
|
-
import { dirname as
|
|
25595
|
+
import { dirname as dirname3, join as join11 } from "path";
|
|
25512
25596
|
|
|
25513
25597
|
// src/hooks/ralph-loop/constants.ts
|
|
25514
25598
|
var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
|
|
@@ -25593,7 +25677,7 @@ async function checkCompletionConditions(ctx) {
|
|
|
25593
25677
|
const continuationState = getContinuationState(ctx.directory, ctx.sessionID);
|
|
25594
25678
|
if (continuationState.hasActiveHookMarker) {
|
|
25595
25679
|
const reason = continuationState.activeHookMarkerReason ?? "continuation hook is active";
|
|
25596
|
-
|
|
25680
|
+
logWaiting(ctx, reason);
|
|
25597
25681
|
return false;
|
|
25598
25682
|
}
|
|
25599
25683
|
if (!continuationState.hasTodoHookMarker && !await areAllTodosComplete(ctx)) {
|
|
@@ -25602,7 +25686,7 @@ async function checkCompletionConditions(ctx) {
|
|
|
25602
25686
|
if (!await areAllChildrenIdle(ctx)) {
|
|
25603
25687
|
return false;
|
|
25604
25688
|
}
|
|
25605
|
-
if (!areContinuationHooksIdle(continuationState)) {
|
|
25689
|
+
if (!areContinuationHooksIdle(ctx, continuationState)) {
|
|
25606
25690
|
return false;
|
|
25607
25691
|
}
|
|
25608
25692
|
return true;
|
|
@@ -25611,13 +25695,13 @@ async function checkCompletionConditions(ctx) {
|
|
|
25611
25695
|
return false;
|
|
25612
25696
|
}
|
|
25613
25697
|
}
|
|
25614
|
-
function areContinuationHooksIdle(continuationState) {
|
|
25698
|
+
function areContinuationHooksIdle(ctx, continuationState) {
|
|
25615
25699
|
if (continuationState.hasActiveBoulder) {
|
|
25616
|
-
|
|
25700
|
+
logWaiting(ctx, "boulder continuation is active");
|
|
25617
25701
|
return false;
|
|
25618
25702
|
}
|
|
25619
25703
|
if (continuationState.hasActiveRalphLoop) {
|
|
25620
|
-
|
|
25704
|
+
logWaiting(ctx, "ralph-loop continuation is active");
|
|
25621
25705
|
return false;
|
|
25622
25706
|
}
|
|
25623
25707
|
return true;
|
|
@@ -25630,7 +25714,7 @@ async function areAllTodosComplete(ctx) {
|
|
|
25630
25714
|
const todos = normalizeSDKResponse(todosRes, []);
|
|
25631
25715
|
const incompleteTodos = todos.filter((t) => t.status !== "completed" && t.status !== "cancelled");
|
|
25632
25716
|
if (incompleteTodos.length > 0) {
|
|
25633
|
-
|
|
25717
|
+
logWaiting(ctx, `${incompleteTodos.length} todos remaining`);
|
|
25634
25718
|
return false;
|
|
25635
25719
|
}
|
|
25636
25720
|
return true;
|
|
@@ -25654,7 +25738,7 @@ async function areAllDescendantsIdle(ctx, sessionID, allStatuses) {
|
|
|
25654
25738
|
for (const child of children) {
|
|
25655
25739
|
const status = allStatuses[child.id];
|
|
25656
25740
|
if (status && status.type !== "idle") {
|
|
25657
|
-
|
|
25741
|
+
logWaiting(ctx, `session ${child.id.slice(0, 8)}... is ${status.type}`);
|
|
25658
25742
|
return false;
|
|
25659
25743
|
}
|
|
25660
25744
|
const descendantsIdle = await areAllDescendantsIdle(ctx, child.id, allStatuses);
|
|
@@ -25664,6 +25748,12 @@ async function areAllDescendantsIdle(ctx, sessionID, allStatuses) {
|
|
|
25664
25748
|
}
|
|
25665
25749
|
return true;
|
|
25666
25750
|
}
|
|
25751
|
+
function logWaiting(ctx, message) {
|
|
25752
|
+
if (!ctx.verbose) {
|
|
25753
|
+
return;
|
|
25754
|
+
}
|
|
25755
|
+
console.log(import_picocolors13.default.dim(` Waiting: ${message}`));
|
|
25756
|
+
}
|
|
25667
25757
|
|
|
25668
25758
|
// src/cli/run/poll-for-completion.ts
|
|
25669
25759
|
init_shared();
|
|
@@ -25783,6 +25873,41 @@ async function loadAgentProfileColors(client3) {
|
|
|
25783
25873
|
}
|
|
25784
25874
|
}
|
|
25785
25875
|
|
|
25876
|
+
// src/cli/run/stdin-suppression.ts
|
|
25877
|
+
function includesCtrlC(chunk) {
|
|
25878
|
+
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
25879
|
+
return text.includes("\x03");
|
|
25880
|
+
}
|
|
25881
|
+
function suppressRunInput(stdin = process.stdin, onInterrupt = () => {
|
|
25882
|
+
process.kill(process.pid, "SIGINT");
|
|
25883
|
+
}) {
|
|
25884
|
+
if (!stdin.isTTY) {
|
|
25885
|
+
return () => {};
|
|
25886
|
+
}
|
|
25887
|
+
const wasRaw = stdin.isRaw === true;
|
|
25888
|
+
const wasPaused = stdin.isPaused?.() ?? false;
|
|
25889
|
+
const canSetRawMode = typeof stdin.setRawMode === "function";
|
|
25890
|
+
const onData = (chunk) => {
|
|
25891
|
+
if (includesCtrlC(chunk)) {
|
|
25892
|
+
onInterrupt();
|
|
25893
|
+
}
|
|
25894
|
+
};
|
|
25895
|
+
if (canSetRawMode) {
|
|
25896
|
+
stdin.setRawMode(true);
|
|
25897
|
+
}
|
|
25898
|
+
stdin.on("data", onData);
|
|
25899
|
+
stdin.resume();
|
|
25900
|
+
return () => {
|
|
25901
|
+
stdin.removeListener("data", onData);
|
|
25902
|
+
if (canSetRawMode) {
|
|
25903
|
+
stdin.setRawMode(wasRaw);
|
|
25904
|
+
}
|
|
25905
|
+
if (wasPaused) {
|
|
25906
|
+
stdin.pause();
|
|
25907
|
+
}
|
|
25908
|
+
};
|
|
25909
|
+
}
|
|
25910
|
+
|
|
25786
25911
|
// src/cli/run/runner.ts
|
|
25787
25912
|
var EVENT_PROCESSOR_SHUTDOWN_TIMEOUT_MS = 2000;
|
|
25788
25913
|
async function waitForEventProcessorShutdown(eventProcessor, timeoutMs = EVENT_PROCESSOR_SHUTDOWN_TIMEOUT_MS) {
|
|
@@ -25813,12 +25938,15 @@ async function run(options) {
|
|
|
25813
25938
|
const cleanup = () => {
|
|
25814
25939
|
serverCleanup();
|
|
25815
25940
|
};
|
|
25816
|
-
|
|
25941
|
+
const restoreInput = suppressRunInput();
|
|
25942
|
+
const handleSigint = () => {
|
|
25817
25943
|
console.log(import_picocolors15.default.yellow(`
|
|
25818
25944
|
Interrupted. Shutting down...`));
|
|
25945
|
+
restoreInput();
|
|
25819
25946
|
cleanup();
|
|
25820
25947
|
process.exit(130);
|
|
25821
|
-
}
|
|
25948
|
+
};
|
|
25949
|
+
process.on("SIGINT", handleSigint);
|
|
25822
25950
|
try {
|
|
25823
25951
|
const sessionID = await resolveSession({
|
|
25824
25952
|
client: client3,
|
|
@@ -25841,6 +25969,9 @@ Interrupted. Shutting down...`));
|
|
|
25841
25969
|
path: { id: sessionID },
|
|
25842
25970
|
body: {
|
|
25843
25971
|
agent: resolvedAgent,
|
|
25972
|
+
tools: {
|
|
25973
|
+
question: false
|
|
25974
|
+
},
|
|
25844
25975
|
parts: [{ type: "text", text: message }]
|
|
25845
25976
|
},
|
|
25846
25977
|
query: { directory }
|
|
@@ -25872,6 +26003,9 @@ Interrupted. Shutting down...`));
|
|
|
25872
26003
|
} catch (err) {
|
|
25873
26004
|
cleanup();
|
|
25874
26005
|
throw err;
|
|
26006
|
+
} finally {
|
|
26007
|
+
process.removeListener("SIGINT", handleSigint);
|
|
26008
|
+
restoreInput();
|
|
25875
26009
|
}
|
|
25876
26010
|
} catch (err) {
|
|
25877
26011
|
if (jsonManager)
|
|
@@ -26750,8 +26884,8 @@ async function checkConfig() {
|
|
|
26750
26884
|
|
|
26751
26885
|
// src/cli/doctor/checks/dependencies.ts
|
|
26752
26886
|
import { existsSync as existsSync24 } from "fs";
|
|
26753
|
-
import { createRequire
|
|
26754
|
-
import { dirname as
|
|
26887
|
+
import { createRequire } from "module";
|
|
26888
|
+
import { dirname as dirname6, join as join22 } from "path";
|
|
26755
26889
|
async function checkBinaryExists(binary2) {
|
|
26756
26890
|
try {
|
|
26757
26891
|
const path9 = Bun.which(binary2);
|
|
@@ -26838,9 +26972,9 @@ async function checkAstGrepNapi() {
|
|
|
26838
26972
|
function findCommentCheckerPackageBinary() {
|
|
26839
26973
|
const binaryName = process.platform === "win32" ? "comment-checker.exe" : "comment-checker";
|
|
26840
26974
|
try {
|
|
26841
|
-
const require2 =
|
|
26975
|
+
const require2 = createRequire(import.meta.url);
|
|
26842
26976
|
const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
|
|
26843
|
-
const binaryPath = join22(
|
|
26977
|
+
const binaryPath = join22(dirname6(pkgPath), "bin", binaryName);
|
|
26844
26978
|
if (existsSync24(binaryPath))
|
|
26845
26979
|
return binaryPath;
|
|
26846
26980
|
} catch {}
|
|
@@ -27458,7 +27592,7 @@ async function doctor(options = { mode: "default" }) {
|
|
|
27458
27592
|
// src/features/mcp-oauth/storage.ts
|
|
27459
27593
|
init_shared();
|
|
27460
27594
|
import { chmodSync, existsSync as existsSync27, mkdirSync as mkdirSync6, readFileSync as readFileSync28, unlinkSync as unlinkSync2, writeFileSync as writeFileSync12 } from "fs";
|
|
27461
|
-
import { dirname as
|
|
27595
|
+
import { dirname as dirname7, join as join25 } from "path";
|
|
27462
27596
|
var STORAGE_FILE_NAME = "mcp-oauth.json";
|
|
27463
27597
|
function getMcpOauthStoragePath() {
|
|
27464
27598
|
return join25(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
|
|
@@ -27508,14 +27642,14 @@ function readStore() {
|
|
|
27508
27642
|
return null;
|
|
27509
27643
|
}
|
|
27510
27644
|
}
|
|
27511
|
-
function writeStore(
|
|
27645
|
+
function writeStore(store2) {
|
|
27512
27646
|
const filePath = getMcpOauthStoragePath();
|
|
27513
27647
|
try {
|
|
27514
|
-
const dir =
|
|
27648
|
+
const dir = dirname7(filePath);
|
|
27515
27649
|
if (!existsSync27(dir)) {
|
|
27516
27650
|
mkdirSync6(dir, { recursive: true });
|
|
27517
27651
|
}
|
|
27518
|
-
writeFileSync12(filePath, JSON.stringify(
|
|
27652
|
+
writeFileSync12(filePath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
|
|
27519
27653
|
chmodSync(filePath, 384);
|
|
27520
27654
|
return true;
|
|
27521
27655
|
} catch {
|
|
@@ -27523,28 +27657,28 @@ function writeStore(store) {
|
|
|
27523
27657
|
}
|
|
27524
27658
|
}
|
|
27525
27659
|
function loadToken(serverHost, resource) {
|
|
27526
|
-
const
|
|
27527
|
-
if (!
|
|
27660
|
+
const store2 = readStore();
|
|
27661
|
+
if (!store2)
|
|
27528
27662
|
return null;
|
|
27529
27663
|
const key = buildKey(serverHost, resource);
|
|
27530
|
-
return
|
|
27664
|
+
return store2[key] ?? null;
|
|
27531
27665
|
}
|
|
27532
27666
|
function saveToken(serverHost, resource, token) {
|
|
27533
|
-
const
|
|
27667
|
+
const store2 = readStore() ?? {};
|
|
27534
27668
|
const key = buildKey(serverHost, resource);
|
|
27535
|
-
|
|
27536
|
-
return writeStore(
|
|
27669
|
+
store2[key] = token;
|
|
27670
|
+
return writeStore(store2);
|
|
27537
27671
|
}
|
|
27538
27672
|
function deleteToken(serverHost, resource) {
|
|
27539
|
-
const
|
|
27540
|
-
if (!
|
|
27673
|
+
const store2 = readStore();
|
|
27674
|
+
if (!store2)
|
|
27541
27675
|
return true;
|
|
27542
27676
|
const key = buildKey(serverHost, resource);
|
|
27543
|
-
if (!(key in
|
|
27677
|
+
if (!(key in store2)) {
|
|
27544
27678
|
return true;
|
|
27545
27679
|
}
|
|
27546
|
-
delete
|
|
27547
|
-
if (Object.keys(
|
|
27680
|
+
delete store2[key];
|
|
27681
|
+
if (Object.keys(store2).length === 0) {
|
|
27548
27682
|
try {
|
|
27549
27683
|
const filePath = getMcpOauthStoragePath();
|
|
27550
27684
|
if (existsSync27(filePath)) {
|
|
@@ -27555,16 +27689,16 @@ function deleteToken(serverHost, resource) {
|
|
|
27555
27689
|
return false;
|
|
27556
27690
|
}
|
|
27557
27691
|
}
|
|
27558
|
-
return writeStore(
|
|
27692
|
+
return writeStore(store2);
|
|
27559
27693
|
}
|
|
27560
27694
|
function listTokensByHost(serverHost) {
|
|
27561
|
-
const
|
|
27562
|
-
if (!
|
|
27695
|
+
const store2 = readStore();
|
|
27696
|
+
if (!store2)
|
|
27563
27697
|
return {};
|
|
27564
27698
|
const host = normalizeHost(serverHost);
|
|
27565
27699
|
const prefix = `${host}/`;
|
|
27566
27700
|
const result = {};
|
|
27567
|
-
for (const [key, value] of Object.entries(
|
|
27701
|
+
for (const [key, value] of Object.entries(store2)) {
|
|
27568
27702
|
if (key.startsWith(prefix)) {
|
|
27569
27703
|
result[key] = value;
|
|
27570
27704
|
}
|