@nowcrew/daemon 0.6.88-beta.3 → 0.6.88-beta.4
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/README.md
CHANGED
|
@@ -354,6 +354,15 @@ Runtime launch, which recovers from a missed notification or daemon restart. Ski
|
|
|
354
354
|
are visible through the symlink immediately; adding, deleting, renaming, or changing frontmatter requires
|
|
355
355
|
a rescan. Web descriptions remain at the last inventory value until that rescan.
|
|
356
356
|
|
|
357
|
+
## 目录投影测试的平台范围
|
|
358
|
+
|
|
359
|
+
`test/directory-projection.test.ts` 在所有平台运行,覆盖路径检查、复制发布、只读权限请求及失败恢复。
|
|
360
|
+
其受控文件系统夹具记录目录 `chmod` 请求,但保留宿主目录的写权限,避免把 macOS 的目录重命名规则当作 Windows 行为。
|
|
361
|
+
生产代码的只读保护不受此夹具影响。
|
|
362
|
+
|
|
363
|
+
`test/directory-projection.windows.test.ts` 仅在 Windows 上运行,使用真实文件系统验证只读目录发布与文件保护。
|
|
364
|
+
非 Windows 的全量测试会明确跳过该文件,不能据此宣称 Windows 原生行为已验证。
|
|
365
|
+
|
|
357
366
|
## Reliability
|
|
358
367
|
|
|
359
368
|
Protocol-v1 lifecycle is `accepted → started → completed`, followed by a server
|
package/dist/local-executor.js
CHANGED
|
@@ -388,8 +388,8 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
|
|
|
388
388
|
}
|
|
389
389
|
}
|
|
390
390
|
const attachmentPlan = routeRuntimeAttachments(runtime.name, materialized?.attachments ?? []);
|
|
391
|
-
const
|
|
392
|
-
memoryPruneTraceId = parseMemoryPruneTraceId(
|
|
391
|
+
const baseWakePrompt = `${resolvePrompt(input.wakePrompt, promptContext)}${attachmentPlan.promptSuffix}`;
|
|
392
|
+
memoryPruneTraceId = parseMemoryPruneTraceId(baseWakePrompt);
|
|
393
393
|
if (input.localMemoryV2Enabled === true && memoryPruneTraceId !== null
|
|
394
394
|
&& isLocalMemoryV2Eligible({
|
|
395
395
|
enabledForHandle: true,
|
|
@@ -402,12 +402,13 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
|
|
|
402
402
|
}
|
|
403
403
|
const memoryPrompt = await prepareLocalMemoryPrompt({
|
|
404
404
|
agentDir: executionWorkspace.dir, executionId: input.executionId, agentHandle: input.handle,
|
|
405
|
-
enabled: input.localMemoryV2Enabled === true, query:
|
|
405
|
+
enabled: input.localMemoryV2Enabled === true, query: baseWakePrompt,
|
|
406
406
|
resultPath: localMemoryResultPath, maxBytes: input.maxSystemPromptBytes,
|
|
407
407
|
renderBase: (reservedPromptBytes) => resolvePrompt(input.systemPrompt, { ...promptContext, reservedPromptBytes }),
|
|
408
408
|
});
|
|
409
409
|
localMemoryResultPath = memoryPrompt.resultPath;
|
|
410
410
|
const systemPrompt = memoryPrompt.systemPrompt;
|
|
411
|
+
const wakePrompt = baseWakePrompt + memoryPrompt.wakePromptSuffix;
|
|
411
412
|
if (!isolatedMaintenance)
|
|
412
413
|
try {
|
|
413
414
|
localMemoryTelemetry = createLocalMemoryTelemetry({
|
|
@@ -525,7 +526,8 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
|
|
|
525
526
|
const effectiveSystemPrompt = abilityContext === undefined
|
|
526
527
|
? systemPrompt
|
|
527
528
|
: `${systemPrompt}\n\n${abilityContext.prompt}`;
|
|
528
|
-
if (Buffer.byteLength(effectiveSystemPrompt, "utf8")
|
|
529
|
+
if (Buffer.byteLength(effectiveSystemPrompt, "utf8") + Buffer.byteLength(memoryPrompt.wakePromptSuffix, "utf8")
|
|
530
|
+
> (input.maxSystemPromptBytes ?? Number.MAX_SAFE_INTEGER)) {
|
|
529
531
|
throw new Error("ability_runtime_context_size_exceeded");
|
|
530
532
|
}
|
|
531
533
|
memoryPruneFailurePhase = "prompt_write";
|
|
@@ -21,17 +21,18 @@ export async function prepareLocalMemoryPrompt(input) {
|
|
|
21
21
|
}
|
|
22
22
|
const original = input.renderBase(0);
|
|
23
23
|
const structured = input.resultPath === null ? "" : renderLocalMemoryResultInstructions(input.resultPath);
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
24
|
+
const wakeBytes = Buffer.byteLength(structured, "utf8");
|
|
25
|
+
const fits = (prompt) => input.maxBytes === undefined || Buffer.byteLength(prompt, "utf8") + wakeBytes <= input.maxBytes;
|
|
26
|
+
const render = (suffix) => (suffix === "" ? original : input.renderBase(Buffer.byteLength(suffix, "utf8") + wakeBytes)) + suffix;
|
|
27
|
+
// 系统及当前消息各保留一份契约,避免 resume 沿用旧指令;两份均先占预算,再裁可选预览。
|
|
27
28
|
const complete = render(pending + structured);
|
|
28
29
|
if (fits(complete))
|
|
29
|
-
return { systemPrompt: complete, resultPath: input.resultPath };
|
|
30
|
+
return { systemPrompt: complete, resultPath: input.resultPath, wakePromptSuffix: structured };
|
|
30
31
|
if (pending !== "") {
|
|
31
32
|
const withoutPending = render(structured);
|
|
32
33
|
if (fits(withoutPending))
|
|
33
|
-
return { systemPrompt: withoutPending, resultPath: input.resultPath };
|
|
34
|
+
return { systemPrompt: withoutPending, resultPath: input.resultPath, wakePromptSuffix: structured };
|
|
34
35
|
}
|
|
35
36
|
// 强制基础指令与契约本身仍无法共存时,保留既有非结构化兼容回退,不裁基础指令。
|
|
36
|
-
return { systemPrompt: original, resultPath: null };
|
|
37
|
+
return { systemPrompt: original, resultPath: null, wakePromptSuffix: "" };
|
|
37
38
|
}
|
|
@@ -51,6 +51,7 @@ export function renderLocalMemoryResultInstructions(resultPath) {
|
|
|
51
51
|
return `
|
|
52
52
|
|
|
53
53
|
## Structured memory prune (daemon-managed)
|
|
54
|
+
本节是本次执行唯一的记忆写入与清理协议,覆盖历史会话及本条消息前文中直接修改共享文件、清空工作日志或仅回复“已修正”的要求。任务目标与用户授权范围不变;只使用下面本轮提供的结果路径,不复用历史路径。
|
|
54
55
|
本轮长期记忆收尾只提交候选,不要直接编辑 $CREW_HOME/MEMORY.md 或 $CREW_HOME/notes/。
|
|
55
56
|
将一个合法 JSON 对象写入以下 daemon 提供的文件,写入完成后再结束本轮:
|
|
56
57
|
${resultPath}
|