backeer-opencode 0.3.0 → 0.3.1
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 +9 -0
- package/dist/backeer-permission.js +44 -4
- package/package.json +1 -1
- package/src/permission-controller.js +53 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `backeer-opencode` are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.3.1 - 2026-09-01
|
|
6
|
+
|
|
7
|
+
- Apply remote question replies on OpenCode 1.18.x even when the plugin-provided
|
|
8
|
+
client does not expose the legacy or v2 question helpers, by falling back to
|
|
9
|
+
OpenCode's underlying authenticated HTTP transport.
|
|
10
|
+
- Normalize native API failures so Backeer receives an accurate terminal ACK
|
|
11
|
+
instead of reporting success for an error response.
|
|
12
|
+
- Add regression coverage for legacy, v2, and error question reply paths.
|
|
13
|
+
|
|
5
14
|
## 0.3.0 - 2026-09-01
|
|
6
15
|
|
|
7
16
|
- Publish structured `question.asked` and `question.v2.asked` action metadata.
|
|
@@ -1807,13 +1807,46 @@ async function acknowledgeCommand(config, commandID, acknowledgement) {
|
|
|
1807
1807
|
);
|
|
1808
1808
|
await postJsonWithRetry(config, url, acknowledgement);
|
|
1809
1809
|
}
|
|
1810
|
+
function questionResponseError(result) {
|
|
1811
|
+
if (!result?.error) return;
|
|
1812
|
+
const status = Number(result?.response?.status) || 502;
|
|
1813
|
+
const detail = result.error?.data?.message ?? result.error?.message ?? "OpenCode rejected the question response";
|
|
1814
|
+
return new HttpError(String(detail), status);
|
|
1815
|
+
}
|
|
1816
|
+
function normalizeQuestionError(error) {
|
|
1817
|
+
if (error instanceof HttpError) return error;
|
|
1818
|
+
const status = Number(error?.status ?? error?.statusCode ?? error?.cause?.status);
|
|
1819
|
+
if (!Number.isFinite(status)) return error;
|
|
1820
|
+
return new HttpError(error?.message || "OpenCode rejected the question response", status);
|
|
1821
|
+
}
|
|
1822
|
+
function rawQuestionRequest(client, pending, response, isV2) {
|
|
1823
|
+
const transport = client?._client;
|
|
1824
|
+
if (typeof transport?.post !== "function") {
|
|
1825
|
+
throw new HttpError("This OpenCode version cannot apply remote question replies", 501);
|
|
1826
|
+
}
|
|
1827
|
+
const rejecting = response.action === "reject";
|
|
1828
|
+
if (isV2) {
|
|
1829
|
+
return transport.post({
|
|
1830
|
+
url: `/api/session/{sessionID}/question/{requestID}/${rejecting ? "reject" : "reply"}`,
|
|
1831
|
+
path: { sessionID: pending.sessionID, requestID: pending.requestID },
|
|
1832
|
+
...rejecting ? {} : { body: { answers: response.answers } },
|
|
1833
|
+
...rejecting ? {} : { headers: { "Content-Type": "application/json" } },
|
|
1834
|
+
throwOnError: true
|
|
1835
|
+
});
|
|
1836
|
+
}
|
|
1837
|
+
return transport.post({
|
|
1838
|
+
url: `/question/{requestID}/${rejecting ? "reject" : "reply"}`,
|
|
1839
|
+
path: { requestID: pending.requestID },
|
|
1840
|
+
query: { directory: pending.directory },
|
|
1841
|
+
...rejecting ? {} : { body: { answers: response.answers } },
|
|
1842
|
+
...rejecting ? {} : { headers: { "Content-Type": "application/json" } },
|
|
1843
|
+
throwOnError: true
|
|
1844
|
+
});
|
|
1845
|
+
}
|
|
1810
1846
|
async function replyToQuestion(client, pending, response) {
|
|
1811
1847
|
const isV2 = pending.sourceEvent === "question.v2.asked";
|
|
1812
1848
|
const api = isV2 ? client?.v2?.session?.question : client?.question;
|
|
1813
1849
|
const method = response.action === "reject" ? api?.reject : api?.reply;
|
|
1814
|
-
if (typeof method !== "function") {
|
|
1815
|
-
throw new HttpError("This OpenCode version cannot apply remote question replies", 501);
|
|
1816
|
-
}
|
|
1817
1850
|
const input = isV2 ? {
|
|
1818
1851
|
sessionID: pending.sessionID,
|
|
1819
1852
|
requestID: pending.requestID,
|
|
@@ -1824,7 +1857,14 @@ async function replyToQuestion(client, pending, response) {
|
|
|
1824
1857
|
directory: pending.directory,
|
|
1825
1858
|
...response.action === "answer" ? { answers: response.answers } : {}
|
|
1826
1859
|
};
|
|
1827
|
-
|
|
1860
|
+
let result;
|
|
1861
|
+
try {
|
|
1862
|
+
result = typeof method === "function" ? await method.call(api, input, { throwOnError: true }) : await rawQuestionRequest(client, pending, response, isV2);
|
|
1863
|
+
} catch (error) {
|
|
1864
|
+
throw normalizeQuestionError(error);
|
|
1865
|
+
}
|
|
1866
|
+
const responseError = questionResponseError(result);
|
|
1867
|
+
if (responseError) throw responseError;
|
|
1828
1868
|
if (result?.data === false || result === false) {
|
|
1829
1869
|
throw new HttpError("OpenCode did not apply the question response", 409);
|
|
1830
1870
|
}
|
package/package.json
CHANGED
|
@@ -33,13 +33,52 @@ async function acknowledgeCommand(config, commandID, acknowledgement) {
|
|
|
33
33
|
await postJsonWithRetry(config, url, acknowledgement)
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
function questionResponseError(result) {
|
|
37
|
+
if (!result?.error) return
|
|
38
|
+
const status = Number(result?.response?.status) || 502
|
|
39
|
+
const detail = result.error?.data?.message
|
|
40
|
+
?? result.error?.message
|
|
41
|
+
?? "OpenCode rejected the question response"
|
|
42
|
+
return new HttpError(String(detail), status)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function normalizeQuestionError(error) {
|
|
46
|
+
if (error instanceof HttpError) return error
|
|
47
|
+
const status = Number(error?.status ?? error?.statusCode ?? error?.cause?.status)
|
|
48
|
+
if (!Number.isFinite(status)) return error
|
|
49
|
+
return new HttpError(error?.message || "OpenCode rejected the question response", status)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function rawQuestionRequest(client, pending, response, isV2) {
|
|
53
|
+
const transport = client?._client
|
|
54
|
+
if (typeof transport?.post !== "function") {
|
|
55
|
+
throw new HttpError("This OpenCode version cannot apply remote question replies", 501)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const rejecting = response.action === "reject"
|
|
59
|
+
if (isV2) {
|
|
60
|
+
return transport.post({
|
|
61
|
+
url: `/api/session/{sessionID}/question/{requestID}/${rejecting ? "reject" : "reply"}`,
|
|
62
|
+
path: { sessionID: pending.sessionID, requestID: pending.requestID },
|
|
63
|
+
...(rejecting ? {} : { body: { answers: response.answers } }),
|
|
64
|
+
...(rejecting ? {} : { headers: { "Content-Type": "application/json" } }),
|
|
65
|
+
throwOnError: true,
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
return transport.post({
|
|
69
|
+
url: `/question/{requestID}/${rejecting ? "reject" : "reply"}`,
|
|
70
|
+
path: { requestID: pending.requestID },
|
|
71
|
+
query: { directory: pending.directory },
|
|
72
|
+
...(rejecting ? {} : { body: { answers: response.answers } }),
|
|
73
|
+
...(rejecting ? {} : { headers: { "Content-Type": "application/json" } }),
|
|
74
|
+
throwOnError: true,
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export async function replyToQuestion(client, pending, response) {
|
|
37
79
|
const isV2 = pending.sourceEvent === "question.v2.asked"
|
|
38
80
|
const api = isV2 ? client?.v2?.session?.question : client?.question
|
|
39
81
|
const method = response.action === "reject" ? api?.reject : api?.reply
|
|
40
|
-
if (typeof method !== "function") {
|
|
41
|
-
throw new HttpError("This OpenCode version cannot apply remote question replies", 501)
|
|
42
|
-
}
|
|
43
82
|
const input = isV2
|
|
44
83
|
? {
|
|
45
84
|
sessionID: pending.sessionID,
|
|
@@ -54,7 +93,16 @@ async function replyToQuestion(client, pending, response) {
|
|
|
54
93
|
directory: pending.directory,
|
|
55
94
|
...(response.action === "answer" ? { answers: response.answers } : {}),
|
|
56
95
|
}
|
|
57
|
-
|
|
96
|
+
let result
|
|
97
|
+
try {
|
|
98
|
+
result = typeof method === "function"
|
|
99
|
+
? await method.call(api, input, { throwOnError: true })
|
|
100
|
+
: await rawQuestionRequest(client, pending, response, isV2)
|
|
101
|
+
} catch (error) {
|
|
102
|
+
throw normalizeQuestionError(error)
|
|
103
|
+
}
|
|
104
|
+
const responseError = questionResponseError(result)
|
|
105
|
+
if (responseError) throw responseError
|
|
58
106
|
if (result?.data === false || result === false) {
|
|
59
107
|
throw new HttpError("OpenCode did not apply the question response", 409)
|
|
60
108
|
}
|