@adhdev/daemon-core 0.8.5 → 0.8.7

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.mjs CHANGED
@@ -875,6 +875,9 @@ function promptLikelyVisible(screenText, promptSnippet) {
875
875
  function normalizeScreenSnapshot(text) {
876
876
  return sanitizeTerminalText(String(text || "")).replace(/\s+/g, " ").trim();
877
877
  }
878
+ function normalizeComparableMessageContent(text) {
879
+ return String(text || "").replace(/\s+/g, " ").trim();
880
+ }
878
881
  function parsePatternEntry(x) {
879
882
  if (x instanceof RegExp) return x;
880
883
  if (x && typeof x === "object" && typeof x.source === "string") {
@@ -1053,11 +1056,44 @@ var init_provider_cli_adapter = __esm({
1053
1056
  this.structuredMessages = [...this.committedMessages];
1054
1057
  }
1055
1058
  normalizeParsedMessages(parsedMessages) {
1056
- return parsedMessages.filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message) => ({
1057
- role: message.role,
1058
- content: typeof message.content === "string" ? message.content : String(message.content || ""),
1059
- timestamp: typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : Date.now()
1060
- }));
1059
+ const referenceMessages = [...this.committedMessages];
1060
+ const usedReferenceIndexes = /* @__PURE__ */ new Set();
1061
+ const now = Date.now();
1062
+ const findReferenceTimestamp = (role, content, parsedIndex) => {
1063
+ const normalizedContent = normalizeComparableMessageContent(content);
1064
+ if (!normalizedContent) return void 0;
1065
+ const sameIndex = referenceMessages[parsedIndex];
1066
+ if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && normalizeComparableMessageContent(sameIndex.content) === normalizedContent && typeof sameIndex.timestamp === "number" && Number.isFinite(sameIndex.timestamp)) {
1067
+ usedReferenceIndexes.add(parsedIndex);
1068
+ return sameIndex.timestamp;
1069
+ }
1070
+ for (let i = 0; i < referenceMessages.length; i++) {
1071
+ if (usedReferenceIndexes.has(i)) continue;
1072
+ const candidate = referenceMessages[i];
1073
+ if (!candidate || candidate.role !== role) continue;
1074
+ const candidateContent = normalizeComparableMessageContent(candidate.content);
1075
+ if (!candidateContent) continue;
1076
+ const exactMatch = candidateContent === normalizedContent;
1077
+ const fuzzyMatch = candidateContent.includes(normalizedContent) || normalizedContent.includes(candidateContent);
1078
+ if (!exactMatch && !fuzzyMatch) continue;
1079
+ if (typeof candidate.timestamp === "number" && Number.isFinite(candidate.timestamp)) {
1080
+ usedReferenceIndexes.add(i);
1081
+ return candidate.timestamp;
1082
+ }
1083
+ }
1084
+ return void 0;
1085
+ };
1086
+ return parsedMessages.filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message, index) => {
1087
+ const role = message.role;
1088
+ const content = typeof message.content === "string" ? message.content : String(message.content || "");
1089
+ const parsedTimestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0;
1090
+ const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(role, content, index);
1091
+ return {
1092
+ role,
1093
+ content,
1094
+ timestamp: referenceTimestamp ?? now
1095
+ };
1096
+ });
1061
1097
  }
1062
1098
  sliceFromOffset(text, start) {
1063
1099
  if (!text) return "";
@@ -1215,11 +1251,15 @@ var init_provider_cli_adapter = __esm({
1215
1251
  let shellCmd;
1216
1252
  let shellArgs;
1217
1253
  const useShellUnix = !isWin && (!!spawnConfig.shell || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1218
- const useShell = isWin ? !!spawnConfig.shell : useShellUnix;
1254
+ const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
1255
+ const useShell = isWin ? !!spawnConfig.shell || isCmdShim : useShellUnix;
1219
1256
  if (useShell) {
1220
1257
  if (!spawnConfig.shell && !isWin) {
1221
1258
  LOG.info("CLI", `[${this.cliType}] Using login shell (script shim or non-native binary)`);
1222
1259
  }
1260
+ if (isCmdShim) {
1261
+ LOG.info("CLI", `[${this.cliType}] Using cmd.exe shell for .cmd/.bat shim: ${binaryPath}`);
1262
+ }
1223
1263
  shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
1224
1264
  if (isWin) {
1225
1265
  shellArgs = ["/c", binaryPath, ...allArgs];
@@ -15819,6 +15859,8 @@ async function handleAutoImplement(ctx, type, req, res) {
15819
15859
  let approvalBuffer = "";
15820
15860
  let lastApprovalTime = 0;
15821
15861
  let completionSignalSeen = false;
15862
+ let autoStopTimer = null;
15863
+ let autoStopIssued = false;
15822
15864
  try {
15823
15865
  const { normalizeCliProviderForRuntime: normalizeCliProviderForRuntime2 } = await Promise.resolve().then(() => (init_provider_cli_adapter(), provider_cli_adapter_exports));
15824
15866
  const normalized = normalizeCliProviderForRuntime2(agentProvider);
@@ -15856,8 +15898,37 @@ async function handleAutoImplement(ctx, type, req, res) {
15856
15898
  lastApprovalTime = Date.now();
15857
15899
  }
15858
15900
  };
15901
+ const clearAutoStopTimer = () => {
15902
+ if (autoStopTimer) {
15903
+ clearTimeout(autoStopTimer);
15904
+ autoStopTimer = null;
15905
+ }
15906
+ };
15907
+ const scheduleAutoStopForVerification = () => {
15908
+ if (!verification || command !== "codex" || completionSignalSeen || autoStopIssued) return;
15909
+ const elapsed = Date.now() - spawnedAt;
15910
+ if (elapsed < 3e4) return;
15911
+ clearAutoStopTimer();
15912
+ autoStopTimer = setTimeout(() => {
15913
+ if (!ctx.autoImplProcess || completionSignalSeen || autoStopIssued) return;
15914
+ autoStopIssued = true;
15915
+ ctx.log(`Auto-implement output quiet for 30s after ${Math.round((Date.now() - spawnedAt) / 1e3)}s. Interrupting agent and switching to daemon verification.`);
15916
+ sendAutoImplSSE(ctx, {
15917
+ event: "output",
15918
+ data: {
15919
+ chunk: "\n[\u{1F916} ADHDev Pipeline] Agent output quiet. Interrupting and running daemon verification...\n",
15920
+ stream: "stdout"
15921
+ }
15922
+ });
15923
+ try {
15924
+ ctx.autoImplProcess.kill("SIGINT");
15925
+ } catch {
15926
+ }
15927
+ }, 3e4);
15928
+ };
15859
15929
  const finalizeCliAutoImpl = async (code) => {
15860
15930
  ctx.autoImplProcess = null;
15931
+ clearAutoStopTimer();
15861
15932
  let success = completionSignalSeen || code === 0;
15862
15933
  let message = success ? completionSignalSeen && code !== 0 ? "\u2705 Auto-implement complete (completion signal)" : "\u2705 Auto-implement complete" : `\u274C Agent exited (code: ${code})`;
15863
15934
  let verificationSummary = null;
@@ -15908,12 +15979,14 @@ async function handleAutoImplement(ctx, type, req, res) {
15908
15979
  if (isPty) {
15909
15980
  child.onData((data) => {
15910
15981
  stdout += data;
15982
+ clearAutoStopTimer();
15911
15983
  if (data.includes("\x1B[6n")) {
15912
15984
  child.write("\x1B[12;1R");
15913
15985
  ctx.log("Terminal CPR request (\\x1b[6n) intercepted in PTY, responding with dummy coordinates [12;1R]");
15914
15986
  }
15915
15987
  checkAutoApproval(data, (s) => child.write(s));
15916
15988
  sendAutoImplSSE(ctx, { event: "output", data: { chunk: data, stream: "stdout" } });
15989
+ scheduleAutoStopForVerification();
15917
15990
  });
15918
15991
  child.onExit(({ exitCode: code }) => {
15919
15992
  void finalizeCliAutoImpl(code);
@@ -15922,15 +15995,19 @@ async function handleAutoImplement(ctx, type, req, res) {
15922
15995
  child.stdout?.on("data", (d) => {
15923
15996
  const chunk = d.toString();
15924
15997
  stdout += chunk;
15998
+ clearAutoStopTimer();
15925
15999
  if (chunk.includes("\x1B[6n")) child.stdin?.write("\x1B[1;1R");
15926
16000
  checkAutoApproval(chunk, (s) => child.stdin?.write(s));
15927
16001
  sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stdout" } });
16002
+ scheduleAutoStopForVerification();
15928
16003
  });
15929
16004
  child.stderr?.on("data", (d) => {
15930
16005
  const chunk = d.toString();
15931
16006
  stderr += chunk;
16007
+ clearAutoStopTimer();
15932
16008
  checkAutoApproval(chunk, (s) => child.stdin?.write(s));
15933
16009
  sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stderr" } });
16010
+ scheduleAutoStopForVerification();
15934
16011
  });
15935
16012
  child.on("exit", (code) => {
15936
16013
  void finalizeCliAutoImpl(code);