@nowcrew/daemon 0.6.93-beta.3 → 0.6.93-beta.5

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.
Files changed (46) hide show
  1. package/dist/cloud-report-upload.js +10 -1
  2. package/dist/execution-journal.js +1 -3
  3. package/dist/execution-protocol.js +1 -1
  4. package/dist/execution-runner.js +1 -3
  5. package/dist/local-execution-prompt.js +3 -8
  6. package/dist/local-executor.js +35 -64
  7. package/dist/local-memory/index-budget.js +3 -9
  8. package/dist/local-memory/inventory-cli.js +1 -23
  9. package/dist/local-memory/inventory-source.js +8 -15
  10. package/dist/local-memory/prompt.js +4 -20
  11. package/dist/local-memory/read-cli.js +77 -75
  12. package/dist/local-memory/rollout.js +8 -54
  13. package/dist/local-memory/runtime.js +13 -148
  14. package/dist/local-memory/write.js +19 -125
  15. package/dist/local-memory-diagnostics.js +2 -41
  16. package/dist/local-memory-telemetry.js +2 -19
  17. package/dist/machine-info.js +0 -3
  18. package/dist/marketplace-protocol.js +1 -1
  19. package/dist/marketplace-remote.js +1 -1
  20. package/dist/marketplace-runner.js +1 -1
  21. package/dist/memory-prune-diagnostics.js +4 -60
  22. package/dist/message-file-preview.js +1 -11
  23. package/dist/prompt.js +1 -5
  24. package/dist/runner.js +1 -1
  25. package/dist/serve.js +3 -36
  26. package/dist/token.js +0 -1
  27. package/dist/workspace-control-handler.js +3 -16
  28. package/dist/workspace.js +2 -10
  29. package/package.json +1 -1
  30. package/dist/local-memory/execution-workspace.js +0 -55
  31. package/dist/local-memory/full-index-search.js +0 -47
  32. package/dist/local-memory/initialization-identity.js +0 -23
  33. package/dist/local-memory/legacy-adapter.js +0 -233
  34. package/dist/local-memory/migration-access.js +0 -184
  35. package/dist/local-memory/migration-cli.js +0 -54
  36. package/dist/local-memory/migration-io.js +0 -199
  37. package/dist/local-memory/migration-plan.js +0 -283
  38. package/dist/local-memory/migration-schema.js +0 -55
  39. package/dist/local-memory/migration-store.js +0 -429
  40. package/dist/local-memory/migration-tool-entry.js +0 -21
  41. package/dist/local-memory/storage-format.js +0 -152
  42. package/dist/memory-migration-controller.js +0 -84
  43. package/dist/memory-migration-inspect.js +0 -75
  44. package/dist/memory-migration-journal.js +0 -14
  45. package/dist/memory-migration-protocol.js +0 -14
  46. package/dist/memory-migration-runtime.js +0 -305
@@ -6,8 +6,6 @@ import { dslog } from "../slog.js";
6
6
  import { LocalMemoryChangeSchema, LocalMemorySingleLineText, validateLocalMemoryChange, } from "./candidate.js";
7
7
  import { LOCAL_MEMORY_INDEX_CODE_POINT_CAP, LOCAL_MEMORY_INDEX_ENTRY_CAP, LOCAL_MEMORY_TOTAL_CODE_POINT_CAP, renderGeneratedIndex, selectLocalMemoryIndexEntries, } from "./index-budget.js";
8
8
  import { persistPendingMemoryCandidate, readPendingMemoryCandidates, removePendingMemoryCandidate, } from "./pending.js";
9
- import { assertLocalMemoryStorageSize, detectLocalMemoryStorageVersion, LOCAL_MEMORY_GENERATED_INDEX_PATTERN, LOCAL_MEMORY_NOTE_BYTE_CAP, LOCAL_MEMORY_READ_BYTE_CAP, parseFullMemoryIndex, replaceFullMemoryIndex, selectLocalMemoryPreview, } from "./storage-format.js";
10
- import { assertMemoryWriterAllowed, withMemoryAccess } from "./migration-access.js";
11
9
  const StatusChangeSchema = z.object({
12
10
  memoryId: LocalMemorySingleLineText,
13
11
  expectedRevision: z.number().int().positive(),
@@ -92,14 +90,12 @@ function parseCards(section) {
92
90
  });
93
91
  }
94
92
  export function parseLocalMemoryIndex(memory) {
95
- if (detectLocalMemoryStorageVersion(memory) === 2)
96
- return parseFullMemoryIndex(memory);
97
93
  const section = indexSection(memory);
98
94
  const generated = GENERATED_INDEX_PATTERN.exec(section)?.[0];
99
95
  return parseCards(generated ?? section);
100
96
  }
101
97
  function parseUnmarkedMemoryIndex(memory) {
102
- const section = indexSection(memory).replace(LOCAL_MEMORY_GENERATED_INDEX_PATTERN, "");
98
+ const section = indexSection(memory).replace(GENERATED_INDEX_PATTERN, "");
103
99
  return parseCards(section);
104
100
  }
105
101
  function replaceGeneratedIndex(memory, entries) {
@@ -126,36 +122,11 @@ function noteSection(id, revision, title, body) {
126
122
  }
127
123
  function notePattern(id) {
128
124
  const escaped = id.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
129
- return new RegExp(`<!--\\s*NOWWORK:MEMORY_ENTRY:BEGIN\\s+id=${escaped}(?=\\s|-->)[^>]*-->[\\s\\S]*?<!--\\s*NOWWORK:MEMORY_ENTRY:END\\s+id=${escaped}\\s*-->\\s*`, "u");
130
- }
131
- function uniqueNoteSection(content, id) {
132
- const escaped = id.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
133
- const begins = [...content.matchAll(new RegExp(`<!--\\s*NOWWORK:MEMORY_ENTRY:BEGIN\\s+id=${escaped}(?=\\s|-->)`, "gu"))];
134
- const ends = [...content.matchAll(new RegExp(`<!--\\s*NOWWORK:MEMORY_ENTRY:END\\s+id=${escaped}\\s*-->`, "gu"))];
135
- if (begins.length === 0 && ends.length === 0)
136
- return null;
137
- const section = notePattern(id).exec(content)?.[0];
138
- if (begins.length !== 1 || ends.length !== 1 || section === undefined
139
- || (section.match(/NOWWORK:MEMORY_ENTRY:(?:BEGIN|END)/gu) ?? []).length !== 2) {
140
- throw new Error("local_memory_note_anchor_invalid");
141
- }
142
- return section;
125
+ return new RegExp(`<!--\\s*NOWWORK:MEMORY_ENTRY:BEGIN\\s+id=${escaped}[^>]*-->[\\s\\S]*?<!--\\s*NOWWORK:MEMORY_ENTRY:END\\s+id=${escaped}\\s*-->\\s*`, "u");
143
126
  }
144
127
  function replaceNote(content, id, replacement) {
145
128
  const pattern = notePattern(id);
146
- return uniqueNoteSection(content, id) !== null ? content.replace(pattern, () => replacement) : null;
147
- }
148
- function updateNoteRevision(content, id, revision) {
149
- const section = uniqueNoteSection(content, id);
150
- const beginning = `<!-- NOWWORK:MEMORY_ENTRY:BEGIN id=${id} `;
151
- const ending = `<!-- NOWWORK:MEMORY_ENTRY:END id=${id} -->`;
152
- if (section === null || content.split(beginning).length !== 2 || content.split(ending).length !== 2) {
153
- throw new Error("local_memory_note_anchor_missing");
154
- }
155
- const updated = section.replace(/^(<!--\s*NOWWORK:MEMORY_ENTRY:BEGIN\s+id=[A-Za-z0-9_-]+\s+revision=)[1-9][0-9]*(\s*-->)/u, (_match, prefix, suffix) => `${prefix}${revision}${suffix}`);
156
- if (!updated.startsWith(`${beginning}revision=${revision} -->`))
157
- throw new Error("local_memory_note_anchor_missing");
158
- return content.replace(notePattern(id), () => updated);
129
+ return pattern.test(content) ? content.replace(pattern, replacement) : null;
159
130
  }
160
131
  function validateCandidate(result) {
161
132
  if (result.outcome === "no_change" && (result.changes.length > 0 || result.statusChanges.length > 0)) {
@@ -228,14 +199,14 @@ function detailCategoryFromFile(file) {
228
199
  return DETAIL_CATEGORIES.has(category) ? category : null;
229
200
  }
230
201
  function readNoteBody(content, id) {
231
- const section = uniqueNoteSection(content, id);
232
- if (section === null)
202
+ const begin = content.indexOf(`<!-- NOWWORK:MEMORY_ENTRY:BEGIN id=${id}`);
203
+ if (begin < 0)
233
204
  return null;
234
- const bodyStart = section.indexOf("\n\n");
235
- const bodyEnd = section.indexOf(`\n<!-- NOWWORK:MEMORY_ENTRY:END id=${id}`, bodyStart + 2);
205
+ const bodyStart = content.indexOf("\n\n", begin);
206
+ const bodyEnd = content.indexOf(`\n<!-- NOWWORK:MEMORY_ENTRY:END id=${id}`, bodyStart + 2);
236
207
  if (bodyStart < 0 || bodyEnd < 0)
237
208
  return null;
238
- return section.slice(bodyStart + 2, bodyEnd).trim();
209
+ return content.slice(bodyStart + 2, bodyEnd).trim();
239
210
  }
240
211
  function archivedChange(entry, detailBody) {
241
212
  const detailCategory = detailCategoryFromFile(entry.file);
@@ -273,29 +244,12 @@ async function assertWritablePaths(agentDir, memoryPath) {
273
244
  if (!memoryStat.isFile() || memoryStat.isSymbolicLink())
274
245
  throw new Error("local_memory_memory_path_invalid");
275
246
  }
276
- async function assertMemoryAccessDirectory(agentDir) {
277
- try {
278
- const stat = await lstat(join(agentDir, ".crew/memory"));
279
- if (!stat.isDirectory() || stat.isSymbolicLink())
280
- throw new Error("local_memory_pending_path_invalid");
281
- }
282
- catch (error) {
283
- if (error.code === "ENOENT")
284
- return;
285
- throw error;
286
- }
287
- }
288
247
  async function readNote(path) {
289
248
  try {
290
249
  const stat = await lstat(path);
291
250
  if (!stat.isFile() || stat.isSymbolicLink())
292
251
  throw new Error("local_memory_note_path_invalid");
293
- if (stat.size > LOCAL_MEMORY_NOTE_BYTE_CAP)
294
- throw new Error("local_memory_note_byte_limit");
295
- const content = await readFile(path, "utf8");
296
- if (Buffer.byteLength(content, "utf8") > LOCAL_MEMORY_NOTE_BYTE_CAP)
297
- throw new Error("local_memory_note_byte_limit");
298
- return content;
252
+ return await readFile(path, "utf8");
299
253
  }
300
254
  catch (error) {
301
255
  if (error.code === "ENOENT")
@@ -315,11 +269,6 @@ async function atomicWrite(path, content) {
315
269
  }
316
270
  }
317
271
  function projectIndex(memory, entries, protectedIds) {
318
- if (detectLocalMemoryStorageVersion(memory) === 2) {
319
- const updated = replaceFullMemoryIndex(memory, entries);
320
- selectLocalMemoryPreview(updated);
321
- return { memory: updated, omittedIds: [], reason: null };
322
- }
323
272
  const empty = replaceGeneratedIndex(memory, []);
324
273
  if (codePointLength(empty) > LOCAL_MEMORY_TOTAL_CODE_POINT_CAP)
325
274
  throw new Error("local_memory_memory_over_budget");
@@ -361,15 +310,8 @@ export async function applyLocalMemoryResult(input) {
361
310
  return emptyResult();
362
311
  const memoryPath = join(input.agentDir, "MEMORY.md");
363
312
  await assertWritablePaths(input.agentDir, memoryPath);
364
- await assertMemoryAccessDirectory(input.agentDir);
365
- return withApplyLease(input.agentDir, async () => withMemoryAccess(input.agentDir, async () => {
366
- await assertMemoryWriterAllowed(input.agentDir, input.writerCapabilities ?? []);
367
- const memoryStat = await lstat(memoryPath);
368
- if (memoryStat.size > 16 * 1024 * 1024)
369
- throw new Error("local_memory_storage_byte_limit");
313
+ return withApplyLease(input.agentDir, async () => {
370
314
  const memory = await readFile(memoryPath, "utf8");
371
- assertLocalMemoryStorageSize(memory);
372
- const fullStorage = detectLocalMemoryStorageVersion(memory) === 2;
373
315
  if (parseUnmarkedMemoryIndex(memory).length > 0)
374
316
  throw new Error("local_memory_legacy_index_requires_migration");
375
317
  let entries = [...parseLocalMemoryIndex(memory)];
@@ -400,26 +342,6 @@ export async function applyLocalMemoryResult(input) {
400
342
  const pendingCandidates = [];
401
343
  const resolvedPendingIds = new Set();
402
344
  const noteUpdates = new Map();
403
- const noteCache = new Map();
404
- let totalReadBytes = Buffer.byteLength(memory, "utf8");
405
- const readStoredNote = async (path) => {
406
- const cached = noteUpdates.get(path) ?? noteCache.get(path);
407
- if (cached !== undefined)
408
- return cached;
409
- const stat = await lstat(path).catch((error) => {
410
- if (error.code === "ENOENT")
411
- return null;
412
- throw error;
413
- });
414
- if (stat !== null && totalReadBytes + stat.size > LOCAL_MEMORY_READ_BYTE_CAP)
415
- throw new Error("local_memory_read_byte_limit");
416
- const content = await readNote(path);
417
- totalReadBytes += Buffer.byteLength(content, "utf8");
418
- if (totalReadBytes > LOCAL_MEMORY_READ_BYTE_CAP)
419
- throw new Error("local_memory_read_byte_limit");
420
- noteCache.set(path, content);
421
- return content;
422
- };
423
345
  let allowActiveEviction = false;
424
346
  const randomId = input.randomId ?? randomUUID;
425
347
  const executionId = input.executionId ?? "unknown";
@@ -461,21 +383,10 @@ export async function applyLocalMemoryResult(input) {
461
383
  if (existingCreate !== undefined && !matchesCreateCandidate(existingCreate, change)) {
462
384
  throw new Error("local_memory_duplicate_candidate");
463
385
  }
464
- if (existingCreate === undefined && entries.some((entry) => (!fullStorage || entry.status === "active" || entry.status === "pinned")
465
- && (normalize(entry.title) === normalize(change.title) || normalize(entry.summary) === normalize(change.summary)))) {
386
+ if (existingCreate === undefined && entries.some((entry) => normalize(entry.title) === normalize(change.title)
387
+ || normalize(entry.summary) === normalize(change.summary))) {
466
388
  throw new Error("local_memory_duplicate_candidate");
467
389
  }
468
- if (existingCreate !== undefined) {
469
- if (existingCreate.revision !== 1 || existingCreate.status !== "active") {
470
- throw new Error("local_memory_create_replay_conflict");
471
- }
472
- const stored = await readStoredNote(resolve(input.agentDir, existingCreate.file));
473
- if (uniqueNoteSection(stored, id)?.trimEnd() !== noteSection(id, 1, change.title, change.detailBody).trimEnd()) {
474
- throw new Error("local_memory_create_replay_conflict");
475
- }
476
- // A proven duplicate is a no-op; it must never rewrite a newer body or status.
477
- continue;
478
- }
479
390
  }
480
391
  const revision = existingCreate?.revision ?? (current === undefined ? 1 : current.revision + 1);
481
392
  const entry = existingCreate ?? entryFromChange(change, id, revision, current?.status ?? "active");
@@ -489,7 +400,7 @@ export async function applyLocalMemoryResult(input) {
489
400
  : item),
490
401
  entry,
491
402
  ];
492
- const allowEvictionForChange = !fullStorage && change.operation === "create" && change.priority === "high";
403
+ const allowEvictionForChange = change.operation === "create" && change.priority === "high";
493
404
  const protectedIds = new Set(allowEvictionForChange ? pinnedIds(entries) : activeOrPinnedIds(entries));
494
405
  if (allowEvictionForChange)
495
406
  allowActiveEviction = true;
@@ -506,7 +417,7 @@ export async function applyLocalMemoryResult(input) {
506
417
  const notePath = resolve(input.agentDir, entry.file);
507
418
  if (!isWithin(resolve(input.agentDir, "notes"), notePath))
508
419
  throw new Error("local_memory_note_path_invalid");
509
- const previous = await readStoredNote(notePath);
420
+ const previous = noteUpdates.get(notePath) ?? await readNote(notePath);
510
421
  const replacement = noteSection(id, revision, change.title, change.detailBody);
511
422
  const existingSection = replaceNote(previous, id, replacement);
512
423
  const next = existingSection ?? (current === undefined
@@ -524,7 +435,7 @@ export async function applyLocalMemoryResult(input) {
524
435
  // Pending create candidates are durable overflow, not dead ends. Promote only
525
436
  // when the current catalog has room; supersede/update candidates stay pending
526
437
  // until a fresh revision-aware decision can safely replay them.
527
- const pendingCandidatesOnDisk = fullStorage ? [] : await readPendingMemoryCandidates({ agentDir: input.agentDir }).catch((error) => {
438
+ const pendingCandidatesOnDisk = await readPendingMemoryCandidates({ agentDir: input.agentDir }).catch((error) => {
528
439
  if (!(error instanceof Error) || error.message !== "memory_pending_directory_over_budget")
529
440
  throw error;
530
441
  // 自动提升是可选工作,目录查询预算不应阻断本轮已验证的更新或腾位操作。
@@ -549,7 +460,7 @@ export async function applyLocalMemoryResult(input) {
549
460
  || normalize(entry.summary) === normalize(change.summary)));
550
461
  if (duplicate !== undefined) {
551
462
  const duplicatePath = resolve(input.agentDir, duplicate.file);
552
- const duplicateBody = readNoteBody(await readStoredNote(duplicatePath), duplicate.id);
463
+ const duplicateBody = readNoteBody(noteUpdates.get(duplicatePath) ?? await readNote(duplicatePath), duplicate.id);
553
464
  if (duplicateBody === change.detailBody
554
465
  || duplicateBody === unwrappedNoteBody(change.title, change.detailBody).trim()) {
555
466
  resolvedPendingIds.add(pending.pendingId);
@@ -567,7 +478,7 @@ export async function applyLocalMemoryResult(input) {
567
478
  const notePath = resolve(input.agentDir, entry.file);
568
479
  if (!isWithin(resolve(input.agentDir, "notes"), notePath))
569
480
  throw new Error("local_memory_note_path_invalid");
570
- const previous = await readStoredNote(notePath);
481
+ const previous = noteUpdates.get(notePath) ?? await readNote(notePath);
571
482
  const replacement = noteSection(id, 1, change.title, change.detailBody);
572
483
  const existingSection = replaceNote(previous, id, replacement);
573
484
  const next = existingSection ?? `${previous.trimEnd()}${previous.trimEnd() ? "\n\n" : ""}${replacement}`;
@@ -576,17 +487,6 @@ export async function applyLocalMemoryResult(input) {
576
487
  createdIds.push(id);
577
488
  resolvedPendingIds.add(pending.pendingId);
578
489
  }
579
- if (fullStorage) {
580
- const changedMetadataIds = new Set([
581
- ...statusChangedIds,
582
- ...input.result.changes.flatMap(change => change.supersedesMemoryId === null ? [] : [change.supersedesMemoryId]),
583
- ]);
584
- for (const id of changedMetadataIds) {
585
- const entry = entries.find(item => item.id === id);
586
- const notePath = resolve(input.agentDir, entry.file);
587
- noteUpdates.set(notePath, updateNoteRevision(await readStoredNote(notePath), id, entry.revision));
588
- }
589
- }
590
490
  let finalProjection = projectIndex(memory, entries, allowActiveEviction ? pinnedIds(entries) : activeOrPinnedIds(entries));
591
491
  if (finalProjection.reason !== null
592
492
  && (!allowActiveEviction || finalProjection.reason === "index_over_budget_pinned")) {
@@ -598,7 +498,7 @@ export async function applyLocalMemoryResult(input) {
598
498
  .filter((entry) => entry?.status === "active");
599
499
  for (const entry of omittedActiveEntries) {
600
500
  const notePath = resolve(input.agentDir, entry.file);
601
- const content = await readStoredNote(notePath);
501
+ const content = noteUpdates.get(notePath) ?? await readNote(notePath);
602
502
  const detailBody = readNoteBody(content, entry.id);
603
503
  const change = detailBody === null ? null : archivedChange(entry, detailBody);
604
504
  if (change === null)
@@ -619,12 +519,6 @@ export async function applyLocalMemoryResult(input) {
619
519
  if (finalProjection.reason !== null)
620
520
  throw new Error(finalProjection.reason);
621
521
  }
622
- // Complete every resource check before the first persistent write.
623
- assertLocalMemoryStorageSize(finalProjection.memory);
624
- for (const content of noteUpdates.values()) {
625
- if (Buffer.byteLength(content, "utf8") > LOCAL_MEMORY_NOTE_BYTE_CAP)
626
- throw new Error("local_memory_note_byte_limit");
627
- }
628
522
  for (const candidate of pendingCandidates)
629
523
  await persistPendingMemoryCandidate({ agentDir: input.agentDir, candidate });
630
524
  for (const [path, content] of noteUpdates)
@@ -641,5 +535,5 @@ export async function applyLocalMemoryResult(input) {
641
535
  deferredIds,
642
536
  pendingIds: deferredIds,
643
537
  };
644
- }));
538
+ });
645
539
  }
@@ -1,5 +1,5 @@
1
1
  import { createHash } from "node:crypto";
2
- import { lstat, readFile, readdir, stat } from "node:fs/promises";
2
+ import { readFile, stat } from "node:fs/promises";
3
3
  import { isAbsolute, join, normalize, relative, resolve } from "node:path";
4
4
  import { parseArgs } from "node:util";
5
5
  import { capMemoryForInject, MEMORY_INJECT_CAP } from "./prompt.js";
@@ -39,52 +39,13 @@ async function inspectFile(path, signal) {
39
39
  return { ...base, error_code: errorCode(error) };
40
40
  }
41
41
  }
42
- async function inspectPendingDirectory(path, signal) {
43
- let metadata;
44
- try {
45
- metadata = await lstat(path);
46
- }
47
- catch (error) {
48
- const code = errorCode(error);
49
- return code === "ENOENT" ? { exists: false, entry_count: 0 } : { exists: false, error_code: code };
50
- }
51
- const base = { exists: true, mtime_ms: metadata.mtimeMs };
52
- if (metadata.isSymbolicLink() || !metadata.isDirectory())
53
- return { ...base, hash_skipped_reason: "not_regular_file" };
54
- try {
55
- const names = (await readdir(path, { withFileTypes: true }))
56
- .filter(entry => entry.name.endsWith(".json"))
57
- .sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0);
58
- if (names.length > 128)
59
- return { ...base, entry_count: names.length, error_code: "entry_limit" };
60
- const hash = createHash("sha256");
61
- let size = 0;
62
- for (const entry of names) {
63
- if (signal.aborted)
64
- throw signal.reason;
65
- if (!entry.isFile() || entry.isSymbolicLink())
66
- return { ...base, entry_count: names.length, error_code: "invalid_entry" };
67
- const fact = await inspectFile(join(path, entry.name), signal);
68
- if (!fact.exists || fact.sha256 === undefined || fact.error_code !== undefined
69
- || fact.hash_skipped_reason !== undefined)
70
- return { ...base, entry_count: names.length, error_code: "incomplete_entry" };
71
- size += fact.size_bytes ?? 0;
72
- hash.update(entry.name).update("\0").update(fact.sha256).update("\0");
73
- }
74
- return { ...base, size_bytes: size, entry_count: names.length, sha256: hash.digest("hex") };
75
- }
76
- catch (error) {
77
- return { ...base, error_code: errorCode(error) };
78
- }
79
- }
80
42
  export async function inspectLocalMemoryFilesWithinDeadline(homeDir, timeoutMs) {
81
43
  const controller = new AbortController();
82
44
  let timer;
83
45
  const inspection = Promise.all([
84
46
  inspectFile(join(homeDir, "MEMORY.md"), controller.signal),
85
47
  inspectFile(join(homeDir, "notes", "lessons.md"), controller.signal),
86
- inspectPendingDirectory(join(homeDir, ".crew", "memory", "pending"), controller.signal),
87
- ]).then(([memory, lessons, pending]) => ({ memory, lessons, pending }));
48
+ ]).then(([memory, lessons]) => ({ memory, lessons }));
88
49
  const timeout = new Promise((_resolve, reject) => {
89
50
  timer = setTimeout(() => {
90
51
  controller.abort();
@@ -38,7 +38,6 @@ export function logLocalMemoryDiagnosticsFailure(identity, phase, error) {
38
38
  function snapshotFields(snapshot) {
39
39
  if (snapshot === null)
40
40
  return {};
41
- const pending = snapshot.pending ?? { exists: false, entry_count: 0 };
42
41
  return {
43
42
  memory_exists: snapshot.memory.exists,
44
43
  memory_size_bytes: snapshot.memory.size_bytes,
@@ -55,12 +54,6 @@ function snapshotFields(snapshot) {
55
54
  lessons_hash_skipped_reason: snapshot.lessons.hash_skipped_reason,
56
55
  lessons_error_code: snapshot.lessons.error_code,
57
56
  lessons_markdown_heading_count: snapshot.lessons.markdown_heading_count,
58
- pending_exists: pending.exists,
59
- pending_size_bytes: pending.size_bytes,
60
- pending_mtime_ms: pending.mtime_ms,
61
- pending_sha256: pending.sha256,
62
- pending_error_code: pending.error_code,
63
- pending_entry_count: pending.entry_count,
64
57
  };
65
58
  }
66
59
  function promptDelivery(runtime, stableProtocolRuntime) {
@@ -190,13 +183,10 @@ export function createLocalMemoryTelemetry(options) {
190
183
  const lessonsChanged = beforeSnapshot !== null && afterSnapshot !== null
191
184
  ? localMemoryFileChanged(beforeSnapshot.lessons, afterSnapshot.lessons)
192
185
  : undefined;
193
- const pendingChanged = beforeSnapshot !== null && afterSnapshot !== null
194
- ? localMemoryFileChanged(beforeSnapshot.pending ?? { exists: false }, afterSnapshot.pending ?? { exists: false })
195
- : undefined;
196
186
  const accessSummary = accessObserver.summary();
197
- const sharedFilesChanged = memoryChanged === undefined || lessonsChanged === undefined || pendingChanged === undefined
187
+ const sharedFilesChanged = memoryChanged === undefined || lessonsChanged === undefined
198
188
  ? undefined
199
- : memoryChanged || lessonsChanged || pendingChanged;
189
+ : memoryChanged || lessonsChanged;
200
190
  safeLog("local_memory.execution_observed", "本地记忆执行观察已完成", {
201
191
  execution_id: options.executionId,
202
192
  agent_handle: options.agentHandle,
@@ -210,7 +200,6 @@ export function createLocalMemoryTelemetry(options) {
210
200
  executor_outcome: executorCompleted ? "succeeded" : "failed",
211
201
  memory_changed: memoryChanged,
212
202
  lessons_changed: lessonsChanged,
213
- pending_changed: pendingChanged,
214
203
  shared_files_changed_during_execution: sharedFilesChanged,
215
204
  unexpected_shared_write: options.isMemoryPrune
216
205
  ? undefined
@@ -235,12 +224,6 @@ export function createLocalMemoryTelemetry(options) {
235
224
  lessons_after_hash_skipped_reason: afterSnapshot.lessons.hash_skipped_reason,
236
225
  lessons_after_error_code: afterSnapshot.lessons.error_code,
237
226
  lessons_after_markdown_heading_count: afterSnapshot.lessons.markdown_heading_count,
238
- pending_after_exists: afterSnapshot.pending?.exists ?? false,
239
- pending_after_size_bytes: afterSnapshot.pending?.size_bytes,
240
- pending_after_mtime_ms: afterSnapshot.pending?.mtime_ms,
241
- pending_after_sha256: afterSnapshot.pending?.sha256,
242
- pending_after_error_code: afterSnapshot.pending?.error_code,
243
- pending_after_entry_count: afterSnapshot.pending?.entry_count ?? 0,
244
227
  }),
245
228
  });
246
229
  },
@@ -25,7 +25,6 @@ import { RUNTIME_HEALTH_PROBE_CAPABILITY } from "./runtime-health.js";
25
25
  import { probeDeepSeekHarnessAcp, deepSeekHarnessLauncher } from "./runtimes/deepseek-harness.js";
26
26
  import { daemonHome } from "./computer-profile.js";
27
27
  import { daemonReleaseProvenance } from "./release-provenance.js";
28
- import { MEMORY_MIGRATION_CAPABILITY, MEMORY_STORAGE_V2_CAPABILITY, MEMORY_STATE_GUARD_CAPABILITY } from "./memory-migration-protocol.js";
29
28
  export { executableRuntimes } from "./runtime-capabilities.js";
30
29
  const execFileP = promisify(execFile);
31
30
  export const PROJECT_WORKSPACES_CAPABILITY = "project_workspaces_v1";
@@ -40,7 +39,6 @@ export const NATIVE_PROJECT_WORKSPACE_READINESS = Object.freeze({
40
39
  });
41
40
  export const DAEMON_CAPABILITIES = Object.freeze([
42
41
  MARKETPLACE_CAPABILITY,
43
- MEMORY_MIGRATION_CAPABILITY, MEMORY_STORAGE_V2_CAPABILITY, MEMORY_STATE_GUARD_CAPABILITY,
44
42
  "scheduled_job_v1",
45
43
  "reply_origin_v1",
46
44
  "origin_decision_v1",
@@ -75,7 +73,6 @@ export const daemonCapabilities = (runtimePlatform = process.platform, readiness
75
73
  return Object.freeze(DAEMON_CAPABILITIES.filter((capability) => ((capability !== MARKETPLACE_CAPABILITY || nativeWorkspacePlatform)
76
74
  && (capability !== PROJECT_WORKSPACES_CAPABILITY || nativeWorkspaceReady)
77
75
  && (capability !== "message_file_preview_v1" || nativeWorkspacePlatform)
78
- && (nativeWorkspacePlatform || ![MEMORY_MIGRATION_CAPABILITY, MEMORY_STORAGE_V2_CAPABILITY, MEMORY_STATE_GUARD_CAPABILITY].includes(capability))
79
76
  && (nativeWorkspacePlatform
80
77
  || (capability !== "project_skills_v1"
81
78
  && capability !== "project_skill_projection_v2"
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  // 与另一个进程中的 marketplace-protocol.ts 保持一致;跨进程契约测试校验摘要。
3
3
  export const MARKETPLACE_CAPABILITY = "marketplace_update_v1";
4
4
  export const MARKETPLACE = "nowwork-pm";
5
- export const PLUGIN = "aiinterview-plugin";
5
+ export const PLUGIN = "AIinterview-plugin";
6
6
  export const MarketplaceModeSchema = z.enum(["inspect", "refresh", "update"]);
7
7
  export const MarketplaceStatusSchema = z.enum(["queued", "running", "completed", "partial", "failed", "unknown"]);
8
8
  export const MarketplaceTargetSchema = z.object({
@@ -10,7 +10,7 @@ const Target = z.object({
10
10
  version: z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._+-]{0,79}$/),
11
11
  source: z.object({ source: z.literal("git-subdir"),
12
12
  url: z.literal("git@codeup.aliyun.com:6128d2e757e7cd986dfae5ab/pm/AIinterview-agent-skill.git"),
13
- path: z.literal("plugins/aiinterview-plugin"), sha: z.string().regex(/^[a-f0-9]{40}$/) }),
13
+ path: z.literal("plugins/AIinterview-plugin"), sha: z.string().regex(/^[a-f0-9]{40}$/) }),
14
14
  });
15
15
  export async function readRemoteMarketplace(runtime, registered, env, command) {
16
16
  const source = validateMarketplaceSource(registered.url, registered.ref);
@@ -12,7 +12,7 @@ import { readMarketplaceSource } from "./marketplace-source.js";
12
12
  export { MarketplaceFailure, runMarketplaceCommand } from "./marketplace-command.js";
13
13
  const SELECTOR = `${PLUGIN}@${MARKETPLACE}`;
14
14
  const SOURCE = "git@codeup.aliyun.com:6128d2e757e7cd986dfae5ab/pm/AIinterview-agent-skill.git";
15
- const SOURCE_PATH = "plugins/aiinterview-plugin";
15
+ const SOURCE_PATH = "plugins/AIinterview-plugin";
16
16
  const obj = (x) => x !== null && typeof x === "object" && !Array.isArray(x) ? x : {};
17
17
  const parse = (text) => { try {
18
18
  return JSON.parse(text);
@@ -7,7 +7,6 @@ import { dslog } from "./slog.js";
7
7
  const TRACE_PATTERN = /\[memory-prune trace_id=([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\]/i;
8
8
  export const MEMORY_PRUNE_HASH_LIMIT_BYTES = 10 * 1024 * 1024;
9
9
  export const MEMORY_PRUNE_NOTES_MANIFEST_LIMIT = 128;
10
- export const MEMORY_PRUNE_PENDING_MANIFEST_LIMIT = 128;
11
10
  export const MEMORY_PRUNE_NOTE_CHANGE_LIMIT = 128;
12
11
  function compareCodeUnits(left, right) {
13
12
  return left < right ? -1 : left > right ? 1 : 0;
@@ -193,50 +192,6 @@ export async function inspectMemoryPruneNotes(homeDir, signal) {
193
192
  ...(signal?.aborted ? { error: "ABORT_ERR" } : {}),
194
193
  };
195
194
  }
196
- export async function inspectMemoryPrunePending(homeDir, signal) {
197
- const pendingDir = join(homeDir, ".crew", "memory", "pending");
198
- try {
199
- const metadata = await lstat(pendingDir);
200
- if (metadata.isSymbolicLink())
201
- return { files: [], total_count: 0, omitted_count: 0, truncated: false, error: "symbolic_link" };
202
- if (!metadata.isDirectory())
203
- return { files: [], total_count: 0, omitted_count: 0, truncated: false, error: "ENOTDIR" };
204
- }
205
- catch (error) {
206
- if (error.code === "ENOENT")
207
- return { files: [], total_count: 0, omitted_count: 0, truncated: false };
208
- return { files: [], total_count: 0, omitted_count: 0, truncated: false, error: diagnosticError(error) };
209
- }
210
- let names;
211
- try {
212
- names = (await readdir(pendingDir, { withFileTypes: true }))
213
- .filter(entry => (entry.isFile() || entry.isSymbolicLink()) && entry.name.endsWith(".json"))
214
- .map(entry => entry.name).sort(compareCodeUnits);
215
- }
216
- catch (error) {
217
- return { files: [], total_count: 0, omitted_count: 0, truncated: false, error: diagnosticError(error) };
218
- }
219
- const selected = names.slice(0, MEMORY_PRUNE_PENDING_MANIFEST_LIMIT);
220
- const files = [];
221
- for (const name of selected) {
222
- if (signal?.aborted)
223
- break;
224
- const path = join(pendingDir, name);
225
- try {
226
- if ((await lstat(path)).isSymbolicLink()) {
227
- files.push({ relative_path: `.crew/memory/pending/${name}`, exists: false, error: "symbolic_link" });
228
- continue;
229
- }
230
- }
231
- catch (error) {
232
- files.push({ relative_path: `.crew/memory/pending/${name}`, exists: false, error: diagnosticError(error) });
233
- continue;
234
- }
235
- files.push({ relative_path: `.crew/memory/pending/${name}`, ...await inspectFile(path, false, undefined, signal) });
236
- }
237
- return { files, total_count: names.length, omitted_count: Math.max(0, names.length - selected.length),
238
- truncated: names.length > selected.length, ...(signal?.aborted ? { error: "ABORT_ERR" } : {}) };
239
- }
240
195
  async function inspectMemoryPruneFixedFiles(homeDir, runDir, workLogPath, signal) {
241
196
  const cwdIsHome = runDir === homeDir;
242
197
  const [memory, lessons, cwdMemory, cwdLessons, workLog] = await Promise.all([
@@ -255,17 +210,15 @@ async function inspectMemoryPruneFixedFiles(homeDir, runDir, workLogPath, signal
255
210
  };
256
211
  }
257
212
  export async function inspectMemoryPruneFiles(homeDir, runDir, workLogPath, signal) {
258
- const [fixedFiles, notesManifest, pendingManifest] = await Promise.all([
213
+ const [fixedFiles, notesManifest] = await Promise.all([
259
214
  inspectMemoryPruneFixedFiles(homeDir, runDir, workLogPath, signal),
260
215
  inspectMemoryPruneNotes(homeDir, signal),
261
- inspectMemoryPrunePending(homeDir, signal),
262
216
  ]);
263
- return { ...fixedFiles, notes_manifest: notesManifest, pending_manifest: pendingManifest };
217
+ return { ...fixedFiles, notes_manifest: notesManifest };
264
218
  }
265
219
  export async function inspectMemoryPruneFilesWithinDeadline(homeDir, runDir, workLogPath, timeoutMs) {
266
220
  const fixedFiles = await withinMemoryPruneDiagnosticsDeadline((signal) => inspectMemoryPruneFixedFiles(homeDir, runDir, workLogPath, signal), timeoutMs);
267
221
  let notesManifest;
268
- let pendingManifest;
269
222
  try {
270
223
  notesManifest = await withinMemoryPruneDiagnosticsDeadline((signal) => inspectMemoryPruneNotes(homeDir, signal), timeoutMs);
271
224
  }
@@ -278,13 +231,7 @@ export async function inspectMemoryPruneFilesWithinDeadline(homeDir, runDir, wor
278
231
  error: diagnosticError(error),
279
232
  };
280
233
  }
281
- try {
282
- pendingManifest = await withinMemoryPruneDiagnosticsDeadline(signal => inspectMemoryPrunePending(homeDir, signal), timeoutMs);
283
- }
284
- catch (error) {
285
- pendingManifest = { files: [], total_count: 0, omitted_count: 0, truncated: false, error: diagnosticError(error) };
286
- }
287
- return { ...fixedFiles, notes_manifest: notesManifest, pending_manifest: pendingManifest };
234
+ return { ...fixedFiles, notes_manifest: notesManifest };
288
235
  }
289
236
  export async function withinMemoryPruneDiagnosticsDeadline(operation, timeoutMs) {
290
237
  const controller = new AbortController();
@@ -414,7 +361,6 @@ export function evaluateMemoryPrunePostcondition(before, after, execution) {
414
361
  && (after.cwd_memory.lessons_reference_count ?? 0) > 0,
415
362
  cwd_lessons_changed: !after.cwd_lessons.same_as_shared_path
416
363
  && fileChanged(before.cwd_lessons, after.cwd_lessons),
417
- pending_changed: diffMemoryPruneNotes(before.pending_manifest ?? { files: [], total_count: 0, omitted_count: 0, truncated: false }, after.pending_manifest ?? { files: [], total_count: 0, omitted_count: 0, truncated: false }).change_count > 0,
418
364
  };
419
365
  let outcome;
420
366
  if (!execution.executorCompleted)
@@ -442,8 +388,6 @@ export function evaluateMemoryPrunePostcondition(before, after, execution) {
442
388
  outcome = "promoted_without_index_change";
443
389
  else if (facts.shared_memory_changed)
444
390
  outcome = "shared_memory_updated";
445
- else if (facts.pending_changed)
446
- outcome = "pending_updated";
447
391
  else
448
392
  outcome = "no_files_changed";
449
393
  return { outcome, ...facts };
@@ -464,7 +408,7 @@ function memoryPruneFileFactFields(fileFacts) {
464
408
  }
465
409
  return fields;
466
410
  }
467
- export function memoryPruneSnapshotFields({ notes_manifest: _notesManifest, pending_manifest: _pendingManifest, ...fileFacts }) {
411
+ export function memoryPruneSnapshotFields({ notes_manifest: _notesManifest, ...fileFacts }) {
468
412
  return memoryPruneFileFactFields(fileFacts);
469
413
  }
470
414
  export function logMemoryPruneDiagnosticsFailure(input, traceId, phase, error) {
@@ -9,7 +9,6 @@ import { z } from "zod";
9
9
  import { isInternalEnvironmentPath } from "./workspace-fs.js";
10
10
  import { opaqueKey, safeKey } from "./workspace.js";
11
11
  import { AgentHandleSchema } from "./execution-protocol.js";
12
- import { withMemoryAccess } from "./local-memory/migration-access.js";
13
12
  const MAX_BYTES = 256 * 1024;
14
13
  const MAX_BINARY_BYTES = 8 * 1024 * 1024;
15
14
  const MAX_CONCURRENT_READS = 4;
@@ -232,16 +231,7 @@ export async function readSharedMessageFile(agentsRoot, rawRequest, registry) {
232
231
  throw new SharedFileError("file_preview_busy");
233
232
  activeReads++;
234
233
  try {
235
- const candidate = await resolveCandidate(agentsRoot, parsed.data, registry);
236
- const agentRoot = await realpath(resolve(agentsRoot, parsed.data.handle)).catch((error) => {
237
- if (error.code === "ENOENT")
238
- return undefined;
239
- throw error;
240
- });
241
- // 记忆保护只用于该Agent根内资料,独立项目文件仍按原执行授权读取。
242
- return await (agentRoot && inside(agentRoot, candidate.path)
243
- ? withMemoryAccess(agentRoot, () => readCandidate(candidate))
244
- : readCandidate(candidate));
234
+ return await readCandidate(await resolveCandidate(agentsRoot, parsed.data, registry));
245
235
  }
246
236
  catch (error) {
247
237
  if (error instanceof SharedFileError)
package/dist/prompt.js CHANGED
@@ -5,7 +5,6 @@
5
5
  * claim-before-work、freshness/draft、"做完所有事再停"、inbox notice 语义、
6
6
  * 分层记忆与压缩安全、协作礼仪。措辞为本项目原创。
7
7
  */
8
- import { detectLocalMemoryStorageVersion, selectLocalMemoryPreview } from "./local-memory/storage-format.js";
9
8
  /** work-log 注入上限(字符):防冷启动注入随文件膨胀。超限保头(目标/结论)+尾(最近进展),
10
9
  * 截中段并提示读全文——全文仍在盘上,只限"默认推送量"不限"可获取量"。纯函数。 */
11
10
  export const WORKLOG_INJECT_CAP = 8000;
@@ -68,10 +67,7 @@ export function capWorkLogForInject(workLog, cap = WORKLOG_INJECT_CAP) {
68
67
  const tail = workLog.slice(-WORKLOG_TAIL);
69
68
  return `${head}\n…(work-log 过长已截去中段,全文用 Read 读 $CREW_TASK_LOG)\n${tail}`;
70
69
  }
71
- export function capMemoryForInject(memory, cap = MEMORY_INJECT_CAP, maxBytes = Number.POSITIVE_INFINITY, query = "") {
72
- if (detectLocalMemoryStorageVersion(memory) === 2) {
73
- return selectLocalMemoryPreview(memory, query, { maxCodePoints: cap, maxBytes }).memory;
74
- }
70
+ export function capMemoryForInject(memory, cap = MEMORY_INJECT_CAP, maxBytes = Number.POSITIVE_INFINITY) {
75
71
  if (memory.length <= cap && Buffer.byteLength(memory, "utf8") <= maxBytes)
76
72
  return memory;
77
73
  const notice = "[MEMORY.md preview truncated; use crew-memory search/read for more.]\n";
package/dist/runner.js CHANGED
@@ -80,7 +80,7 @@ async function runAgentWithMachineEnvironment(config, input, onActivity = defaul
80
80
  ? { scheduledExternalNotificationPolicy: input.scheduled.externalNotificationPolicy }
81
81
  : {}),
82
82
  ...(input.wakeOrigin ? { wakeOrigin: input.wakeOrigin } : {}),
83
- memory: capMemoryForInject(workspace.memory, undefined, undefined, baseWake),
83
+ memory: capMemoryForInject(workspace.memory),
84
84
  ...(resuming ? {} : { workLog: capWorkLogForInject(workspace.workLog) }),
85
85
  collaborationToolsEnabled: config.codexCollaborationTools && runtime === "codex",
86
86
  localMemoryV2Enabled: workspace.localMemoryV2Enabled ?? localMemoryV2Enabled,