opencode-raven 2.1.6 → 2.1.7
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/CHANGELOG.md +6 -0
- package/index.ts +82 -71
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.1.7
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Stats and `/raven` setting updates now patch the latest on-disk configuration instead of rewriting stale in-memory state, preserving externally edited MCP servers and headers.
|
|
7
|
+
- Existing malformed or partially written configuration files are preserved for repair instead of being replaced with defaults.
|
|
8
|
+
|
|
3
9
|
## 2.1.6
|
|
4
10
|
|
|
5
11
|
### Added
|
package/index.ts
CHANGED
|
@@ -469,28 +469,27 @@ export default (async (input: PluginInput) => {
|
|
|
469
469
|
}
|
|
470
470
|
|
|
471
471
|
function loadConfig(): RavenConfig {
|
|
472
|
-
|
|
473
|
-
|
|
472
|
+
if (existsSync(configFile)) {
|
|
473
|
+
try {
|
|
474
474
|
const raw = JSON.parse(readFileSync(configFile, "utf-8"))
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
}
|
|
479
|
-
return normalized
|
|
475
|
+
return normalizeConfig(raw)
|
|
476
|
+
} catch {
|
|
477
|
+
// Preserve malformed or partially-written config so the user can repair it.
|
|
478
|
+
return { ...DEFAULT_CONFIG }
|
|
480
479
|
}
|
|
481
|
-
}
|
|
482
|
-
// Auto-create config file with defaults on first run
|
|
483
|
-
|
|
484
|
-
return { ...DEFAULT_CONFIG }
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
function
|
|
488
|
-
try {
|
|
489
|
-
mkdirSync(ravenConfigDir, { recursive: true })
|
|
490
|
-
writeFileSync(configFile, JSON.stringify(config, null, 2) + "\n")
|
|
491
|
-
} catch { /* non-fatal: config won't persist but toggle still works in-session */ }
|
|
492
|
-
}
|
|
493
|
-
|
|
480
|
+
}
|
|
481
|
+
// Auto-create config file with defaults on first run
|
|
482
|
+
writeConfig(DEFAULT_CONFIG)
|
|
483
|
+
return { ...DEFAULT_CONFIG }
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function writeConfig(config: RavenConfig) {
|
|
487
|
+
try {
|
|
488
|
+
mkdirSync(ravenConfigDir, { recursive: true })
|
|
489
|
+
writeFileSync(configFile, JSON.stringify(config, null, 2) + "\n")
|
|
490
|
+
} catch { /* non-fatal: config won't persist but toggle still works in-session */ }
|
|
491
|
+
}
|
|
492
|
+
|
|
494
493
|
function loadMcpMetadata(): Record<string, OnDemandMcpMetadata> {
|
|
495
494
|
const defaults = cloneOnDemandMcpMetadata(DEFAULT_ON_DEMAND_MCP_METADATA)
|
|
496
495
|
try {
|
|
@@ -515,8 +514,23 @@ export default (async (input: PluginInput) => {
|
|
|
515
514
|
writeFileSync(dynamicGuidanceFile, `## Raven on-demand MCP capabilities\n\n${onDemandMcpGuidance("delegate", dynamicGuidanceMcpOrder())}\n`, "utf-8")
|
|
516
515
|
} catch { /* non-fatal: guidance still exists in tool/subagent paths */ }
|
|
517
516
|
}
|
|
518
|
-
|
|
517
|
+
|
|
519
518
|
let config = loadConfig()
|
|
519
|
+
|
|
520
|
+
function updateConfig(update: Partial<RavenConfig> | ((latest: RavenConfig) => Partial<RavenConfig>)): RavenConfig {
|
|
521
|
+
try {
|
|
522
|
+
const raw = existsSync(configFile) ? JSON.parse(readFileSync(configFile, "utf-8")) : config
|
|
523
|
+
const latest = normalizeConfig(raw)
|
|
524
|
+
const patch = typeof update === "function" ? update(latest) : update
|
|
525
|
+
config = normalizeConfig({ ...latest, ...patch })
|
|
526
|
+
writeConfig({ ...raw, ...patch })
|
|
527
|
+
} catch {
|
|
528
|
+
// Keep malformed or partially-written external edits intact instead of replacing them.
|
|
529
|
+
const patch = typeof update === "function" ? update(config) : update
|
|
530
|
+
config = normalizeConfig({ ...config, ...patch })
|
|
531
|
+
}
|
|
532
|
+
return config
|
|
533
|
+
}
|
|
520
534
|
let mcpMetadata = loadMcpMetadata()
|
|
521
535
|
const ravenSessions = new Set<string>()
|
|
522
536
|
const ravenTaskCalls = new Set<string>()
|
|
@@ -1274,16 +1288,17 @@ Then restart opencode for the model change to take effect. If the task can be co
|
|
|
1274
1288
|
return parsed
|
|
1275
1289
|
}
|
|
1276
1290
|
|
|
1277
|
-
// ── Context saved by Raven delegation ──
|
|
1278
|
-
let sessionBytes = 0
|
|
1279
|
-
let totalBytes = config.stats?.bytes ?? 0
|
|
1280
|
-
|
|
1281
|
-
function addBytes(bytes: number) {
|
|
1282
|
-
sessionBytes += bytes
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1291
|
+
// ── Context saved by Raven delegation ──
|
|
1292
|
+
let sessionBytes = 0
|
|
1293
|
+
let totalBytes = config.stats?.bytes ?? 0
|
|
1294
|
+
|
|
1295
|
+
function addBytes(bytes: number) {
|
|
1296
|
+
sessionBytes += bytes
|
|
1297
|
+
const updated = updateConfig((latest) => ({
|
|
1298
|
+
stats: { bytes: Math.max(totalBytes, latest.stats?.bytes ?? 0) + bytes },
|
|
1299
|
+
}))
|
|
1300
|
+
totalBytes = updated.stats?.bytes ?? totalBytes + bytes
|
|
1301
|
+
}
|
|
1287
1302
|
|
|
1288
1303
|
function formatBytes(bytes: number): string {
|
|
1289
1304
|
return bytes >= 1_000_000 ? `${(bytes / 1_000_000).toFixed(1)}MB`
|
|
@@ -1814,16 +1829,14 @@ Then restart opencode for the model change to take effect. If the task can be co
|
|
|
1814
1829
|
const raw = input.arguments.trim()
|
|
1815
1830
|
const arg = raw.toLowerCase()
|
|
1816
1831
|
|
|
1817
|
-
if (arg === "on") {
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
output.parts.push({ type: "text", text: "Raven tool/MCP routing enabled. Non-Raven agents will be redirected to raven_seek for configured tools." })
|
|
1832
|
+
if (arg === "on") {
|
|
1833
|
+
updateConfig({ enabled: true })
|
|
1834
|
+
output.parts.push({ type: "text", text: "Raven tool/MCP routing enabled. Non-Raven agents will be redirected to raven_seek for configured tools." })
|
|
1821
1835
|
} else if (arg === "help") {
|
|
1822
1836
|
output.parts.push({ type: "text", text: helpText() })
|
|
1823
|
-
} else if (arg === "off") {
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
output.parts.push({ type: "text", text: "Raven tool/MCP routing disabled. All agents can use tools directly." })
|
|
1837
|
+
} else if (arg === "off") {
|
|
1838
|
+
updateConfig({ enabled: false })
|
|
1839
|
+
output.parts.push({ type: "text", text: "Raven tool/MCP routing disabled. All agents can use tools directly." })
|
|
1827
1840
|
} else if (arg === "stats") {
|
|
1828
1841
|
output.parts.push({ type: "text", text: statsText() })
|
|
1829
1842
|
} else if (arg === "route") {
|
|
@@ -1835,16 +1848,18 @@ Then restart opencode for the model change to take effect. If the task can be co
|
|
|
1835
1848
|
const name = parts.slice(3).join(" ").trim()
|
|
1836
1849
|
const key = kind === "tool" ? "routeTools" : kind === "keyword" ? "routeToolKeywords" : undefined
|
|
1837
1850
|
|
|
1838
|
-
if (!key || !["add", "remove", "rm"].includes(action) || !name) {
|
|
1839
|
-
output.parts.push({ type: "text", text: "Usage:\n /raven route tool add <tool_name>\n /raven route tool remove <tool_name>\n /raven route keyword add <keyword>\n /raven route keyword remove <keyword>\n\nGlobal MCPs are auto-routed by detected OpenCode MCP server name." })
|
|
1840
|
-
} else {
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1851
|
+
if (!key || !["add", "remove", "rm"].includes(action) || !name) {
|
|
1852
|
+
output.parts.push({ type: "text", text: "Usage:\n /raven route tool add <tool_name>\n /raven route tool remove <tool_name>\n /raven route keyword add <keyword>\n /raven route keyword remove <keyword>\n\nGlobal MCPs are auto-routed by detected OpenCode MCP server name." })
|
|
1853
|
+
} else {
|
|
1854
|
+
updateConfig((latest) => {
|
|
1855
|
+
const values = uniqueStrings(latest[key])
|
|
1856
|
+
const exists = values.some((value) => value.toLowerCase() === name.toLowerCase())
|
|
1857
|
+
const next = action === "add"
|
|
1858
|
+
? exists ? values : [...values, name]
|
|
1859
|
+
: values.filter((value) => value.toLowerCase() !== name.toLowerCase())
|
|
1860
|
+
return key === "routeTools" ? { routeTools: next } : { routeToolKeywords: next }
|
|
1861
|
+
})
|
|
1862
|
+
output.parts.push({ type: "text", text: routeSummary() })
|
|
1848
1863
|
}
|
|
1849
1864
|
} else if (arg === "mcp") {
|
|
1850
1865
|
output.parts.push({ type: "text", text: `${onDemandMcpStatus()}\n\nUsage:\n /raven mcp refresh [server_name]\n /raven mcp detail full\n /raven mcp detail minimized` })
|
|
@@ -1861,12 +1876,11 @@ Then restart opencode for the model change to take effect. If the task can be co
|
|
|
1861
1876
|
})
|
|
1862
1877
|
} else if (action === "detail") {
|
|
1863
1878
|
const detail = parts[2]?.toLowerCase()
|
|
1864
|
-
if (detail !== "full" && detail !== "minimized") {
|
|
1865
|
-
output.parts.push({ type: "text", text: `Usage: /raven mcp detail full|minimized\nCurrent: ${config.onDemandMcpDescriptionDetail ?? "full"}` })
|
|
1866
|
-
} else {
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
output.parts.push({ type: "text", text: `On-demand MCP guidance detail set to: ${detail}\nRestart opencode for startup instructions/tool descriptions to fully refresh.` })
|
|
1879
|
+
if (detail !== "full" && detail !== "minimized") {
|
|
1880
|
+
output.parts.push({ type: "text", text: `Usage: /raven mcp detail full|minimized\nCurrent: ${config.onDemandMcpDescriptionDetail ?? "full"}` })
|
|
1881
|
+
} else {
|
|
1882
|
+
updateConfig({ onDemandMcpDescriptionDetail: detail })
|
|
1883
|
+
output.parts.push({ type: "text", text: `On-demand MCP guidance detail set to: ${detail}\nRestart opencode for startup instructions/tool descriptions to fully refresh.` })
|
|
1870
1884
|
}
|
|
1871
1885
|
} else {
|
|
1872
1886
|
output.parts.push({ type: "text", text: "Usage:\n /raven mcp\n /raven mcp refresh [server_name]\n /raven mcp detail full\n /raven mcp detail minimized" })
|
|
@@ -1887,31 +1901,28 @@ Then restart opencode for the model change to take effect. If the task can be co
|
|
|
1887
1901
|
}
|
|
1888
1902
|
} else if (arg.startsWith("model ")) {
|
|
1889
1903
|
const model = raw.slice(6).trim()
|
|
1890
|
-
if (!model) {
|
|
1891
|
-
output.parts.push({ type: "text", text: `Usage: /raven model <name>\nCurrent model: ${config.model || fm.model || "(default)"}` })
|
|
1892
|
-
} else {
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
ravenProviderIssue = undefined
|
|
1904
|
+
if (!model) {
|
|
1905
|
+
output.parts.push({ type: "text", text: `Usage: /raven model <name>\nCurrent model: ${config.model || fm.model || "(default)"}` })
|
|
1906
|
+
} else {
|
|
1907
|
+
updateConfig({ model })
|
|
1908
|
+
ravenProviderIssue = undefined
|
|
1896
1909
|
output.parts.push({ type: "text", text: `Raven model set to: ${model}\nRestart opencode for the change to take effect.` })
|
|
1897
1910
|
}
|
|
1898
1911
|
} else if (arg.startsWith("effort ")) {
|
|
1899
1912
|
const effort = raw.slice(7).trim()
|
|
1900
|
-
if (!effort) {
|
|
1901
|
-
output.parts.push({ type: "text", text: `Usage: /raven effort <value>\nCurrent: ${config.reasoning_effort || fm.reasoning_effort || "(default)"}` })
|
|
1902
|
-
} else {
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
output.parts.push({ type: "text", text: `Raven reasoning effort set to: ${effort}\nRestart opencode for the change to take effect.` })
|
|
1913
|
+
if (!effort) {
|
|
1914
|
+
output.parts.push({ type: "text", text: `Usage: /raven effort <value>\nCurrent: ${config.reasoning_effort || fm.reasoning_effort || "(default)"}` })
|
|
1915
|
+
} else {
|
|
1916
|
+
updateConfig({ reasoning_effort: effort })
|
|
1917
|
+
output.parts.push({ type: "text", text: `Raven reasoning effort set to: ${effort}\nRestart opencode for the change to take effect.` })
|
|
1906
1918
|
}
|
|
1907
1919
|
} else if (arg.startsWith("timeout ")) {
|
|
1908
1920
|
const secs = Number(raw.slice(8).trim())
|
|
1909
1921
|
if (!Number.isInteger(secs) || secs < 10 || secs > MAX_TIMEOUT_SECONDS) {
|
|
1910
1922
|
output.parts.push({ type: "text", text: `Usage: /raven timeout <seconds>\nMust be between 10 and ${MAX_TIMEOUT_SECONDS}. Current: ${config.timeout ?? 600}s` })
|
|
1911
|
-
} else {
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
output.parts.push({ type: "text", text: `Raven timeout set to ${secs}s. Takes effect immediately.` })
|
|
1923
|
+
} else {
|
|
1924
|
+
updateConfig({ timeout: secs })
|
|
1925
|
+
output.parts.push({ type: "text", text: `Raven timeout set to ${secs}s. Takes effect immediately.` })
|
|
1915
1926
|
}
|
|
1916
1927
|
} else {
|
|
1917
1928
|
const enabled = config.enabled ? "enabled" : "disabled"
|