@aryaminus/controlkeel-opencode 0.2.20 → 0.2.23
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/.opencode/plugins/controlkeel-governance.ts +50 -6
- package/index.js +50 -6
- package/package.json +1 -1
|
@@ -11,11 +11,41 @@ import { tool } from "@opencode-ai/plugin"
|
|
|
11
11
|
* - routes plan submission and wait decisions through the CK CLI
|
|
12
12
|
*/
|
|
13
13
|
export const ControlKeelGovernance: Plugin = async ({ project, client, $, directory }) => {
|
|
14
|
+
const extractJsonCandidate = (output: string) => {
|
|
15
|
+
const trimmed = output.trim()
|
|
16
|
+
if (!trimmed) {
|
|
17
|
+
return null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const lines = trimmed
|
|
21
|
+
.split(/\r?\n/)
|
|
22
|
+
.map((line) => line.trim())
|
|
23
|
+
.filter((line) => line.length > 0)
|
|
24
|
+
|
|
25
|
+
const jsonLine = [...lines].reverse().find((line) => line.startsWith("{") || line.startsWith("["))
|
|
26
|
+
return jsonLine ?? trimmed
|
|
27
|
+
}
|
|
28
|
+
|
|
14
29
|
const parseJson = (output: string) => {
|
|
30
|
+
const trimmed = output.trim()
|
|
31
|
+
if (!trimmed) {
|
|
32
|
+
throw new Error("ControlKeel returned empty output")
|
|
33
|
+
}
|
|
34
|
+
|
|
15
35
|
try {
|
|
16
|
-
return JSON.parse(
|
|
36
|
+
return JSON.parse(trimmed)
|
|
17
37
|
} catch (_error) {
|
|
18
|
-
|
|
38
|
+
const candidate = extractJsonCandidate(trimmed)
|
|
39
|
+
|
|
40
|
+
if (!candidate || candidate === trimmed) {
|
|
41
|
+
throw new Error(`ControlKeel returned invalid JSON: ${output}`)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
return JSON.parse(candidate)
|
|
46
|
+
} catch (_fallbackError) {
|
|
47
|
+
throw new Error(`ControlKeel returned invalid JSON: ${output}`)
|
|
48
|
+
}
|
|
19
49
|
}
|
|
20
50
|
}
|
|
21
51
|
|
|
@@ -156,9 +186,16 @@ export const ControlKeelGovernance: Plugin = async ({ project, client, $, direct
|
|
|
156
186
|
|
|
157
187
|
const submitProc = Bun.spawn(submitArgs, { stdout: "pipe", stderr: "pipe" })
|
|
158
188
|
const submitOut = await new Response(submitProc.stdout).text()
|
|
159
|
-
await submitProc.
|
|
189
|
+
const submitErr = await new Response(submitProc.stderr).text()
|
|
190
|
+
const submitExit = await submitProc.exited
|
|
191
|
+
|
|
192
|
+
if (submitExit !== 0) {
|
|
193
|
+
throw new Error(
|
|
194
|
+
`controlkeel review plan submit failed with exit code ${submitExit}${submitErr.trim() ? `: ${submitErr.trim()}` : ""}`
|
|
195
|
+
)
|
|
196
|
+
}
|
|
160
197
|
|
|
161
|
-
const submitPayload = parseJson(submitOut)
|
|
198
|
+
const submitPayload = parseJson(submitOut || submitErr)
|
|
162
199
|
|
|
163
200
|
if (typeof submitPayload?.error === "string" && submitPayload.error.includes("session_id")) {
|
|
164
201
|
throw new Error(
|
|
@@ -173,9 +210,16 @@ export const ControlKeelGovernance: Plugin = async ({ project, client, $, direct
|
|
|
173
210
|
|
|
174
211
|
const waitProc = Bun.spawn(["controlkeel", "review", "plan", "wait", "--id", String(reviewId), "--timeout", String(waitTimeoutSecondsSafe), "--json"], { stdout: "pipe", stderr: "pipe" })
|
|
175
212
|
const waitOut = await new Response(waitProc.stdout).text()
|
|
176
|
-
await waitProc.
|
|
213
|
+
const waitErr = await new Response(waitProc.stderr).text()
|
|
214
|
+
const waitExit = await waitProc.exited
|
|
215
|
+
|
|
216
|
+
if (waitExit !== 0) {
|
|
217
|
+
throw new Error(
|
|
218
|
+
`controlkeel review plan wait failed with exit code ${waitExit}${waitErr.trim() ? `: ${waitErr.trim()}` : ""}`
|
|
219
|
+
)
|
|
220
|
+
}
|
|
177
221
|
|
|
178
|
-
const waitPayload = parseJson(waitOut)
|
|
222
|
+
const waitPayload = parseJson(waitOut || waitErr)
|
|
179
223
|
return {
|
|
180
224
|
reviewId,
|
|
181
225
|
submitPayload,
|
package/index.js
CHANGED
|
@@ -7,11 +7,41 @@ import { tool } from "@opencode-ai/plugin"
|
|
|
7
7
|
* but ships as plain JavaScript for npm-based installs.
|
|
8
8
|
*/
|
|
9
9
|
export const ControlKeelGovernance = async ({ $, directory }) => {
|
|
10
|
+
const extractJsonCandidate = (output) => {
|
|
11
|
+
const trimmed = output.trim()
|
|
12
|
+
if (!trimmed) {
|
|
13
|
+
return null
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const lines = trimmed
|
|
17
|
+
.split(/\r?\n/)
|
|
18
|
+
.map((line) => line.trim())
|
|
19
|
+
.filter((line) => line.length > 0)
|
|
20
|
+
|
|
21
|
+
const jsonLine = [...lines].reverse().find((line) => line.startsWith("{") || line.startsWith("["))
|
|
22
|
+
return jsonLine ?? trimmed
|
|
23
|
+
}
|
|
24
|
+
|
|
10
25
|
const parseJson = (output) => {
|
|
26
|
+
const trimmed = output.trim()
|
|
27
|
+
if (!trimmed) {
|
|
28
|
+
throw new Error("ControlKeel returned empty output")
|
|
29
|
+
}
|
|
30
|
+
|
|
11
31
|
try {
|
|
12
|
-
return JSON.parse(
|
|
32
|
+
return JSON.parse(trimmed)
|
|
13
33
|
} catch (_error) {
|
|
14
|
-
|
|
34
|
+
const candidate = extractJsonCandidate(trimmed)
|
|
35
|
+
|
|
36
|
+
if (!candidate || candidate === trimmed) {
|
|
37
|
+
throw new Error(`ControlKeel returned invalid JSON: ${output}`)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
return JSON.parse(candidate)
|
|
42
|
+
} catch (_fallbackError) {
|
|
43
|
+
throw new Error(`ControlKeel returned invalid JSON: ${output}`)
|
|
44
|
+
}
|
|
15
45
|
}
|
|
16
46
|
}
|
|
17
47
|
|
|
@@ -144,9 +174,16 @@ export const ControlKeelGovernance = async ({ $, directory }) => {
|
|
|
144
174
|
|
|
145
175
|
const submitProc = Bun.spawn(submitArgs, { stdout: "pipe", stderr: "pipe" })
|
|
146
176
|
const submitOut = await new Response(submitProc.stdout).text()
|
|
147
|
-
await submitProc.
|
|
177
|
+
const submitErr = await new Response(submitProc.stderr).text()
|
|
178
|
+
const submitExit = await submitProc.exited
|
|
179
|
+
|
|
180
|
+
if (submitExit !== 0) {
|
|
181
|
+
throw new Error(
|
|
182
|
+
`controlkeel review plan submit failed with exit code ${submitExit}${submitErr.trim() ? `: ${submitErr.trim()}` : ""}`
|
|
183
|
+
)
|
|
184
|
+
}
|
|
148
185
|
|
|
149
|
-
const submitPayload = parseJson(submitOut)
|
|
186
|
+
const submitPayload = parseJson(submitOut || submitErr)
|
|
150
187
|
|
|
151
188
|
if (typeof submitPayload?.error === "string" && submitPayload.error.includes("session_id")) {
|
|
152
189
|
throw new Error(
|
|
@@ -161,9 +198,16 @@ export const ControlKeelGovernance = async ({ $, directory }) => {
|
|
|
161
198
|
|
|
162
199
|
const waitProc = Bun.spawn(["controlkeel", "review", "plan", "wait", "--id", String(reviewId), "--timeout", String(waitTimeoutSecondsSafe), "--json"], { stdout: "pipe", stderr: "pipe" })
|
|
163
200
|
const waitOut = await new Response(waitProc.stdout).text()
|
|
164
|
-
await waitProc.
|
|
201
|
+
const waitErr = await new Response(waitProc.stderr).text()
|
|
202
|
+
const waitExit = await waitProc.exited
|
|
203
|
+
|
|
204
|
+
if (waitExit !== 0) {
|
|
205
|
+
throw new Error(
|
|
206
|
+
`controlkeel review plan wait failed with exit code ${waitExit}${waitErr.trim() ? `: ${waitErr.trim()}` : ""}`
|
|
207
|
+
)
|
|
208
|
+
}
|
|
165
209
|
|
|
166
|
-
const waitPayload = parseJson(waitOut)
|
|
210
|
+
const waitPayload = parseJson(waitOut || waitErr)
|
|
167
211
|
return {
|
|
168
212
|
reviewId,
|
|
169
213
|
submitPayload,
|
package/package.json
CHANGED