@aryaminus/controlkeel-opencode 0.2.45 → 0.2.46
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.
|
@@ -10,7 +10,7 @@ Recommended flow:
|
|
|
10
10
|
3. Run `controlkeel review plan submit --body-file .opencode/review-plan.md --submitted-by opencode --task-id <task_id> --json` (or use `--session-id <session_id>`)
|
|
11
11
|
4. Read the returned `review.id` and `browser_url`
|
|
12
12
|
5. If `browser_url` is available, wait with `controlkeel review plan wait --id <review_id> --timeout 30 --json`
|
|
13
|
-
6. If `browser_url` is missing/unreachable **or** wait times out while still `pending`, do **not** loop on wait; ask for explicit user approval in chat and record it with `controlkeel review plan respond --id <review_id> --decision approved --feedback-notes "User approved in chat; browser unavailable or timed out" --json` (or `ck_review_feedback`)
|
|
13
|
+
6. If `browser_url` is missing/unreachable, the browser does not actually open, **or** wait times out while still `pending`, do **not** loop on wait; ask for explicit user approval in chat and record it with `controlkeel review plan respond --id <review_id> --decision approved --feedback-notes "User approved in chat; browser unavailable or timed out" --json` (or `ck_review_feedback`)
|
|
14
14
|
7. Do not execute until the review is approved
|
|
15
15
|
|
|
16
16
|
Fallback when the `submit_plan` tool is stale in a long-running OpenCode session:
|
|
@@ -343,29 +343,42 @@ export const ControlKeelGovernance: Plugin = async ({ project, client, $, direct
|
|
|
343
343
|
submitPayload?.review?.browser_url ??
|
|
344
344
|
null
|
|
345
345
|
|
|
346
|
+
const buildPlanResult = (overrides = {}) => ({
|
|
347
|
+
reviewId,
|
|
348
|
+
browserUrl: overrides.browserUrl ?? browserUrl,
|
|
349
|
+
status: overrides.status ?? submitPayload?.review?.status ?? "pending",
|
|
350
|
+
feedbackNotes:
|
|
351
|
+
overrides.feedbackNotes ?? submitPayload?.review?.feedback_notes ?? null,
|
|
352
|
+
opened: overrides.opened ?? (openPayload?.opened === true),
|
|
353
|
+
timedOut: overrides.timedOut ?? false,
|
|
354
|
+
waitSkipped: overrides.waitSkipped ?? false,
|
|
355
|
+
manualApprovalRequired: overrides.manualApprovalRequired ?? false,
|
|
356
|
+
reason: overrides.reason ?? null,
|
|
357
|
+
guidance: overrides.guidance ?? null,
|
|
358
|
+
})
|
|
359
|
+
|
|
346
360
|
const openError = typeof openPayload?.open_error === "string" ? openPayload.open_error.trim() : ""
|
|
347
361
|
const openFailure = typeof openPayload?.error === "string" ? openPayload.error.trim() : ""
|
|
362
|
+
const browserNotOpened = openPayload?.opened !== true
|
|
348
363
|
|
|
349
364
|
const remoteLocalhostMismatch =
|
|
350
365
|
typeof browserUrl === "string" &&
|
|
351
366
|
browserUrl.includes("localhost") &&
|
|
352
367
|
openPayload?.remote === true
|
|
353
368
|
|
|
354
|
-
if (!browserUrl || openError || openFailure || remoteLocalhostMismatch) {
|
|
355
|
-
return {
|
|
356
|
-
reviewId,
|
|
357
|
-
submitPayload,
|
|
358
|
-
openPayload,
|
|
359
|
-
browserUrl,
|
|
360
|
-
status: submitPayload?.review?.status ?? "pending",
|
|
361
|
-
feedbackNotes: submitPayload?.review?.feedback_notes ?? null,
|
|
362
|
-
timedOut: false,
|
|
369
|
+
if (!browserUrl || openError || openFailure || remoteLocalhostMismatch || browserNotOpened) {
|
|
370
|
+
return buildPlanResult({
|
|
363
371
|
waitSkipped: true,
|
|
364
372
|
manualApprovalRequired: true,
|
|
365
|
-
reason:
|
|
373
|
+
reason:
|
|
374
|
+
!browserUrl
|
|
375
|
+
? "browser_url_unavailable"
|
|
376
|
+
: browserNotOpened
|
|
377
|
+
? "browser_not_opened"
|
|
378
|
+
: "browser_unreachable",
|
|
366
379
|
guidance:
|
|
367
|
-
"Browser review is unavailable from this environment. Ask the user for explicit approval in chat, then record it with `controlkeel review plan respond --id <review_id> --decision approved --feedback-notes \"User approved in chat; browser unavailable\" --json` or `ck_review_feedback`.",
|
|
368
|
-
}
|
|
380
|
+
"Browser review is unavailable from this environment or did not actually open. Ask the user for explicit approval in chat, then record it with `controlkeel review plan respond --id <review_id> --decision approved --feedback-notes \"User approved in chat; browser unavailable\" --json` or `ck_review_feedback`.",
|
|
381
|
+
})
|
|
369
382
|
}
|
|
370
383
|
|
|
371
384
|
const waitEnv = process.env.LOGGER_LEVEL
|
|
@@ -388,10 +401,7 @@ export const ControlKeelGovernance: Plugin = async ({ project, client, $, direct
|
|
|
388
401
|
|
|
389
402
|
if (waitExit !== 0) {
|
|
390
403
|
if (waitTimedOut && waitPending) {
|
|
391
|
-
return {
|
|
392
|
-
reviewId,
|
|
393
|
-
submitPayload,
|
|
394
|
-
waitPayload,
|
|
404
|
+
return buildPlanResult({
|
|
395
405
|
browserUrl: waitPayload?.browser_url ?? submitPayload?.browser_url,
|
|
396
406
|
status: "pending",
|
|
397
407
|
feedbackNotes: waitPayload?.review?.feedback_notes ?? null,
|
|
@@ -401,7 +411,7 @@ export const ControlKeelGovernance: Plugin = async ({ project, client, $, direct
|
|
|
401
411
|
reason: "review_timeout",
|
|
402
412
|
guidance:
|
|
403
413
|
"Plan review is still pending after timeout. Show the `browser_url` to the user if reachable. If browser review is unavailable or the user explicitly approves in chat, record it with `controlkeel review plan respond --id <review_id> --decision approved --feedback-notes \"User approved in chat after timeout/browser issue\" --json` (or `ck_review_feedback`) before proceeding.",
|
|
404
|
-
}
|
|
414
|
+
})
|
|
405
415
|
}
|
|
406
416
|
|
|
407
417
|
throw new Error(
|
|
@@ -409,17 +419,13 @@ export const ControlKeelGovernance: Plugin = async ({ project, client, $, direct
|
|
|
409
419
|
)
|
|
410
420
|
}
|
|
411
421
|
|
|
412
|
-
return {
|
|
413
|
-
reviewId,
|
|
414
|
-
submitPayload,
|
|
415
|
-
openPayload,
|
|
416
|
-
waitPayload,
|
|
422
|
+
return buildPlanResult({
|
|
417
423
|
browserUrl: waitPayload?.browser_url ?? browserUrl,
|
|
418
424
|
status: waitPayload?.review?.status,
|
|
419
425
|
feedbackNotes: waitPayload?.review?.feedback_notes ?? null,
|
|
420
426
|
waitSkipped: false,
|
|
421
427
|
manualApprovalRequired: false,
|
|
422
|
-
}
|
|
428
|
+
})
|
|
423
429
|
} finally {
|
|
424
430
|
// Clean up temp file
|
|
425
431
|
try { await Bun.file(tmpFile).unlink?.() ?? (await $`rm -f ${tmpFile}`.quiet()) } catch {}
|
|
@@ -479,7 +485,7 @@ export const ControlKeelGovernance: Plugin = async ({ project, client, $, direct
|
|
|
479
485
|
args.task_id,
|
|
480
486
|
args.session_id
|
|
481
487
|
)
|
|
482
|
-
return JSON.stringify(result
|
|
488
|
+
return JSON.stringify(result)
|
|
483
489
|
},
|
|
484
490
|
}),
|
|
485
491
|
},
|
package/index.js
CHANGED
|
@@ -326,29 +326,42 @@ export const ControlKeelGovernance = async ({ $, directory }) => {
|
|
|
326
326
|
submitPayload?.review?.browser_url ??
|
|
327
327
|
null
|
|
328
328
|
|
|
329
|
+
const buildPlanResult = (overrides = {}) => ({
|
|
330
|
+
reviewId,
|
|
331
|
+
browserUrl: overrides.browserUrl ?? browserUrl,
|
|
332
|
+
status: overrides.status ?? submitPayload?.review?.status ?? "pending",
|
|
333
|
+
feedbackNotes:
|
|
334
|
+
overrides.feedbackNotes ?? submitPayload?.review?.feedback_notes ?? null,
|
|
335
|
+
opened: overrides.opened ?? (openPayload?.opened === true),
|
|
336
|
+
timedOut: overrides.timedOut ?? false,
|
|
337
|
+
waitSkipped: overrides.waitSkipped ?? false,
|
|
338
|
+
manualApprovalRequired: overrides.manualApprovalRequired ?? false,
|
|
339
|
+
reason: overrides.reason ?? null,
|
|
340
|
+
guidance: overrides.guidance ?? null,
|
|
341
|
+
})
|
|
342
|
+
|
|
329
343
|
const openError = typeof openPayload?.open_error === "string" ? openPayload.open_error.trim() : ""
|
|
330
344
|
const openFailure = typeof openPayload?.error === "string" ? openPayload.error.trim() : ""
|
|
345
|
+
const browserNotOpened = openPayload?.opened !== true
|
|
331
346
|
|
|
332
347
|
const remoteLocalhostMismatch =
|
|
333
348
|
typeof browserUrl === "string" &&
|
|
334
349
|
browserUrl.includes("localhost") &&
|
|
335
350
|
openPayload?.remote === true
|
|
336
351
|
|
|
337
|
-
if (!browserUrl || openError || openFailure || remoteLocalhostMismatch) {
|
|
338
|
-
return {
|
|
339
|
-
reviewId,
|
|
340
|
-
submitPayload,
|
|
341
|
-
openPayload,
|
|
342
|
-
browserUrl,
|
|
343
|
-
status: submitPayload?.review?.status ?? "pending",
|
|
344
|
-
feedbackNotes: submitPayload?.review?.feedback_notes ?? null,
|
|
345
|
-
timedOut: false,
|
|
352
|
+
if (!browserUrl || openError || openFailure || remoteLocalhostMismatch || browserNotOpened) {
|
|
353
|
+
return buildPlanResult({
|
|
346
354
|
waitSkipped: true,
|
|
347
355
|
manualApprovalRequired: true,
|
|
348
|
-
reason:
|
|
356
|
+
reason:
|
|
357
|
+
!browserUrl
|
|
358
|
+
? "browser_url_unavailable"
|
|
359
|
+
: browserNotOpened
|
|
360
|
+
? "browser_not_opened"
|
|
361
|
+
: "browser_unreachable",
|
|
349
362
|
guidance:
|
|
350
|
-
"Browser review is unavailable from this environment. Ask the user for explicit approval in chat, then record it with `controlkeel review plan respond --id <review_id> --decision approved --feedback-notes \"User approved in chat; browser unavailable\" --json` or `ck_review_feedback`.",
|
|
351
|
-
}
|
|
363
|
+
"Browser review is unavailable from this environment or did not actually open. Ask the user for explicit approval in chat, then record it with `controlkeel review plan respond --id <review_id> --decision approved --feedback-notes \"User approved in chat; browser unavailable\" --json` or `ck_review_feedback`.",
|
|
364
|
+
})
|
|
352
365
|
}
|
|
353
366
|
|
|
354
367
|
const waitEnv = process.env.LOGGER_LEVEL
|
|
@@ -371,10 +384,7 @@ export const ControlKeelGovernance = async ({ $, directory }) => {
|
|
|
371
384
|
|
|
372
385
|
if (waitExit !== 0) {
|
|
373
386
|
if (waitTimedOut && waitPending) {
|
|
374
|
-
return {
|
|
375
|
-
reviewId,
|
|
376
|
-
submitPayload,
|
|
377
|
-
waitPayload,
|
|
387
|
+
return buildPlanResult({
|
|
378
388
|
browserUrl: waitPayload?.browser_url ?? submitPayload?.browser_url,
|
|
379
389
|
status: "pending",
|
|
380
390
|
feedbackNotes: waitPayload?.review?.feedback_notes ?? null,
|
|
@@ -384,7 +394,7 @@ export const ControlKeelGovernance = async ({ $, directory }) => {
|
|
|
384
394
|
reason: "review_timeout",
|
|
385
395
|
guidance:
|
|
386
396
|
"Plan review is still pending after timeout. Show the `browser_url` to the user if reachable. If browser review is unavailable or the user explicitly approves in chat, record it with `controlkeel review plan respond --id <review_id> --decision approved --feedback-notes \"User approved in chat after timeout/browser issue\" --json` (or `ck_review_feedback`) before proceeding.",
|
|
387
|
-
}
|
|
397
|
+
})
|
|
388
398
|
}
|
|
389
399
|
|
|
390
400
|
throw new Error(
|
|
@@ -392,17 +402,13 @@ export const ControlKeelGovernance = async ({ $, directory }) => {
|
|
|
392
402
|
)
|
|
393
403
|
}
|
|
394
404
|
|
|
395
|
-
return {
|
|
396
|
-
reviewId,
|
|
397
|
-
submitPayload,
|
|
398
|
-
openPayload,
|
|
399
|
-
waitPayload,
|
|
405
|
+
return buildPlanResult({
|
|
400
406
|
browserUrl: waitPayload?.browser_url ?? browserUrl,
|
|
401
407
|
status: waitPayload?.review?.status,
|
|
402
408
|
feedbackNotes: waitPayload?.review?.feedback_notes ?? null,
|
|
403
409
|
waitSkipped: false,
|
|
404
410
|
manualApprovalRequired: false,
|
|
405
|
-
}
|
|
411
|
+
})
|
|
406
412
|
} finally {
|
|
407
413
|
// Clean up temp file
|
|
408
414
|
try { await Bun.file(tmpFile).unlink?.() ?? (await $`rm -f ${tmpFile}`.quiet()) } catch {}
|
|
@@ -462,7 +468,7 @@ export const ControlKeelGovernance = async ({ $, directory }) => {
|
|
|
462
468
|
args.task_id,
|
|
463
469
|
args.session_id
|
|
464
470
|
)
|
|
465
|
-
return JSON.stringify(result
|
|
471
|
+
return JSON.stringify(result)
|
|
466
472
|
},
|
|
467
473
|
}),
|
|
468
474
|
},
|
package/package.json
CHANGED