@koriit/opencode-claude-bridge 0.1.13 → 0.1.15
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/package.json +1 -1
- package/src/index.ts +27 -0
- package/src/logger.ts +25 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@koriit/opencode-claude-bridge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "An OpenCode plugin that bridges enabled Claude Code plugins (commands, agents, skills, MCP, LSP) into OpenCode at runtime, namespaced so they never shadow your existing items.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/index.ts
CHANGED
|
@@ -95,6 +95,28 @@ export const server: Plugin = async (_input, options) => {
|
|
|
95
95
|
// §6.5 LSP — cfg.lsp injection (opt-in via allowLsp; respects cfg.lsp === false).
|
|
96
96
|
const lspSummary = await injectLsp(selected, cfg, bridge.allowLsp, logger)
|
|
97
97
|
|
|
98
|
+
// Remove commands that OpenCode's native Claude integration may have
|
|
99
|
+
// auto-loaded from blocked plugins. Runs after all bridge injection so
|
|
100
|
+
// OpenCode's own loading has had time to run during the async awaits above.
|
|
101
|
+
const selectedIds = new Set(selected.map((p) => p.id))
|
|
102
|
+
const blockedPlugins = all.filter((p) => !selectedIds.has(p.id))
|
|
103
|
+
if (blockedPlugins.length > 0) {
|
|
104
|
+
const mutableCmd = (cfg as unknown as { command?: Record<string, { description?: string }> }).command
|
|
105
|
+
if (mutableCmd && typeof mutableCmd === "object") {
|
|
106
|
+
for (const [name, entry] of Object.entries(mutableCmd)) {
|
|
107
|
+
const desc = entry?.description
|
|
108
|
+
if (typeof desc === "string") {
|
|
109
|
+
for (const bp of blockedPlugins) {
|
|
110
|
+
if (desc.endsWith(`[${bp.id}]`)) {
|
|
111
|
+
delete mutableCmd[name]
|
|
112
|
+
break
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
98
120
|
// §10 concise per-run summary.
|
|
99
121
|
const renamed = cmdAgentSummary.renamed + skillSummary.renamed + mcpSummary.renamed + lspSummary.renamed
|
|
100
122
|
const summaryParts: string[] = [
|
|
@@ -122,6 +144,11 @@ export const server: Plugin = async (_input, options) => {
|
|
|
122
144
|
}
|
|
123
145
|
},
|
|
124
146
|
|
|
147
|
+
"experimental.chat.system.transform": async (input, output) => {
|
|
148
|
+
if (input.sessionID)
|
|
149
|
+
output.system.push(`Session ID: ${input.sessionID}`)
|
|
150
|
+
},
|
|
151
|
+
|
|
125
152
|
"chat.message": async () => {
|
|
126
153
|
// Show a one-time toast on the first chat message if any warnings were emitted
|
|
127
154
|
// during the config hook. The toast is best-effort — a failure must never throw.
|
package/src/logger.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs"
|
|
2
|
+
|
|
1
3
|
/** Thrown when a soft warning is promoted to a hard error under `strict` mode. */
|
|
2
4
|
export class BridgeError extends Error {
|
|
3
5
|
override name = "BridgeError"
|
|
@@ -25,16 +27,29 @@ export interface Logger {
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* @opencode-ai/core is private and not on npm, but the host Bun Worker already
|
|
31
|
-
* executed `import * as Log from "@opencode-ai/core/util/log"` and called
|
|
32
|
-
* `Log.init({ print: ... })`. A dynamic import of the same specifier returns
|
|
33
|
-
* the cached, fully-configured instance — so output correctly goes to stderr
|
|
34
|
-
* (with --print-logs) or the log file (default), with no argv check needed.
|
|
30
|
+
* Detect whether --print-logs was passed to the parent OpenCode process.
|
|
35
31
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
32
|
+
* process.argv is stripped in Bun Workers (only ["bun", "<worker_script>"] is
|
|
33
|
+
* present), so we cannot check it directly. However, Workers run in the same
|
|
34
|
+
* OS process as the host, so /proc/self/cmdline contains the real command line.
|
|
35
|
+
* Falls back to false on non-Linux platforms or if the file is unreadable.
|
|
36
|
+
*/
|
|
37
|
+
function detectPrintLogs(): boolean {
|
|
38
|
+
try {
|
|
39
|
+
const args = readFileSync("/proc/self/cmdline").toString().split("\0")
|
|
40
|
+
return args.includes("--print-logs")
|
|
41
|
+
} catch {
|
|
42
|
+
return false
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const printLogs = detectPrintLogs()
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Try to import @opencode-ai/core/util/log from the host Bun Worker's module
|
|
50
|
+
* registry. If available, its already-initialized logger routes output to
|
|
51
|
+
* stderr (with --print-logs) or the log file (default) without any extra
|
|
52
|
+
* argv inspection. Falls back to null when the module is unavailable.
|
|
38
53
|
*/
|
|
39
54
|
async function resolveCoreLog() {
|
|
40
55
|
try {
|
|
@@ -47,6 +62,7 @@ async function resolveCoreLog() {
|
|
|
47
62
|
const coreLogPromise = resolveCoreLog()
|
|
48
63
|
|
|
49
64
|
function fallbackWrite(level: "INFO" | "WARN", msg: string): void {
|
|
65
|
+
if (!printLogs) return
|
|
50
66
|
const ts = new Date().toISOString().split(".")[0]
|
|
51
67
|
process.stderr.write(`${level.padEnd(5)} ${ts} service=opencode-claude-bridge ${msg}\n`)
|
|
52
68
|
}
|