@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 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
- const attempts = [{ query: { directory }, body }, flatPayload];
9656
- let firstError = null;
9657
- for (const attempt of attempts) {
9658
- try {
9659
- const result = await client.session.create(attempt);
9660
- const sessionId = extractOpenCodeSessionId(result);
9661
- if (sessionId) return sessionId;
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
- async function callOpenCodePromptWithFallbacks(method, sessionId, flatPayload, structuredPayload) {
9771
- const attempts = [
9772
- { ...structuredPayload, path: { id: sessionId } },
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?.promptAsync === "function") {
9800
+ if (!direct && typeof client?.session?.prompt === "function") {
9798
9801
  try {
9799
- return await callOpenCodePromptWithFallbacks(client.session.promptAsync.bind(client.session), sessionId, flatPayload, structuredPayload);
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?.prompt === "function") {
9807
+ if (!direct && typeof client?.session?.promptAsync === "function") {
9805
9808
  try {
9806
- return await callOpenCodePromptWithFallbacks(client.session.prompt.bind(client.session), sessionId, flatPayload, structuredPayload);
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 attempts = [
9825
- { path: { id: sessionId }, query: { limit } },
9826
- { path: { sessionID: sessionId }, query: { limit } },
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
- admissionVerification = openCodePromptAdmissionVerification(sendResult, sessionId);
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
- let verification = await verifySessionEventDelivery(openCodeClient, { sessionId, beforeMessages, expectedText: text, markers: eventMarkers });
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 canFallbackDirect = Boolean(opencodeBaseUrl);
9910
- if (canFallbackDirect) {
9911
- const retryBeforeMessages = await readOpenCodeSessionMessages(openCodeClient, { sessionId, limit: 50 }).catch(() => beforeMessages);
9912
- const retrySendResult = await sendSessionEvent(openCodeClient, { sessionId, agent, text, directory, opencodeBaseUrl, direct: true, legacyOnly: Boolean(admissionVerification) });
9913
- try {
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 });
@@ -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
- const attempts = [{ query: { directory }, body }, flatPayload];
9663
- let firstError = null;
9664
- for (const attempt of attempts) {
9665
- try {
9666
- const result = await client.session.create(attempt);
9667
- const sessionId = extractOpenCodeSessionId(result);
9668
- if (sessionId) return sessionId;
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
- async function callOpenCodePromptWithFallbacks(method, sessionId, flatPayload, structuredPayload) {
9778
- const attempts = [
9779
- { ...structuredPayload, path: { id: sessionId } },
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?.promptAsync === "function") {
9807
+ if (!direct && typeof client?.session?.prompt === "function") {
9805
9808
  try {
9806
- return await callOpenCodePromptWithFallbacks(client.session.promptAsync.bind(client.session), sessionId, flatPayload, structuredPayload);
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?.prompt === "function") {
9814
+ if (!direct && typeof client?.session?.promptAsync === "function") {
9812
9815
  try {
9813
- return await callOpenCodePromptWithFallbacks(client.session.prompt.bind(client.session), sessionId, flatPayload, structuredPayload);
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 attempts = [
9832
- { path: { id: sessionId }, query: { limit } },
9833
- { path: { sessionID: sessionId }, query: { limit } },
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
- admissionVerification = openCodePromptAdmissionVerification(sendResult, sessionId);
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
- let verification = await verifySessionEventDelivery(openCodeClient, { sessionId, beforeMessages, expectedText: text, markers: eventMarkers });
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 canFallbackDirect = Boolean(opencodeBaseUrl);
9917
- if (canFallbackDirect) {
9918
- const retryBeforeMessages = await readOpenCodeSessionMessages(openCodeClient, { sessionId, limit: 50 }).catch(() => beforeMessages);
9919
- const retrySendResult = await sendSessionEvent(openCodeClient, { sessionId, agent, text, directory, opencodeBaseUrl, direct: true, legacyOnly: Boolean(admissionVerification) });
9920
- try {
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 });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defend-tech/opencode-optima",
3
- "version": "0.1.51",
3
+ "version": "0.1.53",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+ssh://git@github.com/defend-tech/opencode-optima.git"