oh-my-opencode 3.7.3 → 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 +187 -83
- 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,26 +25244,6 @@ async function withWorkingOpencodePath(startServer, finder = findWorkingOpencode
|
|
|
25192
25244
|
}
|
|
25193
25245
|
}
|
|
25194
25246
|
|
|
25195
|
-
// src/cli/run/opencode-bin-path.ts
|
|
25196
|
-
import { delimiter as delimiter2, dirname as dirname2 } from "path";
|
|
25197
|
-
import { createRequire } from "module";
|
|
25198
|
-
var resolveFromCurrentModule = createRequire(import.meta.url).resolve;
|
|
25199
|
-
function prependResolvedOpencodeBinToPath(env = process.env, resolve2 = resolveFromCurrentModule) {
|
|
25200
|
-
let resolvedPath;
|
|
25201
|
-
try {
|
|
25202
|
-
resolvedPath = resolve2("opencode-ai/bin/opencode");
|
|
25203
|
-
} catch {
|
|
25204
|
-
return;
|
|
25205
|
-
}
|
|
25206
|
-
const opencodeBinDir = dirname2(resolvedPath);
|
|
25207
|
-
const currentPath = env.PATH ?? "";
|
|
25208
|
-
const pathSegments = currentPath ? currentPath.split(delimiter2) : [];
|
|
25209
|
-
if (pathSegments.includes(opencodeBinDir)) {
|
|
25210
|
-
return;
|
|
25211
|
-
}
|
|
25212
|
-
env.PATH = currentPath ? `${opencodeBinDir}${delimiter2}${currentPath}` : opencodeBinDir;
|
|
25213
|
-
}
|
|
25214
|
-
|
|
25215
25247
|
// src/cli/run/server-connection.ts
|
|
25216
25248
|
function isPortStartFailure(error45, port) {
|
|
25217
25249
|
if (!(error45 instanceof Error)) {
|
|
@@ -25219,6 +25251,12 @@ function isPortStartFailure(error45, port) {
|
|
|
25219
25251
|
}
|
|
25220
25252
|
return error45.message.includes(`Failed to start server on port ${port}`);
|
|
25221
25253
|
}
|
|
25254
|
+
function isPortRangeExhausted(error45) {
|
|
25255
|
+
if (!(error45 instanceof Error)) {
|
|
25256
|
+
return false;
|
|
25257
|
+
}
|
|
25258
|
+
return error45.message.includes("No available port found in range");
|
|
25259
|
+
}
|
|
25222
25260
|
async function startServer(options) {
|
|
25223
25261
|
const { signal, port } = options;
|
|
25224
25262
|
const { client: client3, server: server2 } = await withWorkingOpencodePath(() => createOpencode({ signal, port, hostname: "127.0.0.1" }));
|
|
@@ -25226,7 +25264,6 @@ async function startServer(options) {
|
|
|
25226
25264
|
return { client: client3, cleanup: () => server2.close() };
|
|
25227
25265
|
}
|
|
25228
25266
|
async function createServerConnection(options) {
|
|
25229
|
-
prependResolvedOpencodeBinToPath();
|
|
25230
25267
|
const { port, attach, signal } = options;
|
|
25231
25268
|
if (attach !== undefined) {
|
|
25232
25269
|
console.log(import_picocolors9.default.dim("Attaching to existing server at"), import_picocolors9.default.cyan(attach));
|
|
@@ -25259,7 +25296,24 @@ async function createServerConnection(options) {
|
|
|
25259
25296
|
const client3 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
|
|
25260
25297
|
return { client: client3, cleanup: () => {} };
|
|
25261
25298
|
}
|
|
25262
|
-
|
|
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: () => {} };
|
|
25316
|
+
}
|
|
25263
25317
|
if (wasAutoSelected) {
|
|
25264
25318
|
console.log(import_picocolors9.default.dim("Auto-selected port"), import_picocolors9.default.cyan(selectedPort.toString()));
|
|
25265
25319
|
} else {
|
|
@@ -25457,7 +25511,7 @@ var NOTEPAD_DIR = "notepads";
|
|
|
25457
25511
|
var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
|
|
25458
25512
|
// src/features/boulder-state/storage.ts
|
|
25459
25513
|
import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync3, readdirSync } from "fs";
|
|
25460
|
-
import { dirname as
|
|
25514
|
+
import { dirname as dirname2, join as join9, basename } from "path";
|
|
25461
25515
|
function getBoulderFilePath(directory) {
|
|
25462
25516
|
return join9(directory, BOULDER_DIR, BOULDER_FILE);
|
|
25463
25517
|
}
|
|
@@ -25538,7 +25592,7 @@ function getActiveContinuationMarkerReason(marker) {
|
|
|
25538
25592
|
// src/hooks/ralph-loop/storage.ts
|
|
25539
25593
|
init_frontmatter();
|
|
25540
25594
|
import { existsSync as existsSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync9, unlinkSync, mkdirSync as mkdirSync5 } from "fs";
|
|
25541
|
-
import { dirname as
|
|
25595
|
+
import { dirname as dirname3, join as join11 } from "path";
|
|
25542
25596
|
|
|
25543
25597
|
// src/hooks/ralph-loop/constants.ts
|
|
25544
25598
|
var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
|
|
@@ -25623,7 +25677,7 @@ async function checkCompletionConditions(ctx) {
|
|
|
25623
25677
|
const continuationState = getContinuationState(ctx.directory, ctx.sessionID);
|
|
25624
25678
|
if (continuationState.hasActiveHookMarker) {
|
|
25625
25679
|
const reason = continuationState.activeHookMarkerReason ?? "continuation hook is active";
|
|
25626
|
-
|
|
25680
|
+
logWaiting(ctx, reason);
|
|
25627
25681
|
return false;
|
|
25628
25682
|
}
|
|
25629
25683
|
if (!continuationState.hasTodoHookMarker && !await areAllTodosComplete(ctx)) {
|
|
@@ -25632,7 +25686,7 @@ async function checkCompletionConditions(ctx) {
|
|
|
25632
25686
|
if (!await areAllChildrenIdle(ctx)) {
|
|
25633
25687
|
return false;
|
|
25634
25688
|
}
|
|
25635
|
-
if (!areContinuationHooksIdle(continuationState)) {
|
|
25689
|
+
if (!areContinuationHooksIdle(ctx, continuationState)) {
|
|
25636
25690
|
return false;
|
|
25637
25691
|
}
|
|
25638
25692
|
return true;
|
|
@@ -25641,13 +25695,13 @@ async function checkCompletionConditions(ctx) {
|
|
|
25641
25695
|
return false;
|
|
25642
25696
|
}
|
|
25643
25697
|
}
|
|
25644
|
-
function areContinuationHooksIdle(continuationState) {
|
|
25698
|
+
function areContinuationHooksIdle(ctx, continuationState) {
|
|
25645
25699
|
if (continuationState.hasActiveBoulder) {
|
|
25646
|
-
|
|
25700
|
+
logWaiting(ctx, "boulder continuation is active");
|
|
25647
25701
|
return false;
|
|
25648
25702
|
}
|
|
25649
25703
|
if (continuationState.hasActiveRalphLoop) {
|
|
25650
|
-
|
|
25704
|
+
logWaiting(ctx, "ralph-loop continuation is active");
|
|
25651
25705
|
return false;
|
|
25652
25706
|
}
|
|
25653
25707
|
return true;
|
|
@@ -25660,7 +25714,7 @@ async function areAllTodosComplete(ctx) {
|
|
|
25660
25714
|
const todos = normalizeSDKResponse(todosRes, []);
|
|
25661
25715
|
const incompleteTodos = todos.filter((t) => t.status !== "completed" && t.status !== "cancelled");
|
|
25662
25716
|
if (incompleteTodos.length > 0) {
|
|
25663
|
-
|
|
25717
|
+
logWaiting(ctx, `${incompleteTodos.length} todos remaining`);
|
|
25664
25718
|
return false;
|
|
25665
25719
|
}
|
|
25666
25720
|
return true;
|
|
@@ -25684,7 +25738,7 @@ async function areAllDescendantsIdle(ctx, sessionID, allStatuses) {
|
|
|
25684
25738
|
for (const child of children) {
|
|
25685
25739
|
const status = allStatuses[child.id];
|
|
25686
25740
|
if (status && status.type !== "idle") {
|
|
25687
|
-
|
|
25741
|
+
logWaiting(ctx, `session ${child.id.slice(0, 8)}... is ${status.type}`);
|
|
25688
25742
|
return false;
|
|
25689
25743
|
}
|
|
25690
25744
|
const descendantsIdle = await areAllDescendantsIdle(ctx, child.id, allStatuses);
|
|
@@ -25694,6 +25748,12 @@ async function areAllDescendantsIdle(ctx, sessionID, allStatuses) {
|
|
|
25694
25748
|
}
|
|
25695
25749
|
return true;
|
|
25696
25750
|
}
|
|
25751
|
+
function logWaiting(ctx, message) {
|
|
25752
|
+
if (!ctx.verbose) {
|
|
25753
|
+
return;
|
|
25754
|
+
}
|
|
25755
|
+
console.log(import_picocolors13.default.dim(` Waiting: ${message}`));
|
|
25756
|
+
}
|
|
25697
25757
|
|
|
25698
25758
|
// src/cli/run/poll-for-completion.ts
|
|
25699
25759
|
init_shared();
|
|
@@ -25813,6 +25873,41 @@ async function loadAgentProfileColors(client3) {
|
|
|
25813
25873
|
}
|
|
25814
25874
|
}
|
|
25815
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
|
+
|
|
25816
25911
|
// src/cli/run/runner.ts
|
|
25817
25912
|
var EVENT_PROCESSOR_SHUTDOWN_TIMEOUT_MS = 2000;
|
|
25818
25913
|
async function waitForEventProcessorShutdown(eventProcessor, timeoutMs = EVENT_PROCESSOR_SHUTDOWN_TIMEOUT_MS) {
|
|
@@ -25843,12 +25938,15 @@ async function run(options) {
|
|
|
25843
25938
|
const cleanup = () => {
|
|
25844
25939
|
serverCleanup();
|
|
25845
25940
|
};
|
|
25846
|
-
|
|
25941
|
+
const restoreInput = suppressRunInput();
|
|
25942
|
+
const handleSigint = () => {
|
|
25847
25943
|
console.log(import_picocolors15.default.yellow(`
|
|
25848
25944
|
Interrupted. Shutting down...`));
|
|
25945
|
+
restoreInput();
|
|
25849
25946
|
cleanup();
|
|
25850
25947
|
process.exit(130);
|
|
25851
|
-
}
|
|
25948
|
+
};
|
|
25949
|
+
process.on("SIGINT", handleSigint);
|
|
25852
25950
|
try {
|
|
25853
25951
|
const sessionID = await resolveSession({
|
|
25854
25952
|
client: client3,
|
|
@@ -25871,6 +25969,9 @@ Interrupted. Shutting down...`));
|
|
|
25871
25969
|
path: { id: sessionID },
|
|
25872
25970
|
body: {
|
|
25873
25971
|
agent: resolvedAgent,
|
|
25972
|
+
tools: {
|
|
25973
|
+
question: false
|
|
25974
|
+
},
|
|
25874
25975
|
parts: [{ type: "text", text: message }]
|
|
25875
25976
|
},
|
|
25876
25977
|
query: { directory }
|
|
@@ -25902,6 +26003,9 @@ Interrupted. Shutting down...`));
|
|
|
25902
26003
|
} catch (err) {
|
|
25903
26004
|
cleanup();
|
|
25904
26005
|
throw err;
|
|
26006
|
+
} finally {
|
|
26007
|
+
process.removeListener("SIGINT", handleSigint);
|
|
26008
|
+
restoreInput();
|
|
25905
26009
|
}
|
|
25906
26010
|
} catch (err) {
|
|
25907
26011
|
if (jsonManager)
|
|
@@ -26780,8 +26884,8 @@ async function checkConfig() {
|
|
|
26780
26884
|
|
|
26781
26885
|
// src/cli/doctor/checks/dependencies.ts
|
|
26782
26886
|
import { existsSync as existsSync24 } from "fs";
|
|
26783
|
-
import { createRequire
|
|
26784
|
-
import { dirname as
|
|
26887
|
+
import { createRequire } from "module";
|
|
26888
|
+
import { dirname as dirname6, join as join22 } from "path";
|
|
26785
26889
|
async function checkBinaryExists(binary2) {
|
|
26786
26890
|
try {
|
|
26787
26891
|
const path9 = Bun.which(binary2);
|
|
@@ -26868,9 +26972,9 @@ async function checkAstGrepNapi() {
|
|
|
26868
26972
|
function findCommentCheckerPackageBinary() {
|
|
26869
26973
|
const binaryName = process.platform === "win32" ? "comment-checker.exe" : "comment-checker";
|
|
26870
26974
|
try {
|
|
26871
|
-
const require2 =
|
|
26975
|
+
const require2 = createRequire(import.meta.url);
|
|
26872
26976
|
const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
|
|
26873
|
-
const binaryPath = join22(
|
|
26977
|
+
const binaryPath = join22(dirname6(pkgPath), "bin", binaryName);
|
|
26874
26978
|
if (existsSync24(binaryPath))
|
|
26875
26979
|
return binaryPath;
|
|
26876
26980
|
} catch {}
|
|
@@ -27488,7 +27592,7 @@ async function doctor(options = { mode: "default" }) {
|
|
|
27488
27592
|
// src/features/mcp-oauth/storage.ts
|
|
27489
27593
|
init_shared();
|
|
27490
27594
|
import { chmodSync, existsSync as existsSync27, mkdirSync as mkdirSync6, readFileSync as readFileSync28, unlinkSync as unlinkSync2, writeFileSync as writeFileSync12 } from "fs";
|
|
27491
|
-
import { dirname as
|
|
27595
|
+
import { dirname as dirname7, join as join25 } from "path";
|
|
27492
27596
|
var STORAGE_FILE_NAME = "mcp-oauth.json";
|
|
27493
27597
|
function getMcpOauthStoragePath() {
|
|
27494
27598
|
return join25(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
|
|
@@ -27538,14 +27642,14 @@ function readStore() {
|
|
|
27538
27642
|
return null;
|
|
27539
27643
|
}
|
|
27540
27644
|
}
|
|
27541
|
-
function writeStore(
|
|
27645
|
+
function writeStore(store2) {
|
|
27542
27646
|
const filePath = getMcpOauthStoragePath();
|
|
27543
27647
|
try {
|
|
27544
|
-
const dir =
|
|
27648
|
+
const dir = dirname7(filePath);
|
|
27545
27649
|
if (!existsSync27(dir)) {
|
|
27546
27650
|
mkdirSync6(dir, { recursive: true });
|
|
27547
27651
|
}
|
|
27548
|
-
writeFileSync12(filePath, JSON.stringify(
|
|
27652
|
+
writeFileSync12(filePath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
|
|
27549
27653
|
chmodSync(filePath, 384);
|
|
27550
27654
|
return true;
|
|
27551
27655
|
} catch {
|
|
@@ -27553,28 +27657,28 @@ function writeStore(store) {
|
|
|
27553
27657
|
}
|
|
27554
27658
|
}
|
|
27555
27659
|
function loadToken(serverHost, resource) {
|
|
27556
|
-
const
|
|
27557
|
-
if (!
|
|
27660
|
+
const store2 = readStore();
|
|
27661
|
+
if (!store2)
|
|
27558
27662
|
return null;
|
|
27559
27663
|
const key = buildKey(serverHost, resource);
|
|
27560
|
-
return
|
|
27664
|
+
return store2[key] ?? null;
|
|
27561
27665
|
}
|
|
27562
27666
|
function saveToken(serverHost, resource, token) {
|
|
27563
|
-
const
|
|
27667
|
+
const store2 = readStore() ?? {};
|
|
27564
27668
|
const key = buildKey(serverHost, resource);
|
|
27565
|
-
|
|
27566
|
-
return writeStore(
|
|
27669
|
+
store2[key] = token;
|
|
27670
|
+
return writeStore(store2);
|
|
27567
27671
|
}
|
|
27568
27672
|
function deleteToken(serverHost, resource) {
|
|
27569
|
-
const
|
|
27570
|
-
if (!
|
|
27673
|
+
const store2 = readStore();
|
|
27674
|
+
if (!store2)
|
|
27571
27675
|
return true;
|
|
27572
27676
|
const key = buildKey(serverHost, resource);
|
|
27573
|
-
if (!(key in
|
|
27677
|
+
if (!(key in store2)) {
|
|
27574
27678
|
return true;
|
|
27575
27679
|
}
|
|
27576
|
-
delete
|
|
27577
|
-
if (Object.keys(
|
|
27680
|
+
delete store2[key];
|
|
27681
|
+
if (Object.keys(store2).length === 0) {
|
|
27578
27682
|
try {
|
|
27579
27683
|
const filePath = getMcpOauthStoragePath();
|
|
27580
27684
|
if (existsSync27(filePath)) {
|
|
@@ -27585,16 +27689,16 @@ function deleteToken(serverHost, resource) {
|
|
|
27585
27689
|
return false;
|
|
27586
27690
|
}
|
|
27587
27691
|
}
|
|
27588
|
-
return writeStore(
|
|
27692
|
+
return writeStore(store2);
|
|
27589
27693
|
}
|
|
27590
27694
|
function listTokensByHost(serverHost) {
|
|
27591
|
-
const
|
|
27592
|
-
if (!
|
|
27695
|
+
const store2 = readStore();
|
|
27696
|
+
if (!store2)
|
|
27593
27697
|
return {};
|
|
27594
27698
|
const host = normalizeHost(serverHost);
|
|
27595
27699
|
const prefix = `${host}/`;
|
|
27596
27700
|
const result = {};
|
|
27597
|
-
for (const [key, value] of Object.entries(
|
|
27701
|
+
for (const [key, value] of Object.entries(store2)) {
|
|
27598
27702
|
if (key.startsWith(prefix)) {
|
|
27599
27703
|
result[key] = value;
|
|
27600
27704
|
}
|
|
@@ -10,9 +10,14 @@ export interface ProviderAvailability {
|
|
|
10
10
|
kimiForCoding: boolean;
|
|
11
11
|
isMaxPlan: boolean;
|
|
12
12
|
}
|
|
13
|
+
export interface UltraworkConfig {
|
|
14
|
+
model: string;
|
|
15
|
+
variant?: string;
|
|
16
|
+
}
|
|
13
17
|
export interface AgentConfig {
|
|
14
18
|
model: string;
|
|
15
19
|
variant?: string;
|
|
20
|
+
ultrawork?: UltraworkConfig;
|
|
16
21
|
}
|
|
17
22
|
export interface CategoryConfig {
|
|
18
23
|
model: string;
|
|
@@ -39,5 +39,9 @@ export interface EventState {
|
|
|
39
39
|
thinkingAtLineStart: boolean;
|
|
40
40
|
/** Current assistant message ID — prevents counter resets on repeated message.updated for same message */
|
|
41
41
|
currentMessageId: string | null;
|
|
42
|
+
/** Assistant message start timestamp by message ID */
|
|
43
|
+
messageStartedAtById: Record<string, number>;
|
|
44
|
+
/** Prevent duplicate completion metadata lines per message */
|
|
45
|
+
completionMetaPrintedByMessageId: Record<string, boolean>;
|
|
42
46
|
}
|
|
43
47
|
export declare function createEventState(): EventState;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type StdinLike = {
|
|
2
|
+
isTTY?: boolean;
|
|
3
|
+
isRaw?: boolean;
|
|
4
|
+
setRawMode?: (mode: boolean) => void;
|
|
5
|
+
isPaused?: () => boolean;
|
|
6
|
+
resume: () => void;
|
|
7
|
+
pause: () => void;
|
|
8
|
+
on: (event: "data", listener: (chunk: string | Uint8Array) => void) => void;
|
|
9
|
+
removeListener: (event: "data", listener: (chunk: string | Uint8Array) => void) => void;
|
|
10
|
+
};
|
|
11
|
+
export declare function suppressRunInput(stdin?: StdinLike, onInterrupt?: () => void): () => void;
|
|
12
|
+
export {};
|