@hiai-gg/hiai-opencode 0.1.4 → 0.1.5
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/AGENTS.md +5 -3
- package/ARCHITECTURE.md +7 -6
- package/README.md +16 -4
- package/config/hiai-opencode.schema.json +71 -148
- package/dist/config/defaults.d.ts +1 -0
- package/dist/config/platform-schema.d.ts +273 -4
- package/dist/config/schema/categories.d.ts +2 -2
- package/dist/config/types.d.ts +21 -2
- package/dist/create-tools.d.ts +2 -0
- package/dist/index.js +577 -342
- package/dist/internals/plugins/websearch-cited/index.d.ts +7 -1
- package/dist/mcp/types.d.ts +1 -1
- package/dist/plugin/tool-registry.d.ts +2 -0
- package/dist/tools/skill-mcp/tools.d.ts +2 -0
- package/hiai-opencode.json +39 -173
- package/package.json +1 -1
- package/src/config/defaults.ts +158 -28
- package/src/config/loader.test.ts +16 -1
- package/src/config/loader.ts +4 -2
- package/src/config/platform-schema.ts +36 -2
- package/src/config/types.ts +33 -2
- package/src/create-tools.ts +4 -1
- package/src/index.ts +39 -1
- package/src/internals/plugins/websearch-cited/index.ts +10 -5
- package/src/lsp/index.ts +1 -0
- package/src/mcp/registry.ts +6 -1
- package/src/plugin/tool-registry.ts +4 -0
- package/src/tools/skill-mcp/tools.ts +45 -7
package/dist/index.js
CHANGED
|
@@ -33657,9 +33657,9 @@ function parseOpenAIOptions(providerConfig, model) {
|
|
|
33657
33657
|
}
|
|
33658
33658
|
return result;
|
|
33659
33659
|
}
|
|
33660
|
-
var GOOGLE_PROVIDER_ID = "google", OPENAI_PROVIDER_ID = "openai", OPENROUTER_PROVIDER_ID = "openrouter", CITED_SEARCH_TOOL_DESCRIPTION = "Performs a Gemini-style grounded web search: returns a concise digest with inline citations and a Sources list of URLs. NOTE: for LLM rate limits, DO NOT parallel this tool > 5", WEBSEARCH_ARGS, WEBSEARCH_ALLOWED_KEYS, WEBSEARCH_ALLOWED_KEYS_DESCRIPTION, authRegistry, WebsearchCitedPlugin = () => {
|
|
33661
|
-
let selectedProvider;
|
|
33662
|
-
let selectedModel;
|
|
33660
|
+
var GOOGLE_PROVIDER_ID = "google", OPENAI_PROVIDER_ID = "openai", OPENROUTER_PROVIDER_ID = "openrouter", CITED_SEARCH_TOOL_DESCRIPTION = "Performs a Gemini-style grounded web search: returns a concise digest with inline citations and a Sources list of URLs. NOTE: for LLM rate limits, DO NOT parallel this tool > 5", WEBSEARCH_ARGS, WEBSEARCH_ALLOWED_KEYS, WEBSEARCH_ALLOWED_KEYS_DESCRIPTION, authRegistry, WebsearchCitedPlugin = (_ctx, fallback) => {
|
|
33661
|
+
let selectedProvider = fallback?.providerID;
|
|
33662
|
+
let selectedModel = fallback?.model;
|
|
33663
33663
|
let openaiConfig = {};
|
|
33664
33664
|
let configError;
|
|
33665
33665
|
return Promise.resolve({
|
|
@@ -33689,6 +33689,9 @@ var GOOGLE_PROVIDER_ID = "google", OPENAI_PROVIDER_ID = "openai", OPENROUTER_PRO
|
|
|
33689
33689
|
const openaiProvider = config4.provider?.openai;
|
|
33690
33690
|
openaiConfig = parseOpenAIOptions(openaiProvider, selectedModel);
|
|
33691
33691
|
}
|
|
33692
|
+
} else if (!error92 && fallback) {
|
|
33693
|
+
selectedProvider = fallback.providerID;
|
|
33694
|
+
selectedModel = fallback.model;
|
|
33692
33695
|
}
|
|
33693
33696
|
return Promise.resolve();
|
|
33694
33697
|
},
|
|
@@ -33809,7 +33812,7 @@ class EventEmitter {
|
|
|
33809
33812
|
import { dlopen, FFIType, ptr } from "bun:ffi";
|
|
33810
33813
|
import { Buffer as Buffer2 } from "buffer";
|
|
33811
33814
|
import { join as join104, dirname as dirname31, basename as basename16 } from "path";
|
|
33812
|
-
import { existsSync as
|
|
33815
|
+
import { existsSync as existsSync92 } from "fs";
|
|
33813
33816
|
function shQuote(s) {
|
|
33814
33817
|
if (s.length === 0)
|
|
33815
33818
|
return "''";
|
|
@@ -33817,7 +33820,7 @@ function shQuote(s) {
|
|
|
33817
33820
|
}
|
|
33818
33821
|
function resolveLibPath() {
|
|
33819
33822
|
const env = process.env.BUN_PTY_LIB;
|
|
33820
|
-
if (env &&
|
|
33823
|
+
if (env && existsSync92(env))
|
|
33821
33824
|
return env;
|
|
33822
33825
|
try {
|
|
33823
33826
|
const embeddedPath = __require(`../rust-pty/target/release/${process.platform === "win32" ? "rust_pty.dll" : process.platform === "darwin" ? process.arch === "arm64" ? "librust_pty_arm64.dylib" : "librust_pty.dylib" : process.arch === "arm64" ? "librust_pty_arm64.so" : "librust_pty.so"}`);
|
|
@@ -33843,7 +33846,7 @@ function resolveLibPath() {
|
|
|
33843
33846
|
}
|
|
33844
33847
|
}
|
|
33845
33848
|
for (const path10 of fallbackPaths) {
|
|
33846
|
-
if (
|
|
33849
|
+
if (existsSync92(path10))
|
|
33847
33850
|
return path10;
|
|
33848
33851
|
}
|
|
33849
33852
|
throw new Error(`librust_pty shared library not found.
|
|
@@ -35060,7 +35063,7 @@ var init_plugin = __esm(() => {
|
|
|
35060
35063
|
});
|
|
35061
35064
|
|
|
35062
35065
|
// src/index.ts
|
|
35063
|
-
import { existsSync as
|
|
35066
|
+
import { existsSync as existsSync93 } from "fs";
|
|
35064
35067
|
import { join as join105 } from "path";
|
|
35065
35068
|
|
|
35066
35069
|
// src/hooks/todo-continuation-enforcer/index.ts
|
|
@@ -120534,14 +120537,42 @@ import * as fs12 from "fs";
|
|
|
120534
120537
|
import * as path6 from "path";
|
|
120535
120538
|
|
|
120536
120539
|
// src/config/loader.ts
|
|
120537
|
-
import { existsSync as
|
|
120538
|
-
import { join as
|
|
120540
|
+
import { existsSync as existsSync58, readFileSync as readFileSync43 } from "fs";
|
|
120541
|
+
import { join as join67 } from "path";
|
|
120539
120542
|
|
|
120540
120543
|
// src/config/platform-schema.ts
|
|
120541
120544
|
var AgentConfigSchema = exports_external.object({
|
|
120542
120545
|
model: exports_external.string(),
|
|
120543
120546
|
description: exports_external.string().optional()
|
|
120544
120547
|
});
|
|
120548
|
+
var ModelRecommendationSchema = exports_external.enum([
|
|
120549
|
+
"xhigh",
|
|
120550
|
+
"high",
|
|
120551
|
+
"middle",
|
|
120552
|
+
"fast",
|
|
120553
|
+
"vision",
|
|
120554
|
+
"writing",
|
|
120555
|
+
"design"
|
|
120556
|
+
]);
|
|
120557
|
+
var ModelSlotConfigSchema = exports_external.union([
|
|
120558
|
+
exports_external.string(),
|
|
120559
|
+
exports_external.object({
|
|
120560
|
+
model: exports_external.string(),
|
|
120561
|
+
recommended: ModelRecommendationSchema.optional()
|
|
120562
|
+
})
|
|
120563
|
+
]);
|
|
120564
|
+
var ModelSlotsConfigSchema = exports_external.object({
|
|
120565
|
+
bob: ModelSlotConfigSchema.optional(),
|
|
120566
|
+
coder: ModelSlotConfigSchema.optional(),
|
|
120567
|
+
strategist: ModelSlotConfigSchema.optional(),
|
|
120568
|
+
guard: ModelSlotConfigSchema.optional(),
|
|
120569
|
+
critic: ModelSlotConfigSchema.optional(),
|
|
120570
|
+
designer: ModelSlotConfigSchema.optional(),
|
|
120571
|
+
researcher: ModelSlotConfigSchema.optional(),
|
|
120572
|
+
manager: ModelSlotConfigSchema.optional(),
|
|
120573
|
+
brainstormer: ModelSlotConfigSchema.optional(),
|
|
120574
|
+
vision: ModelSlotConfigSchema.optional()
|
|
120575
|
+
});
|
|
120545
120576
|
var FallbackEntrySchema = exports_external.object({
|
|
120546
120577
|
providers: exports_external.array(exports_external.string()),
|
|
120547
120578
|
model: exports_external.string(),
|
|
@@ -120578,8 +120609,9 @@ var McpServerConfigSchema = exports_external.object({
|
|
|
120578
120609
|
environment: exports_external.record(exports_external.string(), exports_external.string()).optional()
|
|
120579
120610
|
});
|
|
120580
120611
|
var LspServerConfigSchema = exports_external.object({
|
|
120581
|
-
|
|
120582
|
-
|
|
120612
|
+
enabled: exports_external.boolean().optional(),
|
|
120613
|
+
command: exports_external.array(exports_external.string()).optional(),
|
|
120614
|
+
extensions: exports_external.array(exports_external.string()).optional(),
|
|
120583
120615
|
initialization: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
120584
120616
|
});
|
|
120585
120617
|
var Subtask2ConfigSchema = exports_external.object({
|
|
@@ -120626,7 +120658,8 @@ var AuthKeysSchema = exports_external.object({
|
|
|
120626
120658
|
openai: exports_external.string().optional(),
|
|
120627
120659
|
openrouter: exports_external.string().optional(),
|
|
120628
120660
|
stitch: exports_external.string().optional(),
|
|
120629
|
-
firecrawl: exports_external.string().optional()
|
|
120661
|
+
firecrawl: exports_external.string().optional(),
|
|
120662
|
+
context7: exports_external.string().optional()
|
|
120630
120663
|
});
|
|
120631
120664
|
var OllamaConfigSchema = exports_external.object({
|
|
120632
120665
|
enabled: exports_external.boolean().default(false),
|
|
@@ -120706,6 +120739,7 @@ var AgentRequirementsConfigSchema = exports_external.object({
|
|
|
120706
120739
|
}).catchall(ModelRequirementSchema);
|
|
120707
120740
|
var HiaiOpencodeConfigSchema = exports_external.object({
|
|
120708
120741
|
$schema: exports_external.string().optional(),
|
|
120742
|
+
models: ModelSlotsConfigSchema.optional(),
|
|
120709
120743
|
agents: AgentsConfigSchema.optional(),
|
|
120710
120744
|
agentRequirements: AgentRequirementsConfigSchema.optional(),
|
|
120711
120745
|
categories: exports_external.record(exports_external.string(), CategoryConfigSchema2).optional(),
|
|
@@ -120722,45 +120756,280 @@ var HiaiOpencodeConfigSchema = exports_external.object({
|
|
|
120722
120756
|
});
|
|
120723
120757
|
|
|
120724
120758
|
// src/config/defaults.ts
|
|
120725
|
-
import { existsSync as
|
|
120726
|
-
import { dirname as dirname18, join as
|
|
120759
|
+
import { existsSync as existsSync57, readFileSync as readFileSync42 } from "fs";
|
|
120760
|
+
import { dirname as dirname18, join as join66, normalize as normalize2 } from "path";
|
|
120761
|
+
|
|
120762
|
+
// src/mcp/registry.ts
|
|
120763
|
+
import { join as join65 } from "path";
|
|
120764
|
+
import { existsSync as existsSync56 } from "fs";
|
|
120765
|
+
function resolveAssetScript(...segments) {
|
|
120766
|
+
const candidates = [
|
|
120767
|
+
join65(import.meta.dirname, "..", "assets", ...segments),
|
|
120768
|
+
join65(import.meta.dirname, "..", "..", "assets", ...segments)
|
|
120769
|
+
];
|
|
120770
|
+
return candidates.find((candidate) => existsSync56(candidate)) ?? candidates[0];
|
|
120771
|
+
}
|
|
120772
|
+
function createNpmPackageCommand(pkg, ...args) {
|
|
120773
|
+
return ["node", resolveAssetScript("runtime", "npm-package-runner.mjs"), pkg, ...args];
|
|
120774
|
+
}
|
|
120775
|
+
var HIAI_MCP_REGISTRY = {
|
|
120776
|
+
playwright: {
|
|
120777
|
+
name: "playwright",
|
|
120778
|
+
enabledByDefault: true,
|
|
120779
|
+
install: "npm",
|
|
120780
|
+
optionalEnv: ["HIAI_PLAYWRIGHT_INSTALL_BROWSERS"],
|
|
120781
|
+
config: {
|
|
120782
|
+
enabled: true,
|
|
120783
|
+
command: ["node", resolveAssetScript("mcp", "playwright.mjs")],
|
|
120784
|
+
timeout: 600000
|
|
120785
|
+
}
|
|
120786
|
+
},
|
|
120787
|
+
stitch: {
|
|
120788
|
+
name: "stitch",
|
|
120789
|
+
enabledByDefault: true,
|
|
120790
|
+
install: "remote",
|
|
120791
|
+
requiredEnv: ["STITCH_AI_API_KEY"],
|
|
120792
|
+
config: {
|
|
120793
|
+
enabled: true,
|
|
120794
|
+
type: "remote",
|
|
120795
|
+
url: "https://stitch.googleapis.com/mcp",
|
|
120796
|
+
headers: { "X-Goog-Api-Key": "{env:STITCH_AI_API_KEY}" },
|
|
120797
|
+
timeout: 600000
|
|
120798
|
+
}
|
|
120799
|
+
},
|
|
120800
|
+
"sequential-thinking": {
|
|
120801
|
+
name: "sequential-thinking",
|
|
120802
|
+
enabledByDefault: true,
|
|
120803
|
+
install: "npm",
|
|
120804
|
+
config: {
|
|
120805
|
+
enabled: true,
|
|
120806
|
+
command: createNpmPackageCommand("@modelcontextprotocol/server-sequential-thinking"),
|
|
120807
|
+
timeout: 600000
|
|
120808
|
+
}
|
|
120809
|
+
},
|
|
120810
|
+
firecrawl: {
|
|
120811
|
+
name: "firecrawl",
|
|
120812
|
+
enabledByDefault: true,
|
|
120813
|
+
install: "npm",
|
|
120814
|
+
requiredEnv: ["FIRECRAWL_API_KEY"],
|
|
120815
|
+
config: {
|
|
120816
|
+
enabled: true,
|
|
120817
|
+
command: createNpmPackageCommand("firecrawl-mcp"),
|
|
120818
|
+
timeout: 600000,
|
|
120819
|
+
environment: { FIRECRAWL_API_KEY: "{env:FIRECRAWL_API_KEY}" }
|
|
120820
|
+
}
|
|
120821
|
+
},
|
|
120822
|
+
rag: {
|
|
120823
|
+
name: "rag",
|
|
120824
|
+
enabledByDefault: true,
|
|
120825
|
+
install: "user-service",
|
|
120826
|
+
optionalEnv: ["OPENCODE_RAG_URL"],
|
|
120827
|
+
config: {
|
|
120828
|
+
enabled: true,
|
|
120829
|
+
type: "local",
|
|
120830
|
+
command: ["node", resolveAssetScript("mcp", "rag.mjs")],
|
|
120831
|
+
environment: {
|
|
120832
|
+
OPENCODE_RAG_URL: "{env:OPENCODE_RAG_URL:-http://localhost:9002/tools/search}"
|
|
120833
|
+
},
|
|
120834
|
+
timeout: 600000
|
|
120835
|
+
}
|
|
120836
|
+
},
|
|
120837
|
+
context7: {
|
|
120838
|
+
name: "context7",
|
|
120839
|
+
enabledByDefault: true,
|
|
120840
|
+
install: "remote",
|
|
120841
|
+
optionalEnv: ["CONTEXT7_API_KEY"],
|
|
120842
|
+
config: {
|
|
120843
|
+
enabled: true,
|
|
120844
|
+
type: "remote",
|
|
120845
|
+
url: "https://mcp.context7.com/mcp",
|
|
120846
|
+
headers: { "X-API-KEY": "{env:CONTEXT7_API_KEY}" },
|
|
120847
|
+
timeout: 600000
|
|
120848
|
+
}
|
|
120849
|
+
},
|
|
120850
|
+
mempalace: {
|
|
120851
|
+
name: "mempalace",
|
|
120852
|
+
enabledByDefault: true,
|
|
120853
|
+
install: "python",
|
|
120854
|
+
optionalEnv: ["MEMPALACE_PYTHON", "MEMPALACE_PALACE_PATH", "HIAI_MCP_AUTO_INSTALL"],
|
|
120855
|
+
config: {
|
|
120856
|
+
enabled: true,
|
|
120857
|
+
type: "local",
|
|
120858
|
+
command: ["node", resolveAssetScript("mcp", "mempalace.mjs"), "--palace", "./.opencode/palace"],
|
|
120859
|
+
timeout: 600000
|
|
120860
|
+
}
|
|
120861
|
+
}
|
|
120862
|
+
};
|
|
120863
|
+
function createDefaultMcpConfig() {
|
|
120864
|
+
return Object.fromEntries(Object.entries(HIAI_MCP_REGISTRY).map(([name, entry]) => [
|
|
120865
|
+
name,
|
|
120866
|
+
{ ...entry.config, enabled: entry.enabledByDefault }
|
|
120867
|
+
]));
|
|
120868
|
+
}
|
|
120869
|
+
|
|
120870
|
+
// src/config/defaults.ts
|
|
120871
|
+
var REQUIRED_MODEL_SLOTS = [
|
|
120872
|
+
"bob",
|
|
120873
|
+
"coder",
|
|
120874
|
+
"strategist",
|
|
120875
|
+
"guard",
|
|
120876
|
+
"critic",
|
|
120877
|
+
"designer",
|
|
120878
|
+
"researcher",
|
|
120879
|
+
"manager",
|
|
120880
|
+
"brainstormer",
|
|
120881
|
+
"vision"
|
|
120882
|
+
];
|
|
120883
|
+
var DEFAULT_LSP = {
|
|
120884
|
+
typescript: {
|
|
120885
|
+
enabled: true,
|
|
120886
|
+
command: ["typescript-language-server", "--stdio"],
|
|
120887
|
+
extensions: [".ts", ".tsx", ".mts", ".cts"]
|
|
120888
|
+
},
|
|
120889
|
+
svelte: {
|
|
120890
|
+
enabled: true,
|
|
120891
|
+
command: ["svelteserver", "--stdio"],
|
|
120892
|
+
extensions: [".svelte"]
|
|
120893
|
+
},
|
|
120894
|
+
eslint: {
|
|
120895
|
+
enabled: true,
|
|
120896
|
+
command: ["node", "{pluginRoot}/assets/runtime/npm-package-runner.mjs", "eslint-lsp", "--stdio"],
|
|
120897
|
+
extensions: [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".svelte"]
|
|
120898
|
+
},
|
|
120899
|
+
bash: {
|
|
120900
|
+
enabled: true,
|
|
120901
|
+
command: ["node", "{pluginRoot}/assets/runtime/npm-package-runner.mjs", "bash-language-server", "start"],
|
|
120902
|
+
extensions: [".sh", ".bash"]
|
|
120903
|
+
},
|
|
120904
|
+
pyright: {
|
|
120905
|
+
enabled: true,
|
|
120906
|
+
command: ["pyright-langserver", "--stdio"],
|
|
120907
|
+
extensions: [".py"]
|
|
120908
|
+
}
|
|
120909
|
+
};
|
|
120727
120910
|
function findPluginRoot() {
|
|
120728
120911
|
const candidates = [
|
|
120729
|
-
|
|
120730
|
-
|
|
120731
|
-
|
|
120912
|
+
join66(import.meta.dirname, "..", ".."),
|
|
120913
|
+
join66(import.meta.dirname, ".."),
|
|
120914
|
+
join66(import.meta.dirname, "..", ".."),
|
|
120732
120915
|
dirname18(process.argv[1] ?? ""),
|
|
120733
120916
|
process.cwd()
|
|
120734
120917
|
];
|
|
120735
120918
|
for (const candidate of candidates) {
|
|
120736
120919
|
const root = normalize2(candidate);
|
|
120737
|
-
if (
|
|
120920
|
+
if (existsSync57(join66(root, "hiai-opencode.json")))
|
|
120738
120921
|
return root;
|
|
120739
|
-
}
|
|
120740
120922
|
}
|
|
120741
120923
|
throw new Error("[hiai-opencode] Cannot find bundled hiai-opencode.json. The package is incomplete.");
|
|
120742
120924
|
}
|
|
120743
120925
|
function expandPluginRootPlaceholders(value, pluginRoot) {
|
|
120744
|
-
if (typeof value === "string")
|
|
120926
|
+
if (typeof value === "string")
|
|
120745
120927
|
return value.replaceAll("{pluginRoot}", pluginRoot);
|
|
120746
|
-
|
|
120747
|
-
if (Array.isArray(value)) {
|
|
120928
|
+
if (Array.isArray(value))
|
|
120748
120929
|
return value.map((item) => expandPluginRootPlaceholders(item, pluginRoot));
|
|
120749
|
-
}
|
|
120750
120930
|
if (value && typeof value === "object") {
|
|
120751
|
-
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [
|
|
120752
|
-
key,
|
|
120753
|
-
expandPluginRootPlaceholders(entry, pluginRoot)
|
|
120754
|
-
]));
|
|
120931
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, expandPluginRootPlaceholders(entry, pluginRoot)]));
|
|
120755
120932
|
}
|
|
120756
120933
|
return value;
|
|
120757
120934
|
}
|
|
120935
|
+
function requireModelSlots(config2) {
|
|
120936
|
+
const models = config2.models ?? {};
|
|
120937
|
+
const resolved = Object.fromEntries(REQUIRED_MODEL_SLOTS.map((slot) => {
|
|
120938
|
+
const value = models[slot];
|
|
120939
|
+
const model = typeof value === "string" ? value : value?.model;
|
|
120940
|
+
return [slot, model?.trim() ?? ""];
|
|
120941
|
+
}));
|
|
120942
|
+
const missing = REQUIRED_MODEL_SLOTS.filter((slot) => !resolved[slot]);
|
|
120943
|
+
if (missing.length > 0) {
|
|
120944
|
+
throw new Error(`[hiai-opencode] Missing required model slot(s) in hiai-opencode.json: ${missing.join(", ")}`);
|
|
120945
|
+
}
|
|
120946
|
+
return resolved;
|
|
120947
|
+
}
|
|
120948
|
+
function deriveAgents(models) {
|
|
120949
|
+
return {
|
|
120950
|
+
bob: { model: models.bob },
|
|
120951
|
+
coder: { model: models.coder },
|
|
120952
|
+
strategist: { model: models.strategist },
|
|
120953
|
+
guard: { model: models.guard },
|
|
120954
|
+
critic: { model: models.critic },
|
|
120955
|
+
designer: { model: models.designer },
|
|
120956
|
+
researcher: { model: models.researcher },
|
|
120957
|
+
"platform-manager": { model: models.manager },
|
|
120958
|
+
brainstormer: { model: models.brainstormer },
|
|
120959
|
+
multimodal: { model: models.vision },
|
|
120960
|
+
sub: { model: models.coder },
|
|
120961
|
+
"quality-guardian": { model: models.critic },
|
|
120962
|
+
"agent-skills": { model: models.manager }
|
|
120963
|
+
};
|
|
120964
|
+
}
|
|
120965
|
+
function deriveCategories(models) {
|
|
120966
|
+
return {
|
|
120967
|
+
"visual-engineering": { model: models.designer, variant: "high" },
|
|
120968
|
+
artistry: { model: models.designer, variant: "high" },
|
|
120969
|
+
ultrabrain: { model: models.strategist, variant: "xhigh" },
|
|
120970
|
+
deep: { model: models.coder, variant: "medium" },
|
|
120971
|
+
quick: { model: models.researcher },
|
|
120972
|
+
writing: { model: models.brainstormer },
|
|
120973
|
+
git: { model: models.manager },
|
|
120974
|
+
"unspecified-low": { model: models.coder },
|
|
120975
|
+
"unspecified-high": { model: models.bob, variant: "max" }
|
|
120976
|
+
};
|
|
120977
|
+
}
|
|
120978
|
+
function deriveMcp(config2) {
|
|
120979
|
+
const defaults = createDefaultMcpConfig();
|
|
120980
|
+
const userMcp = config2.mcp ?? {};
|
|
120981
|
+
return Object.fromEntries(Object.entries(defaults).map(([name, entry]) => {
|
|
120982
|
+
const override = userMcp[name] ?? {};
|
|
120983
|
+
return [name, { ...entry, ...override }];
|
|
120984
|
+
}));
|
|
120985
|
+
}
|
|
120986
|
+
function deriveLsp(config2) {
|
|
120987
|
+
const userLsp = config2.lsp ?? {};
|
|
120988
|
+
return Object.fromEntries(Object.entries(DEFAULT_LSP).map(([name, entry]) => {
|
|
120989
|
+
const override = userLsp[name] ?? {};
|
|
120990
|
+
return [name, { ...entry, ...override }];
|
|
120991
|
+
}));
|
|
120992
|
+
}
|
|
120993
|
+
function materializeConfig(rawConfig) {
|
|
120994
|
+
const models = requireModelSlots(rawConfig);
|
|
120995
|
+
return {
|
|
120996
|
+
...rawConfig,
|
|
120997
|
+
agents: deriveAgents(models),
|
|
120998
|
+
agentRequirements: {},
|
|
120999
|
+
categories: deriveCategories(models),
|
|
121000
|
+
categoryRequirements: {},
|
|
121001
|
+
modelFamilies: [],
|
|
121002
|
+
mcp: deriveMcp(rawConfig),
|
|
121003
|
+
lsp: deriveLsp(rawConfig),
|
|
121004
|
+
subtask2: {
|
|
121005
|
+
replace_generic: true,
|
|
121006
|
+
generic_return: null,
|
|
121007
|
+
...rawConfig.subtask2 ?? {}
|
|
121008
|
+
},
|
|
121009
|
+
skills: {
|
|
121010
|
+
enabled: true,
|
|
121011
|
+
disabled: [],
|
|
121012
|
+
...rawConfig.skills ?? {}
|
|
121013
|
+
},
|
|
121014
|
+
permissions: {
|
|
121015
|
+
read: { "*": "allow", "*.env": "deny", "*.env.*": "deny", "*.env.example": "allow" },
|
|
121016
|
+
edit: { "*": "allow" },
|
|
121017
|
+
bash: { "*": "allow" },
|
|
121018
|
+
deny_paths: ["**/backup/**", "**/secrets.*", "**/.env", "**/.env.*"],
|
|
121019
|
+
...rawConfig.permissions ?? {}
|
|
121020
|
+
}
|
|
121021
|
+
};
|
|
121022
|
+
}
|
|
120758
121023
|
function loadBundledDefaultConfig() {
|
|
120759
121024
|
const pluginRoot = findPluginRoot();
|
|
120760
|
-
const configPath =
|
|
121025
|
+
const configPath = join66(pluginRoot, "hiai-opencode.json");
|
|
120761
121026
|
const raw = readFileSync42(configPath, "utf-8");
|
|
120762
121027
|
const parsed = JSON.parse(raw);
|
|
120763
|
-
|
|
121028
|
+
const materialized = materializeConfig(parsed);
|
|
121029
|
+
return expandPluginRootPlaceholders(materialized, pluginRoot);
|
|
121030
|
+
}
|
|
121031
|
+
function applyModelSlots(config2) {
|
|
121032
|
+
return materializeConfig(config2);
|
|
120764
121033
|
}
|
|
120765
121034
|
var defaultConfig = loadBundledDefaultConfig();
|
|
120766
121035
|
|
|
@@ -120809,8 +121078,8 @@ function deepMerge2(base, override) {
|
|
|
120809
121078
|
function findConfigFile(searchDirs) {
|
|
120810
121079
|
for (const dir of searchDirs) {
|
|
120811
121080
|
for (const filename of CONFIG_FILENAMES) {
|
|
120812
|
-
const candidate =
|
|
120813
|
-
if (
|
|
121081
|
+
const candidate = join67(dir, filename);
|
|
121082
|
+
if (existsSync58(candidate))
|
|
120814
121083
|
return candidate;
|
|
120815
121084
|
}
|
|
120816
121085
|
}
|
|
@@ -120882,8 +121151,8 @@ function normalizeCompactLspConfig(rawConfig) {
|
|
|
120882
121151
|
function loadConfig(projectDir) {
|
|
120883
121152
|
const searchDirs = [
|
|
120884
121153
|
projectDir,
|
|
120885
|
-
|
|
120886
|
-
|
|
121154
|
+
join67(projectDir, ".opencode"),
|
|
121155
|
+
join67(process.env.HOME || "", ".config", "opencode")
|
|
120887
121156
|
];
|
|
120888
121157
|
const configPath = findConfigFile(searchDirs);
|
|
120889
121158
|
if (!configPath)
|
|
@@ -120893,7 +121162,8 @@ function loadConfig(projectDir) {
|
|
|
120893
121162
|
const normalizedParsed = normalizeCompactLspConfig(parsed);
|
|
120894
121163
|
const validated = HiaiOpencodeConfigSchema.parse(normalizedParsed);
|
|
120895
121164
|
const normalized = normalizeAgentAliases(validated);
|
|
120896
|
-
|
|
121165
|
+
const merged = deepMerge2(BASE_CONFIG, normalized);
|
|
121166
|
+
return applyModelSlots(merged);
|
|
120897
121167
|
}
|
|
120898
121168
|
function resolveEnvVars(value) {
|
|
120899
121169
|
return value.replace(/\{env:([^}]+)\}/g, (_, expression) => {
|
|
@@ -120904,12 +121174,12 @@ function resolveEnvVars(value) {
|
|
|
120904
121174
|
// src/shared/migrate-legacy-config-file.ts
|
|
120905
121175
|
init_logger();
|
|
120906
121176
|
init_plugin_identity();
|
|
120907
|
-
import { existsSync as
|
|
120908
|
-
import { join as
|
|
121177
|
+
import { existsSync as existsSync59, readFileSync as readFileSync44, renameSync as renameSync3, rmSync as rmSync2 } from "fs";
|
|
121178
|
+
import { join as join68, dirname as dirname19, basename as basename9 } from "path";
|
|
120909
121179
|
function buildCanonicalPath(legacyPath) {
|
|
120910
121180
|
const dir = dirname19(legacyPath);
|
|
120911
121181
|
const ext = basename9(legacyPath).includes(".jsonc") ? ".jsonc" : ".json";
|
|
120912
|
-
return
|
|
121182
|
+
return join68(dir, `${CONFIG_BASENAME}${ext}`);
|
|
120913
121183
|
}
|
|
120914
121184
|
function archiveLegacyConfigFile(legacyPath) {
|
|
120915
121185
|
const backupPath = `${legacyPath}.bak`;
|
|
@@ -120941,12 +121211,12 @@ function archiveLegacyConfigFile(legacyPath) {
|
|
|
120941
121211
|
}
|
|
120942
121212
|
}
|
|
120943
121213
|
function migrateLegacyConfigFile(legacyPath) {
|
|
120944
|
-
if (!
|
|
121214
|
+
if (!existsSync59(legacyPath))
|
|
120945
121215
|
return false;
|
|
120946
121216
|
if (!basename9(legacyPath).startsWith(LEGACY_CONFIG_BASENAME))
|
|
120947
121217
|
return false;
|
|
120948
121218
|
const canonicalPath = buildCanonicalPath(legacyPath);
|
|
120949
|
-
if (
|
|
121219
|
+
if (existsSync59(canonicalPath))
|
|
120950
121220
|
return false;
|
|
120951
121221
|
try {
|
|
120952
121222
|
const content = readFileSync44(legacyPath, "utf-8");
|
|
@@ -122469,11 +122739,11 @@ function createRuntimeFallbackHook(ctx, options) {
|
|
|
122469
122739
|
};
|
|
122470
122740
|
}
|
|
122471
122741
|
// src/hooks/write-existing-file-guard/hook.ts
|
|
122472
|
-
import { existsSync as
|
|
122473
|
-
import { basename as basename11, dirname as dirname21, isAbsolute as isAbsolute11, join as
|
|
122742
|
+
import { existsSync as existsSync62, realpathSync as realpathSync6 } from "fs";
|
|
122743
|
+
import { basename as basename11, dirname as dirname21, isAbsolute as isAbsolute11, join as join70, normalize as normalize3, relative as relative8, resolve as resolve14 } from "path";
|
|
122474
122744
|
|
|
122475
122745
|
// src/hooks/write-existing-file-guard/tool-execute-before-handler.ts
|
|
122476
|
-
import { existsSync as
|
|
122746
|
+
import { existsSync as existsSync61 } from "fs";
|
|
122477
122747
|
|
|
122478
122748
|
// src/hooks/write-existing-file-guard/session-read-permissions.ts
|
|
122479
122749
|
function touchSession(sessionLastAccess, sessionID) {
|
|
@@ -122561,7 +122831,7 @@ async function handleWriteExistingFileGuardToolExecuteBefore(params) {
|
|
|
122561
122831
|
return;
|
|
122562
122832
|
}
|
|
122563
122833
|
if (toolName === "read") {
|
|
122564
|
-
if (!
|
|
122834
|
+
if (!existsSync61(resolvedPath) || !input.sessionID) {
|
|
122565
122835
|
return;
|
|
122566
122836
|
}
|
|
122567
122837
|
registerReadPermission({
|
|
@@ -122577,7 +122847,7 @@ async function handleWriteExistingFileGuardToolExecuteBefore(params) {
|
|
|
122577
122847
|
if (argsRecord && "overwrite" in argsRecord) {
|
|
122578
122848
|
delete argsRecord.overwrite;
|
|
122579
122849
|
}
|
|
122580
|
-
if (!
|
|
122850
|
+
if (!existsSync61(resolvedPath)) {
|
|
122581
122851
|
return;
|
|
122582
122852
|
}
|
|
122583
122853
|
const isBobPath2 = canonicalPath.includes("/.bob/");
|
|
@@ -122636,7 +122906,7 @@ function isPathInsideDirectory(pathToCheck, directory) {
|
|
|
122636
122906
|
}
|
|
122637
122907
|
function toCanonicalPath2(absolutePath) {
|
|
122638
122908
|
let canonicalPath = absolutePath;
|
|
122639
|
-
if (
|
|
122909
|
+
if (existsSync62(absolutePath)) {
|
|
122640
122910
|
try {
|
|
122641
122911
|
canonicalPath = realpathSync6.native(absolutePath);
|
|
122642
122912
|
} catch {
|
|
@@ -122644,8 +122914,8 @@ function toCanonicalPath2(absolutePath) {
|
|
|
122644
122914
|
}
|
|
122645
122915
|
} else {
|
|
122646
122916
|
const absoluteDir = dirname21(absolutePath);
|
|
122647
|
-
const resolvedDir =
|
|
122648
|
-
canonicalPath =
|
|
122917
|
+
const resolvedDir = existsSync62(absoluteDir) ? realpathSync6.native(absoluteDir) : absoluteDir;
|
|
122918
|
+
canonicalPath = join70(resolvedDir, basename11(absolutePath));
|
|
122649
122919
|
}
|
|
122650
122920
|
return normalize3(canonicalPath);
|
|
122651
122921
|
}
|
|
@@ -123921,23 +124191,23 @@ init_logger();
|
|
|
123921
124191
|
init_plugin_identity();
|
|
123922
124192
|
|
|
123923
124193
|
// src/hooks/legacy-plugin-toast/auto-migrate.ts
|
|
123924
|
-
import { existsSync as
|
|
123925
|
-
import { join as
|
|
124194
|
+
import { existsSync as existsSync63, readFileSync as readFileSync46 } from "fs";
|
|
124195
|
+
import { join as join71 } from "path";
|
|
123926
124196
|
init_plugin_identity();
|
|
123927
124197
|
function detectOpenCodeConfigPath(overrideConfigDir) {
|
|
123928
124198
|
if (overrideConfigDir) {
|
|
123929
|
-
const jsoncPath =
|
|
123930
|
-
const jsonPath =
|
|
123931
|
-
if (
|
|
124199
|
+
const jsoncPath = join71(overrideConfigDir, "opencode.jsonc");
|
|
124200
|
+
const jsonPath = join71(overrideConfigDir, "opencode.json");
|
|
124201
|
+
if (existsSync63(jsoncPath))
|
|
123932
124202
|
return jsoncPath;
|
|
123933
|
-
if (
|
|
124203
|
+
if (existsSync63(jsonPath))
|
|
123934
124204
|
return jsonPath;
|
|
123935
124205
|
return null;
|
|
123936
124206
|
}
|
|
123937
124207
|
const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
|
|
123938
|
-
if (
|
|
124208
|
+
if (existsSync63(paths.configJsonc))
|
|
123939
124209
|
return paths.configJsonc;
|
|
123940
|
-
if (
|
|
124210
|
+
if (existsSync63(paths.configJson))
|
|
123941
124211
|
return paths.configJson;
|
|
123942
124212
|
return null;
|
|
123943
124213
|
}
|
|
@@ -124064,7 +124334,7 @@ async function queryOllama(args) {
|
|
|
124064
124334
|
}
|
|
124065
124335
|
|
|
124066
124336
|
// src/hooks/fast-apply/tool-execute-before-handler.ts
|
|
124067
|
-
import { existsSync as
|
|
124337
|
+
import { existsSync as existsSync64, readFileSync as readFileSync47 } from "fs";
|
|
124068
124338
|
async function handleFastApplyToolExecuteBefore(args) {
|
|
124069
124339
|
const { input, output, config: config2 } = args;
|
|
124070
124340
|
const normalizedTool = input.tool.toLowerCase();
|
|
@@ -124083,7 +124353,7 @@ async function handleFastApplyToolExecuteBefore(args) {
|
|
|
124083
124353
|
});
|
|
124084
124354
|
return;
|
|
124085
124355
|
}
|
|
124086
|
-
if (!
|
|
124356
|
+
if (!existsSync64(filePath)) {
|
|
124087
124357
|
log("[fast-apply] Skipping: file does not exist (new file)", {
|
|
124088
124358
|
sessionID: input.sessionID,
|
|
124089
124359
|
callID: input.callID,
|
|
@@ -124472,10 +124742,10 @@ var DEFAULT_MAX_SYMBOLS = 200;
|
|
|
124472
124742
|
var DEFAULT_MAX_DIAGNOSTICS = 200;
|
|
124473
124743
|
var DEFAULT_MAX_DIRECTORY_FILES = 50;
|
|
124474
124744
|
// src/tools/lsp/server-config-loader.ts
|
|
124475
|
-
import { existsSync as
|
|
124476
|
-
import { join as
|
|
124745
|
+
import { existsSync as existsSync65, readFileSync as readFileSync48 } from "fs";
|
|
124746
|
+
import { join as join72 } from "path";
|
|
124477
124747
|
function loadJsonFile(path7) {
|
|
124478
|
-
if (!
|
|
124748
|
+
if (!existsSync65(path7))
|
|
124479
124749
|
return null;
|
|
124480
124750
|
try {
|
|
124481
124751
|
return parseJsonc(readFileSync48(path7, "utf-8"));
|
|
@@ -124487,9 +124757,9 @@ function getConfigPaths2() {
|
|
|
124487
124757
|
const cwd = process.cwd();
|
|
124488
124758
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
124489
124759
|
return {
|
|
124490
|
-
project: detectPluginConfigFile(
|
|
124760
|
+
project: detectPluginConfigFile(join72(cwd, ".opencode")).path,
|
|
124491
124761
|
user: detectPluginConfigFile(configDir).path,
|
|
124492
|
-
opencode: detectConfigFile(
|
|
124762
|
+
opencode: detectConfigFile(join72(configDir, "opencode")).path
|
|
124493
124763
|
};
|
|
124494
124764
|
}
|
|
124495
124765
|
function loadAllConfigs() {
|
|
@@ -124558,20 +124828,20 @@ function getMergedServers() {
|
|
|
124558
124828
|
}
|
|
124559
124829
|
|
|
124560
124830
|
// src/tools/lsp/server-installation.ts
|
|
124561
|
-
import { existsSync as
|
|
124562
|
-
import { delimiter, join as
|
|
124831
|
+
import { existsSync as existsSync66 } from "fs";
|
|
124832
|
+
import { delimiter, join as join74 } from "path";
|
|
124563
124833
|
|
|
124564
124834
|
// src/tools/lsp/server-path-bases.ts
|
|
124565
|
-
import { join as
|
|
124835
|
+
import { join as join73 } from "path";
|
|
124566
124836
|
function getLspServerAdditionalPathBases(workingDirectory) {
|
|
124567
124837
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
124568
|
-
const dataDir =
|
|
124838
|
+
const dataDir = join73(getDataDir(), "opencode");
|
|
124569
124839
|
return [
|
|
124570
|
-
|
|
124571
|
-
|
|
124572
|
-
|
|
124573
|
-
|
|
124574
|
-
|
|
124840
|
+
join73(workingDirectory, "node_modules", ".bin"),
|
|
124841
|
+
join73(configDir, "bin"),
|
|
124842
|
+
join73(configDir, "node_modules", ".bin"),
|
|
124843
|
+
join73(dataDir, "bin"),
|
|
124844
|
+
join73(dataDir, "bin", "node_modules", ".bin")
|
|
124575
124845
|
];
|
|
124576
124846
|
}
|
|
124577
124847
|
|
|
@@ -124581,7 +124851,7 @@ function isServerInstalled(command) {
|
|
|
124581
124851
|
return false;
|
|
124582
124852
|
const cmd = command[0];
|
|
124583
124853
|
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
124584
|
-
if (
|
|
124854
|
+
if (existsSync66(cmd))
|
|
124585
124855
|
return true;
|
|
124586
124856
|
}
|
|
124587
124857
|
const isWindows2 = process.platform === "win32";
|
|
@@ -124602,14 +124872,14 @@ function isServerInstalled(command) {
|
|
|
124602
124872
|
const paths = pathEnv.split(delimiter);
|
|
124603
124873
|
for (const p of paths) {
|
|
124604
124874
|
for (const suffix of exts) {
|
|
124605
|
-
if (
|
|
124875
|
+
if (existsSync66(join74(p, cmd + suffix))) {
|
|
124606
124876
|
return true;
|
|
124607
124877
|
}
|
|
124608
124878
|
}
|
|
124609
124879
|
}
|
|
124610
124880
|
for (const base of getLspServerAdditionalPathBases(process.cwd())) {
|
|
124611
124881
|
for (const suffix of exts) {
|
|
124612
|
-
if (
|
|
124882
|
+
if (existsSync66(join74(base, cmd + suffix))) {
|
|
124613
124883
|
return true;
|
|
124614
124884
|
}
|
|
124615
124885
|
}
|
|
@@ -124667,13 +124937,13 @@ function getLanguageId(ext) {
|
|
|
124667
124937
|
init_logger();
|
|
124668
124938
|
var {spawn: bunSpawn2 } = globalThis.Bun;
|
|
124669
124939
|
import { spawn as nodeSpawn2 } from "child_process";
|
|
124670
|
-
import { existsSync as
|
|
124940
|
+
import { existsSync as existsSync67, statSync as statSync7 } from "fs";
|
|
124671
124941
|
function shouldUseNodeSpawn() {
|
|
124672
124942
|
return process.platform === "win32";
|
|
124673
124943
|
}
|
|
124674
124944
|
function validateCwd(cwd) {
|
|
124675
124945
|
try {
|
|
124676
|
-
if (!
|
|
124946
|
+
if (!existsSync67(cwd)) {
|
|
124677
124947
|
return { valid: false, error: `Working directory does not exist: ${cwd}` };
|
|
124678
124948
|
}
|
|
124679
124949
|
const stats = statSync7(cwd);
|
|
@@ -125435,10 +125705,10 @@ var lspManager = LSPServerManager.getInstance();
|
|
|
125435
125705
|
// src/tools/lsp/lsp-client-wrapper.ts
|
|
125436
125706
|
import { extname as extname5, resolve as resolve16 } from "path";
|
|
125437
125707
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
125438
|
-
import { existsSync as
|
|
125708
|
+
import { existsSync as existsSync68, statSync as statSync8 } from "fs";
|
|
125439
125709
|
init_plugin_identity();
|
|
125440
125710
|
function isDirectoryPath(filePath) {
|
|
125441
|
-
if (!
|
|
125711
|
+
if (!existsSync68(filePath)) {
|
|
125442
125712
|
return false;
|
|
125443
125713
|
}
|
|
125444
125714
|
return statSync8(filePath).isDirectory();
|
|
@@ -125448,14 +125718,14 @@ function uriToPath(uri) {
|
|
|
125448
125718
|
}
|
|
125449
125719
|
function findWorkspaceRoot(filePath) {
|
|
125450
125720
|
let dir = resolve16(filePath);
|
|
125451
|
-
if (!
|
|
125721
|
+
if (!existsSync68(dir) || !isDirectoryPath(dir)) {
|
|
125452
125722
|
dir = __require("path").dirname(dir);
|
|
125453
125723
|
}
|
|
125454
125724
|
const markers = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
125455
125725
|
let prevDir = "";
|
|
125456
125726
|
while (dir !== prevDir) {
|
|
125457
125727
|
for (const marker of markers) {
|
|
125458
|
-
if (
|
|
125728
|
+
if (existsSync68(__require("path").join(dir, marker))) {
|
|
125459
125729
|
return dir;
|
|
125460
125730
|
}
|
|
125461
125731
|
}
|
|
@@ -125865,8 +126135,8 @@ init_tool();
|
|
|
125865
126135
|
import { resolve as resolve18 } from "path";
|
|
125866
126136
|
|
|
125867
126137
|
// src/tools/lsp/directory-diagnostics.ts
|
|
125868
|
-
import { existsSync as
|
|
125869
|
-
import { extname as extname6, join as
|
|
126138
|
+
import { existsSync as existsSync69, lstatSync as lstatSync2, readdirSync as readdirSync19 } from "fs";
|
|
126139
|
+
import { extname as extname6, join as join75, resolve as resolve17 } from "path";
|
|
125870
126140
|
var SKIP_DIRECTORIES = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
|
|
125871
126141
|
function collectFilesWithExtension(dir, extension, maxFiles) {
|
|
125872
126142
|
const files = [];
|
|
@@ -125882,7 +126152,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
|
|
|
125882
126152
|
for (const entry of entries) {
|
|
125883
126153
|
if (files.length >= maxFiles)
|
|
125884
126154
|
return;
|
|
125885
|
-
const fullPath =
|
|
126155
|
+
const fullPath = join75(currentDir, entry);
|
|
125886
126156
|
let stat;
|
|
125887
126157
|
try {
|
|
125888
126158
|
stat = lstatSync2(fullPath);
|
|
@@ -125911,7 +126181,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
125911
126181
|
throw new Error(`Extension must start with a dot (e.g., ".ts", not "${extension}"). ` + `Use ".${extension}" instead.`);
|
|
125912
126182
|
}
|
|
125913
126183
|
const absDir = resolve17(directory);
|
|
125914
|
-
if (!
|
|
126184
|
+
if (!existsSync69(absDir)) {
|
|
125915
126185
|
throw new Error(`Directory does not exist: ${absDir}`);
|
|
125916
126186
|
}
|
|
125917
126187
|
const serverResult = findServerForExtension(extension);
|
|
@@ -125985,7 +126255,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
125985
126255
|
|
|
125986
126256
|
// src/tools/lsp/infer-extension.ts
|
|
125987
126257
|
import { readdirSync as readdirSync20, lstatSync as lstatSync3 } from "fs";
|
|
125988
|
-
import { extname as extname7, join as
|
|
126258
|
+
import { extname as extname7, join as join76 } from "path";
|
|
125989
126259
|
var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
|
|
125990
126260
|
var MAX_SCAN_ENTRIES = 500;
|
|
125991
126261
|
function inferExtensionFromDirectory(directory) {
|
|
@@ -126003,7 +126273,7 @@ function inferExtensionFromDirectory(directory) {
|
|
|
126003
126273
|
for (const entry of entries) {
|
|
126004
126274
|
if (scanned >= MAX_SCAN_ENTRIES)
|
|
126005
126275
|
return;
|
|
126006
|
-
const fullPath =
|
|
126276
|
+
const fullPath = join76(dir, entry);
|
|
126007
126277
|
let stat;
|
|
126008
126278
|
try {
|
|
126009
126279
|
stat = lstatSync3(fullPath);
|
|
@@ -126172,12 +126442,12 @@ var DEFAULT_MAX_MATCHES = 500;
|
|
|
126172
126442
|
|
|
126173
126443
|
// src/tools/ast-grep/sg-cli-path.ts
|
|
126174
126444
|
import { createRequire as createRequire4 } from "module";
|
|
126175
|
-
import { dirname as dirname22, join as
|
|
126176
|
-
import { existsSync as
|
|
126445
|
+
import { dirname as dirname22, join as join78 } from "path";
|
|
126446
|
+
import { existsSync as existsSync71, statSync as statSync9 } from "fs";
|
|
126177
126447
|
|
|
126178
126448
|
// src/tools/ast-grep/downloader.ts
|
|
126179
|
-
import { existsSync as
|
|
126180
|
-
import { join as
|
|
126449
|
+
import { existsSync as existsSync70 } from "fs";
|
|
126450
|
+
import { join as join77 } from "path";
|
|
126181
126451
|
import { homedir as homedir14 } from "os";
|
|
126182
126452
|
import { createRequire as createRequire3 } from "module";
|
|
126183
126453
|
init_logger();
|
|
@@ -126205,12 +126475,12 @@ var PLATFORM_MAP2 = {
|
|
|
126205
126475
|
function getCacheDir3() {
|
|
126206
126476
|
if (process.platform === "win32") {
|
|
126207
126477
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
126208
|
-
const base2 = localAppData ||
|
|
126209
|
-
return
|
|
126478
|
+
const base2 = localAppData || join77(homedir14(), "AppData", "Local");
|
|
126479
|
+
return join77(base2, CACHE_DIR_NAME, "bin");
|
|
126210
126480
|
}
|
|
126211
126481
|
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
126212
|
-
const base = xdgCache ||
|
|
126213
|
-
return
|
|
126482
|
+
const base = xdgCache || join77(homedir14(), ".cache");
|
|
126483
|
+
return join77(base, CACHE_DIR_NAME, "bin");
|
|
126214
126484
|
}
|
|
126215
126485
|
function getBinaryName3() {
|
|
126216
126486
|
return process.platform === "win32" ? "sg.exe" : "sg";
|
|
@@ -126227,8 +126497,8 @@ async function downloadAstGrep(version3 = DEFAULT_VERSION) {
|
|
|
126227
126497
|
}
|
|
126228
126498
|
const cacheDir = getCacheDir3();
|
|
126229
126499
|
const binaryName = getBinaryName3();
|
|
126230
|
-
const binaryPath =
|
|
126231
|
-
if (
|
|
126500
|
+
const binaryPath = join77(cacheDir, binaryName);
|
|
126501
|
+
if (existsSync70(binaryPath)) {
|
|
126232
126502
|
return binaryPath;
|
|
126233
126503
|
}
|
|
126234
126504
|
const { arch, os: os4 } = platformInfo;
|
|
@@ -126236,7 +126506,7 @@ async function downloadAstGrep(version3 = DEFAULT_VERSION) {
|
|
|
126236
126506
|
const downloadUrl = `https://github.com/${REPO2}/releases/download/${version3}/${assetName}`;
|
|
126237
126507
|
log(`[${PUBLISHED_PACKAGE_NAME}] Downloading ast-grep binary...`);
|
|
126238
126508
|
try {
|
|
126239
|
-
const archivePath =
|
|
126509
|
+
const archivePath = join77(cacheDir, assetName);
|
|
126240
126510
|
ensureCacheDir(cacheDir);
|
|
126241
126511
|
await downloadArchive(downloadUrl, archivePath);
|
|
126242
126512
|
await extractZipArchive(archivePath, cacheDir);
|
|
@@ -126290,8 +126560,8 @@ function findSgCliPathSync() {
|
|
|
126290
126560
|
const require2 = createRequire4(import.meta.url);
|
|
126291
126561
|
const cliPackageJsonPath = require2.resolve("@ast-grep/cli/package.json");
|
|
126292
126562
|
const cliDirectory = dirname22(cliPackageJsonPath);
|
|
126293
|
-
const sgPath =
|
|
126294
|
-
if (
|
|
126563
|
+
const sgPath = join78(cliDirectory, binaryName);
|
|
126564
|
+
if (existsSync71(sgPath) && isValidBinary(sgPath)) {
|
|
126295
126565
|
return sgPath;
|
|
126296
126566
|
}
|
|
126297
126567
|
} catch {}
|
|
@@ -126302,8 +126572,8 @@ function findSgCliPathSync() {
|
|
|
126302
126572
|
const packageJsonPath = require2.resolve(`${platformPackage}/package.json`);
|
|
126303
126573
|
const packageDirectory = dirname22(packageJsonPath);
|
|
126304
126574
|
const astGrepBinaryName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
|
|
126305
|
-
const binaryPath =
|
|
126306
|
-
if (
|
|
126575
|
+
const binaryPath = join78(packageDirectory, astGrepBinaryName);
|
|
126576
|
+
if (existsSync71(binaryPath) && isValidBinary(binaryPath)) {
|
|
126307
126577
|
return binaryPath;
|
|
126308
126578
|
}
|
|
126309
126579
|
} catch {}
|
|
@@ -126311,7 +126581,7 @@ function findSgCliPathSync() {
|
|
|
126311
126581
|
if (process.platform === "darwin") {
|
|
126312
126582
|
const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
|
|
126313
126583
|
for (const path7 of homebrewPaths) {
|
|
126314
|
-
if (
|
|
126584
|
+
if (existsSync71(path7) && isValidBinary(path7)) {
|
|
126315
126585
|
return path7;
|
|
126316
126586
|
}
|
|
126317
126587
|
}
|
|
@@ -126335,14 +126605,14 @@ function setSgCliPath(path7) {
|
|
|
126335
126605
|
}
|
|
126336
126606
|
// src/tools/ast-grep/cli.ts
|
|
126337
126607
|
var {spawn: spawn17 } = globalThis.Bun;
|
|
126338
|
-
import { existsSync as
|
|
126608
|
+
import { existsSync as existsSync73 } from "fs";
|
|
126339
126609
|
|
|
126340
126610
|
// src/tools/ast-grep/cli-binary-path-resolution.ts
|
|
126341
|
-
import { existsSync as
|
|
126611
|
+
import { existsSync as existsSync72 } from "fs";
|
|
126342
126612
|
var resolvedCliPath3 = null;
|
|
126343
126613
|
var initPromise3 = null;
|
|
126344
126614
|
async function getAstGrepPath() {
|
|
126345
|
-
if (resolvedCliPath3 !== null &&
|
|
126615
|
+
if (resolvedCliPath3 !== null && existsSync72(resolvedCliPath3)) {
|
|
126346
126616
|
return resolvedCliPath3;
|
|
126347
126617
|
}
|
|
126348
126618
|
if (initPromise3) {
|
|
@@ -126350,7 +126620,7 @@ async function getAstGrepPath() {
|
|
|
126350
126620
|
}
|
|
126351
126621
|
initPromise3 = (async () => {
|
|
126352
126622
|
const syncPath = findSgCliPathSync();
|
|
126353
|
-
if (syncPath &&
|
|
126623
|
+
if (syncPath && existsSync72(syncPath)) {
|
|
126354
126624
|
resolvedCliPath3 = syncPath;
|
|
126355
126625
|
setSgCliPath(syncPath);
|
|
126356
126626
|
return syncPath;
|
|
@@ -126449,7 +126719,7 @@ async function runSg(options) {
|
|
|
126449
126719
|
const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
|
|
126450
126720
|
args.push(...paths);
|
|
126451
126721
|
let cliPath = getSgCliPath();
|
|
126452
|
-
if (!cliPath || !
|
|
126722
|
+
if (!cliPath || !existsSync73(cliPath)) {
|
|
126453
126723
|
const downloadedPath = await getAstGrepPath();
|
|
126454
126724
|
if (downloadedPath) {
|
|
126455
126725
|
cliPath = downloadedPath;
|
|
@@ -126704,20 +126974,20 @@ import { resolve as resolve19 } from "path";
|
|
|
126704
126974
|
var {spawn: spawn18 } = globalThis.Bun;
|
|
126705
126975
|
|
|
126706
126976
|
// src/tools/grep/constants.ts
|
|
126707
|
-
import { existsSync as
|
|
126708
|
-
import { join as
|
|
126977
|
+
import { existsSync as existsSync75 } from "fs";
|
|
126978
|
+
import { join as join80, dirname as dirname23 } from "path";
|
|
126709
126979
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
126710
126980
|
|
|
126711
126981
|
// src/tools/grep/downloader.ts
|
|
126712
|
-
import { existsSync as
|
|
126713
|
-
import { join as
|
|
126982
|
+
import { existsSync as existsSync74, readdirSync as readdirSync21 } from "fs";
|
|
126983
|
+
import { join as join79 } from "path";
|
|
126714
126984
|
init_plugin_identity();
|
|
126715
126985
|
function findFileRecursive(dir, filename) {
|
|
126716
126986
|
try {
|
|
126717
126987
|
const entries = readdirSync21(dir, { withFileTypes: true, recursive: true });
|
|
126718
126988
|
for (const entry of entries) {
|
|
126719
126989
|
if (entry.isFile() && entry.name === filename) {
|
|
126720
|
-
return
|
|
126990
|
+
return join79(entry.parentPath ?? dir, entry.name);
|
|
126721
126991
|
}
|
|
126722
126992
|
}
|
|
126723
126993
|
} catch {
|
|
@@ -126738,11 +127008,11 @@ function getPlatformKey() {
|
|
|
126738
127008
|
}
|
|
126739
127009
|
function getInstallDir() {
|
|
126740
127010
|
const homeDir = process.env.HOME || process.env.USERPROFILE || ".";
|
|
126741
|
-
return
|
|
127011
|
+
return join79(homeDir, ".cache", CACHE_DIR_NAME, "bin");
|
|
126742
127012
|
}
|
|
126743
127013
|
function getRgPath() {
|
|
126744
127014
|
const isWindows2 = process.platform === "win32";
|
|
126745
|
-
return
|
|
127015
|
+
return join79(getInstallDir(), isWindows2 ? "rg.exe" : "rg");
|
|
126746
127016
|
}
|
|
126747
127017
|
async function extractTarGz2(archivePath, destDir) {
|
|
126748
127018
|
const platformKey = getPlatformKey();
|
|
@@ -126759,7 +127029,7 @@ async function extractZip2(archivePath, destDir) {
|
|
|
126759
127029
|
const binaryName = process.platform === "win32" ? "rg.exe" : "rg";
|
|
126760
127030
|
const foundPath = findFileRecursive(destDir, binaryName);
|
|
126761
127031
|
if (foundPath) {
|
|
126762
|
-
const destPath =
|
|
127032
|
+
const destPath = join79(destDir, binaryName);
|
|
126763
127033
|
if (foundPath !== destPath) {
|
|
126764
127034
|
const { renameSync: renameSync4 } = await import("fs");
|
|
126765
127035
|
renameSync4(foundPath, destPath);
|
|
@@ -126774,13 +127044,13 @@ async function downloadAndInstallRipgrep() {
|
|
|
126774
127044
|
}
|
|
126775
127045
|
const installDir = getInstallDir();
|
|
126776
127046
|
const rgPath = getRgPath();
|
|
126777
|
-
if (
|
|
127047
|
+
if (existsSync74(rgPath)) {
|
|
126778
127048
|
return rgPath;
|
|
126779
127049
|
}
|
|
126780
127050
|
ensureCacheDir(installDir);
|
|
126781
127051
|
const filename = `ripgrep-${RG_VERSION}-${config4.platform}.${config4.extension}`;
|
|
126782
127052
|
const url3 = `https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/${filename}`;
|
|
126783
|
-
const archivePath =
|
|
127053
|
+
const archivePath = join79(installDir, filename);
|
|
126784
127054
|
try {
|
|
126785
127055
|
await downloadArchive(url3, archivePath);
|
|
126786
127056
|
if (config4.extension === "tar.gz") {
|
|
@@ -126789,7 +127059,7 @@ async function downloadAndInstallRipgrep() {
|
|
|
126789
127059
|
await extractZip2(archivePath, installDir);
|
|
126790
127060
|
}
|
|
126791
127061
|
ensureExecutable(rgPath);
|
|
126792
|
-
if (!
|
|
127062
|
+
if (!existsSync74(rgPath)) {
|
|
126793
127063
|
throw new Error("ripgrep binary not found after extraction");
|
|
126794
127064
|
}
|
|
126795
127065
|
return rgPath;
|
|
@@ -126801,7 +127071,7 @@ async function downloadAndInstallRipgrep() {
|
|
|
126801
127071
|
}
|
|
126802
127072
|
function getInstalledRipgrepPath() {
|
|
126803
127073
|
const rgPath = getRgPath();
|
|
126804
|
-
return
|
|
127074
|
+
return existsSync74(rgPath) ? rgPath : null;
|
|
126805
127075
|
}
|
|
126806
127076
|
|
|
126807
127077
|
// src/tools/grep/constants.ts
|
|
@@ -126827,14 +127097,14 @@ function getOpenCodeBundledRg() {
|
|
|
126827
127097
|
const isWindows2 = process.platform === "win32";
|
|
126828
127098
|
const rgName = isWindows2 ? "rg.exe" : "rg";
|
|
126829
127099
|
const candidates = [
|
|
126830
|
-
|
|
126831
|
-
|
|
126832
|
-
|
|
126833
|
-
|
|
126834
|
-
|
|
127100
|
+
join80(getDataDir(), "opencode", "bin", rgName),
|
|
127101
|
+
join80(execDir, rgName),
|
|
127102
|
+
join80(execDir, "bin", rgName),
|
|
127103
|
+
join80(execDir, "..", "bin", rgName),
|
|
127104
|
+
join80(execDir, "..", "libexec", rgName)
|
|
126835
127105
|
];
|
|
126836
127106
|
for (const candidate of candidates) {
|
|
126837
|
-
if (
|
|
127107
|
+
if (existsSync75(candidate)) {
|
|
126838
127108
|
return candidate;
|
|
126839
127109
|
}
|
|
126840
127110
|
}
|
|
@@ -127961,9 +128231,9 @@ var skill = createSkillTool();
|
|
|
127961
128231
|
init_tool();
|
|
127962
128232
|
|
|
127963
128233
|
// src/tools/session-manager/constants.ts
|
|
127964
|
-
import { join as
|
|
127965
|
-
var TODO_DIR2 =
|
|
127966
|
-
var TRANSCRIPT_DIR2 =
|
|
128234
|
+
import { join as join81 } from "path";
|
|
128235
|
+
var TODO_DIR2 = join81(getClaudeConfigDir(), "todos");
|
|
128236
|
+
var TRANSCRIPT_DIR2 = join81(getClaudeConfigDir(), "transcripts");
|
|
127967
128237
|
var SESSION_LIST_DESCRIPTION = `List all OpenCode sessions with optional filtering.
|
|
127968
128238
|
|
|
127969
128239
|
Returns a list of available session IDs with metadata including message count, date range, and agents used.
|
|
@@ -128036,11 +128306,11 @@ Has Todos: Yes (12 items, 8 completed)
|
|
|
128036
128306
|
Has Transcript: Yes (234 entries)`;
|
|
128037
128307
|
|
|
128038
128308
|
// src/tools/session-manager/file-storage.ts
|
|
128039
|
-
import { existsSync as
|
|
128309
|
+
import { existsSync as existsSync76 } from "fs";
|
|
128040
128310
|
import { readdir, readFile } from "fs/promises";
|
|
128041
|
-
import { join as
|
|
128311
|
+
import { join as join82 } from "path";
|
|
128042
128312
|
async function getFileMainSessions(directory) {
|
|
128043
|
-
if (!
|
|
128313
|
+
if (!existsSync76(SESSION_STORAGE))
|
|
128044
128314
|
return [];
|
|
128045
128315
|
const sessions = [];
|
|
128046
128316
|
try {
|
|
@@ -128048,13 +128318,13 @@ async function getFileMainSessions(directory) {
|
|
|
128048
128318
|
for (const projectDir of projectDirs) {
|
|
128049
128319
|
if (!projectDir.isDirectory())
|
|
128050
128320
|
continue;
|
|
128051
|
-
const projectPath =
|
|
128321
|
+
const projectPath = join82(SESSION_STORAGE, projectDir.name);
|
|
128052
128322
|
const sessionFiles = await readdir(projectPath);
|
|
128053
128323
|
for (const file3 of sessionFiles) {
|
|
128054
128324
|
if (!file3.endsWith(".json"))
|
|
128055
128325
|
continue;
|
|
128056
128326
|
try {
|
|
128057
|
-
const content = await readFile(
|
|
128327
|
+
const content = await readFile(join82(projectPath, file3), "utf-8");
|
|
128058
128328
|
const meta3 = JSON.parse(content);
|
|
128059
128329
|
if (meta3.parentID)
|
|
128060
128330
|
continue;
|
|
@@ -128072,7 +128342,7 @@ async function getFileMainSessions(directory) {
|
|
|
128072
128342
|
return sessions.sort((a, b) => b.time.updated - a.time.updated);
|
|
128073
128343
|
}
|
|
128074
128344
|
async function getFileAllSessions() {
|
|
128075
|
-
if (!
|
|
128345
|
+
if (!existsSync76(MESSAGE_STORAGE))
|
|
128076
128346
|
return [];
|
|
128077
128347
|
const sessions = [];
|
|
128078
128348
|
async function scanDirectory(dir) {
|
|
@@ -128081,7 +128351,7 @@ async function getFileAllSessions() {
|
|
|
128081
128351
|
for (const entry of entries) {
|
|
128082
128352
|
if (!entry.isDirectory())
|
|
128083
128353
|
continue;
|
|
128084
|
-
const sessionPath =
|
|
128354
|
+
const sessionPath = join82(dir, entry.name);
|
|
128085
128355
|
const files = await readdir(sessionPath);
|
|
128086
128356
|
if (files.some((file3) => file3.endsWith(".json"))) {
|
|
128087
128357
|
sessions.push(entry.name);
|
|
@@ -128101,7 +128371,7 @@ async function fileSessionExists(sessionID) {
|
|
|
128101
128371
|
}
|
|
128102
128372
|
async function getFileSessionMessages(sessionID) {
|
|
128103
128373
|
const messageDir = getMessageDir(sessionID);
|
|
128104
|
-
if (!messageDir || !
|
|
128374
|
+
if (!messageDir || !existsSync76(messageDir))
|
|
128105
128375
|
return [];
|
|
128106
128376
|
const messages = [];
|
|
128107
128377
|
try {
|
|
@@ -128110,7 +128380,7 @@ async function getFileSessionMessages(sessionID) {
|
|
|
128110
128380
|
if (!file3.endsWith(".json"))
|
|
128111
128381
|
continue;
|
|
128112
128382
|
try {
|
|
128113
|
-
const content = await readFile(
|
|
128383
|
+
const content = await readFile(join82(messageDir, file3), "utf-8");
|
|
128114
128384
|
const meta3 = JSON.parse(content);
|
|
128115
128385
|
const parts = await readParts2(meta3.id);
|
|
128116
128386
|
messages.push({
|
|
@@ -128136,8 +128406,8 @@ async function getFileSessionMessages(sessionID) {
|
|
|
128136
128406
|
});
|
|
128137
128407
|
}
|
|
128138
128408
|
async function readParts2(messageID) {
|
|
128139
|
-
const partDir =
|
|
128140
|
-
if (!
|
|
128409
|
+
const partDir = join82(PART_STORAGE, messageID);
|
|
128410
|
+
if (!existsSync76(partDir))
|
|
128141
128411
|
return [];
|
|
128142
128412
|
const parts = [];
|
|
128143
128413
|
try {
|
|
@@ -128146,7 +128416,7 @@ async function readParts2(messageID) {
|
|
|
128146
128416
|
if (!file3.endsWith(".json"))
|
|
128147
128417
|
continue;
|
|
128148
128418
|
try {
|
|
128149
|
-
const content = await readFile(
|
|
128419
|
+
const content = await readFile(join82(partDir, file3), "utf-8");
|
|
128150
128420
|
parts.push(JSON.parse(content));
|
|
128151
128421
|
} catch {
|
|
128152
128422
|
continue;
|
|
@@ -128158,14 +128428,14 @@ async function readParts2(messageID) {
|
|
|
128158
128428
|
return parts.sort((a, b) => a.id.localeCompare(b.id));
|
|
128159
128429
|
}
|
|
128160
128430
|
async function getFileSessionTodos(sessionID) {
|
|
128161
|
-
if (!
|
|
128431
|
+
if (!existsSync76(TODO_DIR2))
|
|
128162
128432
|
return [];
|
|
128163
128433
|
try {
|
|
128164
128434
|
const allFiles = await readdir(TODO_DIR2);
|
|
128165
128435
|
const todoFiles = allFiles.filter((file3) => file3 === `${sessionID}.json`);
|
|
128166
128436
|
for (const file3 of todoFiles) {
|
|
128167
128437
|
try {
|
|
128168
|
-
const content = await readFile(
|
|
128438
|
+
const content = await readFile(join82(TODO_DIR2, file3), "utf-8");
|
|
128169
128439
|
const data = JSON.parse(content);
|
|
128170
128440
|
if (!Array.isArray(data))
|
|
128171
128441
|
continue;
|
|
@@ -128185,10 +128455,10 @@ async function getFileSessionTodos(sessionID) {
|
|
|
128185
128455
|
return [];
|
|
128186
128456
|
}
|
|
128187
128457
|
async function getFileSessionTranscript(sessionID) {
|
|
128188
|
-
if (!
|
|
128458
|
+
if (!existsSync76(TRANSCRIPT_DIR2))
|
|
128189
128459
|
return 0;
|
|
128190
|
-
const transcriptFile =
|
|
128191
|
-
if (!
|
|
128460
|
+
const transcriptFile = join82(TRANSCRIPT_DIR2, `${sessionID}.jsonl`);
|
|
128461
|
+
if (!existsSync76(transcriptFile))
|
|
128192
128462
|
return 0;
|
|
128193
128463
|
try {
|
|
128194
128464
|
const content = await readFile(transcriptFile, "utf-8");
|
|
@@ -128953,6 +129223,26 @@ function findMcpServer(mcpName, skills) {
|
|
|
128953
129223
|
}
|
|
128954
129224
|
return null;
|
|
128955
129225
|
}
|
|
129226
|
+
function convertBuiltinMcpConfig(config4) {
|
|
129227
|
+
if (config4.enabled === false)
|
|
129228
|
+
return null;
|
|
129229
|
+
if (config4.type === "remote") {
|
|
129230
|
+
return {
|
|
129231
|
+
type: "http",
|
|
129232
|
+
url: config4.url,
|
|
129233
|
+
headers: config4.headers
|
|
129234
|
+
};
|
|
129235
|
+
}
|
|
129236
|
+
const [command, ...args] = config4.command ?? [];
|
|
129237
|
+
if (!command)
|
|
129238
|
+
return null;
|
|
129239
|
+
return {
|
|
129240
|
+
type: "stdio",
|
|
129241
|
+
command,
|
|
129242
|
+
args,
|
|
129243
|
+
env: config4.environment
|
|
129244
|
+
};
|
|
129245
|
+
}
|
|
128956
129246
|
function formatAvailableMcps(skills) {
|
|
128957
129247
|
const mcps = [];
|
|
128958
129248
|
for (const skill2 of skills) {
|
|
@@ -128965,6 +129255,11 @@ function formatAvailableMcps(skills) {
|
|
|
128965
129255
|
return mcps.length > 0 ? mcps.join(`
|
|
128966
129256
|
`) : " (none found)";
|
|
128967
129257
|
}
|
|
129258
|
+
function formatAvailableBuiltinMcps(builtinMcp) {
|
|
129259
|
+
const names = Object.entries(builtinMcp ?? {}).filter(([, config4]) => config4.enabled !== false).map(([name]) => ` - "${name}" from hiai-opencode config`);
|
|
129260
|
+
return names.length > 0 ? names.join(`
|
|
129261
|
+
`) : " (none found)";
|
|
129262
|
+
}
|
|
128968
129263
|
function formatBuiltinMcpHint(mcpName) {
|
|
128969
129264
|
const nativeTools = BUILTIN_MCP_TOOL_HINTS[mcpName];
|
|
128970
129265
|
if (!nativeTools)
|
|
@@ -129010,7 +129305,7 @@ function applyGrepFilter(output, pattern) {
|
|
|
129010
129305
|
}
|
|
129011
129306
|
}
|
|
129012
129307
|
function createSkillMcpTool(options) {
|
|
129013
|
-
const { manager, getLoadedSkills, getSessionID } = options;
|
|
129308
|
+
const { manager, getLoadedSkills, getSessionID, builtinMcp } = options;
|
|
129014
129309
|
return tool({
|
|
129015
129310
|
description: SKILL_MCP_DESCRIPTION,
|
|
129016
129311
|
args: {
|
|
@@ -129025,7 +129320,9 @@ function createSkillMcpTool(options) {
|
|
|
129025
129320
|
const operation = validateOperationParams(args);
|
|
129026
129321
|
const skills = getLoadedSkills();
|
|
129027
129322
|
const found = findMcpServer(args.mcp_name, skills);
|
|
129028
|
-
|
|
129323
|
+
const builtinConfig = builtinMcp?.[args.mcp_name];
|
|
129324
|
+
const convertedBuiltinConfig = builtinConfig ? convertBuiltinMcpConfig(builtinConfig) : null;
|
|
129325
|
+
if (!found && !convertedBuiltinConfig) {
|
|
129029
129326
|
const builtinHint = formatBuiltinMcpHint(args.mcp_name);
|
|
129030
129327
|
if (builtinHint) {
|
|
129031
129328
|
throw new Error(builtinHint);
|
|
@@ -129035,7 +129332,10 @@ function createSkillMcpTool(options) {
|
|
|
129035
129332
|
` + `Available MCP servers in loaded skills:
|
|
129036
129333
|
` + formatAvailableMcps(skills) + `
|
|
129037
129334
|
|
|
129038
|
-
` + `
|
|
129335
|
+
` + `Available MCP servers in hiai-opencode config:
|
|
129336
|
+
` + formatAvailableBuiltinMcps(builtinMcp) + `
|
|
129337
|
+
|
|
129338
|
+
` + `Hint: Load the skill first for skill-embedded MCPs. Builtin hiai-opencode MCPs can be called directly when enabled in hiai-opencode.json.`);
|
|
129039
129339
|
}
|
|
129040
129340
|
const sessionID = toolContext.sessionID || getSessionID?.();
|
|
129041
129341
|
if (!sessionID) {
|
|
@@ -129043,13 +129343,13 @@ function createSkillMcpTool(options) {
|
|
|
129043
129343
|
}
|
|
129044
129344
|
const info = {
|
|
129045
129345
|
serverName: args.mcp_name,
|
|
129046
|
-
skillName: found
|
|
129346
|
+
skillName: found?.skill.name ?? "hiai-opencode",
|
|
129047
129347
|
sessionID,
|
|
129048
|
-
scope: found
|
|
129348
|
+
scope: found?.skill.scope ?? "user"
|
|
129049
129349
|
};
|
|
129050
129350
|
const context = {
|
|
129051
|
-
config: found
|
|
129052
|
-
skillName: found
|
|
129351
|
+
config: found?.config ?? convertedBuiltinConfig,
|
|
129352
|
+
skillName: found?.skill.name ?? "hiai-opencode"
|
|
129053
129353
|
};
|
|
129054
129354
|
const parsedArgs = parseArguments(args.arguments);
|
|
129055
129355
|
let output;
|
|
@@ -130568,9 +130868,9 @@ async function resolveMultimodalLookerAgentMetadata(ctx) {
|
|
|
130568
130868
|
|
|
130569
130869
|
// src/tools/look-at/image-converter.ts
|
|
130570
130870
|
import * as childProcess from "child_process";
|
|
130571
|
-
import { existsSync as
|
|
130871
|
+
import { existsSync as existsSync77, mkdtempSync, readFileSync as readFileSync51, rmSync as rmSync3, unlinkSync as unlinkSync10, writeFileSync as writeFileSync18 } from "fs";
|
|
130572
130872
|
import { tmpdir as tmpdir7 } from "os";
|
|
130573
|
-
import { dirname as dirname26, join as
|
|
130873
|
+
import { dirname as dirname26, join as join83 } from "path";
|
|
130574
130874
|
var SUPPORTED_FORMATS = new Set([
|
|
130575
130875
|
"image/jpeg",
|
|
130576
130876
|
"image/png",
|
|
@@ -130608,11 +130908,11 @@ function needsConversion(mimeType) {
|
|
|
130608
130908
|
return mimeType.startsWith("image/");
|
|
130609
130909
|
}
|
|
130610
130910
|
function convertImageToJpeg(inputPath, mimeType) {
|
|
130611
|
-
if (!
|
|
130911
|
+
if (!existsSync77(inputPath)) {
|
|
130612
130912
|
throw new Error(`File not found: ${inputPath}`);
|
|
130613
130913
|
}
|
|
130614
|
-
const tempDir = mkdtempSync(
|
|
130615
|
-
const outputPath =
|
|
130914
|
+
const tempDir = mkdtempSync(join83(tmpdir7(), "opencode-img-"));
|
|
130915
|
+
const outputPath = join83(tempDir, "converted.jpg");
|
|
130616
130916
|
log(`[image-converter] Converting ${mimeType} to JPEG: ${inputPath}`);
|
|
130617
130917
|
try {
|
|
130618
130918
|
if (process.platform === "darwin") {
|
|
@@ -130622,7 +130922,7 @@ function convertImageToJpeg(inputPath, mimeType) {
|
|
|
130622
130922
|
encoding: "utf-8",
|
|
130623
130923
|
timeout: CONVERSION_TIMEOUT_MS
|
|
130624
130924
|
});
|
|
130625
|
-
if (
|
|
130925
|
+
if (existsSync77(outputPath)) {
|
|
130626
130926
|
log(`[image-converter] Converted using sips: ${outputPath}`);
|
|
130627
130927
|
return outputPath;
|
|
130628
130928
|
}
|
|
@@ -130637,7 +130937,7 @@ function convertImageToJpeg(inputPath, mimeType) {
|
|
|
130637
130937
|
encoding: "utf-8",
|
|
130638
130938
|
timeout: CONVERSION_TIMEOUT_MS
|
|
130639
130939
|
});
|
|
130640
|
-
if (
|
|
130940
|
+
if (existsSync77(outputPath)) {
|
|
130641
130941
|
log(`[image-converter] Converted using ImageMagick: ${outputPath}`);
|
|
130642
130942
|
return outputPath;
|
|
130643
130943
|
}
|
|
@@ -130650,7 +130950,7 @@ function convertImageToJpeg(inputPath, mimeType) {
|
|
|
130650
130950
|
` + ` RHEL/CentOS: sudo yum install ImageMagick`);
|
|
130651
130951
|
} catch (error92) {
|
|
130652
130952
|
try {
|
|
130653
|
-
if (
|
|
130953
|
+
if (existsSync77(outputPath)) {
|
|
130654
130954
|
unlinkSync10(outputPath);
|
|
130655
130955
|
}
|
|
130656
130956
|
} catch {}
|
|
@@ -130664,11 +130964,11 @@ function convertImageToJpeg(inputPath, mimeType) {
|
|
|
130664
130964
|
function cleanupConvertedImage(filePath) {
|
|
130665
130965
|
try {
|
|
130666
130966
|
const tempDirectory = dirname26(filePath);
|
|
130667
|
-
if (
|
|
130967
|
+
if (existsSync77(filePath)) {
|
|
130668
130968
|
unlinkSync10(filePath);
|
|
130669
130969
|
log(`[image-converter] Cleaned up temporary file: ${filePath}`);
|
|
130670
130970
|
}
|
|
130671
|
-
if (
|
|
130971
|
+
if (existsSync77(tempDirectory)) {
|
|
130672
130972
|
rmSync3(tempDirectory, { recursive: true, force: true });
|
|
130673
130973
|
log(`[image-converter] Cleaned up temporary directory: ${tempDirectory}`);
|
|
130674
130974
|
}
|
|
@@ -130677,9 +130977,9 @@ function cleanupConvertedImage(filePath) {
|
|
|
130677
130977
|
}
|
|
130678
130978
|
}
|
|
130679
130979
|
function convertBase64ImageToJpeg(base64Data, mimeType) {
|
|
130680
|
-
const tempDir = mkdtempSync(
|
|
130980
|
+
const tempDir = mkdtempSync(join83(tmpdir7(), "opencode-b64-"));
|
|
130681
130981
|
const inputExt = mimeType.split("/")[1] || "bin";
|
|
130682
|
-
const inputPath =
|
|
130982
|
+
const inputPath = join83(tempDir, `input.${inputExt}`);
|
|
130683
130983
|
const tempFiles = [inputPath];
|
|
130684
130984
|
try {
|
|
130685
130985
|
const cleanBase64 = base64Data.replace(/^data:[^;]+;base64,/, "");
|
|
@@ -130695,7 +130995,7 @@ function convertBase64ImageToJpeg(base64Data, mimeType) {
|
|
|
130695
130995
|
} catch (error92) {
|
|
130696
130996
|
tempFiles.forEach((file3) => {
|
|
130697
130997
|
try {
|
|
130698
|
-
if (
|
|
130998
|
+
if (existsSync77(file3))
|
|
130699
130999
|
unlinkSync10(file3);
|
|
130700
131000
|
} catch {}
|
|
130701
131001
|
});
|
|
@@ -132876,19 +133176,19 @@ function applyFallbackEntrySettings(input) {
|
|
|
132876
133176
|
// src/tools/delegate-task/subagent-discovery.ts
|
|
132877
133177
|
init_agent_display_names();
|
|
132878
133178
|
// src/features/claude-code-agent-loader/loader.ts
|
|
132879
|
-
import { existsSync as
|
|
132880
|
-
import { join as
|
|
133179
|
+
import { existsSync as existsSync80, readdirSync as readdirSync22 } from "fs";
|
|
133180
|
+
import { join as join84 } from "path";
|
|
132881
133181
|
|
|
132882
133182
|
// src/features/claude-code-agent-loader/agent-definitions-loader.ts
|
|
132883
|
-
import { existsSync as
|
|
133183
|
+
import { existsSync as existsSync79, readFileSync as readFileSync53 } from "fs";
|
|
132884
133184
|
import { basename as basename13, extname as extname8 } from "path";
|
|
132885
133185
|
init_logger();
|
|
132886
133186
|
|
|
132887
133187
|
// src/features/claude-code-agent-loader/json-agent-loader.ts
|
|
132888
|
-
import { existsSync as
|
|
133188
|
+
import { existsSync as existsSync78, readFileSync as readFileSync52 } from "fs";
|
|
132889
133189
|
function parseJsonAgentFile(filePath, scope) {
|
|
132890
133190
|
try {
|
|
132891
|
-
if (!
|
|
133191
|
+
if (!existsSync78(filePath)) {
|
|
132892
133192
|
return null;
|
|
132893
133193
|
}
|
|
132894
133194
|
const content = readFileSync52(filePath, "utf-8");
|
|
@@ -132927,7 +133227,7 @@ function parseJsonAgentFile(filePath, scope) {
|
|
|
132927
133227
|
// src/features/claude-code-agent-loader/agent-definitions-loader.ts
|
|
132928
133228
|
function parseMarkdownAgentFile(filePath, scope) {
|
|
132929
133229
|
try {
|
|
132930
|
-
if (!
|
|
133230
|
+
if (!existsSync79(filePath)) {
|
|
132931
133231
|
return null;
|
|
132932
133232
|
}
|
|
132933
133233
|
const content = readFileSync53(filePath, "utf-8");
|
|
@@ -132962,7 +133262,7 @@ function parseMarkdownAgentFile(filePath, scope) {
|
|
|
132962
133262
|
function loadAgentDefinitions(paths, scope) {
|
|
132963
133263
|
const result = Object.create(null);
|
|
132964
133264
|
for (const filePath of paths) {
|
|
132965
|
-
if (!
|
|
133265
|
+
if (!existsSync79(filePath)) {
|
|
132966
133266
|
log(`[agent-definitions-loader] File not found, skipping: ${filePath}`);
|
|
132967
133267
|
continue;
|
|
132968
133268
|
}
|
|
@@ -132987,7 +133287,7 @@ function loadAgentDefinitions(paths, scope) {
|
|
|
132987
133287
|
|
|
132988
133288
|
// src/features/claude-code-agent-loader/loader.ts
|
|
132989
133289
|
function loadAgentsFromDir(agentsDir, scope) {
|
|
132990
|
-
if (!
|
|
133290
|
+
if (!existsSync80(agentsDir)) {
|
|
132991
133291
|
return [];
|
|
132992
133292
|
}
|
|
132993
133293
|
const entries = readdirSync22(agentsDir, { withFileTypes: true });
|
|
@@ -132995,7 +133295,7 @@ function loadAgentsFromDir(agentsDir, scope) {
|
|
|
132995
133295
|
for (const entry of entries) {
|
|
132996
133296
|
if (!isMarkdownFile(entry))
|
|
132997
133297
|
continue;
|
|
132998
|
-
const agentPath =
|
|
133298
|
+
const agentPath = join84(agentsDir, entry.name);
|
|
132999
133299
|
const agent = parseMarkdownAgentFile(agentPath, scope);
|
|
133000
133300
|
if (agent) {
|
|
133001
133301
|
agents.push(agent);
|
|
@@ -133004,7 +133304,7 @@ function loadAgentsFromDir(agentsDir, scope) {
|
|
|
133004
133304
|
return agents;
|
|
133005
133305
|
}
|
|
133006
133306
|
function loadUserAgents() {
|
|
133007
|
-
const userAgentsDir =
|
|
133307
|
+
const userAgentsDir = join84(getClaudeConfigDir(), "agents");
|
|
133008
133308
|
const agents = loadAgentsFromDir(userAgentsDir, "user");
|
|
133009
133309
|
const result = Object.create(null);
|
|
133010
133310
|
for (const agent of agents) {
|
|
@@ -133013,7 +133313,7 @@ function loadUserAgents() {
|
|
|
133013
133313
|
return result;
|
|
133014
133314
|
}
|
|
133015
133315
|
function loadProjectAgents(directory) {
|
|
133016
|
-
const projectAgentsDir =
|
|
133316
|
+
const projectAgentsDir = join84(directory ?? process.cwd(), ".claude", "agents");
|
|
133017
133317
|
const agents = loadAgentsFromDir(projectAgentsDir, "project");
|
|
133018
133318
|
const result = Object.create(null);
|
|
133019
133319
|
for (const agent of agents) {
|
|
@@ -133023,7 +133323,7 @@ function loadProjectAgents(directory) {
|
|
|
133023
133323
|
}
|
|
133024
133324
|
function loadOpencodeGlobalAgents() {
|
|
133025
133325
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
133026
|
-
const opencodeAgentsDir =
|
|
133326
|
+
const opencodeAgentsDir = join84(configDir, "agents");
|
|
133027
133327
|
const agents = loadAgentsFromDir(opencodeAgentsDir, "opencode");
|
|
133028
133328
|
const result = Object.create(null);
|
|
133029
133329
|
for (const agent of agents) {
|
|
@@ -133032,7 +133332,7 @@ function loadOpencodeGlobalAgents() {
|
|
|
133032
133332
|
return result;
|
|
133033
133333
|
}
|
|
133034
133334
|
function loadOpencodeProjectAgents(directory) {
|
|
133035
|
-
const opencodeProjectDir =
|
|
133335
|
+
const opencodeProjectDir = join84(directory ?? process.cwd(), ".opencode", "agents");
|
|
133036
133336
|
const agents = loadAgentsFromDir(opencodeProjectDir, "opencode-project");
|
|
133037
133337
|
const result = Object.create(null);
|
|
133038
133338
|
for (const agent of agents) {
|
|
@@ -133575,7 +133875,7 @@ function createDelegateTask(options) {
|
|
|
133575
133875
|
init_constants();
|
|
133576
133876
|
// src/tools/task/task-create.ts
|
|
133577
133877
|
init_tool();
|
|
133578
|
-
import { join as
|
|
133878
|
+
import { join as join87 } from "path";
|
|
133579
133879
|
|
|
133580
133880
|
// src/tools/task/types.ts
|
|
133581
133881
|
var TaskStatusSchema = exports_external.enum(["pending", "in_progress", "completed", "deleted"]);
|
|
@@ -133629,18 +133929,18 @@ var TaskDeleteInputSchema = exports_external.object({
|
|
|
133629
133929
|
});
|
|
133630
133930
|
|
|
133631
133931
|
// src/features/claude-tasks/storage.ts
|
|
133632
|
-
import { join as
|
|
133633
|
-
import { existsSync as
|
|
133932
|
+
import { join as join86, dirname as dirname28, basename as basename14, isAbsolute as isAbsolute12 } from "path";
|
|
133933
|
+
import { existsSync as existsSync82, mkdirSync as mkdirSync16, readFileSync as readFileSync55, writeFileSync as writeFileSync19, renameSync as renameSync4, unlinkSync as unlinkSync11, readdirSync as readdirSync23 } from "fs";
|
|
133634
133934
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
133635
133935
|
function getTaskDir(config4 = {}) {
|
|
133636
133936
|
const tasksConfig = config4.bob?.tasks;
|
|
133637
133937
|
const storagePath = tasksConfig?.storage_path;
|
|
133638
133938
|
if (storagePath) {
|
|
133639
|
-
return isAbsolute12(storagePath) ? storagePath :
|
|
133939
|
+
return isAbsolute12(storagePath) ? storagePath : join86(process.cwd(), storagePath);
|
|
133640
133940
|
}
|
|
133641
133941
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
133642
133942
|
const listId = resolveTaskListId(config4);
|
|
133643
|
-
return
|
|
133943
|
+
return join86(configDir, "tasks", listId);
|
|
133644
133944
|
}
|
|
133645
133945
|
function sanitizePathSegment(value) {
|
|
133646
133946
|
return value.replace(/[^a-zA-Z0-9_-]/g, "-") || "default";
|
|
@@ -133658,13 +133958,13 @@ function resolveTaskListId(config4 = {}) {
|
|
|
133658
133958
|
return sanitizePathSegment(basename14(process.cwd()));
|
|
133659
133959
|
}
|
|
133660
133960
|
function ensureDir(dirPath) {
|
|
133661
|
-
if (!
|
|
133961
|
+
if (!existsSync82(dirPath)) {
|
|
133662
133962
|
mkdirSync16(dirPath, { recursive: true });
|
|
133663
133963
|
}
|
|
133664
133964
|
}
|
|
133665
133965
|
function readJsonSafe(filePath, schema2) {
|
|
133666
133966
|
try {
|
|
133667
|
-
if (!
|
|
133967
|
+
if (!existsSync82(filePath)) {
|
|
133668
133968
|
return null;
|
|
133669
133969
|
}
|
|
133670
133970
|
const content = readFileSync55(filePath, "utf-8");
|
|
@@ -133687,7 +133987,7 @@ function writeJsonAtomic(filePath, data) {
|
|
|
133687
133987
|
renameSync4(tempPath, filePath);
|
|
133688
133988
|
} catch (error92) {
|
|
133689
133989
|
try {
|
|
133690
|
-
if (
|
|
133990
|
+
if (existsSync82(tempPath)) {
|
|
133691
133991
|
unlinkSync11(tempPath);
|
|
133692
133992
|
}
|
|
133693
133993
|
} catch {}
|
|
@@ -133699,7 +133999,7 @@ function generateTaskId() {
|
|
|
133699
133999
|
return `T-${randomUUID2()}`;
|
|
133700
134000
|
}
|
|
133701
134001
|
function acquireLock(dirPath) {
|
|
133702
|
-
const lockPath =
|
|
134002
|
+
const lockPath = join86(dirPath, ".lock");
|
|
133703
134003
|
const lockId = randomUUID2();
|
|
133704
134004
|
const createLock = (timestamp2) => {
|
|
133705
134005
|
writeFileSync19(lockPath, JSON.stringify({ id: lockId, timestamp: timestamp2 }), {
|
|
@@ -133747,7 +134047,7 @@ function acquireLock(dirPath) {
|
|
|
133747
134047
|
acquired: true,
|
|
133748
134048
|
release: () => {
|
|
133749
134049
|
try {
|
|
133750
|
-
if (!
|
|
134050
|
+
if (!existsSync82(lockPath))
|
|
133751
134051
|
return;
|
|
133752
134052
|
const lockContent = readFileSync55(lockPath, "utf-8");
|
|
133753
134053
|
const lockData = JSON.parse(lockContent);
|
|
@@ -133912,7 +134212,7 @@ async function handleCreate(args, config4, ctx, context) {
|
|
|
133912
134212
|
threadID: context.sessionID
|
|
133913
134213
|
};
|
|
133914
134214
|
const validatedTask = TaskObjectSchema.parse(task);
|
|
133915
|
-
writeJsonAtomic(
|
|
134215
|
+
writeJsonAtomic(join87(taskDir, `${taskId}.json`), validatedTask);
|
|
133916
134216
|
await syncTaskTodoUpdate(ctx, validatedTask, context.sessionID);
|
|
133917
134217
|
return JSON.stringify({
|
|
133918
134218
|
task: {
|
|
@@ -133935,7 +134235,7 @@ async function handleCreate(args, config4, ctx, context) {
|
|
|
133935
134235
|
}
|
|
133936
134236
|
// src/tools/task/task-get.ts
|
|
133937
134237
|
init_tool();
|
|
133938
|
-
import { join as
|
|
134238
|
+
import { join as join88 } from "path";
|
|
133939
134239
|
var TASK_ID_PATTERN = /^T-[A-Za-z0-9-]+$/;
|
|
133940
134240
|
function parseTaskId(id) {
|
|
133941
134241
|
if (!TASK_ID_PATTERN.test(id))
|
|
@@ -133960,7 +134260,7 @@ Returns null if the task does not exist or the file is invalid.`,
|
|
|
133960
134260
|
return JSON.stringify({ error: "invalid_task_id" });
|
|
133961
134261
|
}
|
|
133962
134262
|
const taskDir = getTaskDir(config4);
|
|
133963
|
-
const taskPath =
|
|
134263
|
+
const taskPath = join88(taskDir, `${taskId}.json`);
|
|
133964
134264
|
const task = readJsonSafe(taskPath, TaskObjectSchema);
|
|
133965
134265
|
return JSON.stringify({ task: task ?? null });
|
|
133966
134266
|
} catch (error92) {
|
|
@@ -133974,8 +134274,8 @@ Returns null if the task does not exist or the file is invalid.`,
|
|
|
133974
134274
|
}
|
|
133975
134275
|
// src/tools/task/task-list.ts
|
|
133976
134276
|
init_tool();
|
|
133977
|
-
import { join as
|
|
133978
|
-
import { existsSync as
|
|
134277
|
+
import { join as join89 } from "path";
|
|
134278
|
+
import { existsSync as existsSync83, readdirSync as readdirSync24 } from "fs";
|
|
133979
134279
|
function createTaskList(config4) {
|
|
133980
134280
|
return tool({
|
|
133981
134281
|
description: `List all active tasks with summary information.
|
|
@@ -133986,7 +134286,7 @@ Returns summary format: id, subject, status, owner, blockedBy (not full descript
|
|
|
133986
134286
|
args: {},
|
|
133987
134287
|
execute: async () => {
|
|
133988
134288
|
const taskDir = getTaskDir(config4);
|
|
133989
|
-
if (!
|
|
134289
|
+
if (!existsSync83(taskDir)) {
|
|
133990
134290
|
return JSON.stringify({ tasks: [] });
|
|
133991
134291
|
}
|
|
133992
134292
|
const files = readdirSync24(taskDir).filter((f) => f.endsWith(".json") && f.startsWith("T-")).map((f) => f.replace(".json", ""));
|
|
@@ -133995,7 +134295,7 @@ Returns summary format: id, subject, status, owner, blockedBy (not full descript
|
|
|
133995
134295
|
}
|
|
133996
134296
|
const allTasks = [];
|
|
133997
134297
|
for (const fileId of files) {
|
|
133998
|
-
const task = readJsonSafe(
|
|
134298
|
+
const task = readJsonSafe(join89(taskDir, `${fileId}.json`), TaskObjectSchema);
|
|
133999
134299
|
if (task) {
|
|
134000
134300
|
allTasks.push(task);
|
|
134001
134301
|
}
|
|
@@ -134024,7 +134324,7 @@ Returns summary format: id, subject, status, owner, blockedBy (not full descript
|
|
|
134024
134324
|
}
|
|
134025
134325
|
// src/tools/task/task-update.ts
|
|
134026
134326
|
init_tool();
|
|
134027
|
-
import { join as
|
|
134327
|
+
import { join as join90 } from "path";
|
|
134028
134328
|
var TASK_ID_PATTERN2 = /^T-[A-Za-z0-9-]+$/;
|
|
134029
134329
|
function parseTaskId2(id) {
|
|
134030
134330
|
if (!TASK_ID_PATTERN2.test(id))
|
|
@@ -134072,7 +134372,7 @@ async function handleUpdate(args, config4, ctx, context) {
|
|
|
134072
134372
|
return JSON.stringify({ error: "task_lock_unavailable" });
|
|
134073
134373
|
}
|
|
134074
134374
|
try {
|
|
134075
|
-
const taskPath =
|
|
134375
|
+
const taskPath = join90(taskDir, `${taskId}.json`);
|
|
134076
134376
|
const task = readJsonSafe(taskPath, TaskObjectSchema);
|
|
134077
134377
|
if (!task) {
|
|
134078
134378
|
return JSON.stringify({ error: "task_not_found" });
|
|
@@ -134942,7 +135242,7 @@ Diff.prototype = {
|
|
|
134942
135242
|
tokenize: function tokenize(value) {
|
|
134943
135243
|
return Array.from(value);
|
|
134944
135244
|
},
|
|
134945
|
-
join: function
|
|
135245
|
+
join: function join91(chars) {
|
|
134946
135246
|
return chars.join("");
|
|
134947
135247
|
},
|
|
134948
135248
|
postProcess: function postProcess(changeObjects) {
|
|
@@ -137203,7 +137503,7 @@ function unregisterManagerForCleanup(manager) {
|
|
|
137203
137503
|
|
|
137204
137504
|
// src/features/background-agent/compaction-aware-message-resolver.ts
|
|
137205
137505
|
import { readdirSync as readdirSync25, readFileSync as readFileSync56 } from "fs";
|
|
137206
|
-
import { join as
|
|
137506
|
+
import { join as join92 } from "path";
|
|
137207
137507
|
function hasFullAgentAndModel(message) {
|
|
137208
137508
|
return !!message.agent && !isCompactionAgent(message.agent) && !!message.model?.providerID && !!message.model?.modelID;
|
|
137209
137509
|
}
|
|
@@ -137282,7 +137582,7 @@ function findNearestMessageExcludingCompaction(messageDir, sessionID) {
|
|
|
137282
137582
|
const messages = [];
|
|
137283
137583
|
for (const file3 of files) {
|
|
137284
137584
|
try {
|
|
137285
|
-
const content = readFileSync56(
|
|
137585
|
+
const content = readFileSync56(join92(messageDir, file3), "utf-8");
|
|
137286
137586
|
const parsed = JSON.parse(content);
|
|
137287
137587
|
if (hasCompactionPartInStorage(parsed.id) || isCompactionAgent(parsed.agent)) {
|
|
137288
137588
|
continue;
|
|
@@ -137372,7 +137672,7 @@ function handleSessionIdleBackgroundEvent(args) {
|
|
|
137372
137672
|
}
|
|
137373
137673
|
|
|
137374
137674
|
// src/features/background-agent/manager.ts
|
|
137375
|
-
import { join as
|
|
137675
|
+
import { join as join93 } from "path";
|
|
137376
137676
|
|
|
137377
137677
|
// src/features/background-agent/task-poller.ts
|
|
137378
137678
|
init_plugin_identity();
|
|
@@ -139048,7 +139348,7 @@ ${originalText}`;
|
|
|
139048
139348
|
parentSessionID: task.parentSessionID
|
|
139049
139349
|
});
|
|
139050
139350
|
}
|
|
139051
|
-
const messageDir =
|
|
139351
|
+
const messageDir = join93(MESSAGE_STORAGE, task.parentSessionID);
|
|
139052
139352
|
const currentMessage = messageDir ? findNearestMessageExcludingCompaction(messageDir, task.parentSessionID) : null;
|
|
139053
139353
|
agent = currentMessage?.agent ?? task.parentAgent;
|
|
139054
139354
|
model = currentMessage?.model?.providerID && currentMessage?.model?.modelID ? { providerID: currentMessage.model.providerID, modelID: currentMessage.model.modelID } : undefined;
|
|
@@ -139379,11 +139679,11 @@ ${originalText}`;
|
|
|
139379
139679
|
}
|
|
139380
139680
|
}
|
|
139381
139681
|
// src/features/mcp-oauth/storage.ts
|
|
139382
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
139383
|
-
import { dirname as dirname29, join as
|
|
139682
|
+
import { chmodSync as chmodSync2, existsSync as existsSync84, mkdirSync as mkdirSync17, readFileSync as readFileSync57, renameSync as renameSync5, unlinkSync as unlinkSync12, writeFileSync as writeFileSync20 } from "fs";
|
|
139683
|
+
import { dirname as dirname29, join as join94 } from "path";
|
|
139384
139684
|
var STORAGE_FILE_NAME = "mcp-oauth.json";
|
|
139385
139685
|
function getMcpOauthStoragePath() {
|
|
139386
|
-
return
|
|
139686
|
+
return join94(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
|
|
139387
139687
|
}
|
|
139388
139688
|
function normalizeHost(serverHost) {
|
|
139389
139689
|
let host = serverHost.trim();
|
|
@@ -139420,7 +139720,7 @@ function buildKey(serverHost, resource) {
|
|
|
139420
139720
|
}
|
|
139421
139721
|
function readStore() {
|
|
139422
139722
|
const filePath = getMcpOauthStoragePath();
|
|
139423
|
-
if (!
|
|
139723
|
+
if (!existsSync84(filePath)) {
|
|
139424
139724
|
return null;
|
|
139425
139725
|
}
|
|
139426
139726
|
try {
|
|
@@ -139434,7 +139734,7 @@ function writeStore(store2) {
|
|
|
139434
139734
|
const filePath = getMcpOauthStoragePath();
|
|
139435
139735
|
try {
|
|
139436
139736
|
const dir = dirname29(filePath);
|
|
139437
|
-
if (!
|
|
139737
|
+
if (!existsSync84(dir)) {
|
|
139438
139738
|
mkdirSync17(dir, { recursive: true });
|
|
139439
139739
|
}
|
|
139440
139740
|
const tempPath = `${filePath}.tmp.${Date.now()}`;
|
|
@@ -146081,8 +146381,8 @@ class TmuxSessionManager {
|
|
|
146081
146381
|
var SESSION_TIMEOUT_MS3 = 10 * 60 * 1000;
|
|
146082
146382
|
var MIN_STABILITY_TIME_MS4 = 10 * 1000;
|
|
146083
146383
|
// src/features/claude-code-mcp-loader/loader.ts
|
|
146084
|
-
import { existsSync as
|
|
146085
|
-
import { join as
|
|
146384
|
+
import { existsSync as existsSync85, readFileSync as readFileSync58 } from "fs";
|
|
146385
|
+
import { join as join95 } from "path";
|
|
146086
146386
|
import { homedir as homedir15 } from "os";
|
|
146087
146387
|
init_logger();
|
|
146088
146388
|
function getMcpConfigPaths() {
|
|
@@ -146090,10 +146390,10 @@ function getMcpConfigPaths() {
|
|
|
146090
146390
|
const cwd = process.cwd();
|
|
146091
146391
|
const explicitClaudeConfigDir = process.env.CLAUDE_CONFIG_DIR?.trim() || process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
146092
146392
|
const candidates = [
|
|
146093
|
-
...explicitClaudeConfigDir ? [] : [{ path:
|
|
146094
|
-
{ path:
|
|
146095
|
-
{ path:
|
|
146096
|
-
{ path:
|
|
146393
|
+
...explicitClaudeConfigDir ? [] : [{ path: join95(homedir15(), ".claude.json"), scope: "user" }],
|
|
146394
|
+
{ path: join95(claudeConfigDir, ".mcp.json"), scope: "user" },
|
|
146395
|
+
{ path: join95(cwd, ".mcp.json"), scope: "project" },
|
|
146396
|
+
{ path: join95(cwd, ".claude", ".mcp.json"), scope: "local" }
|
|
146097
146397
|
];
|
|
146098
146398
|
const seen = new Set;
|
|
146099
146399
|
return candidates.filter(({ path: path9 }) => {
|
|
@@ -146104,7 +146404,7 @@ function getMcpConfigPaths() {
|
|
|
146104
146404
|
});
|
|
146105
146405
|
}
|
|
146106
146406
|
async function loadMcpConfigFile(filePath) {
|
|
146107
|
-
if (!
|
|
146407
|
+
if (!existsSync85(filePath)) {
|
|
146108
146408
|
return null;
|
|
146109
146409
|
}
|
|
146110
146410
|
try {
|
|
@@ -146120,7 +146420,7 @@ function getSystemMcpServerNames() {
|
|
|
146120
146420
|
const paths = getMcpConfigPaths();
|
|
146121
146421
|
const cwd = process.cwd();
|
|
146122
146422
|
for (const { path: path9 } of paths) {
|
|
146123
|
-
if (!
|
|
146423
|
+
if (!existsSync85(path9))
|
|
146124
146424
|
continue;
|
|
146125
146425
|
try {
|
|
146126
146426
|
const content = readFileSync58(path9, "utf-8");
|
|
@@ -150468,7 +150768,7 @@ var researcherPromptMetadata = {
|
|
|
150468
150768
|
};
|
|
150469
150769
|
|
|
150470
150770
|
// src/agents/builtin-agents/resolve-file-uri.ts
|
|
150471
|
-
import { existsSync as
|
|
150771
|
+
import { existsSync as existsSync86, readFileSync as readFileSync59 } from "fs";
|
|
150472
150772
|
import { homedir as homedir16 } from "os";
|
|
150473
150773
|
import { isAbsolute as isAbsolute13, resolve as resolve22 } from "path";
|
|
150474
150774
|
init_logger();
|
|
@@ -150493,7 +150793,7 @@ function resolvePromptAppend(promptAppend, configDir) {
|
|
|
150493
150793
|
});
|
|
150494
150794
|
return `[WARNING: Path rejected: ${promptAppend}]`;
|
|
150495
150795
|
}
|
|
150496
|
-
if (!
|
|
150796
|
+
if (!existsSync86(filePath)) {
|
|
150497
150797
|
return `[WARNING: Could not resolve file URI: ${promptAppend}]`;
|
|
150498
150798
|
}
|
|
150499
150799
|
try {
|
|
@@ -154448,7 +154748,7 @@ async function applyAgentConfig(params) {
|
|
|
154448
154748
|
init_agent_display_names();
|
|
154449
154749
|
// src/features/claude-code-command-loader/loader.ts
|
|
154450
154750
|
import { promises as fs14 } from "fs";
|
|
154451
|
-
import { join as
|
|
154751
|
+
import { join as join96, basename as basename15 } from "path";
|
|
154452
154752
|
init_logger();
|
|
154453
154753
|
async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix = "") {
|
|
154454
154754
|
try {
|
|
@@ -154479,7 +154779,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
|
|
|
154479
154779
|
if (entry.isDirectory()) {
|
|
154480
154780
|
if (entry.name.startsWith("."))
|
|
154481
154781
|
continue;
|
|
154482
|
-
const subDirPath =
|
|
154782
|
+
const subDirPath = join96(commandsDir, entry.name);
|
|
154483
154783
|
const subPrefix = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
154484
154784
|
const subCommands = await loadCommandsFromDir(subDirPath, scope, visited, subPrefix);
|
|
154485
154785
|
commands2.push(...subCommands);
|
|
@@ -154487,7 +154787,7 @@ async function loadCommandsFromDir(commandsDir, scope, visited = new Set, prefix
|
|
|
154487
154787
|
}
|
|
154488
154788
|
if (!isMarkdownFile(entry))
|
|
154489
154789
|
continue;
|
|
154490
|
-
const commandPath =
|
|
154790
|
+
const commandPath = join96(commandsDir, entry.name);
|
|
154491
154791
|
const baseCommandName = basename15(entry.name, ".md");
|
|
154492
154792
|
const commandName = prefix ? `${prefix}/${baseCommandName}` : baseCommandName;
|
|
154493
154793
|
try {
|
|
@@ -154546,12 +154846,12 @@ function commandsToRecord(commands2) {
|
|
|
154546
154846
|
return result;
|
|
154547
154847
|
}
|
|
154548
154848
|
async function loadUserCommands() {
|
|
154549
|
-
const userCommandsDir =
|
|
154849
|
+
const userCommandsDir = join96(getClaudeConfigDir(), "commands");
|
|
154550
154850
|
const commands2 = await loadCommandsFromDir(userCommandsDir, "user");
|
|
154551
154851
|
return commandsToRecord(commands2);
|
|
154552
154852
|
}
|
|
154553
154853
|
async function loadProjectCommands(directory) {
|
|
154554
|
-
const projectCommandsDir =
|
|
154854
|
+
const projectCommandsDir = join96(directory ?? process.cwd(), ".claude", "commands");
|
|
154555
154855
|
const commands2 = await loadCommandsFromDir(projectCommandsDir, "project");
|
|
154556
154856
|
return commandsToRecord(commands2);
|
|
154557
154857
|
}
|
|
@@ -154637,7 +154937,7 @@ function remapCommandAgentFields(commands2) {
|
|
|
154637
154937
|
|
|
154638
154938
|
// src/plugin-handlers/mcp-config-handler.ts
|
|
154639
154939
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
154640
|
-
import { existsSync as
|
|
154940
|
+
import { existsSync as existsSync87 } from "fs";
|
|
154641
154941
|
|
|
154642
154942
|
// src/mcp/websearch.ts
|
|
154643
154943
|
init_logger();
|
|
@@ -154790,7 +155090,7 @@ function hasUsableLocalMcpRuntime(name, entry) {
|
|
|
154790
155090
|
return false;
|
|
154791
155091
|
}
|
|
154792
155092
|
if (binary2 === "node" && typeof args[0] === "string" && args[0].endsWith(".mjs")) {
|
|
154793
|
-
if (!
|
|
155093
|
+
if (!existsSync87(args[0])) {
|
|
154794
155094
|
return false;
|
|
154795
155095
|
}
|
|
154796
155096
|
const probe2 = spawnSync5(binary2, ["--version"], {
|
|
@@ -155109,6 +155409,8 @@ function applyToolConfig(params) {
|
|
|
155109
155409
|
function buildLspConfig(lsp) {
|
|
155110
155410
|
const result = {};
|
|
155111
155411
|
for (const [name, server] of Object.entries(lsp)) {
|
|
155412
|
+
if (server.enabled === false)
|
|
155413
|
+
continue;
|
|
155112
155414
|
result[name] = {
|
|
155113
155415
|
command: server.command,
|
|
155114
155416
|
extensions: server.extensions,
|
|
@@ -155402,6 +155704,7 @@ function createToolRegistry(args) {
|
|
|
155402
155704
|
managers,
|
|
155403
155705
|
skillContext,
|
|
155404
155706
|
availableCategories,
|
|
155707
|
+
builtinMcp,
|
|
155405
155708
|
interactiveBashEnabled = isInteractiveBashEnabled(),
|
|
155406
155709
|
toolFactories
|
|
155407
155710
|
} = args;
|
|
@@ -155449,7 +155752,8 @@ function createToolRegistry(args) {
|
|
|
155449
155752
|
const skillMcpTool = factories.createSkillMcpTool({
|
|
155450
155753
|
manager: managers.skillMcpManager,
|
|
155451
155754
|
getLoadedSkills: () => skillContext.mergedSkills,
|
|
155452
|
-
getSessionID: getSessionIDForMcp
|
|
155755
|
+
getSessionID: getSessionIDForMcp,
|
|
155756
|
+
builtinMcp
|
|
155453
155757
|
});
|
|
155454
155758
|
const commands2 = factories.discoverCommandsSync(ctx.directory, {
|
|
155455
155759
|
pluginsEnabled: pluginConfig.claude_code?.plugins ?? true,
|
|
@@ -155505,7 +155809,7 @@ function createToolRegistry(args) {
|
|
|
155505
155809
|
|
|
155506
155810
|
// src/create-tools.ts
|
|
155507
155811
|
async function createTools(args) {
|
|
155508
|
-
const { ctx, pluginConfig, managers } = args;
|
|
155812
|
+
const { ctx, pluginConfig, platformConfig, managers } = args;
|
|
155509
155813
|
const skillContext = await createSkillContext({
|
|
155510
155814
|
directory: ctx.directory,
|
|
155511
155815
|
pluginConfig
|
|
@@ -155516,7 +155820,8 @@ async function createTools(args) {
|
|
|
155516
155820
|
pluginConfig,
|
|
155517
155821
|
managers,
|
|
155518
155822
|
skillContext,
|
|
155519
|
-
availableCategories
|
|
155823
|
+
availableCategories,
|
|
155824
|
+
builtinMcp: platformConfig?.mcp
|
|
155520
155825
|
});
|
|
155521
155826
|
return {
|
|
155522
155827
|
filteredTools,
|
|
@@ -155785,10 +156090,10 @@ init_agent_display_names();
|
|
|
155785
156090
|
|
|
155786
156091
|
// src/plugin/ultrawork-db-model-override.ts
|
|
155787
156092
|
import { Database } from "bun:sqlite";
|
|
155788
|
-
import { join as
|
|
155789
|
-
import { existsSync as
|
|
156093
|
+
import { join as join97 } from "path";
|
|
156094
|
+
import { existsSync as existsSync88 } from "fs";
|
|
155790
156095
|
function getDbPath() {
|
|
155791
|
-
return
|
|
156096
|
+
return join97(getDataDir(), "opencode", "opencode.db");
|
|
155792
156097
|
}
|
|
155793
156098
|
var MAX_MICROTASK_RETRIES = 10;
|
|
155794
156099
|
function tryUpdateMessageModel(db, messageId, targetModel, variant) {
|
|
@@ -155865,7 +156170,7 @@ function retryViaMicrotask(db, messageId, targetModel, variant, attempt) {
|
|
|
155865
156170
|
function scheduleDeferredModelOverride(messageId, targetModel, variant) {
|
|
155866
156171
|
queueMicrotask(() => {
|
|
155867
156172
|
const dbPath = getDbPath();
|
|
155868
|
-
if (!
|
|
156173
|
+
if (!existsSync88(dbPath)) {
|
|
155869
156174
|
log("[ultrawork-db-override] DB not found, skipping deferred override");
|
|
155870
156175
|
return;
|
|
155871
156176
|
}
|
|
@@ -157208,110 +157513,11 @@ function createFirstMessageVariantGate() {
|
|
|
157208
157513
|
init_plugin_identity();
|
|
157209
157514
|
|
|
157210
157515
|
// src/shared/startup-diagnostics.ts
|
|
157211
|
-
import { existsSync as
|
|
157516
|
+
import { existsSync as existsSync89, readFileSync as readFileSync60 } from "fs";
|
|
157212
157517
|
import { join as join98 } from "path";
|
|
157213
|
-
|
|
157214
|
-
// src/mcp/registry.ts
|
|
157215
|
-
import { join as join97 } from "path";
|
|
157216
|
-
function resolveAssetScript(...segments) {
|
|
157217
|
-
return join97(import.meta.dirname, "..", "assets", ...segments);
|
|
157218
|
-
}
|
|
157219
|
-
function createNpmPackageCommand(pkg, ...args) {
|
|
157220
|
-
return ["node", resolveAssetScript("runtime", "npm-package-runner.mjs"), pkg, ...args];
|
|
157221
|
-
}
|
|
157222
|
-
var HIAI_MCP_REGISTRY = {
|
|
157223
|
-
playwright: {
|
|
157224
|
-
name: "playwright",
|
|
157225
|
-
enabledByDefault: true,
|
|
157226
|
-
install: "npm",
|
|
157227
|
-
optionalEnv: ["HIAI_PLAYWRIGHT_INSTALL_BROWSERS"],
|
|
157228
|
-
config: {
|
|
157229
|
-
enabled: true,
|
|
157230
|
-
command: ["node", resolveAssetScript("mcp", "playwright.mjs")],
|
|
157231
|
-
timeout: 600000
|
|
157232
|
-
}
|
|
157233
|
-
},
|
|
157234
|
-
stitch: {
|
|
157235
|
-
name: "stitch",
|
|
157236
|
-
enabledByDefault: true,
|
|
157237
|
-
install: "remote",
|
|
157238
|
-
requiredEnv: ["STITCH_AI_API_KEY"],
|
|
157239
|
-
config: {
|
|
157240
|
-
enabled: true,
|
|
157241
|
-
type: "remote",
|
|
157242
|
-
url: "https://stitch.googleapis.com/mcp",
|
|
157243
|
-
headers: { "X-Goog-Api-Key": "{env:STITCH_AI_API_KEY}" },
|
|
157244
|
-
timeout: 600000
|
|
157245
|
-
}
|
|
157246
|
-
},
|
|
157247
|
-
"sequential-thinking": {
|
|
157248
|
-
name: "sequential-thinking",
|
|
157249
|
-
enabledByDefault: true,
|
|
157250
|
-
install: "npm",
|
|
157251
|
-
config: {
|
|
157252
|
-
enabled: true,
|
|
157253
|
-
command: createNpmPackageCommand("@modelcontextprotocol/server-sequential-thinking"),
|
|
157254
|
-
timeout: 600000
|
|
157255
|
-
}
|
|
157256
|
-
},
|
|
157257
|
-
firecrawl: {
|
|
157258
|
-
name: "firecrawl",
|
|
157259
|
-
enabledByDefault: true,
|
|
157260
|
-
install: "npm",
|
|
157261
|
-
requiredEnv: ["FIRECRAWL_API_KEY"],
|
|
157262
|
-
config: {
|
|
157263
|
-
enabled: true,
|
|
157264
|
-
command: createNpmPackageCommand("firecrawl-mcp"),
|
|
157265
|
-
timeout: 600000,
|
|
157266
|
-
environment: { FIRECRAWL_API_KEY: "{env:FIRECRAWL_API_KEY}" }
|
|
157267
|
-
}
|
|
157268
|
-
},
|
|
157269
|
-
rag: {
|
|
157270
|
-
name: "rag",
|
|
157271
|
-
enabledByDefault: true,
|
|
157272
|
-
install: "user-service",
|
|
157273
|
-
optionalEnv: ["OPENCODE_RAG_URL"],
|
|
157274
|
-
config: {
|
|
157275
|
-
enabled: true,
|
|
157276
|
-
type: "local",
|
|
157277
|
-
command: ["node", resolveAssetScript("mcp", "rag.mjs")],
|
|
157278
|
-
environment: {
|
|
157279
|
-
OPENCODE_RAG_URL: "{env:OPENCODE_RAG_URL:-http://localhost:9002/tools/search}"
|
|
157280
|
-
},
|
|
157281
|
-
timeout: 600000
|
|
157282
|
-
}
|
|
157283
|
-
},
|
|
157284
|
-
context7: {
|
|
157285
|
-
name: "context7",
|
|
157286
|
-
enabledByDefault: true,
|
|
157287
|
-
install: "remote",
|
|
157288
|
-
optionalEnv: ["CONTEXT7_API_KEY"],
|
|
157289
|
-
config: {
|
|
157290
|
-
enabled: true,
|
|
157291
|
-
type: "remote",
|
|
157292
|
-
url: "https://mcp.context7.com/mcp",
|
|
157293
|
-
headers: { "X-API-KEY": "{env:CONTEXT7_API_KEY}" },
|
|
157294
|
-
timeout: 600000
|
|
157295
|
-
}
|
|
157296
|
-
},
|
|
157297
|
-
mempalace: {
|
|
157298
|
-
name: "mempalace",
|
|
157299
|
-
enabledByDefault: true,
|
|
157300
|
-
install: "python",
|
|
157301
|
-
optionalEnv: ["MEMPALACE_PYTHON", "MEMPALACE_PALACE_PATH", "HIAI_MCP_AUTO_INSTALL"],
|
|
157302
|
-
config: {
|
|
157303
|
-
enabled: true,
|
|
157304
|
-
type: "local",
|
|
157305
|
-
command: ["node", resolveAssetScript("mcp", "mempalace.mjs"), "--palace", "./.opencode/palace"],
|
|
157306
|
-
timeout: 600000
|
|
157307
|
-
}
|
|
157308
|
-
}
|
|
157309
|
-
};
|
|
157310
|
-
|
|
157311
|
-
// src/shared/startup-diagnostics.ts
|
|
157312
157518
|
init_plugin_identity();
|
|
157313
157519
|
function readPlugins(configPath) {
|
|
157314
|
-
if (!
|
|
157520
|
+
if (!existsSync89(configPath))
|
|
157315
157521
|
return [];
|
|
157316
157522
|
try {
|
|
157317
157523
|
const content = readFileSync60(configPath, "utf-8");
|
|
@@ -159564,7 +159770,7 @@ init_websearch_cited();
|
|
|
159564
159770
|
// src/features/builtin-skills/materialize.ts
|
|
159565
159771
|
import {
|
|
159566
159772
|
cpSync,
|
|
159567
|
-
existsSync as
|
|
159773
|
+
existsSync as existsSync91,
|
|
159568
159774
|
mkdirSync as mkdirSync20,
|
|
159569
159775
|
readdirSync as readdirSync26,
|
|
159570
159776
|
readFileSync as readFileSync61,
|
|
@@ -159598,7 +159804,7 @@ function buildSkillFrontmatter(skill2) {
|
|
|
159598
159804
|
`);
|
|
159599
159805
|
}
|
|
159600
159806
|
function shouldWriteSkillFile(skillFilePath) {
|
|
159601
|
-
if (!
|
|
159807
|
+
if (!existsSync91(skillFilePath))
|
|
159602
159808
|
return true;
|
|
159603
159809
|
try {
|
|
159604
159810
|
const existing = readFileSync61(skillFilePath, "utf-8");
|
|
@@ -159630,7 +159836,7 @@ function writeManagedSkillMetadata(targetDir, metadata) {
|
|
|
159630
159836
|
}
|
|
159631
159837
|
function readManagedSkillMetadata(targetDir) {
|
|
159632
159838
|
const metadataPath = join103(targetDir, MANAGED_SKILL_METADATA);
|
|
159633
|
-
if (!
|
|
159839
|
+
if (!existsSync91(metadataPath)) {
|
|
159634
159840
|
return null;
|
|
159635
159841
|
}
|
|
159636
159842
|
try {
|
|
@@ -159640,12 +159846,12 @@ function readManagedSkillMetadata(targetDir) {
|
|
|
159640
159846
|
}
|
|
159641
159847
|
}
|
|
159642
159848
|
function isLegacyManagedSkillDir(targetDir, origin) {
|
|
159643
|
-
if (origin === "plugin" &&
|
|
159849
|
+
if (origin === "plugin" && existsSync91(join103(targetDir, LEGACY_MANAGED_DIR_MARKER))) {
|
|
159644
159850
|
return true;
|
|
159645
159851
|
}
|
|
159646
159852
|
if (origin === "builtin") {
|
|
159647
159853
|
const skillFilePath = join103(targetDir, "SKILL.md");
|
|
159648
|
-
if (!
|
|
159854
|
+
if (!existsSync91(skillFilePath)) {
|
|
159649
159855
|
return false;
|
|
159650
159856
|
}
|
|
159651
159857
|
try {
|
|
@@ -159657,7 +159863,7 @@ function isLegacyManagedSkillDir(targetDir, origin) {
|
|
|
159657
159863
|
return false;
|
|
159658
159864
|
}
|
|
159659
159865
|
function shouldSyncManagedSkillDir(targetDir, origin) {
|
|
159660
|
-
if (!
|
|
159866
|
+
if (!existsSync91(targetDir))
|
|
159661
159867
|
return true;
|
|
159662
159868
|
const metadata = readManagedSkillMetadata(targetDir);
|
|
159663
159869
|
if (metadata?.generatedBy === "hiai-opencode" && metadata.origin === origin) {
|
|
@@ -159673,7 +159879,7 @@ function shouldCleanupManagedSkillDir(targetDir, origin) {
|
|
|
159673
159879
|
return isLegacyManagedSkillDir(targetDir, origin);
|
|
159674
159880
|
}
|
|
159675
159881
|
function cleanupRemovedManagedSkillDirs(rootDir, origin, expectedSkillNames) {
|
|
159676
|
-
if (!
|
|
159882
|
+
if (!existsSync91(rootDir)) {
|
|
159677
159883
|
return;
|
|
159678
159884
|
}
|
|
159679
159885
|
for (const entry of readdirSync26(rootDir, { withFileTypes: true })) {
|
|
@@ -159761,7 +159967,7 @@ function materializeBuiltinSkills(skills) {
|
|
|
159761
159967
|
}
|
|
159762
159968
|
function materializePluginSkillDirectories(pluginRootDir) {
|
|
159763
159969
|
const sourceSkillsDir = join103(pluginRootDir, "skills");
|
|
159764
|
-
if (!
|
|
159970
|
+
if (!existsSync91(sourceSkillsDir)) {
|
|
159765
159971
|
return;
|
|
159766
159972
|
}
|
|
159767
159973
|
const { assembledSkillsDir, pluginSourceDir, configDir } = getSkillLayout();
|
|
@@ -159826,6 +160032,34 @@ function materializePluginSkillDirectories(pluginRootDir) {
|
|
|
159826
160032
|
|
|
159827
160033
|
// src/index.ts
|
|
159828
160034
|
var activePluginDispose = null;
|
|
160035
|
+
function createWebsearchFallback(config4) {
|
|
160036
|
+
const model = config4.agents?.researcher?.model?.trim();
|
|
160037
|
+
if (!model) {
|
|
160038
|
+
return;
|
|
160039
|
+
}
|
|
160040
|
+
if (model.startsWith("openrouter/")) {
|
|
160041
|
+
return {
|
|
160042
|
+
providerID: OPENROUTER_PROVIDER_ID,
|
|
160043
|
+
model: model.slice("openrouter/".length)
|
|
160044
|
+
};
|
|
160045
|
+
}
|
|
160046
|
+
if (model.startsWith("openai/")) {
|
|
160047
|
+
return {
|
|
160048
|
+
providerID: OPENAI_PROVIDER_ID,
|
|
160049
|
+
model: model.slice("openai/".length)
|
|
160050
|
+
};
|
|
160051
|
+
}
|
|
160052
|
+
if (model.startsWith("google/")) {
|
|
160053
|
+
return {
|
|
160054
|
+
providerID: GOOGLE_PROVIDER_ID,
|
|
160055
|
+
model: model.slice("google/".length)
|
|
160056
|
+
};
|
|
160057
|
+
}
|
|
160058
|
+
return {
|
|
160059
|
+
providerID: OPENROUTER_PROVIDER_ID,
|
|
160060
|
+
model
|
|
160061
|
+
};
|
|
160062
|
+
}
|
|
159829
160063
|
function configureBundledBunPtyLibrary() {
|
|
159830
160064
|
if (process.env.BUN_PTY_LIB?.trim()) {
|
|
159831
160065
|
return;
|
|
@@ -159836,7 +160070,7 @@ function configureBundledBunPtyLibrary() {
|
|
|
159836
160070
|
join105(import.meta.dirname, "..", "..", "bun-pty", "rust-pty", "target", "release", libraryName),
|
|
159837
160071
|
join105(import.meta.dirname, "..", "..", "..", "bun-pty", "rust-pty", "target", "release", libraryName)
|
|
159838
160072
|
];
|
|
159839
|
-
const resolved = candidates.find((candidate) =>
|
|
160073
|
+
const resolved = candidates.find((candidate) => existsSync93(candidate));
|
|
159840
160074
|
if (resolved) {
|
|
159841
160075
|
process.env.BUN_PTY_LIB = resolved;
|
|
159842
160076
|
}
|
|
@@ -159887,6 +160121,7 @@ var HiaiOpenCodePlugin = async (ctx) => {
|
|
|
159887
160121
|
const toolsResult = await createTools({
|
|
159888
160122
|
ctx,
|
|
159889
160123
|
pluginConfig: pluginConfig2,
|
|
160124
|
+
platformConfig: internalConfig,
|
|
159890
160125
|
managers
|
|
159891
160126
|
});
|
|
159892
160127
|
const hooks = createHooks({
|
|
@@ -159922,7 +160157,7 @@ var HiaiOpenCodePlugin = async (ctx) => {
|
|
|
159922
160157
|
} catch (err) {
|
|
159923
160158
|
console.error("[hiai-opencode] PTYPlugin failed to load:", err);
|
|
159924
160159
|
}
|
|
159925
|
-
const websearchResult = await websearch_cited_default(ctx);
|
|
160160
|
+
const websearchResult = await websearch_cited_default(ctx, createWebsearchFallback(internalConfig));
|
|
159926
160161
|
const websearchGoogleResult = await WebsearchCitedGooglePlugin(ctx);
|
|
159927
160162
|
const websearchOpenAIResult = await WebsearchCitedOpenAIPlugin(ctx);
|
|
159928
160163
|
const combinedResult = {
|