@defend-tech/opencode-optima 0.1.50 → 0.1.51

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
@@ -9719,7 +9719,13 @@ async function readOpenCodeJsonResponse(response, endpointName) {
9719
9719
  return { raw };
9720
9720
  }
9721
9721
  }
9722
- async function sendOpenCodeSessionEventDirect({ baseUrl, sessionId, text, agent, fetchImpl = globalThis.fetch, legacyOnly = false } = {}) {
9722
+ function appendDirectoryQuery(url, directory) {
9723
+ const value = String(directory || "").trim();
9724
+ if (!value) return url;
9725
+ const separator = url.includes("?") ? "&" : "?";
9726
+ return `${url}${separator}directory=${encodeURIComponent(value)}`;
9727
+ }
9728
+ async function sendOpenCodeSessionEventDirect({ baseUrl, sessionId, text, agent, directory, fetchImpl = globalThis.fetch, legacyOnly = false } = {}) {
9723
9729
  if (typeof fetchImpl !== "function") throw new Error("OpenCode direct prompt delivery requires fetch.");
9724
9730
  const root = normalizeOpenCodeBaseUrl(baseUrl, "");
9725
9731
  if (!root) throw new Error("OpenCode direct prompt delivery requires a base URL.");
@@ -9727,7 +9733,7 @@ async function sendOpenCodeSessionEventDirect({ baseUrl, sessionId, text, agent,
9727
9733
  const attempts = [
9728
9734
  legacyOnly ? null : {
9729
9735
  name: "v2 prompt",
9730
- url: `${root}/api/session/${encodedSession}/prompt`,
9736
+ url: appendDirectoryQuery(`${root}/api/session/${encodedSession}/prompt`, directory),
9731
9737
  body: { prompt: { text }, delivery: "queue", resume: true },
9732
9738
  accept: (response, data) => {
9733
9739
  if (!response.ok) return null;
@@ -9737,7 +9743,7 @@ async function sendOpenCodeSessionEventDirect({ baseUrl, sessionId, text, agent,
9737
9743
  },
9738
9744
  {
9739
9745
  name: "legacy async prompt",
9740
- url: `${root}/session/${encodedSession}/prompt_async`,
9746
+ url: appendDirectoryQuery(`${root}/session/${encodedSession}/prompt_async`, directory),
9741
9747
  body: { agent, parts: [{ type: "text", text }] },
9742
9748
  accept: (response, data) => {
9743
9749
  if (response.status !== 204 && !response.ok) return null;
@@ -9802,7 +9808,7 @@ async function sendOpenCodeSessionEvent(client, { sessionId, agent, text, direct
9802
9808
  firstError ??= error;
9803
9809
  }
9804
9810
  }
9805
- if (directBaseUrl) return sendOpenCodeSessionEventDirect({ baseUrl: directBaseUrl, sessionId, text, agent, fetchImpl, legacyOnly });
9811
+ if (directBaseUrl) return sendOpenCodeSessionEventDirect({ baseUrl: directBaseUrl, sessionId, text, agent, directory, fetchImpl, legacyOnly });
9806
9812
  if (firstError) throw firstError;
9807
9813
  throw new Error("OpenCode client does not expose session.prompt or session.promptAsync.");
9808
9814
  }
@@ -9837,6 +9843,11 @@ function openCodeMessageText(message) {
9837
9843
  for (const part of partList) parts.push(part?.text, part?.content);
9838
9844
  return parts.filter((value) => typeof value === "string").join("\n");
9839
9845
  }
9846
+ function openCodeMessageStableKey(message, index = 0) {
9847
+ const id = message?.id || message?.messageID || message?.messageId || message?.data?.id || null;
9848
+ if (id) return `id:${id}`;
9849
+ return `idx:${index}:text:${openCodeMessageText(message)}`;
9850
+ }
9840
9851
  async function verifyOpenCodeSessionEventDelivery(client, { sessionId, beforeMessages = null, expectedText = "", markers = [], attempts = 8, delayMs = 250 } = {}) {
9841
9852
  let lastError = "message_verification_unavailable";
9842
9853
  for (let attempt = 0; attempt < Math.max(1, attempts); attempt += 1) {
@@ -9844,13 +9855,15 @@ async function verifyOpenCodeSessionEventDelivery(client, { sessionId, beforeMes
9844
9855
  const afterMessages = await readOpenCodeSessionMessages(client, { sessionId, limit: 50 });
9845
9856
  if (!afterMessages) return { ok: false, reason: "message_verification_unavailable" };
9846
9857
  const beforeCount = Array.isArray(beforeMessages) ? beforeMessages.length : null;
9847
- const lastMessage = afterMessages.at(-1) || null;
9858
+ const beforeKeys = Array.isArray(beforeMessages) ? new Set(beforeMessages.map(openCodeMessageStableKey)) : null;
9859
+ const newMessages = beforeKeys ? afterMessages.filter((message, index) => !beforeKeys.has(openCodeMessageStableKey(message, index))) : afterMessages;
9860
+ const lastMessage = newMessages.at(-1) || afterMessages.at(-1) || null;
9848
9861
  const lastMessageId = lastMessage?.id || lastMessage?.messageID || lastMessage?.messageId || null;
9849
9862
  if (beforeCount !== null && afterMessages.length > beforeCount) return { ok: true, method: "message_count", beforeCount, afterCount: afterMessages.length, lastMessageId };
9850
9863
  const textNeedles = [expectedText, ...markers].map((value) => String(value || "").trim()).filter(Boolean);
9851
- const haystack = afterMessages.slice(-20).map(openCodeMessageText).join("\n");
9864
+ const haystack = newMessages.slice(-20).map(openCodeMessageText).join("\n");
9852
9865
  const matched = textNeedles.find((needle) => haystack.includes(needle));
9853
- if (matched) return { ok: true, method: "message_text", marker: matched, beforeCount, afterCount: afterMessages.length, lastMessageId };
9866
+ if (matched && (!beforeKeys || newMessages.length > 0)) return { ok: true, method: "message_text", marker: matched, beforeCount, afterCount: afterMessages.length, lastMessageId };
9854
9867
  lastError = "message_not_visible";
9855
9868
  } catch (error) {
9856
9869
  lastError = error.message || "message_verification_failed";
@@ -9726,7 +9726,13 @@ async function readOpenCodeJsonResponse(response, endpointName) {
9726
9726
  return { raw };
9727
9727
  }
9728
9728
  }
9729
- async function sendOpenCodeSessionEventDirect({ baseUrl, sessionId, text, agent, fetchImpl = globalThis.fetch, legacyOnly = false } = {}) {
9729
+ function appendDirectoryQuery(url, directory) {
9730
+ const value = String(directory || "").trim();
9731
+ if (!value) return url;
9732
+ const separator = url.includes("?") ? "&" : "?";
9733
+ return `${url}${separator}directory=${encodeURIComponent(value)}`;
9734
+ }
9735
+ async function sendOpenCodeSessionEventDirect({ baseUrl, sessionId, text, agent, directory, fetchImpl = globalThis.fetch, legacyOnly = false } = {}) {
9730
9736
  if (typeof fetchImpl !== "function") throw new Error("OpenCode direct prompt delivery requires fetch.");
9731
9737
  const root = normalizeOpenCodeBaseUrl(baseUrl, "");
9732
9738
  if (!root) throw new Error("OpenCode direct prompt delivery requires a base URL.");
@@ -9734,7 +9740,7 @@ async function sendOpenCodeSessionEventDirect({ baseUrl, sessionId, text, agent,
9734
9740
  const attempts = [
9735
9741
  legacyOnly ? null : {
9736
9742
  name: "v2 prompt",
9737
- url: `${root}/api/session/${encodedSession}/prompt`,
9743
+ url: appendDirectoryQuery(`${root}/api/session/${encodedSession}/prompt`, directory),
9738
9744
  body: { prompt: { text }, delivery: "queue", resume: true },
9739
9745
  accept: (response, data) => {
9740
9746
  if (!response.ok) return null;
@@ -9744,7 +9750,7 @@ async function sendOpenCodeSessionEventDirect({ baseUrl, sessionId, text, agent,
9744
9750
  },
9745
9751
  {
9746
9752
  name: "legacy async prompt",
9747
- url: `${root}/session/${encodedSession}/prompt_async`,
9753
+ url: appendDirectoryQuery(`${root}/session/${encodedSession}/prompt_async`, directory),
9748
9754
  body: { agent, parts: [{ type: "text", text }] },
9749
9755
  accept: (response, data) => {
9750
9756
  if (response.status !== 204 && !response.ok) return null;
@@ -9809,7 +9815,7 @@ async function sendOpenCodeSessionEvent(client, { sessionId, agent, text, direct
9809
9815
  firstError ??= error;
9810
9816
  }
9811
9817
  }
9812
- if (directBaseUrl) return sendOpenCodeSessionEventDirect({ baseUrl: directBaseUrl, sessionId, text, agent, fetchImpl, legacyOnly });
9818
+ if (directBaseUrl) return sendOpenCodeSessionEventDirect({ baseUrl: directBaseUrl, sessionId, text, agent, directory, fetchImpl, legacyOnly });
9813
9819
  if (firstError) throw firstError;
9814
9820
  throw new Error("OpenCode client does not expose session.prompt or session.promptAsync.");
9815
9821
  }
@@ -9844,6 +9850,11 @@ function openCodeMessageText(message) {
9844
9850
  for (const part of partList) parts.push(part?.text, part?.content);
9845
9851
  return parts.filter((value) => typeof value === "string").join("\n");
9846
9852
  }
9853
+ function openCodeMessageStableKey(message, index = 0) {
9854
+ const id = message?.id || message?.messageID || message?.messageId || message?.data?.id || null;
9855
+ if (id) return `id:${id}`;
9856
+ return `idx:${index}:text:${openCodeMessageText(message)}`;
9857
+ }
9847
9858
  async function verifyOpenCodeSessionEventDelivery(client, { sessionId, beforeMessages = null, expectedText = "", markers = [], attempts = 8, delayMs = 250 } = {}) {
9848
9859
  let lastError = "message_verification_unavailable";
9849
9860
  for (let attempt = 0; attempt < Math.max(1, attempts); attempt += 1) {
@@ -9851,13 +9862,15 @@ async function verifyOpenCodeSessionEventDelivery(client, { sessionId, beforeMes
9851
9862
  const afterMessages = await readOpenCodeSessionMessages(client, { sessionId, limit: 50 });
9852
9863
  if (!afterMessages) return { ok: false, reason: "message_verification_unavailable" };
9853
9864
  const beforeCount = Array.isArray(beforeMessages) ? beforeMessages.length : null;
9854
- const lastMessage = afterMessages.at(-1) || null;
9865
+ const beforeKeys = Array.isArray(beforeMessages) ? new Set(beforeMessages.map(openCodeMessageStableKey)) : null;
9866
+ const newMessages = beforeKeys ? afterMessages.filter((message, index) => !beforeKeys.has(openCodeMessageStableKey(message, index))) : afterMessages;
9867
+ const lastMessage = newMessages.at(-1) || afterMessages.at(-1) || null;
9855
9868
  const lastMessageId = lastMessage?.id || lastMessage?.messageID || lastMessage?.messageId || null;
9856
9869
  if (beforeCount !== null && afterMessages.length > beforeCount) return { ok: true, method: "message_count", beforeCount, afterCount: afterMessages.length, lastMessageId };
9857
9870
  const textNeedles = [expectedText, ...markers].map((value) => String(value || "").trim()).filter(Boolean);
9858
- const haystack = afterMessages.slice(-20).map(openCodeMessageText).join("\n");
9871
+ const haystack = newMessages.slice(-20).map(openCodeMessageText).join("\n");
9859
9872
  const matched = textNeedles.find((needle) => haystack.includes(needle));
9860
- if (matched) return { ok: true, method: "message_text", marker: matched, beforeCount, afterCount: afterMessages.length, lastMessageId };
9873
+ if (matched && (!beforeKeys || newMessages.length > 0)) return { ok: true, method: "message_text", marker: matched, beforeCount, afterCount: afterMessages.length, lastMessageId };
9861
9874
  lastError = "message_not_visible";
9862
9875
  } catch (error) {
9863
9876
  lastError = error.message || "message_verification_failed";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defend-tech/opencode-optima",
3
- "version": "0.1.50",
3
+ "version": "0.1.51",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+ssh://git@github.com/defend-tech/opencode-optima.git"