@nowcrew/daemon 0.6.6 → 0.6.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/README.md +26 -18
- package/dist/agent-memory/bridge.js +9 -6
- package/dist/agent-memory/client.js +2 -2
- package/dist/computer-service.js +9 -1
- package/dist/execution-protocol.js +1 -0
- package/dist/execution-runner.js +2 -2
- package/dist/machine-info.js +1 -0
- package/dist/main.js +0 -0
- package/dist/prompt.js +15 -10
- package/dist/workspace.js +30 -13
- package/package.json +8 -9
- package/dist/remote/claude-bridge.js +0 -558
- package/dist/remote/claude-channel.js +0 -164
- package/dist/remote/codex-client.js +0 -451
- package/dist/remote/codex-runtime.js +0 -77
- package/dist/remote/config.js +0 -135
- package/dist/remote/gateway.js +0 -879
- package/dist/remote/identity.js +0 -39
- package/dist/remote/owner.js +0 -77
- package/dist/remote/protocol.js +0 -211
- package/dist/remote/remote-cli.js +0 -254
- package/dist/remote/runtime-probe.js +0 -182
- package/dist/remote/session-discovery.js +0 -249
- package/dist/remote/wrapper.js +0 -40
- package/dist/remote-web/assets/index-B_6VM_tw.js +0 -94
- package/dist/remote-web/assets/index-L6EiQbJn.css +0 -1
- package/dist/remote-web/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/dist/remote-web/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/dist/remote-web/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/dist/remote-web/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/dist/remote-web/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/dist/remote-web/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/dist/remote-web/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/dist/remote-web/icons/nowwork-192.png +0 -0
- package/dist/remote-web/icons/nowwork-512.png +0 -0
- package/dist/remote-web/icons/nowwork.svg +0 -7
- package/dist/remote-web/index.html +0 -20
- package/dist/remote-web/manifest.webmanifest +0 -13
- package/dist/remote-web/sw.js +0 -12
package/README.md
CHANGED
|
@@ -392,37 +392,45 @@ control frames.
|
|
|
392
392
|
|
|
393
393
|
## Optional TencentDB Agent Memory Bridge
|
|
394
394
|
|
|
395
|
-
Execution protocol v1 can opt
|
|
395
|
+
Execution protocol v1 can opt NowWork Agents into the private TencentDB Agent Memory Panel.
|
|
396
396
|
This is an external context backend, not a replacement for NowWork messages, tasks, workspace memory,
|
|
397
397
|
or server authorization. It is disabled unless every required variable is present:
|
|
398
398
|
|
|
399
399
|
```text
|
|
400
400
|
CREW_AGENT_MEMORY_URL=https://memory.example/path
|
|
401
|
-
CREW_AGENT_MEMORY_INSTANCE_ID=
|
|
402
|
-
CREW_AGENT_MEMORY_USER_KEY=<load from a secret store>
|
|
403
|
-
CREW_AGENT_MEMORY_USER_ID=<external user id>
|
|
404
|
-
CREW_AGENT_MEMORY_TEAM_ID
|
|
405
|
-
|
|
406
|
-
|
|
401
|
+
CREW_AGENT_MEMORY_INSTANCE_ID=nowwork
|
|
402
|
+
CREW_AGENT_MEMORY_USER_KEY=<load the external Agent owner's key from a secret store>
|
|
403
|
+
CREW_AGENT_MEMORY_USER_ID=<external Agent owner user id>
|
|
404
|
+
CREW_AGENT_MEMORY_TEAM_ID=team-ueasyuv7sx
|
|
405
|
+
# Legacy single-Agent fallback during rolling upgrades:
|
|
406
|
+
CREW_AGENT_MEMORY_AGENT_ID=agt-vmszw3z170
|
|
407
|
+
CREW_AGENT_MEMORY_AGENT_HANDLE=cindy
|
|
407
408
|
CREW_AGENT_MEMORY_TIMEOUT_MS=3000
|
|
408
409
|
CREW_AGENT_MEMORY_RECALL_LIMIT=8
|
|
409
410
|
```
|
|
410
411
|
|
|
411
|
-
The
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
412
|
+
The Agent configuration page owns each non-secret external Agent ID. Turn on `Use long-term memory`,
|
|
413
|
+
enter the matching `agt-*` ID, and save. The server carries that mapping in execution protocol v1; the
|
|
414
|
+
daemon combines it with the configured instance, user key, and team. Different NowWork Agents must use
|
|
415
|
+
different external Agent IDs. `CREW_AGENT_MEMORY_AGENT_ID` and `CREW_AGENT_MEMORY_AGENT_HANDLE` remain
|
|
416
|
+
required as a compatibility fallback for older server records during rolling upgrades. Partial daemon
|
|
417
|
+
configuration fails startup. Removing all `CREW_AGENT_MEMORY_*` variables and restarting the daemon is
|
|
418
|
+
the complete rollback.
|
|
415
419
|
|
|
416
|
-
|
|
417
|
-
|
|
420
|
+
The user key must be able to access the selected external Agent's chat-memory asset. Team membership by
|
|
421
|
+
itself is insufficient for another owner's private asset: the Panel API returns `ASSET_NOT_ACCESSIBLE`.
|
|
422
|
+
Use a key issued to that Agent's owner, or create a dedicated external Agent owned by the daemon account.
|
|
423
|
+
|
|
424
|
+
On macOS, keep the one-time key in Keychain and resolve it only into the daemon startup environment. Use
|
|
425
|
+
a dedicated service name for the `nowwork` instance; do not reuse a key issued by the `default` instance:
|
|
418
426
|
|
|
419
427
|
```bash
|
|
420
428
|
export CREW_AGENT_MEMORY_USER_KEY="$(security find-generic-password \
|
|
421
|
-
-a
|
|
422
|
-
export
|
|
423
|
-
|
|
424
|
-
export CREW_AGENT_MEMORY_AGENT_ID=
|
|
425
|
-
|
|
429
|
+
-a zuosong -s nowwork-agent-memory-nowwork -w)"
|
|
430
|
+
export CREW_AGENT_MEMORY_USER_ID=usr-uebdjxnkbh
|
|
431
|
+
export CREW_AGENT_MEMORY_TEAM_ID=team-ueasyuv7sx
|
|
432
|
+
export CREW_AGENT_MEMORY_AGENT_ID=agt-vmszw3z170
|
|
433
|
+
export CREW_AGENT_MEMORY_AGENT_HANDLE=cindy
|
|
426
434
|
```
|
|
427
435
|
|
|
428
436
|
Do not place the key in a tracked `.env`, shell history, command argument, service description, or log.
|
|
@@ -12,11 +12,12 @@ function safeReport(report, eventType, message, fields) {
|
|
|
12
12
|
export function createAgentMemoryBridge(config, dependencies = {}) {
|
|
13
13
|
const client = dependencies.client ?? createAgentMemoryClient(config);
|
|
14
14
|
const report = dependencies.report ?? dslog;
|
|
15
|
-
const
|
|
15
|
+
const resolveAgentId = (agentHandle, agentId) => agentId ?? (agentHandle === config.agentHandle ? config.agentId : null);
|
|
16
16
|
return {
|
|
17
|
-
recall: async (agentHandle, wakePrompt, executionId) => {
|
|
17
|
+
recall: async (agentHandle, wakePrompt, executionId, agentId) => {
|
|
18
18
|
const startedAt = Date.now();
|
|
19
|
-
|
|
19
|
+
const externalAgentId = resolveAgentId(agentHandle, agentId ?? null);
|
|
20
|
+
if (externalAgentId === null) {
|
|
20
21
|
safeReport(report, "external_agent_memory.recall_observed", "外部 Agent Memory recall 已跳过", {
|
|
21
22
|
execution_id: executionId,
|
|
22
23
|
agent_handle: agentHandle,
|
|
@@ -26,6 +27,7 @@ export function createAgentMemoryBridge(config, dependencies = {}) {
|
|
|
26
27
|
});
|
|
27
28
|
return "";
|
|
28
29
|
}
|
|
30
|
+
const blockId = `chat_memory-${config.teamId}-${externalAgentId}`;
|
|
29
31
|
const incoming = extractIncomingMessage(wakePrompt);
|
|
30
32
|
if (incoming === null) {
|
|
31
33
|
safeReport(report, "external_agent_memory.recall_observed", "外部 Agent Memory recall 已跳过", {
|
|
@@ -68,9 +70,10 @@ export function createAgentMemoryBridge(config, dependencies = {}) {
|
|
|
68
70
|
return "";
|
|
69
71
|
}
|
|
70
72
|
},
|
|
71
|
-
capture: async (agentHandle, executionId, wakePrompt, finalText) => {
|
|
73
|
+
capture: async (agentHandle, executionId, wakePrompt, finalText, agentId) => {
|
|
72
74
|
const startedAt = Date.now();
|
|
73
|
-
|
|
75
|
+
const externalAgentId = resolveAgentId(agentHandle, agentId ?? null);
|
|
76
|
+
if (externalAgentId === null) {
|
|
74
77
|
safeReport(report, "external_agent_memory.capture_observed", "外部 Agent Memory capture 已跳过", {
|
|
75
78
|
execution_id: executionId,
|
|
76
79
|
agent_handle: agentHandle,
|
|
@@ -103,7 +106,7 @@ export function createAgentMemoryBridge(config, dependencies = {}) {
|
|
|
103
106
|
return;
|
|
104
107
|
}
|
|
105
108
|
try {
|
|
106
|
-
const result = await client.importConversation(`nowwork-${executionId}`, messages);
|
|
109
|
+
const result = await client.importConversation(externalAgentId, `nowwork-${executionId}`, messages);
|
|
107
110
|
safeReport(report, "external_agent_memory.capture_observed", "外部 Agent Memory capture 已完成", {
|
|
108
111
|
execution_id: executionId,
|
|
109
112
|
agent_handle: agentHandle,
|
|
@@ -79,10 +79,10 @@ export function createAgentMemoryClient(config, dependencies = {}) {
|
|
|
79
79
|
...(item.created_at === undefined ? {} : { createdAt: item.created_at }),
|
|
80
80
|
}));
|
|
81
81
|
},
|
|
82
|
-
importConversation: async (sessionId, messages) => {
|
|
82
|
+
importConversation: async (agentId, sessionId, messages) => {
|
|
83
83
|
const parsed = ImportDataSchema.safeParse(await post("import", {
|
|
84
84
|
team_id: config.teamId,
|
|
85
|
-
agent_id:
|
|
85
|
+
agent_id: agentId,
|
|
86
86
|
session_id: sessionId,
|
|
87
87
|
messages,
|
|
88
88
|
}));
|
package/dist/computer-service.js
CHANGED
|
@@ -7,9 +7,17 @@ import { dirname, resolve } from "node:path";
|
|
|
7
7
|
const execFileAsync = promisify(execFile);
|
|
8
8
|
const WINDOWS_STOP_TIMEOUT_MS = 5_000;
|
|
9
9
|
const WINDOWS_STOP_POLL_MS = 100;
|
|
10
|
+
/** Windows cannot spawn .cmd/.bat shims directly with shell:false; route them through cmd.exe explicitly. */
|
|
11
|
+
export function systemCommandInvocation(command, args, platform = process.platform, comSpec = process.env.ComSpec ?? process.env.COMSPEC ?? "cmd.exe") {
|
|
12
|
+
if (platform === "win32" && /\.(?:cmd|bat)$/iu.test(command)) {
|
|
13
|
+
return { command: comSpec, args: ["/d", "/s", "/c", command, ...args] };
|
|
14
|
+
}
|
|
15
|
+
return { command, args: [...args] };
|
|
16
|
+
}
|
|
10
17
|
export const systemCommandRunner = async (command, args) => {
|
|
11
18
|
try {
|
|
12
|
-
const
|
|
19
|
+
const invocation = systemCommandInvocation(command, args);
|
|
20
|
+
const result = await execFileAsync(invocation.command, [...invocation.args], { encoding: "utf8" });
|
|
13
21
|
return { exitCode: 0, stdout: result.stdout, stderr: result.stderr };
|
|
14
22
|
}
|
|
15
23
|
catch (error) {
|
|
@@ -115,6 +115,7 @@ export const ExecutionStartSchema = z.object({
|
|
|
115
115
|
id: z.string().min(1),
|
|
116
116
|
handle: AgentHandleSchema,
|
|
117
117
|
memoryEnabled: z.boolean().optional(),
|
|
118
|
+
memoryAgentId: z.string().regex(/^agt-[A-Za-z0-9_-]+$/).max(100).optional(),
|
|
118
119
|
projectSkills: z.array(ProjectSkillRefSchema).max(MAX_AGENT_PROJECT_SKILL_BINDINGS).optional(),
|
|
119
120
|
abilityRelease: AbilityReleaseSnapshotSchema.optional(),
|
|
120
121
|
}).strict(),
|
package/dist/execution-runner.js
CHANGED
|
@@ -415,7 +415,7 @@ export async function runExecution(config, input, dependencies) {
|
|
|
415
415
|
let recalledMemory = "";
|
|
416
416
|
if (spec.agent.memoryEnabled === true && dependencies.agentMemory !== undefined) {
|
|
417
417
|
try {
|
|
418
|
-
recalledMemory = await cancellable(dependencies.agentMemory.recall(spec.agent.handle, spec.instructions.wakePrompt, spec.executionId), dependencies.cancellation);
|
|
418
|
+
recalledMemory = await cancellable(dependencies.agentMemory.recall(spec.agent.handle, spec.instructions.wakePrompt, spec.executionId, spec.agent.memoryAgentId ?? null), dependencies.cancellation);
|
|
419
419
|
}
|
|
420
420
|
catch (error) {
|
|
421
421
|
if (error instanceof ExecutionCancelledError)
|
|
@@ -720,7 +720,7 @@ export async function runExecution(config, input, dependencies) {
|
|
|
720
720
|
&& memoryCaptureFinalText !== null
|
|
721
721
|
&& dependencies.agentMemory !== undefined) {
|
|
722
722
|
try {
|
|
723
|
-
await dependencies.agentMemory.capture(spec.agent.handle, spec.executionId, spec.instructions.wakePrompt, memoryCaptureFinalText);
|
|
723
|
+
await dependencies.agentMemory.capture(spec.agent.handle, spec.executionId, spec.instructions.wakePrompt, memoryCaptureFinalText, spec.agent.memoryAgentId ?? null);
|
|
724
724
|
}
|
|
725
725
|
catch {
|
|
726
726
|
// External memory is optional and must never alter the durable execution outcome.
|
package/dist/machine-info.js
CHANGED
|
@@ -31,6 +31,7 @@ export const DAEMON_CAPABILITIES = [
|
|
|
31
31
|
"execution_answer_stream_v1",
|
|
32
32
|
"execution_machine_queue_v1",
|
|
33
33
|
"execution_agent_memory_policy_v1",
|
|
34
|
+
"execution_agent_memory_mapping_v1",
|
|
34
35
|
"project_skills_v1",
|
|
35
36
|
RUNTIME_HEALTH_PROBE_CAPABILITY,
|
|
36
37
|
"agent_ability_release_v1",
|
package/dist/main.js
CHANGED
|
File without changes
|
package/dist/prompt.js
CHANGED
|
@@ -29,7 +29,7 @@ export function capWorkLogForInject(workLog, cap = WORKLOG_INJECT_CAP) {
|
|
|
29
29
|
}
|
|
30
30
|
export function capMemoryForInject(memory, cap = MEMORY_INJECT_CAP) {
|
|
31
31
|
return memory.length > cap
|
|
32
|
-
? `${memory.slice(0, cap)}\n…(MEMORY.md 过长已截断,详情用 Read 读 $CREW_HOME/MEMORY.md
|
|
32
|
+
? `${memory.slice(0, cap)}\n…(MEMORY.md 过长已截断,详情用 Read 读 $CREW_HOME/MEMORY.md;功能明细仅按索引中的 file 读取)`
|
|
33
33
|
: memory;
|
|
34
34
|
}
|
|
35
35
|
export function buildSystemPrompt(ctx) {
|
|
@@ -59,7 +59,7 @@ export function buildSystemPrompt(ctx) {
|
|
|
59
59
|
// scheduled 换成静默版,不出现任何"先确认/先回复"的措辞。
|
|
60
60
|
const startupSequence = alwaysReport
|
|
61
61
|
? `## 启动序列(每轮汇报定时任务)
|
|
62
|
-
1.
|
|
62
|
+
1. 使用本提示词末尾已注入的 MEMORY.md 索引;命中相关条目时,再按索引中的 file 从 $CREW_HOME 读取明细。
|
|
63
63
|
2. 执行唤醒提示词里给出的定时指令。
|
|
64
64
|
3. Return exactly one self-contained final report as your runtime final response.
|
|
65
65
|
4. Do not call crew message send; the daemon delivers the final response.
|
|
@@ -67,14 +67,14 @@ export function buildSystemPrompt(ctx) {
|
|
|
67
67
|
6. 只有存在需要后续跟进的具体事项时,才用 \`crew task create\` 创建任务。`
|
|
68
68
|
: scheduled
|
|
69
69
|
? `## 启动序列(静默定时任务)
|
|
70
|
-
1.
|
|
70
|
+
1. 使用本提示词末尾已注入的 MEMORY.md 索引;命中相关条目时,再按索引中的 file 从 $CREW_HOME 读取明细。
|
|
71
71
|
2. 执行唤醒提示词里给出的定时指令。**默认零输出**:不判断"是否需要先确认/声明接手",本轮没有人在等你回复。
|
|
72
72
|
3. 只有发现异常、需要人处理、或指令明确要求汇报时,才用 \`crew message send --send-draft\` 输出到频道(用法见上面"通信"一节)。
|
|
73
73
|
4. 只有存在需要后续跟进的具体事项时,才用 \`crew task create\` 创建任务。
|
|
74
74
|
5. 无异常时直接结束,不需要任何输出,不必读频道历史(除非指令要求)。`
|
|
75
75
|
: `## 启动序列
|
|
76
76
|
1. 若本轮来信可以直接回答,不要先发确认消息;处理完后只发一条完整回复。只有需要澄清、调用工具、协调他人或较长时间处理时,才先发有信息量的确认/进度消息。
|
|
77
|
-
2.
|
|
77
|
+
2. 使用本提示词末尾已注入的 MEMORY.md 索引;命中相关条目时,再按索引中的 file 从 $CREW_HOME 读取明细。
|
|
78
78
|
3. 若本轮只有"有未读"的 inbox notice、没有正文:notice 表示存在你尚未看到的消息(正文被暂时省略以免刷屏,不是没有内容)。是否读、何时读由你判断,可用 \`crew message check\` / \`crew message read\` 拉取。**绝不能仅凭一条 content-free notice 就断定"没有工作"**;若选择暂不读,要诚实当作 defer。
|
|
79
79
|
4. 收到消息就处理,并用 \`crew message send\` 回复。
|
|
80
80
|
5. **做完你负责的所有事再停。** 多步任务(调研/改码/测试)要全部完成、汇报结果后再停。新消息会在你存活期间自动送达,无需轮询等待。`;
|
|
@@ -235,7 +235,7 @@ ${taskAndScheduleCommands}`;
|
|
|
235
235
|
## 并行与记忆(CRITICAL — 防冲突 + 防上下文膨胀)
|
|
236
236
|
你**可能同时在处理多个任务**(你自己的多个并行进程)。为避免互相覆盖、并保持上下文精简,严格遵守:
|
|
237
237
|
- **只写两处**:① 本任务的隔离 cwd(代码/草稿);② 本任务的工作日志 **\`$CREW_TASK_LOG\`**(每任务一份,别人不会碰)。在工作日志里记:当前阶段 / 下一步 / 卡在谁 / 关键结论(每条尽量 ≤3 行)。
|
|
238
|
-
-
|
|
238
|
+
- **普通任务进行中不要改 \`$CREW_HOME/MEMORY.md\` 或 notes/**(那是共享文件,多个并行运行同时写会冲突)。这些只读参考;任务 done/closed 后的专门收尾执行才按收尾指令写入功能明细和索引。
|
|
239
239
|
- **跨任务协调看实时清单**:用 \`crew task list --mine\` 查你当前所有任务及其状态(谁在排队、谁在评审)。例:你一次只能测一个页面时,据此判断"正在测 #1、#2 排队",在 #2 的工作日志里标注"等 #1 完成"。
|
|
240
240
|
- 需要更多背景时再 \`Read $CREW_HOME/notes/<topic>.md\`;不要一次把所有笔记读进上下文。
|
|
241
241
|
|
|
@@ -259,14 +259,19 @@ ${actionRule}
|
|
|
259
259
|
${interactiveTaskRules}${freshnessRule}${externalReplyRule}${collaborationEtiquette}${humanLanguageSection}${communicationStyle}${skillIntentRule}
|
|
260
260
|
|
|
261
261
|
## Workspace 与分层记忆(CRITICAL — 索引+按需,配合上面的并行规则)
|
|
262
|
-
你的持久记忆在 \`$CREW_HOME\`(跨你所有任务共享)
|
|
263
|
-
1. **MEMORY.md =
|
|
264
|
-
2. **notes/<
|
|
262
|
+
你的持久记忆在 \`$CREW_HOME\`(跨你所有任务共享),按“常驻索引 + 功能明细 + 当前工作”分层:
|
|
263
|
+
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\` 只保留未分类经验和历史兼容内容,不是所有新经验的默认目的地。**普通任务进行中只读不写**(多个并行运行同时写会冲突);任务结束后的专门收尾执行按收尾指令写入。
|
|
265
|
+
- 对旧版 MEMORY.md,如果条目没有完整结构化字段但明确指向 \`notes/<file>.md\`,把它视为 legacy 索引;仍需结合条目标题/链接和当前请求判断相关性,不要因为缺少 summary/triggers 就假定正文已注入。
|
|
265
266
|
3. **本任务 work-log = \`$CREW_TASK_LOG\`**:每任务一份(别的运行不会碰),记当前阶段/下一步/卡点/关键结论。系统已把它的当前内容注入末尾让你续上;有进展就更新它——这是你**唯一**该在任务中持续写的记忆文件。**work-log 是现状快照,不是流水账**:保持 ≤100 行,更新时重写全文替换过时内容,不要无限追加(过长会被注入截断)。
|
|
266
267
|
|
|
267
|
-
|
|
268
|
+
**按需读取规则(提示词引导,不是 Daemon 自动召回保证)**:
|
|
269
|
+
- 当前请求命中 MEMORY.md 某条目的 \`summary\` 或 \`triggers\`,或用户明确询问历史经验/偏好时,在最终回答或执行动作前用 \`Read $CREW_HOME/<file>\` 读取对应明细;不要再次拼接 \`notes/\`。
|
|
270
|
+
- 未命中时不要为了“保险”读取全部 notes;只读取能直接影响当前任务的文件。MEMORY.md 注入的是索引,不会自动让 note 正文可用。
|
|
268
271
|
|
|
269
|
-
|
|
272
|
+
**沉淀与瘦身由系统触发,不要平时做**:任务被改为 done/closed 时,系统会单独唤醒你收尾——那时按功能分类把可复用经验提炼进合适的 \`notes/<topic>.md\`,更新 MEMORY.md 索引。收尾只有三种清理结果:有内容且明细与索引全部写入成功后清空 work-log;无可留存内容时直接清空;任一记忆写入失败则保留 work-log、停止并报告失败,不得继续清空。不要默认全部写入 \`notes/lessons.md\`。平时别动 MEMORY.md/notes,既防并行冲突,也防 MEMORY.md 膨胀。
|
|
273
|
+
|
|
274
|
+
**为什么(CRITICAL)**:上下文会被周期压缩;你的恢复力来自——注入的 MEMORY.md 索引(始终精简)+ 本任务 work-log + 按需读相关 notes,而**不是**把一切堆进 MEMORY.md 或一次性加载所有明细。
|
|
270
275
|
${ctx.memory ? `\n## [注入] 你的 MEMORY.md(索引,只读参考)\n${ctx.memory}` : ""}${ctx.workLog ? `\n## [注入] 本任务 work-log(续上进度;更新写到 $CREW_TASK_LOG)\n${ctx.workLog}` : ""}`;
|
|
271
276
|
}
|
|
272
277
|
/** 静默定时任务的唤醒提示词:不注入协作礼仪/线程提示;默认零输出(设计文档 §5.4)。
|
package/dist/workspace.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* 准备 agent 在本机的工作区:
|
|
3
3
|
* <agentsRoot>/<handle>/
|
|
4
4
|
* ├── MEMORY.md 长期记忆/角色 (首次创建种子)
|
|
5
|
+
* ├── notes/ 按功能拆分的长期记忆明细
|
|
5
6
|
* ├── .crew/prompts/<execution>.md 按 execution 隔离的系统提示词
|
|
6
7
|
* └── .crew/crew 注入 PATH 的 CLI wrapper (0755)
|
|
7
8
|
*
|
|
@@ -37,7 +38,9 @@ export async function prepareWorkspace(input) {
|
|
|
37
38
|
const dir = join(input.agentsRoot, input.handle);
|
|
38
39
|
const crewDir = join(dir, ".crew");
|
|
39
40
|
await mkdir(crewDir, { recursive: true });
|
|
40
|
-
//
|
|
41
|
+
// 预先创建明细目录,让收尾流程可以按功能创建 notes/<topic>.md。
|
|
42
|
+
await mkdir(join(dir, "notes"), { recursive: true });
|
|
43
|
+
// MEMORY.md:首次创建"持久身份 + 知识索引"骨架,之后由 agent 自己维护
|
|
41
44
|
const memoryPath = join(dir, "MEMORY.md");
|
|
42
45
|
const memorySeedCreated = !(await exists(memoryPath));
|
|
43
46
|
if (memorySeedCreated) {
|
|
@@ -144,7 +147,7 @@ export async function rotateAgentSession(sessionDir) {
|
|
|
144
147
|
return id;
|
|
145
148
|
}
|
|
146
149
|
/**
|
|
147
|
-
* MEMORY.md 种子骨架:分层记忆的"
|
|
150
|
+
* MEMORY.md 种子骨架:分层记忆的"持久身份 + 知识索引"结构。
|
|
148
151
|
* 第一次准备工作区时写入;之后 agent 自己维护(系统提示词里有协议)。
|
|
149
152
|
* 建 agent 时填了 description,则用它种子化 ## Role(否则留占位符,由 agent 自填)。
|
|
150
153
|
*/
|
|
@@ -161,19 +164,33 @@ ${role}
|
|
|
161
164
|
(What you optimize for.)
|
|
162
165
|
|
|
163
166
|
## Knowledge Index
|
|
164
|
-
<!-- The map to your detailed notes.
|
|
165
|
-
<!--
|
|
166
|
-
|
|
167
|
+
<!-- The map to your detailed notes. Keep one structured entry per durable note. -->
|
|
168
|
+
<!-- Use this shape:
|
|
169
|
+
### [Topic label]
|
|
170
|
+
- file: notes/<topic>.md
|
|
171
|
+
- type: procedural | semantic | episodic | preference
|
|
172
|
+
- scope: agent_global
|
|
173
|
+
- summary: what this note contains and when it matters
|
|
174
|
+
- triggers: comma-separated topics, commands, or scenarios
|
|
175
|
+
- priority: high | medium | low
|
|
176
|
+
- updated: YYYY-MM-DD
|
|
177
|
+
-->
|
|
178
|
+
<!-- Example:
|
|
179
|
+
### Testing practices
|
|
180
|
+
- file: notes/testing.md
|
|
181
|
+
- type: procedural
|
|
182
|
+
- scope: agent_global
|
|
183
|
+
- summary: Test strategy, regression coverage, and defect-prevention practices.
|
|
184
|
+
- triggers: test, testing, regression, quality, bug, automation
|
|
185
|
+
- priority: high
|
|
186
|
+
- updated: YYYY-MM-DD
|
|
187
|
+
-->
|
|
167
188
|
|
|
168
|
-
## Active Context
|
|
169
|
-
<!-- Running log of what you're doing now: in-progress tasks, next steps, what you owe whom.
|
|
170
|
-
Write an entry here BEFORE a long task so you can resume after sleep/compaction. -->
|
|
171
|
-
|
|
172
|
-
---
|
|
173
189
|
How to maintain this file:
|
|
174
190
|
- This is the FIRST file read on every startup (including after context compaction).
|
|
175
|
-
- Keep
|
|
176
|
-
|
|
177
|
-
-
|
|
191
|
+
- Keep durable identity, goals, and the Knowledge Index here; current task progress belongs in $CREW_TASK_LOG.
|
|
192
|
+
- Put details in functional notes/<topic>.md files; keep this file focused on durable identity and the index.
|
|
193
|
+
- Every note index entry must include file, type, scope, summary, triggers, priority, and updated.
|
|
194
|
+
- Keep notes/lessons.md as an uncategorized compatibility area, not the default destination for all lessons.
|
|
178
195
|
`;
|
|
179
196
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nowcrew/daemon",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "crew daemon — 运行在用户机器:拉起/管理 agent 进程,注入 crew CLI,归一化 runtime 事件",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -16,13 +16,6 @@
|
|
|
16
16
|
"publishConfig": {
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
19
|
-
"scripts": {
|
|
20
|
-
"daemon": "pnpm --filter @nowcrew/cli build && tsx src/main.ts",
|
|
21
|
-
"build": "tsc -p tsconfig.json",
|
|
22
|
-
"prepublishOnly": "pnpm build && node ../scripts/daemon-release-artifact.mjs --strict-registry",
|
|
23
|
-
"test": "vitest run",
|
|
24
|
-
"typecheck": "tsc --noEmit"
|
|
25
|
-
},
|
|
26
19
|
"dependencies": {
|
|
27
20
|
"@agentclientprotocol/sdk": "1.2.1",
|
|
28
21
|
"@nowcrew/cli": "^0.4.13",
|
|
@@ -41,5 +34,11 @@
|
|
|
41
34
|
"tsx": "^4.19.0",
|
|
42
35
|
"typescript": "^5.6.0",
|
|
43
36
|
"vitest": "^2.1.0"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"daemon": "pnpm --filter @nowcrew/cli build && tsx src/main.ts",
|
|
40
|
+
"build": "tsc -p tsconfig.json",
|
|
41
|
+
"test": "vitest run",
|
|
42
|
+
"typecheck": "tsc --noEmit"
|
|
44
43
|
}
|
|
45
|
-
}
|
|
44
|
+
}
|