@defend-tech/opencode-optima 0.1.51 → 0.1.53
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/dist/index.js +58 -69
- package/dist/sanitize_cli.js +58 -69
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9648,23 +9648,16 @@ function extractOpenCodeSessionId(result) {
|
|
|
9648
9648
|
return data?.id || data?.sessionID || data?.sessionId || result?.id || result?.sessionID || result?.sessionId;
|
|
9649
9649
|
}
|
|
9650
9650
|
async function createOpenCodeSession(client, { title, directory, agent } = {}) {
|
|
9651
|
-
const flatPayload = { directory, title };
|
|
9652
|
-
if (agent) flatPayload.agent = agent;
|
|
9653
9651
|
const body = { title };
|
|
9654
9652
|
if (agent) body.agent = agent;
|
|
9655
|
-
|
|
9656
|
-
|
|
9657
|
-
|
|
9658
|
-
|
|
9659
|
-
|
|
9660
|
-
|
|
9661
|
-
|
|
9662
|
-
firstError ??= new Error("OpenCode session create response did not include a session id.");
|
|
9663
|
-
} catch (error) {
|
|
9664
|
-
firstError ??= error;
|
|
9665
|
-
}
|
|
9653
|
+
try {
|
|
9654
|
+
const result = await client.session.create({ query: { directory }, body });
|
|
9655
|
+
const sessionId = extractOpenCodeSessionId(result);
|
|
9656
|
+
if (sessionId) return sessionId;
|
|
9657
|
+
throw new Error("OpenCode session create response did not include a session id.");
|
|
9658
|
+
} catch (error) {
|
|
9659
|
+
throw error || new Error("OpenCode session create failed.");
|
|
9666
9660
|
}
|
|
9667
|
-
throw firstError || new Error("OpenCode session create failed.");
|
|
9668
9661
|
}
|
|
9669
9662
|
async function waitForOpenCodeReadiness(client, { worktree = process.cwd(), attempts = 10, delayMs = 500, now = () => /* @__PURE__ */ new Date() } = {}) {
|
|
9670
9663
|
if (typeof client?.session?.create !== "function") return { ok: true, skipped: true, reason: "session_create_probe_unavailable" };
|
|
@@ -9767,9 +9760,19 @@ async function sendOpenCodeSessionEventDirect({ baseUrl, sessionId, text, agent,
|
|
|
9767
9760
|
}
|
|
9768
9761
|
throw firstError || new Error("OpenCode direct prompt delivery failed.");
|
|
9769
9762
|
}
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9763
|
+
function tagOpenCodePromptResult(result, deliveryMethod) {
|
|
9764
|
+
if (result && typeof result === "object") {
|
|
9765
|
+
try {
|
|
9766
|
+
Object.defineProperty(result, "__optimaPromptDelivery", { value: deliveryMethod, enumerable: false, configurable: true });
|
|
9767
|
+
} catch {
|
|
9768
|
+
return { result, __optimaPromptDelivery: deliveryMethod };
|
|
9769
|
+
}
|
|
9770
|
+
}
|
|
9771
|
+
return result;
|
|
9772
|
+
}
|
|
9773
|
+
async function callOpenCodePromptWithFallbacks(method, sessionId, flatPayload, structuredPayload, deliveryMethod) {
|
|
9774
|
+
const attempts = deliveryMethod === "prompt" ? [structuredPayload] : [
|
|
9775
|
+
structuredPayload,
|
|
9773
9776
|
{ ...structuredPayload, path: { sessionID: sessionId } },
|
|
9774
9777
|
{ sessionID: sessionId, ...flatPayload },
|
|
9775
9778
|
{ id: sessionId, ...flatPayload }
|
|
@@ -9777,14 +9780,14 @@ async function callOpenCodePromptWithFallbacks(method, sessionId, flatPayload, s
|
|
|
9777
9780
|
let firstError = null;
|
|
9778
9781
|
for (const attempt of attempts) {
|
|
9779
9782
|
try {
|
|
9780
|
-
return assertOpenCodePromptAccepted(await method(attempt));
|
|
9783
|
+
return tagOpenCodePromptResult(assertOpenCodePromptAccepted(await method(attempt)), deliveryMethod);
|
|
9781
9784
|
} catch (error) {
|
|
9782
9785
|
firstError ??= error;
|
|
9783
9786
|
}
|
|
9784
9787
|
}
|
|
9785
9788
|
throw firstError;
|
|
9786
9789
|
}
|
|
9787
|
-
async function sendOpenCodeSessionEvent(client, { sessionId, agent, text, directory, opencodeBaseUrl, baseUrl, fetchImpl, direct = false, legacyOnly = false } = {}) {
|
|
9790
|
+
async function sendOpenCodeSessionEvent(client, { sessionId, agent, text, directory, opencodeBaseUrl, baseUrl, fetchImpl, direct = false, legacyOnly = false, allowDirectFallback = true } = {}) {
|
|
9788
9791
|
const directBaseUrl = opencodeBaseUrl || baseUrl;
|
|
9789
9792
|
const parts = [{ type: "text", text }];
|
|
9790
9793
|
const flatPayload = { directory, agent, parts };
|
|
@@ -9794,21 +9797,21 @@ async function sendOpenCodeSessionEvent(client, { sessionId, agent, text, direct
|
|
|
9794
9797
|
body: { agent, parts }
|
|
9795
9798
|
};
|
|
9796
9799
|
let firstError = null;
|
|
9797
|
-
if (!direct && typeof client?.session?.
|
|
9800
|
+
if (!direct && typeof client?.session?.prompt === "function") {
|
|
9798
9801
|
try {
|
|
9799
|
-
return await callOpenCodePromptWithFallbacks(client.session.
|
|
9802
|
+
return await callOpenCodePromptWithFallbacks(client.session.prompt.bind(client.session), sessionId, flatPayload, structuredPayload, "prompt");
|
|
9800
9803
|
} catch (error) {
|
|
9801
9804
|
firstError ??= error;
|
|
9802
9805
|
}
|
|
9803
9806
|
}
|
|
9804
|
-
if (!direct && typeof client?.session?.
|
|
9807
|
+
if (!direct && typeof client?.session?.promptAsync === "function") {
|
|
9805
9808
|
try {
|
|
9806
|
-
return await callOpenCodePromptWithFallbacks(client.session.
|
|
9809
|
+
return await callOpenCodePromptWithFallbacks(client.session.promptAsync.bind(client.session), sessionId, flatPayload, structuredPayload, "prompt_async");
|
|
9807
9810
|
} catch (error) {
|
|
9808
9811
|
firstError ??= error;
|
|
9809
9812
|
}
|
|
9810
9813
|
}
|
|
9811
|
-
if (directBaseUrl) return sendOpenCodeSessionEventDirect({ baseUrl: directBaseUrl, sessionId, text, agent, directory, fetchImpl, legacyOnly });
|
|
9814
|
+
if (allowDirectFallback && directBaseUrl) return sendOpenCodeSessionEventDirect({ baseUrl: directBaseUrl, sessionId, text, agent, directory, fetchImpl, legacyOnly });
|
|
9812
9815
|
if (firstError) throw firstError;
|
|
9813
9816
|
throw new Error("OpenCode client does not expose session.prompt or session.promptAsync.");
|
|
9814
9817
|
}
|
|
@@ -9819,23 +9822,11 @@ function normalizeOpenCodeSessionMessages(result) {
|
|
|
9819
9822
|
if (Array.isArray(data?.items)) return [...data.items];
|
|
9820
9823
|
return [];
|
|
9821
9824
|
}
|
|
9822
|
-
async function readOpenCodeSessionMessages(client, { sessionId, limit = 20 } = {}) {
|
|
9825
|
+
async function readOpenCodeSessionMessages(client, { sessionId, directory, limit = 20 } = {}) {
|
|
9823
9826
|
if (typeof client?.session?.messages !== "function") return null;
|
|
9824
|
-
const
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
{ sessionID: sessionId, limit },
|
|
9828
|
-
{ id: sessionId, limit }
|
|
9829
|
-
];
|
|
9830
|
-
let firstError = null;
|
|
9831
|
-
for (const attempt of attempts) {
|
|
9832
|
-
try {
|
|
9833
|
-
return normalizeOpenCodeSessionMessages(await client.session.messages(attempt));
|
|
9834
|
-
} catch (error) {
|
|
9835
|
-
firstError ??= error;
|
|
9836
|
-
}
|
|
9837
|
-
}
|
|
9838
|
-
throw firstError;
|
|
9827
|
+
const query = { limit };
|
|
9828
|
+
if (directory) query.directory = directory;
|
|
9829
|
+
return normalizeOpenCodeSessionMessages(await client.session.messages({ path: { id: sessionId }, query }));
|
|
9839
9830
|
}
|
|
9840
9831
|
function openCodeMessageText(message) {
|
|
9841
9832
|
const parts = [message?.text, message?.content, message?.message, message?.body?.text, message?.data?.text];
|
|
@@ -9848,11 +9839,11 @@ function openCodeMessageStableKey(message, index = 0) {
|
|
|
9848
9839
|
if (id) return `id:${id}`;
|
|
9849
9840
|
return `idx:${index}:text:${openCodeMessageText(message)}`;
|
|
9850
9841
|
}
|
|
9851
|
-
async function verifyOpenCodeSessionEventDelivery(client, { sessionId, beforeMessages = null, expectedText = "", markers = [], attempts = 8, delayMs = 250 } = {}) {
|
|
9842
|
+
async function verifyOpenCodeSessionEventDelivery(client, { sessionId, directory, beforeMessages = null, expectedText = "", markers = [], attempts = 8, delayMs = 250 } = {}) {
|
|
9852
9843
|
let lastError = "message_verification_unavailable";
|
|
9853
9844
|
for (let attempt = 0; attempt < Math.max(1, attempts); attempt += 1) {
|
|
9854
9845
|
try {
|
|
9855
|
-
const afterMessages = await readOpenCodeSessionMessages(client, { sessionId, limit: 50 });
|
|
9846
|
+
const afterMessages = await readOpenCodeSessionMessages(client, { sessionId, directory, limit: 50 });
|
|
9856
9847
|
if (!afterMessages) return { ok: false, reason: "message_verification_unavailable" };
|
|
9857
9848
|
const beforeCount = Array.isArray(beforeMessages) ? beforeMessages.length : null;
|
|
9858
9849
|
const beforeKeys = Array.isArray(beforeMessages) ? new Set(beforeMessages.map(openCodeMessageStableKey)) : null;
|
|
@@ -9886,46 +9877,44 @@ async function applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason,
|
|
|
9886
9877
|
return { ok: false, error: error.message, tagName };
|
|
9887
9878
|
}
|
|
9888
9879
|
}
|
|
9880
|
+
function openCodeBlockingPromptVerification(result, sessionId) {
|
|
9881
|
+
if (result?.__optimaPromptDelivery !== "prompt") return null;
|
|
9882
|
+
const response = result?.response ?? result;
|
|
9883
|
+
const data = response?.data ?? result?.data ?? null;
|
|
9884
|
+
const parts = normalizePromptResponseParts(result);
|
|
9885
|
+
const messageId = data?.id ?? response?.id ?? result?.id ?? data?.messageID ?? response?.messageID ?? result?.messageID;
|
|
9886
|
+
const deliveredSessionId = response?.sessionID ?? response?.sessionId ?? data?.sessionID ?? data?.sessionId ?? result?.sessionID ?? result?.sessionId;
|
|
9887
|
+
if (deliveredSessionId && String(deliveredSessionId) !== String(sessionId)) {
|
|
9888
|
+
throw new Error(`OpenCode blocking prompt targeted foreign session ${deliveredSessionId}.`);
|
|
9889
|
+
}
|
|
9890
|
+
if (parts.length > 0 || messageId) return { ok: true, method: parts.length > 0 ? "blocking_prompt_parts" : "blocking_prompt_message", messageId: messageId ? String(messageId) : null, sessionId: deliveredSessionId ? String(deliveredSessionId) : String(sessionId), parts: parts.length };
|
|
9891
|
+
return null;
|
|
9892
|
+
}
|
|
9889
9893
|
async function deliverClickUpSessionEventWithVerification({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, sessionId, agent, text, directory, opencodeBaseUrl, eventMarkers = [], verifySessionEventDelivery = verifyOpenCodeSessionEventDelivery, applyBlockerOnFailure = true } = {}) {
|
|
9890
|
-
const beforeMessages = await readOpenCodeSessionMessages(openCodeClient, { sessionId, limit: 50 }).catch(() => null);
|
|
9891
|
-
const sendResult = await sendSessionEvent(openCodeClient, { sessionId, agent, text, directory, opencodeBaseUrl });
|
|
9894
|
+
const beforeMessages = await readOpenCodeSessionMessages(openCodeClient, { sessionId, directory, limit: 50 }).catch(() => null);
|
|
9895
|
+
const sendResult = await sendSessionEvent(openCodeClient, { sessionId, agent, text, directory, opencodeBaseUrl, allowDirectFallback: false });
|
|
9896
|
+
let blockingPromptVerification = null;
|
|
9892
9897
|
let admissionVerification = null;
|
|
9893
9898
|
try {
|
|
9894
|
-
|
|
9899
|
+
blockingPromptVerification = openCodeBlockingPromptVerification(sendResult, sessionId);
|
|
9900
|
+
if (!blockingPromptVerification) admissionVerification = openCodePromptAdmissionVerification(sendResult, sessionId);
|
|
9895
9901
|
} catch (error) {
|
|
9896
9902
|
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_failed", taskId, sessionId, reason: error.message, fallbackAttempted: false });
|
|
9897
9903
|
if (!applyBlockerOnFailure) return { ok: false, action: "message_delivery_failed", reason: error.message, taskId, sessionId, fallbackAttempted: false };
|
|
9898
9904
|
const blocker2 = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: error.message, source: "delivery_admission_failed" });
|
|
9899
9905
|
return { ok: false, action: "message_delivery_failed", reason: error.message, taskId, sessionId, fallbackAttempted: false, blockerTag: blocker2 };
|
|
9900
9906
|
}
|
|
9901
|
-
|
|
9907
|
+
if (blockingPromptVerification) return { ok: true, verification: blockingPromptVerification, admissionVerification: null, fallback: false };
|
|
9908
|
+
let verification = await verifySessionEventDelivery(openCodeClient, { sessionId, directory, beforeMessages, expectedText: text, markers: eventMarkers });
|
|
9902
9909
|
if (verification?.ok) return { ok: true, verification, admissionVerification, fallback: false };
|
|
9903
|
-
if (verification?.reason === "message_verification_unavailable" && !admissionVerification) {
|
|
9904
|
-
return { ok: true, verification: { ok: true, method: "legacy_prompt_accepted", skipped: true }, fallback: false };
|
|
9905
|
-
}
|
|
9906
9910
|
if (admissionVerification) {
|
|
9907
9911
|
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_admitted_but_invisible", taskId, sessionId, admission: admissionVerification, reason: verification?.reason || "message_not_visible" });
|
|
9908
9912
|
}
|
|
9909
|
-
const
|
|
9910
|
-
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
admissionVerification = openCodePromptAdmissionVerification(retrySendResult, sessionId);
|
|
9915
|
-
} catch (error) {
|
|
9916
|
-
verification = { ok: false, reason: error.message };
|
|
9917
|
-
}
|
|
9918
|
-
verification = await verifySessionEventDelivery(openCodeClient, { sessionId, beforeMessages: retryBeforeMessages, expectedText: text, markers: eventMarkers });
|
|
9919
|
-
if (verification?.ok) return { ok: true, verification, admissionVerification, fallback: true };
|
|
9920
|
-
if (verification?.reason === "message_verification_unavailable" && !admissionVerification) {
|
|
9921
|
-
return { ok: true, verification: { ok: true, method: "legacy_prompt_accepted", skipped: true }, fallback: true };
|
|
9922
|
-
}
|
|
9923
|
-
}
|
|
9924
|
-
const reason = verification?.reason || "message_delivery_failed";
|
|
9925
|
-
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_failed", taskId, sessionId, reason, fallbackAttempted: canFallbackDirect });
|
|
9926
|
-
if (!applyBlockerOnFailure) return { ok: false, action: "message_delivery_failed", reason, taskId, sessionId, fallbackAttempted: canFallbackDirect };
|
|
9927
|
-
const blocker = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason, source: canFallbackDirect ? "delivery_fallback_failed" : "delivery_verification_failed" });
|
|
9928
|
-
return { ok: false, action: "message_delivery_failed", reason, taskId, sessionId, fallbackAttempted: canFallbackDirect, blockerTag: blocker };
|
|
9913
|
+
const reason = verification?.reason || (admissionVerification ? "prompt_admission_not_delivered" : "message_delivery_failed");
|
|
9914
|
+
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_failed", taskId, sessionId, reason, fallbackAttempted: false, httpFallbackDisabled: Boolean(opencodeBaseUrl) });
|
|
9915
|
+
if (!applyBlockerOnFailure) return { ok: false, action: "message_delivery_failed", reason, taskId, sessionId, fallbackAttempted: false };
|
|
9916
|
+
const blocker = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason, source: "delivery_verification_failed" });
|
|
9917
|
+
return { ok: false, action: "message_delivery_failed", reason, taskId, sessionId, fallbackAttempted: false, blockerTag: blocker };
|
|
9929
9918
|
}
|
|
9930
9919
|
async function recoverClickUpPmSession({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, staleSessionId, sessionTitle, taskRoute, metadataWithRouting, config, prompt, eventMarkers = [], deliveryEvidencePath, evidencePath, eventKey, createSession, verifySessionEventDelivery } = {}) {
|
|
9931
9920
|
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_recovery_started", taskId, staleSessionId, worktree: taskRoute?.worktree });
|
package/dist/sanitize_cli.js
CHANGED
|
@@ -9655,23 +9655,16 @@ function extractOpenCodeSessionId(result) {
|
|
|
9655
9655
|
return data?.id || data?.sessionID || data?.sessionId || result?.id || result?.sessionID || result?.sessionId;
|
|
9656
9656
|
}
|
|
9657
9657
|
async function createOpenCodeSession(client, { title, directory, agent } = {}) {
|
|
9658
|
-
const flatPayload = { directory, title };
|
|
9659
|
-
if (agent) flatPayload.agent = agent;
|
|
9660
9658
|
const body = { title };
|
|
9661
9659
|
if (agent) body.agent = agent;
|
|
9662
|
-
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
|
|
9669
|
-
firstError ??= new Error("OpenCode session create response did not include a session id.");
|
|
9670
|
-
} catch (error) {
|
|
9671
|
-
firstError ??= error;
|
|
9672
|
-
}
|
|
9660
|
+
try {
|
|
9661
|
+
const result = await client.session.create({ query: { directory }, body });
|
|
9662
|
+
const sessionId = extractOpenCodeSessionId(result);
|
|
9663
|
+
if (sessionId) return sessionId;
|
|
9664
|
+
throw new Error("OpenCode session create response did not include a session id.");
|
|
9665
|
+
} catch (error) {
|
|
9666
|
+
throw error || new Error("OpenCode session create failed.");
|
|
9673
9667
|
}
|
|
9674
|
-
throw firstError || new Error("OpenCode session create failed.");
|
|
9675
9668
|
}
|
|
9676
9669
|
async function waitForOpenCodeReadiness(client, { worktree = process.cwd(), attempts = 10, delayMs = 500, now = () => /* @__PURE__ */ new Date() } = {}) {
|
|
9677
9670
|
if (typeof client?.session?.create !== "function") return { ok: true, skipped: true, reason: "session_create_probe_unavailable" };
|
|
@@ -9774,9 +9767,19 @@ async function sendOpenCodeSessionEventDirect({ baseUrl, sessionId, text, agent,
|
|
|
9774
9767
|
}
|
|
9775
9768
|
throw firstError || new Error("OpenCode direct prompt delivery failed.");
|
|
9776
9769
|
}
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
|
|
9770
|
+
function tagOpenCodePromptResult(result, deliveryMethod) {
|
|
9771
|
+
if (result && typeof result === "object") {
|
|
9772
|
+
try {
|
|
9773
|
+
Object.defineProperty(result, "__optimaPromptDelivery", { value: deliveryMethod, enumerable: false, configurable: true });
|
|
9774
|
+
} catch {
|
|
9775
|
+
return { result, __optimaPromptDelivery: deliveryMethod };
|
|
9776
|
+
}
|
|
9777
|
+
}
|
|
9778
|
+
return result;
|
|
9779
|
+
}
|
|
9780
|
+
async function callOpenCodePromptWithFallbacks(method, sessionId, flatPayload, structuredPayload, deliveryMethod) {
|
|
9781
|
+
const attempts = deliveryMethod === "prompt" ? [structuredPayload] : [
|
|
9782
|
+
structuredPayload,
|
|
9780
9783
|
{ ...structuredPayload, path: { sessionID: sessionId } },
|
|
9781
9784
|
{ sessionID: sessionId, ...flatPayload },
|
|
9782
9785
|
{ id: sessionId, ...flatPayload }
|
|
@@ -9784,14 +9787,14 @@ async function callOpenCodePromptWithFallbacks(method, sessionId, flatPayload, s
|
|
|
9784
9787
|
let firstError = null;
|
|
9785
9788
|
for (const attempt of attempts) {
|
|
9786
9789
|
try {
|
|
9787
|
-
return assertOpenCodePromptAccepted(await method(attempt));
|
|
9790
|
+
return tagOpenCodePromptResult(assertOpenCodePromptAccepted(await method(attempt)), deliveryMethod);
|
|
9788
9791
|
} catch (error) {
|
|
9789
9792
|
firstError ??= error;
|
|
9790
9793
|
}
|
|
9791
9794
|
}
|
|
9792
9795
|
throw firstError;
|
|
9793
9796
|
}
|
|
9794
|
-
async function sendOpenCodeSessionEvent(client, { sessionId, agent, text, directory, opencodeBaseUrl, baseUrl, fetchImpl, direct = false, legacyOnly = false } = {}) {
|
|
9797
|
+
async function sendOpenCodeSessionEvent(client, { sessionId, agent, text, directory, opencodeBaseUrl, baseUrl, fetchImpl, direct = false, legacyOnly = false, allowDirectFallback = true } = {}) {
|
|
9795
9798
|
const directBaseUrl = opencodeBaseUrl || baseUrl;
|
|
9796
9799
|
const parts = [{ type: "text", text }];
|
|
9797
9800
|
const flatPayload = { directory, agent, parts };
|
|
@@ -9801,21 +9804,21 @@ async function sendOpenCodeSessionEvent(client, { sessionId, agent, text, direct
|
|
|
9801
9804
|
body: { agent, parts }
|
|
9802
9805
|
};
|
|
9803
9806
|
let firstError = null;
|
|
9804
|
-
if (!direct && typeof client?.session?.
|
|
9807
|
+
if (!direct && typeof client?.session?.prompt === "function") {
|
|
9805
9808
|
try {
|
|
9806
|
-
return await callOpenCodePromptWithFallbacks(client.session.
|
|
9809
|
+
return await callOpenCodePromptWithFallbacks(client.session.prompt.bind(client.session), sessionId, flatPayload, structuredPayload, "prompt");
|
|
9807
9810
|
} catch (error) {
|
|
9808
9811
|
firstError ??= error;
|
|
9809
9812
|
}
|
|
9810
9813
|
}
|
|
9811
|
-
if (!direct && typeof client?.session?.
|
|
9814
|
+
if (!direct && typeof client?.session?.promptAsync === "function") {
|
|
9812
9815
|
try {
|
|
9813
|
-
return await callOpenCodePromptWithFallbacks(client.session.
|
|
9816
|
+
return await callOpenCodePromptWithFallbacks(client.session.promptAsync.bind(client.session), sessionId, flatPayload, structuredPayload, "prompt_async");
|
|
9814
9817
|
} catch (error) {
|
|
9815
9818
|
firstError ??= error;
|
|
9816
9819
|
}
|
|
9817
9820
|
}
|
|
9818
|
-
if (directBaseUrl) return sendOpenCodeSessionEventDirect({ baseUrl: directBaseUrl, sessionId, text, agent, directory, fetchImpl, legacyOnly });
|
|
9821
|
+
if (allowDirectFallback && directBaseUrl) return sendOpenCodeSessionEventDirect({ baseUrl: directBaseUrl, sessionId, text, agent, directory, fetchImpl, legacyOnly });
|
|
9819
9822
|
if (firstError) throw firstError;
|
|
9820
9823
|
throw new Error("OpenCode client does not expose session.prompt or session.promptAsync.");
|
|
9821
9824
|
}
|
|
@@ -9826,23 +9829,11 @@ function normalizeOpenCodeSessionMessages(result) {
|
|
|
9826
9829
|
if (Array.isArray(data?.items)) return [...data.items];
|
|
9827
9830
|
return [];
|
|
9828
9831
|
}
|
|
9829
|
-
async function readOpenCodeSessionMessages(client, { sessionId, limit = 20 } = {}) {
|
|
9832
|
+
async function readOpenCodeSessionMessages(client, { sessionId, directory, limit = 20 } = {}) {
|
|
9830
9833
|
if (typeof client?.session?.messages !== "function") return null;
|
|
9831
|
-
const
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
{ sessionID: sessionId, limit },
|
|
9835
|
-
{ id: sessionId, limit }
|
|
9836
|
-
];
|
|
9837
|
-
let firstError = null;
|
|
9838
|
-
for (const attempt of attempts) {
|
|
9839
|
-
try {
|
|
9840
|
-
return normalizeOpenCodeSessionMessages(await client.session.messages(attempt));
|
|
9841
|
-
} catch (error) {
|
|
9842
|
-
firstError ??= error;
|
|
9843
|
-
}
|
|
9844
|
-
}
|
|
9845
|
-
throw firstError;
|
|
9834
|
+
const query = { limit };
|
|
9835
|
+
if (directory) query.directory = directory;
|
|
9836
|
+
return normalizeOpenCodeSessionMessages(await client.session.messages({ path: { id: sessionId }, query }));
|
|
9846
9837
|
}
|
|
9847
9838
|
function openCodeMessageText(message) {
|
|
9848
9839
|
const parts = [message?.text, message?.content, message?.message, message?.body?.text, message?.data?.text];
|
|
@@ -9855,11 +9846,11 @@ function openCodeMessageStableKey(message, index = 0) {
|
|
|
9855
9846
|
if (id) return `id:${id}`;
|
|
9856
9847
|
return `idx:${index}:text:${openCodeMessageText(message)}`;
|
|
9857
9848
|
}
|
|
9858
|
-
async function verifyOpenCodeSessionEventDelivery(client, { sessionId, beforeMessages = null, expectedText = "", markers = [], attempts = 8, delayMs = 250 } = {}) {
|
|
9849
|
+
async function verifyOpenCodeSessionEventDelivery(client, { sessionId, directory, beforeMessages = null, expectedText = "", markers = [], attempts = 8, delayMs = 250 } = {}) {
|
|
9859
9850
|
let lastError = "message_verification_unavailable";
|
|
9860
9851
|
for (let attempt = 0; attempt < Math.max(1, attempts); attempt += 1) {
|
|
9861
9852
|
try {
|
|
9862
|
-
const afterMessages = await readOpenCodeSessionMessages(client, { sessionId, limit: 50 });
|
|
9853
|
+
const afterMessages = await readOpenCodeSessionMessages(client, { sessionId, directory, limit: 50 });
|
|
9863
9854
|
if (!afterMessages) return { ok: false, reason: "message_verification_unavailable" };
|
|
9864
9855
|
const beforeCount = Array.isArray(beforeMessages) ? beforeMessages.length : null;
|
|
9865
9856
|
const beforeKeys = Array.isArray(beforeMessages) ? new Set(beforeMessages.map(openCodeMessageStableKey)) : null;
|
|
@@ -9893,46 +9884,44 @@ async function applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason,
|
|
|
9893
9884
|
return { ok: false, error: error.message, tagName };
|
|
9894
9885
|
}
|
|
9895
9886
|
}
|
|
9887
|
+
function openCodeBlockingPromptVerification(result, sessionId) {
|
|
9888
|
+
if (result?.__optimaPromptDelivery !== "prompt") return null;
|
|
9889
|
+
const response = result?.response ?? result;
|
|
9890
|
+
const data = response?.data ?? result?.data ?? null;
|
|
9891
|
+
const parts = normalizePromptResponseParts(result);
|
|
9892
|
+
const messageId = data?.id ?? response?.id ?? result?.id ?? data?.messageID ?? response?.messageID ?? result?.messageID;
|
|
9893
|
+
const deliveredSessionId = response?.sessionID ?? response?.sessionId ?? data?.sessionID ?? data?.sessionId ?? result?.sessionID ?? result?.sessionId;
|
|
9894
|
+
if (deliveredSessionId && String(deliveredSessionId) !== String(sessionId)) {
|
|
9895
|
+
throw new Error(`OpenCode blocking prompt targeted foreign session ${deliveredSessionId}.`);
|
|
9896
|
+
}
|
|
9897
|
+
if (parts.length > 0 || messageId) return { ok: true, method: parts.length > 0 ? "blocking_prompt_parts" : "blocking_prompt_message", messageId: messageId ? String(messageId) : null, sessionId: deliveredSessionId ? String(deliveredSessionId) : String(sessionId), parts: parts.length };
|
|
9898
|
+
return null;
|
|
9899
|
+
}
|
|
9896
9900
|
async function deliverClickUpSessionEventWithVerification({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, sessionId, agent, text, directory, opencodeBaseUrl, eventMarkers = [], verifySessionEventDelivery = verifyOpenCodeSessionEventDelivery, applyBlockerOnFailure = true } = {}) {
|
|
9897
|
-
const beforeMessages = await readOpenCodeSessionMessages(openCodeClient, { sessionId, limit: 50 }).catch(() => null);
|
|
9898
|
-
const sendResult = await sendSessionEvent(openCodeClient, { sessionId, agent, text, directory, opencodeBaseUrl });
|
|
9901
|
+
const beforeMessages = await readOpenCodeSessionMessages(openCodeClient, { sessionId, directory, limit: 50 }).catch(() => null);
|
|
9902
|
+
const sendResult = await sendSessionEvent(openCodeClient, { sessionId, agent, text, directory, opencodeBaseUrl, allowDirectFallback: false });
|
|
9903
|
+
let blockingPromptVerification = null;
|
|
9899
9904
|
let admissionVerification = null;
|
|
9900
9905
|
try {
|
|
9901
|
-
|
|
9906
|
+
blockingPromptVerification = openCodeBlockingPromptVerification(sendResult, sessionId);
|
|
9907
|
+
if (!blockingPromptVerification) admissionVerification = openCodePromptAdmissionVerification(sendResult, sessionId);
|
|
9902
9908
|
} catch (error) {
|
|
9903
9909
|
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_failed", taskId, sessionId, reason: error.message, fallbackAttempted: false });
|
|
9904
9910
|
if (!applyBlockerOnFailure) return { ok: false, action: "message_delivery_failed", reason: error.message, taskId, sessionId, fallbackAttempted: false };
|
|
9905
9911
|
const blocker2 = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: error.message, source: "delivery_admission_failed" });
|
|
9906
9912
|
return { ok: false, action: "message_delivery_failed", reason: error.message, taskId, sessionId, fallbackAttempted: false, blockerTag: blocker2 };
|
|
9907
9913
|
}
|
|
9908
|
-
|
|
9914
|
+
if (blockingPromptVerification) return { ok: true, verification: blockingPromptVerification, admissionVerification: null, fallback: false };
|
|
9915
|
+
let verification = await verifySessionEventDelivery(openCodeClient, { sessionId, directory, beforeMessages, expectedText: text, markers: eventMarkers });
|
|
9909
9916
|
if (verification?.ok) return { ok: true, verification, admissionVerification, fallback: false };
|
|
9910
|
-
if (verification?.reason === "message_verification_unavailable" && !admissionVerification) {
|
|
9911
|
-
return { ok: true, verification: { ok: true, method: "legacy_prompt_accepted", skipped: true }, fallback: false };
|
|
9912
|
-
}
|
|
9913
9917
|
if (admissionVerification) {
|
|
9914
9918
|
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_admitted_but_invisible", taskId, sessionId, admission: admissionVerification, reason: verification?.reason || "message_not_visible" });
|
|
9915
9919
|
}
|
|
9916
|
-
const
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
admissionVerification = openCodePromptAdmissionVerification(retrySendResult, sessionId);
|
|
9922
|
-
} catch (error) {
|
|
9923
|
-
verification = { ok: false, reason: error.message };
|
|
9924
|
-
}
|
|
9925
|
-
verification = await verifySessionEventDelivery(openCodeClient, { sessionId, beforeMessages: retryBeforeMessages, expectedText: text, markers: eventMarkers });
|
|
9926
|
-
if (verification?.ok) return { ok: true, verification, admissionVerification, fallback: true };
|
|
9927
|
-
if (verification?.reason === "message_verification_unavailable" && !admissionVerification) {
|
|
9928
|
-
return { ok: true, verification: { ok: true, method: "legacy_prompt_accepted", skipped: true }, fallback: true };
|
|
9929
|
-
}
|
|
9930
|
-
}
|
|
9931
|
-
const reason = verification?.reason || "message_delivery_failed";
|
|
9932
|
-
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_failed", taskId, sessionId, reason, fallbackAttempted: canFallbackDirect });
|
|
9933
|
-
if (!applyBlockerOnFailure) return { ok: false, action: "message_delivery_failed", reason, taskId, sessionId, fallbackAttempted: canFallbackDirect };
|
|
9934
|
-
const blocker = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason, source: canFallbackDirect ? "delivery_fallback_failed" : "delivery_verification_failed" });
|
|
9935
|
-
return { ok: false, action: "message_delivery_failed", reason, taskId, sessionId, fallbackAttempted: canFallbackDirect, blockerTag: blocker };
|
|
9920
|
+
const reason = verification?.reason || (admissionVerification ? "prompt_admission_not_delivered" : "message_delivery_failed");
|
|
9921
|
+
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_failed", taskId, sessionId, reason, fallbackAttempted: false, httpFallbackDisabled: Boolean(opencodeBaseUrl) });
|
|
9922
|
+
if (!applyBlockerOnFailure) return { ok: false, action: "message_delivery_failed", reason, taskId, sessionId, fallbackAttempted: false };
|
|
9923
|
+
const blocker = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason, source: "delivery_verification_failed" });
|
|
9924
|
+
return { ok: false, action: "message_delivery_failed", reason, taskId, sessionId, fallbackAttempted: false, blockerTag: blocker };
|
|
9936
9925
|
}
|
|
9937
9926
|
async function recoverClickUpPmSession({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, staleSessionId, sessionTitle, taskRoute, metadataWithRouting, config, prompt, eventMarkers = [], deliveryEvidencePath, evidencePath, eventKey, createSession, verifySessionEventDelivery } = {}) {
|
|
9938
9927
|
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_recovery_started", taskId, staleSessionId, worktree: taskRoute?.worktree });
|