@nowcrew/daemon 0.6.88-beta.12 → 0.6.88-beta.14

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.
@@ -878,23 +878,26 @@ export function createExecutionJournal(agentsRoot, options = {}) {
878
878
  },
879
879
  acknowledgeCompletion: async (executionId) => {
880
880
  validateExecutionId(executionId);
881
- const updated = await serializedExecution(executionId, "acknowledge_completion", async () => {
881
+ const result = await serializedExecution(executionId, "acknowledge_completion", async () => {
882
882
  const entry = await requireRecord(executionId);
883
883
  if (entry.state !== "completed" && entry.state !== "interrupted") {
884
884
  throw new JournalTransitionError(`Cannot acknowledge ${entry.state} execution`);
885
885
  }
886
- if (entry.completionAcknowledged)
887
- return confirmDurable(entry);
886
+ if (entry.completionAcknowledged) {
887
+ return { entry: await confirmDurable(entry), newlyAcknowledged: false };
888
+ }
888
889
  const updated = JournalEntrySchema.parse({
889
890
  ...entry,
890
891
  completionAcknowledged: true,
891
892
  updatedAt: now().toISOString(),
892
893
  });
893
894
  await writeRecord(updated);
894
- return updated;
895
+ return { entry: updated, newlyAcknowledged: true };
895
896
  });
896
- await serializedDirectory(pruneInternal);
897
- return updated;
897
+ // 重复 ACK 仍确认持久化,但不能反复全目录清理并阻塞后续控制帧。
898
+ if (result.newlyAcknowledged)
899
+ await serializedDirectory(pruneInternal);
900
+ return result.entry;
898
901
  },
899
902
  get: async (executionId) => {
900
903
  validateExecutionId(executionId);
@@ -109,9 +109,15 @@ function replaceGeneratedIndex(memory, entries) {
109
109
  }
110
110
  return `${memory.trimEnd()}\n\n## Knowledge Index\n${generated}\n`;
111
111
  }
112
+ function unwrappedNoteBody(title, body) {
113
+ const detail = body.trim();
114
+ const heading = /^([^\r\n]+)\r?\n\r?\n/u.exec(detail);
115
+ // Agent 可能回传包含包装标题的全文;只解开一层,保留内部及历史标题。
116
+ return heading?.[1] === `## ${title}` ? detail.slice(heading[0].length) : detail;
117
+ }
112
118
  function noteSection(id, revision, title, body) {
113
119
  return `<!-- NOWWORK:MEMORY_ENTRY:BEGIN id=${id} revision=${revision} -->\n`
114
- + `## ${title}\n\n${body.trim()}\n`
120
+ + `## ${title}\n\n${unwrappedNoteBody(title, body)}\n`
115
121
  + `<!-- NOWWORK:MEMORY_ENTRY:END id=${id} -->\n`;
116
122
  }
117
123
  function notePattern(id) {
@@ -455,8 +461,10 @@ export async function applyLocalMemoryResult(input) {
455
461
  if (duplicate !== undefined) {
456
462
  const duplicatePath = resolve(input.agentDir, duplicate.file);
457
463
  const duplicateBody = readNoteBody(noteUpdates.get(duplicatePath) ?? await readNote(duplicatePath), duplicate.id);
458
- if (duplicateBody === change.detailBody)
464
+ if (duplicateBody === change.detailBody
465
+ || duplicateBody === unwrappedNoteBody(change.title, change.detailBody).trim()) {
459
466
  resolvedPendingIds.add(pending.pendingId);
467
+ }
460
468
  continue;
461
469
  }
462
470
  const entry = entryFromChange(change, id, 1, "active");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nowcrew/daemon",
3
- "version": "0.6.88-beta.12",
3
+ "version": "0.6.88-beta.14",
4
4
  "type": "module",
5
5
  "description": "crew daemon — 运行在用户机器:拉起/管理 agent 进程,注入 crew CLI,归一化 runtime 事件",
6
6
  "license": "Apache-2.0",