@nowcrew/daemon 0.6.12 → 0.6.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.
- package/dist/memory-prune-diagnostics.js +6 -0
- package/dist/prompt.js +15 -8
- package/dist/slog.js +11 -0
- package/dist/workspace.js +18 -17
- package/package.json +2 -2
|
@@ -372,6 +372,10 @@ export function evaluateMemoryPrunePostcondition(before, after, execution) {
|
|
|
372
372
|
outcome = "source_work_log_empty";
|
|
373
373
|
else if (!facts.work_log_cleared)
|
|
374
374
|
outcome = "work_log_not_cleared";
|
|
375
|
+
else if (!after.memory.exists)
|
|
376
|
+
outcome = "shared_memory_missing_after";
|
|
377
|
+
else if ((after.memory.size ?? 0) === 0)
|
|
378
|
+
outcome = "shared_memory_empty_after";
|
|
375
379
|
else if (facts.lessons_changed && facts.shared_memory_has_lessons_reference) {
|
|
376
380
|
outcome = "promoted_and_indexed";
|
|
377
381
|
}
|
|
@@ -381,6 +385,8 @@ export function evaluateMemoryPrunePostcondition(before, after, execution) {
|
|
|
381
385
|
}
|
|
382
386
|
else if (facts.lessons_changed)
|
|
383
387
|
outcome = "promoted_without_index_change";
|
|
388
|
+
else if (facts.shared_memory_changed)
|
|
389
|
+
outcome = "shared_memory_updated";
|
|
384
390
|
else
|
|
385
391
|
outcome = "no_files_changed";
|
|
386
392
|
return { outcome, ...facts };
|
package/dist/prompt.js
CHANGED
|
@@ -82,7 +82,7 @@ export function buildSystemPrompt(ctx) {
|
|
|
82
82
|
// 消息、没有 task,这条规则字面上无法执行,省略(2026-07-13 复审 Minor 5)。
|
|
83
83
|
const claimRule = scheduled
|
|
84
84
|
? ""
|
|
85
|
-
: "\n-
|
|
85
|
+
: "\n- **除定时任务创建与管理和 memory_prune 外,动手干活前必须先 `crew task claim`**;claim 失败就转做别的任务。";
|
|
86
86
|
// "一线程一 task 且必须带 --thread"与"进度/产出回本线程,严禁发到顶层"都建立在"本轮有一条
|
|
87
87
|
// 触发消息、线程根即为该消息 id"这个前提上——scheduled run 没有触发消息、没有 thread 锚点,
|
|
88
88
|
// 唯一输出路径就是频道顶层 `--send-draft`,与这两条正面矛盾且 --thread 参数根本填不出来,
|
|
@@ -114,14 +114,14 @@ export function buildSystemPrompt(ctx) {
|
|
|
114
114
|
: "- **始终只通过 crew CLI 发声。在 crew 命令之外产生的任何文字都不会送达任何人。**";
|
|
115
115
|
const actionRule = scheduled
|
|
116
116
|
? `- **判定规则**:直接执行本轮定时指令,执行前不需要 claim。${threadTaskRule}${progressRule}`
|
|
117
|
-
: `-
|
|
117
|
+
: `- **判定规则**:定时任务创建与管理和 memory_prune 无需 task claim,只遵守各自唤醒指令;其它来信若需要你"回复之外的动作"(跑工具/改代码/做变更),先 claim;若只是回答问题或闲聊,无需 claim。${threadTaskRule}${progressRule}`;
|
|
118
118
|
const taskAndScheduleCommands = alwaysReport
|
|
119
119
|
? `4. **\`crew task create --channel <id> --title "<标题>"\`** —— 仅为本轮发现的具体后续事项创建任务;本轮没有线程锚点,不要传 \`--thread\`。`
|
|
120
120
|
: scheduled
|
|
121
121
|
? `5. **\`crew task create --channel <id> --title "<标题>"\`** —— 仅为本轮发现的具体后续事项创建任务;本轮没有线程锚点,不要传 \`--thread\`。`
|
|
122
122
|
: `5. **\`crew task list --channel <id>\`** —— 看任务板。支持 \`--status <s>\` / \`--mine\`。
|
|
123
123
|
6. **\`crew task create --channel <id> --title "<标题>" --thread <当前线程根msgId>\`** —— 新建任务并**绑定到当前线程**。\`--thread\` 传你读到的那条**触发消息 id**(线程根),任务就和讨论同处一个线程。省略 \`--thread\` 会另起新线程,**几乎总是错的——务必带上**。
|
|
124
|
-
7. **\`crew task claim <taskId>\`** ——
|
|
124
|
+
7. **\`crew task claim <taskId>\`** —— 除定时任务创建与管理和 memory_prune 外,执行需要动作的工作前先认领任务。
|
|
125
125
|
8. **\`crew task update <taskId> --status <in_progress|in_review|done>\`** —— 推进任务状态。
|
|
126
126
|
9. **\`crew task unclaim <taskId>\`** —— 释放认领,把任务让给别人。
|
|
127
127
|
10. **\`crew task assign <taskId> --to <handle>\`** —— 把任务指派/交接给另一个 agent(用于交接,见下)。
|
|
@@ -176,7 +176,7 @@ ${taskAndScheduleCommands}`;
|
|
|
176
176
|
## 协作礼仪
|
|
177
177
|
- **尊重正在进行的对话**:人类正与他人一来一回时,除非明确 @你或显然在叫你,否则不要插话。
|
|
178
178
|
- **只有真正干活的人来汇报**:别替别人总结或冒领他们的工作。
|
|
179
|
-
-
|
|
179
|
+
- **除定时任务创建与管理和 memory_prune 外,claim 后再动手**:claim 失败立即停手,换一个任务。
|
|
180
180
|
- **停止前检查你欠的具体阻塞项**:若你还欠某人一个 handoff/review/决定/回复且正卡着对方,先发一条最小可行动消息再停。
|
|
181
181
|
- **少发废话**:只在有可行动内容时发消息,不要播报"我在等/我空闲"。`;
|
|
182
182
|
// 对人说话:约束的是"表达方式",不是"执行规则"——claim/thread/freshness 等操作协议照常执行,
|
|
@@ -234,8 +234,15 @@ ${taskAndScheduleCommands}`;
|
|
|
234
234
|
|
|
235
235
|
## 并行与记忆(CRITICAL — 防冲突 + 防上下文膨胀)
|
|
236
236
|
你**可能同时在处理多个任务**(你自己的多个并行进程)。为避免互相覆盖、并保持上下文精简,严格遵守:
|
|
237
|
-
-
|
|
238
|
-
-
|
|
237
|
+
- **普通任务默认只写两处**:① 本任务的隔离 cwd(代码/草稿);② 本任务的工作日志 **\`$CREW_TASK_LOG\`**(每任务一份,别人不会碰)。默认不要修改共享 \`$CREW_HOME/MEMORY.md\` 或 notes/;只有当前用户明确要求更新共享记忆时,才按下方条件写入相关共享文件。在工作日志里记:当前阶段 / 下一步 / 卡在谁 / 关键结论(每条尽量 ≤3 行)。
|
|
238
|
+
- **当前请求明确要求更新记忆,或当前消息是对本线程紧邻记忆方案的无歧义确认时**,可以按最小范围直接写共享记忆;先读取相关索引和 note,语义已存在时不重复追加,不要把 Agent 自己判断值得记住视为用户授权。
|
|
239
|
+
- 本节的直接更新共享记忆和相关 task 流转仅适用于用户消息触发的普通交互执行。memory_prune 和 scheduled 执行只遵守各自唤醒指令,不得依据本节认领、创建、重开或推进 task。
|
|
240
|
+
- 普通交互执行将写共享记忆时,使用当前线程唯一的普通 task:已有非终态 task 时先按归属规则确保当前 Agent 成功认领;当前线程没有 task 时先创建并认领一个普通 task;已有 task 为 done/closed 时不得由 Agent 重开,done 报告当前轻量方案无法安全复用终态 task,closed 保持人工终态。遇到终态或归属问题时报告冲突且不得创建第二个 task 或新的任务类型。完成写入后,只有任务本身的全部工作已完成时才推进终态以触发 prune。
|
|
241
|
+
- 提出共享记忆修改方案并等待用户确认时,该 task 仍有剩余工作,保持 in_review 或其它非终态;收到无歧义确认后再执行写入,并仅在全部工作完成后推进终态。
|
|
242
|
+
- 普通执行直接更新后,仍然保留任务结束后的专门收尾执行,不因已经写过而跳过 prune。
|
|
243
|
+
- 新建 note 必须说明现有分类为何不适用;MEMORY.md 默认只更新 Knowledge Index,不得默认修改 Role、Core Goals 或 Active Context;只有用户明确要求或任务本身就是档案/状态维护时例外。
|
|
244
|
+
- 未明确要求、记忆意图含糊或仅由 Agent 自己判断值得记住时,不直接写共享记忆,也不把含糊内容写成长期记忆候选。含糊表达本身不作为长期记忆候选,但不得因此跳过整个 task 的 memory_prune;任务按正常状态流程完成。收尾只能处理该任务其它符合现有收尾规则的稳定内容,不允许让收尾代替用户补充记忆授权。
|
|
245
|
+
- 若用户明确要求本次不要修改共享记忆,同样不写共享记忆或长期记忆候选。任务尚未完成时,把该禁止要求作为运行状态写入 $CREW_TASK_LOG;该运行状态不是长期记忆候选,后续执行必须保留该状态。若用户之后在同一任务中明确撤销禁止,移除该运行状态并按最新明确授权处理。完成 task 前检查该状态:Agent 可自行改状态时,使用 crew task update <taskId> --status done --skip-memory-prune。CLI 返回状态由 Server 管理时沿用上述 Server 管理任务的安全回退:不重试、不绕过权限;收尾会读取该运行状态并禁止共享记忆写入,但本路径不提供机器级 skip 保证。不要只在回复里声明不修改。
|
|
239
246
|
- **跨任务协调看实时清单**:用 \`crew task list --mine\` 查你当前所有任务及其状态(谁在排队、谁在评审)。例:你一次只能测一个页面时,据此判断"正在测 #1、#2 排队",在 #2 的工作日志里标注"等 #1 完成"。
|
|
240
247
|
- 需要更多背景时再 \`Read $CREW_HOME/notes/<topic>.md\`;不要一次把所有笔记读进上下文。
|
|
241
248
|
|
|
@@ -261,7 +268,7 @@ ${interactiveTaskRules}${freshnessRule}${externalReplyRule}${collaborationEtique
|
|
|
261
268
|
## Workspace 与分层记忆(CRITICAL — 索引+按需,配合上面的并行规则)
|
|
262
269
|
你的持久记忆在 \`$CREW_HOME\`(跨你所有任务共享),按“常驻索引 + 功能明细 + 当前工作”分层:
|
|
263
270
|
1. **MEMORY.md = 常驻索引 + 角色**:系统每次已把它(截断索引版)注入本提示词末尾。索引条目包含 \`file/type/scope/summary/triggers/priority/updated\`,其中 file 是相对于 \`$CREW_HOME\` 的路径(例如 \`notes/testing.md\`),先用这些字段判断当前问题是否相关;通常不必再读整份 MEMORY.md。
|
|
264
|
-
2. **notes/<topic>.md = 功能明细**:按用户偏好、项目规则、测试、调试、Git、事故复盘等主题拆分。优先读取与当前任务匹配的文件;\`notes/lessons.md\`
|
|
271
|
+
2. **notes/<topic>.md = 功能明细**:按用户偏好、项目规则、测试、调试、Git、事故复盘等主题拆分。优先读取与当前任务匹配的文件;\`notes/lessons.md\` 只保留未分类经验和历史兼容内容,不是所有新经验的默认目的地。普通任务默认只读不写,但当前用户明确要求时可以按最小范围更新;任务结束后的专门收尾执行仍按收尾指令复核。
|
|
265
272
|
- 对旧版 MEMORY.md,如果条目没有完整结构化字段但明确指向 \`notes/<file>.md\`,把它视为 legacy 索引;仍需结合条目标题/链接和当前请求判断相关性,不要因为缺少 summary/triggers 就假定正文已注入。
|
|
266
273
|
3. **本任务 work-log = \`$CREW_TASK_LOG\`**:每任务一份(别的运行不会碰),记当前阶段/下一步/卡点/关键结论。系统已把它的当前内容注入末尾让你续上;有进展就更新它——这是你**唯一**该在任务中持续写的记忆文件。**work-log 是现状快照,不是流水账**:保持 ≤100 行,更新时重写全文替换过时内容,不要无限追加(过长会被注入截断)。
|
|
267
274
|
|
|
@@ -269,7 +276,7 @@ ${interactiveTaskRules}${freshnessRule}${externalReplyRule}${collaborationEtique
|
|
|
269
276
|
- 当前请求命中 MEMORY.md 某条目的 \`summary\` 或 \`triggers\`,或用户明确询问历史经验/偏好时,在最终回答或执行动作前用 \`Read $CREW_HOME/<file>\` 读取对应明细;不要再次拼接 \`notes/\`。
|
|
270
277
|
- 未命中时不要为了“保险”读取全部 notes;只读取能直接影响当前任务的文件。MEMORY.md 注入的是索引,不会自动让 note 正文可用。
|
|
271
278
|
|
|
272
|
-
|
|
279
|
+
**沉淀与瘦身由系统触发,不要平时自行扩展范围**:任务被改为 done/closed 时,系统会单独唤醒你收尾——那时按功能分类把可复用经验提炼进合适的 \`notes/<topic>.md\`,更新 MEMORY.md 索引。普通执行已经按用户明确要求写入时,收尾先检查、后修改,只在明确缺漏时做最小必要修正,不得重复追加或只为优化措辞而改写。最终结论必须且只能归类为:无变化、已修正、冲突、失败;无变化或已修正时必须满足对应后置条件并清空 work-log,冲突或失败时保留 work-log,任一记忆写入失败则保留 work-log。不要默认全部写入 \`notes/lessons.md\`。默认不要改 MEMORY.md/notes,但不能覆盖当前用户明确授权的最小范围更新。
|
|
273
280
|
|
|
274
281
|
**为什么(CRITICAL)**:上下文会被周期压缩;你的恢复力来自——注入的 MEMORY.md 索引(始终精简)+ 本任务 work-log + 按需读相关 notes,而**不是**把一切堆进 MEMORY.md 或一次性加载所有明细。
|
|
275
282
|
${ctx.memory ? `\n## [注入] 你的 MEMORY.md(索引,只读参考)\n${ctx.memory}` : ""}${ctx.workLog ? `\n## [注入] 本任务 work-log(续上进度;更新写到 $CREW_TASK_LOG)\n${ctx.workLog}` : ""}`;
|
package/dist/slog.js
CHANGED
|
@@ -27,6 +27,16 @@ let flushPromise = null;
|
|
|
27
27
|
let inFlightBatch = [];
|
|
28
28
|
let lastErrorAt = 0;
|
|
29
29
|
let exitHookInstalled = false;
|
|
30
|
+
function deploymentEnvironment(serverHost) {
|
|
31
|
+
if (serverHost === "nowwork-in.nowcoder.com")
|
|
32
|
+
return "prod";
|
|
33
|
+
if (serverHost === "nowwork-dev.nowcoder.com")
|
|
34
|
+
return "dev";
|
|
35
|
+
if (serverHost === "localhost" || serverHost === "127.0.0.1"
|
|
36
|
+
|| serverHost === "::1" || serverHost === "[::1]")
|
|
37
|
+
return "local";
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
30
40
|
function spoolDir() {
|
|
31
41
|
return process.env.CREW_SLS_SPOOL_DIR ?? join(homedir(), ".crew", "logs", "sls-spool");
|
|
32
42
|
}
|
|
@@ -49,6 +59,7 @@ export function initSlog(serverUrl, machineToken, identity = {}) {
|
|
|
49
59
|
cli_version: identity.cliVersion,
|
|
50
60
|
daemon_profile: identity.profileName,
|
|
51
61
|
server_host: serverHost,
|
|
62
|
+
env: deploymentEnvironment(serverHost),
|
|
52
63
|
agents_root_fingerprint: identity.agentsRoot === undefined
|
|
53
64
|
? undefined
|
|
54
65
|
: createHash("sha256").update(resolve(identity.agentsRoot), "utf8").digest("hex"),
|
package/dist/workspace.js
CHANGED
|
@@ -154,43 +154,44 @@ export async function rotateAgentSession(sessionDir) {
|
|
|
154
154
|
function memorySeed(handle, description) {
|
|
155
155
|
const role = description?.trim()
|
|
156
156
|
? description.trim()
|
|
157
|
-
: "
|
|
157
|
+
: "(填写你的身份与职责,保持在几行以内。)";
|
|
158
158
|
return `# ${handle}
|
|
159
159
|
|
|
160
160
|
## Role
|
|
161
161
|
${role}
|
|
162
162
|
|
|
163
163
|
## Core Goals
|
|
164
|
-
|
|
164
|
+
(填写长期核心目标和主要优化方向。)
|
|
165
165
|
|
|
166
166
|
## Knowledge Index
|
|
167
|
-
<!--
|
|
168
|
-
<!--
|
|
169
|
-
### [
|
|
167
|
+
<!-- 长期记忆明细索引。每份可复用记忆对应一个结构化条目。 -->
|
|
168
|
+
<!-- 使用以下格式:
|
|
169
|
+
### [主题名称]
|
|
170
170
|
- file: notes/<topic>.md
|
|
171
171
|
- type: procedural | semantic | episodic | preference
|
|
172
172
|
- scope: agent_global
|
|
173
|
-
- summary:
|
|
174
|
-
- triggers:
|
|
173
|
+
- summary: 这份记忆包含什么,以及何时需要使用
|
|
174
|
+
- triggers: 触发这份记忆的主题、命令或场景
|
|
175
175
|
- priority: high | medium | low
|
|
176
176
|
- updated: YYYY-MM-DD
|
|
177
177
|
-->
|
|
178
|
-
<!--
|
|
179
|
-
###
|
|
178
|
+
<!-- 示例:
|
|
179
|
+
### 测试实践
|
|
180
180
|
- file: notes/testing.md
|
|
181
181
|
- type: procedural
|
|
182
182
|
- scope: agent_global
|
|
183
|
-
- summary:
|
|
184
|
-
- triggers:
|
|
183
|
+
- summary: 记录测试策略、回归范围和缺陷预防方法,开发或修复功能时使用
|
|
184
|
+
- triggers: 测试、回归、质量、缺陷、自动化
|
|
185
185
|
- priority: high
|
|
186
186
|
- updated: YYYY-MM-DD
|
|
187
187
|
-->
|
|
188
188
|
|
|
189
|
-
|
|
190
|
-
-
|
|
191
|
-
-
|
|
192
|
-
-
|
|
193
|
-
-
|
|
194
|
-
-
|
|
189
|
+
维护规则:
|
|
190
|
+
- 每次启动时,系统都会优先读取这份文件,包括上下文压缩后的恢复过程。
|
|
191
|
+
- 这里只保留长期身份、核心目标和 Knowledge Index;当前任务进度写入 $CREW_TASK_LOG。
|
|
192
|
+
- 详细记忆按功能主题保存到 notes/<topic>.md,保持本文件只包含长期身份和精简索引。
|
|
193
|
+
- 每条索引必须保留 file、type、scope、summary、triggers、priority、updated 这些英文协议字段名。
|
|
194
|
+
- 记忆内容语言必须跟随当前系统提示词的指令语言;标题、summary、triggers 和 notes 正文使用该语言,代码、命令、文件路径、专有名词和协议字段值可按需保留英文。
|
|
195
|
+
- notes/lessons.md 只用于暂时无法分类的内容,不要作为所有新经验的默认保存位置。
|
|
195
196
|
`;
|
|
196
197
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nowcrew/daemon",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "crew daemon — 运行在用户机器:拉起/管理 agent 进程,注入 crew CLI,归一化 runtime 事件",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@agentclientprotocol/sdk": "1.2.1",
|
|
21
|
-
"@nowcrew/cli": "^0.4.
|
|
21
|
+
"@nowcrew/cli": "^0.4.13",
|
|
22
22
|
"cross-spawn": "^7.0.6",
|
|
23
23
|
"ws": "^8",
|
|
24
24
|
"yaml": "^2.8.1",
|