team-anya-cli 0.1.0

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 (163) hide show
  1. package/README.md +38 -0
  2. package/anya/prompts/execution-guides/git-delivery.md +38 -0
  3. package/anya/prompts/execution-guides/testing-and-self-heal.md +28 -0
  4. package/anya/prompts/protocols/brief-assembly.md +55 -0
  5. package/anya/prompts/protocols/report.md +175 -0
  6. package/anya/prompts/protocols/review.md +90 -0
  7. package/anya/prompts/task-claude-md.template.md +32 -0
  8. package/apps/server/dist/broker/cc-broker.js +257 -0
  9. package/apps/server/dist/cli.js +296 -0
  10. package/apps/server/dist/config.js +76 -0
  11. package/apps/server/dist/daemon.js +51 -0
  12. package/apps/server/dist/gateway/chat-sync.js +135 -0
  13. package/apps/server/dist/gateway/command-router.js +114 -0
  14. package/apps/server/dist/gateway/commands/cancel.js +32 -0
  15. package/apps/server/dist/gateway/commands/help.js +16 -0
  16. package/apps/server/dist/gateway/commands/index.js +26 -0
  17. package/apps/server/dist/gateway/commands/restart.js +34 -0
  18. package/apps/server/dist/gateway/commands/status.js +34 -0
  19. package/apps/server/dist/gateway/commands/tasks.js +33 -0
  20. package/apps/server/dist/gateway/feishu-sender.js +346 -0
  21. package/apps/server/dist/gateway/feishu-ws.js +254 -0
  22. package/apps/server/dist/gateway/http.js +994 -0
  23. package/apps/server/dist/gateway/media-downloader.js +149 -0
  24. package/apps/server/dist/gateway/message-events.js +10 -0
  25. package/apps/server/dist/gateway/message-intake.js +50 -0
  26. package/apps/server/dist/gateway/message-queue.js +104 -0
  27. package/apps/server/dist/gateway/session-reader.js +142 -0
  28. package/apps/server/dist/gateway/ws-push.js +115 -0
  29. package/apps/server/dist/loid/brain.js +104 -0
  30. package/apps/server/dist/loid/clarifier.js +162 -0
  31. package/apps/server/dist/loid/context-builder.js +413 -0
  32. package/apps/server/dist/loid/mcp-server.js +104 -0
  33. package/apps/server/dist/loid/memory-settler.js +189 -0
  34. package/apps/server/dist/loid/opportunity-manager.js +148 -0
  35. package/apps/server/dist/loid/profile-updater.js +179 -0
  36. package/apps/server/dist/loid/reporter.js +148 -0
  37. package/apps/server/dist/loid/schemas.js +117 -0
  38. package/apps/server/dist/loid/self-calibrator.js +314 -0
  39. package/apps/server/dist/loid/session-manager.js +217 -0
  40. package/apps/server/dist/loid/session.js +271 -0
  41. package/apps/server/dist/loid/worktree-manager.js +191 -0
  42. package/apps/server/dist/main.js +337 -0
  43. package/apps/server/dist/tracing/index.js +2 -0
  44. package/apps/server/dist/tracing/trace-context.js +92 -0
  45. package/apps/server/dist/types/message.js +2 -0
  46. package/apps/server/dist/yor/yor-mcp-server.js +104 -0
  47. package/apps/server/dist/yor/yor-orchestrator.js +233 -0
  48. package/apps/web/dist/assets/index-CHIT0Dya.css +1 -0
  49. package/apps/web/dist/assets/index-CJzAjoVH.js +798 -0
  50. package/apps/web/dist/index.html +13 -0
  51. package/package.json +42 -0
  52. package/packages/cc-client/dist/claude-code-backend.js +664 -0
  53. package/packages/cc-client/dist/index.js +2 -0
  54. package/packages/cc-client/package.json +11 -0
  55. package/packages/core/dist/constants.js +59 -0
  56. package/packages/core/dist/errors.js +35 -0
  57. package/packages/core/dist/index.js +7 -0
  58. package/packages/core/dist/office-init.js +97 -0
  59. package/packages/core/dist/scope/checker.js +114 -0
  60. package/packages/core/dist/scope/defaults.js +40 -0
  61. package/packages/core/dist/scope/index.js +3 -0
  62. package/packages/core/dist/state-machine.js +85 -0
  63. package/packages/core/dist/types/audit.js +12 -0
  64. package/packages/core/dist/types/backend.js +2 -0
  65. package/packages/core/dist/types/commitment.js +17 -0
  66. package/packages/core/dist/types/communication.js +18 -0
  67. package/packages/core/dist/types/index.js +8 -0
  68. package/packages/core/dist/types/opportunity.js +27 -0
  69. package/packages/core/dist/types/org.js +26 -0
  70. package/packages/core/dist/types/task.js +46 -0
  71. package/packages/core/package.json +10 -0
  72. package/packages/db/dist/client.js +69 -0
  73. package/packages/db/dist/index.js +603 -0
  74. package/packages/db/dist/schema/audit-events.js +13 -0
  75. package/packages/db/dist/schema/cc-sessions.js +14 -0
  76. package/packages/db/dist/schema/chats.js +33 -0
  77. package/packages/db/dist/schema/commitments.js +18 -0
  78. package/packages/db/dist/schema/communication-events.js +14 -0
  79. package/packages/db/dist/schema/index.js +12 -0
  80. package/packages/db/dist/schema/message-log.js +20 -0
  81. package/packages/db/dist/schema/opportunities.js +23 -0
  82. package/packages/db/dist/schema/org.js +36 -0
  83. package/packages/db/dist/schema/projects.js +23 -0
  84. package/packages/db/dist/schema/tasks.js +46 -0
  85. package/packages/db/dist/schema/trace-spans.js +19 -0
  86. package/packages/db/package.json +12 -0
  87. package/packages/db/src/migrations/0000_simple_magneto.sql +148 -0
  88. package/packages/db/src/migrations/0001_nifty_morph.sql +42 -0
  89. package/packages/db/src/migrations/0002_common_joshua_kane.sql +20 -0
  90. package/packages/db/src/migrations/0003_add_cc_sessions.sql +13 -0
  91. package/packages/db/src/migrations/0004_jittery_triathlon.sql +1 -0
  92. package/packages/db/src/migrations/meta/0000_snapshot.json +987 -0
  93. package/packages/db/src/migrations/meta/0001_snapshot.json +1280 -0
  94. package/packages/db/src/migrations/meta/0002_snapshot.json +1417 -0
  95. package/packages/db/src/migrations/meta/0004_snapshot.json +1505 -0
  96. package/packages/db/src/migrations/meta/_journal.json +41 -0
  97. package/packages/mcp-tools/dist/index.js +41 -0
  98. package/packages/mcp-tools/dist/layer1/audit-append.js +38 -0
  99. package/packages/mcp-tools/dist/layer1/audit-query.js +51 -0
  100. package/packages/mcp-tools/dist/layer1/memory-brief.js +168 -0
  101. package/packages/mcp-tools/dist/layer1/memory-context.js +124 -0
  102. package/packages/mcp-tools/dist/layer1/memory-digest.js +126 -0
  103. package/packages/mcp-tools/dist/layer1/memory-forget.js +108 -0
  104. package/packages/mcp-tools/dist/layer1/memory-learn.js +63 -0
  105. package/packages/mcp-tools/dist/layer1/memory-recall.js +287 -0
  106. package/packages/mcp-tools/dist/layer1/memory-reflect.js +80 -0
  107. package/packages/mcp-tools/dist/layer1/memory-remember.js +119 -0
  108. package/packages/mcp-tools/dist/layer1/memory-search.js +263 -0
  109. package/packages/mcp-tools/dist/layer1/memory-write.js +21 -0
  110. package/packages/mcp-tools/dist/layer1/org-lookup.js +47 -0
  111. package/packages/mcp-tools/dist/layer1/project-get.js +28 -0
  112. package/packages/mcp-tools/dist/layer1/project-list.js +20 -0
  113. package/packages/mcp-tools/dist/layer1/report-daily.js +68 -0
  114. package/packages/mcp-tools/dist/layer1/task-get.js +29 -0
  115. package/packages/mcp-tools/dist/layer1/task-update.js +34 -0
  116. package/packages/mcp-tools/dist/layer2/loid/decision-log.js +15 -0
  117. package/packages/mcp-tools/dist/layer2/loid/decision-no-action.js +15 -0
  118. package/packages/mcp-tools/dist/layer2/loid/delivery-create-pr.js +30 -0
  119. package/packages/mcp-tools/dist/layer2/loid/delivery-share.js +12 -0
  120. package/packages/mcp-tools/dist/layer2/loid/delivery-submit.js +77 -0
  121. package/packages/mcp-tools/dist/layer2/loid/delivery-upload.js +18 -0
  122. package/packages/mcp-tools/dist/layer2/loid/project-remove.js +16 -0
  123. package/packages/mcp-tools/dist/layer2/loid/project-upsert.js +33 -0
  124. package/packages/mcp-tools/dist/layer2/loid/task-dispatch.js +177 -0
  125. package/packages/mcp-tools/dist/layer2/loid/task-lookup.js +38 -0
  126. package/packages/mcp-tools/dist/layer2/loid/yor-approve.js +8 -0
  127. package/packages/mcp-tools/dist/layer2/loid/yor-kill.js +7 -0
  128. package/packages/mcp-tools/dist/layer2/loid/yor-rework.js +7 -0
  129. package/packages/mcp-tools/dist/layer2/loid/yor-spawn.js +15 -0
  130. package/packages/mcp-tools/dist/layer2/loid/yor-status.js +8 -0
  131. package/packages/mcp-tools/dist/layer2/yor/task-block.js +11 -0
  132. package/packages/mcp-tools/dist/layer2/yor/task-deliver.js +35 -0
  133. package/packages/mcp-tools/dist/layer2/yor/task-progress.js +21 -0
  134. package/packages/mcp-tools/dist/layer3/adapters/feishu-adapter.js +191 -0
  135. package/packages/mcp-tools/dist/layer3/adapters/types.js +28 -0
  136. package/packages/mcp-tools/dist/layer3/channel-receive.js +11 -0
  137. package/packages/mcp-tools/dist/layer3/channel-send.js +90 -0
  138. package/packages/mcp-tools/dist/layer3/file-upload.js +44 -0
  139. package/packages/mcp-tools/dist/registry.js +779 -0
  140. package/packages/mcp-tools/package.json +13 -0
  141. package/workspace/.claude/settings.local.json +9 -0
  142. package/workspace/.mcp.json +12 -0
  143. package/workspace/CHARTER.md +73 -0
  144. package/workspace/CLAUDE.md +49 -0
  145. package/workspace/PROTOCOL.md +126 -0
  146. package/workspace/TOOLS.md +464 -0
  147. package/workspace/audit/.gitkeep +0 -0
  148. package/workspace/loid/CLAUDE.md +12 -0
  149. package/workspace/loid/PLAYBOOK.md +198 -0
  150. package/workspace/loid/PROFILE.md +78 -0
  151. package/workspace/memory/commitments/.gitkeep +0 -0
  152. package/workspace/memory/execution/.gitkeep +0 -0
  153. package/workspace/memory/people/.gitkeep +0 -0
  154. package/workspace/memory/projects/.gitkeep +0 -0
  155. package/workspace/memory/self/.gitkeep +0 -0
  156. package/workspace/reference/identity/.gitkeep +0 -0
  157. package/workspace/reference/org/escalation.yaml +24 -0
  158. package/workspace/reference/org/ownership.yaml +28 -0
  159. package/workspace/reports/.gitkeep +0 -0
  160. package/workspace/yor/CLAUDE.md +22 -0
  161. package/workspace/yor/PLAYBOOK.md +73 -0
  162. package/workspace/yor/PROFILE.md +52 -0
  163. package/workspace/yor/SELF-HEAL.md +39 -0
@@ -0,0 +1,41 @@
1
+ {
2
+ "version": "7",
3
+ "dialect": "sqlite",
4
+ "entries": [
5
+ {
6
+ "idx": 0,
7
+ "version": "6",
8
+ "when": 1771231965763,
9
+ "tag": "0000_simple_magneto",
10
+ "breakpoints": true
11
+ },
12
+ {
13
+ "idx": 1,
14
+ "version": "6",
15
+ "when": 1771898136519,
16
+ "tag": "0001_nifty_morph",
17
+ "breakpoints": true
18
+ },
19
+ {
20
+ "idx": 2,
21
+ "version": "6",
22
+ "when": 1771903810417,
23
+ "tag": "0002_common_joshua_kane",
24
+ "breakpoints": true
25
+ },
26
+ {
27
+ "idx": 3,
28
+ "version": "6",
29
+ "when": 1772006400000,
30
+ "tag": "0003_add_cc_sessions",
31
+ "breakpoints": true
32
+ },
33
+ {
34
+ "idx": 4,
35
+ "version": "6",
36
+ "when": 1771937237299,
37
+ "tag": "0004_jittery_triathlon",
38
+ "breakpoints": true
39
+ }
40
+ ]
41
+ }
@@ -0,0 +1,41 @@
1
+ // ── Layer 1: 共享基础 — 记忆工具(v2) ──
2
+ export { memoryRecall } from './layer1/memory-recall.js';
3
+ export { memoryRemember } from './layer1/memory-remember.js';
4
+ export { memoryDigest } from './layer1/memory-digest.js';
5
+ export { memoryBrief } from './layer1/memory-brief.js';
6
+ export { memoryForget } from './layer1/memory-forget.js';
7
+ // ── Layer 1: 旧版记忆工具(deprecated,保留编译兼容) ──
8
+ /** @deprecated 使用 memoryBrief 替代 */
9
+ export { memoryContext } from './layer1/memory-context.js';
10
+ /** @deprecated 使用 memoryRecall 替代 */
11
+ export { memorySearch, buildSearchIndex } from './layer1/memory-search.js';
12
+ /** @deprecated 使用 memoryRemember 替代 */
13
+ export { memoryLearn } from './layer1/memory-learn.js';
14
+ /** @deprecated 使用 memoryDigest 替代 */
15
+ export { memoryReflect } from './layer1/memory-reflect.js';
16
+ export { orgLookup } from './layer1/org-lookup.js';
17
+ export { taskGet } from './layer1/task-get.js';
18
+ export { auditAppend, appendToAuditFile } from './layer1/audit-append.js';
19
+ export { auditQuery } from './layer1/audit-query.js';
20
+ export { reportDaily } from './layer1/report-daily.js';
21
+ // ── Layer 2: Loid 专属 ──
22
+ export { taskDispatch } from './layer2/loid/task-dispatch.js';
23
+ export { taskLookup } from './layer2/loid/task-lookup.js';
24
+ export { decisionLog } from './layer2/loid/decision-log.js';
25
+ // ── Layer 2: Yor 专属 ──
26
+ export { taskDeliver } from './layer2/yor/task-deliver.js';
27
+ export { taskBlock } from './layer2/yor/task-block.js';
28
+ export { taskProgress } from './layer2/yor/task-progress.js';
29
+ // ── Layer 3: 外部桥梁 ──
30
+ export { channelSend } from './layer3/channel-send.js';
31
+ export { channelReceive } from './layer3/channel-receive.js';
32
+ export { fileUpload } from './layer3/file-upload.js';
33
+ export { ChannelRegistry } from './layer3/adapters/types.js';
34
+ export { FeishuAdapter, detectMediaKind, resolveFileType, isMarkdown } from './layer3/adapters/feishu-adapter.js';
35
+ // ── Registry ──
36
+ export { createToolRouter, getToolsForRole, TOOL_REGISTRY } from './registry.js';
37
+ // ── 向后兼容(旧导出名保留) ──
38
+ export { taskGet as taskContext } from './layer1/task-get.js';
39
+ /** @deprecated 使用 memoryLearn 替代 */
40
+ export { memoryWrite } from './layer1/memory-write.js';
41
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,38 @@
1
+ import { appendFile, mkdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { insertAuditEvent } from '@team-anya/db';
4
+ /**
5
+ * 审计事件双写:SQLite + 文件
6
+ */
7
+ export async function auditAppend(db, workspacePath, input) {
8
+ // 1. 写入 SQLite
9
+ const result = insertAuditEvent(db, {
10
+ event_type: input.event_type,
11
+ actor: input.actor,
12
+ task_id: input.task_id ?? null,
13
+ summary: input.summary,
14
+ detail: input.detail ? JSON.stringify(input.detail) : null,
15
+ });
16
+ // 2. 写入审计文件
17
+ await appendToAuditFile(workspacePath, input);
18
+ return { event_id: result.id };
19
+ }
20
+ /**
21
+ * 仅写审计文件(taskTransition 内部调用)
22
+ */
23
+ export async function appendToAuditFile(workspacePath, input) {
24
+ const date = new Date().toISOString().slice(0, 10);
25
+ const auditDir = join(workspacePath, 'audit');
26
+ await mkdir(auditDir, { recursive: true });
27
+ const filePath = join(auditDir, `events-${date}.jsonl`);
28
+ const entry = {
29
+ ts: new Date().toISOString(),
30
+ type: input.event_type,
31
+ actor: input.actor,
32
+ task_id: input.task_id,
33
+ summary: input.summary,
34
+ ...(input.detail ? { detail: input.detail } : {}),
35
+ };
36
+ await appendFile(filePath, JSON.stringify(entry) + '\n');
37
+ }
38
+ //# sourceMappingURL=audit-append.js.map
@@ -0,0 +1,51 @@
1
+ import { getAuditEventsByTask, getAuditEventsByType, getAuditEventsByDate } from '@team-anya/db';
2
+ /**
3
+ * 查询审计事件
4
+ *
5
+ * 支持按 task_id、event_type、actor、时间范围过滤。
6
+ * 补齐"只写不读"的缺陷。
7
+ */
8
+ export async function auditQuery(db, input) {
9
+ const limit = input.limit ?? 20;
10
+ let events;
11
+ // 按优先级选择查询路径
12
+ if (input.task_id) {
13
+ events = getAuditEventsByTask(db, input.task_id);
14
+ }
15
+ else if (input.event_type) {
16
+ events = getAuditEventsByType(db, input.event_type);
17
+ }
18
+ else if (input.since) {
19
+ // 按日期查询(取 since 的日期部分)
20
+ const date = input.since.slice(0, 10);
21
+ events = getAuditEventsByDate(db, date);
22
+ }
23
+ else {
24
+ // 无过滤条件时,查今天的事件
25
+ const today = new Date().toISOString().slice(0, 10);
26
+ events = getAuditEventsByDate(db, today);
27
+ }
28
+ // 应用 actor 过滤
29
+ if (input.actor) {
30
+ events = events.filter(e => e.actor === input.actor);
31
+ }
32
+ // 应用 since 时间过滤
33
+ if (input.since) {
34
+ const sinceTime = new Date(input.since).getTime();
35
+ events = events.filter(e => new Date(e.created_at).getTime() >= sinceTime);
36
+ }
37
+ // 按时间倒序,截取 limit
38
+ events.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
39
+ return {
40
+ events: events.slice(0, limit).map(e => ({
41
+ id: e.id,
42
+ event_type: e.event_type,
43
+ actor: e.actor,
44
+ task_id: e.task_id,
45
+ summary: e.summary,
46
+ detail: e.detail,
47
+ created_at: e.created_at,
48
+ })),
49
+ };
50
+ }
51
+ //# sourceMappingURL=audit-query.js.map
@@ -0,0 +1,168 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import * as yaml from 'yaml';
4
+ import { memoryRecall } from './memory-recall.js';
5
+ // 1 token ~ 3 characters(中英混合粗估)
6
+ const CHARS_PER_TOKEN = 3;
7
+ /**
8
+ * 组装记忆摘要(替代 memory.context)
9
+ *
10
+ * 按优先级在 token 预算内组装记忆:
11
+ * 1. 人的记忆
12
+ * 2. 项目注意事项
13
+ * 3. 相关执行经验
14
+ * 4. 活跃承诺
15
+ * 5. 自我提醒
16
+ */
17
+ export async function memoryBrief(workspacePath, input) {
18
+ const tokenBudget = input.token_budget ?? 1500;
19
+ const maxChars = tokenBudget * CHARS_PER_TOKEN;
20
+ const sections = [];
21
+ const sources = [];
22
+ let charsUsed = 0;
23
+ const appendSection = (label, content, count) => {
24
+ const sectionText = `### ${label}\n${content}`;
25
+ if (charsUsed + sectionText.length > maxChars) {
26
+ const remaining = maxChars - charsUsed;
27
+ if (remaining > 50) {
28
+ sections.push(`### ${label}\n${content.slice(0, remaining - label.length - 10)}...(截断)`);
29
+ sources.push({ label, count });
30
+ charsUsed = maxChars;
31
+ }
32
+ return false;
33
+ }
34
+ sections.push(sectionText);
35
+ sources.push({ label, count });
36
+ charsUsed += sectionText.length;
37
+ return true;
38
+ };
39
+ // 1. 人的记忆
40
+ if (input.sender_id) {
41
+ const personContent = await readPersonSummary(workspacePath, input.sender_id);
42
+ if (personContent) {
43
+ appendSection(`关于 ${input.sender_id}`, personContent, 1);
44
+ }
45
+ }
46
+ // 2. 项目注意事项
47
+ if (input.project_id) {
48
+ const pitfalls = await readProjectPitfalls(workspacePath, input.project_id);
49
+ if (pitfalls) {
50
+ appendSection(`${input.project_id} 注意事项`, pitfalls, 1);
51
+ }
52
+ }
53
+ // 3. 相关执行经验(BM25 搜索)
54
+ if (input.task_type || input.project_id) {
55
+ const query = [input.task_type, input.project_id].filter(Boolean).join(' ');
56
+ if (query) {
57
+ const result = await memoryRecall(workspacePath, {
58
+ query,
59
+ scope: ['execution'],
60
+ depth: 'summary',
61
+ limit: 3,
62
+ });
63
+ if (result.results.length > 0) {
64
+ const content = result.results.map(r => `- ${r.content}`).join('\n');
65
+ appendSection('执行经验', content, result.results.length);
66
+ }
67
+ }
68
+ }
69
+ // 4. 活跃承诺
70
+ if (input.sender_id) {
71
+ const commitments = await readActiveCommitments(workspacePath, input.sender_id);
72
+ if (commitments) {
73
+ appendSection('相关承诺', commitments, 1);
74
+ }
75
+ }
76
+ // 5. 自我提醒
77
+ const selfReminders = await readSelfReminders(workspacePath, input.task_type);
78
+ if (selfReminders) {
79
+ appendSection('自我提醒', selfReminders, 1);
80
+ }
81
+ const brief = sections.length > 0
82
+ ? `## 记忆摘要\n\n${sections.join('\n\n')}`
83
+ : '';
84
+ return {
85
+ brief,
86
+ sources,
87
+ budget_used: Math.ceil(charsUsed / CHARS_PER_TOKEN),
88
+ };
89
+ }
90
+ // ── 内部读取函数 ──
91
+ async function readPersonSummary(workspacePath, personId) {
92
+ try {
93
+ const filePath = join(workspacePath, 'memory', 'people', `${personId}.yaml`);
94
+ const content = await readFile(filePath, 'utf-8');
95
+ const doc = yaml.parse(content);
96
+ if (!doc?.observations)
97
+ return null;
98
+ // 取最近 3 条
99
+ const recent = doc.observations.slice(-3);
100
+ return recent.map((o) => `- ${typeof o === 'string' ? o : (o.content ?? '')}`).join('\n');
101
+ }
102
+ catch {
103
+ return null;
104
+ }
105
+ }
106
+ async function readProjectPitfalls(workspacePath, projectId) {
107
+ try {
108
+ const filePath = join(workspacePath, 'memory', 'projects', projectId, 'pitfall.yaml');
109
+ const content = await readFile(filePath, 'utf-8');
110
+ const doc = yaml.parse(content);
111
+ if (!doc?.entries)
112
+ return null;
113
+ // 只取 heat > 0 的活跃条目
114
+ const active = doc.entries.filter((e) => !e.meta || e.meta.heat > 0);
115
+ const recent = active.slice(-5);
116
+ return recent.map((e) => `- ${typeof e === 'string' ? e : (e.content ?? '')}`).join('\n');
117
+ }
118
+ catch {
119
+ return null;
120
+ }
121
+ }
122
+ async function readActiveCommitments(workspacePath, senderId) {
123
+ try {
124
+ const filePath = join(workspacePath, 'memory', 'commitments', 'active.yaml');
125
+ const content = await readFile(filePath, 'utf-8');
126
+ const doc = yaml.parse(content);
127
+ if (!doc?.active)
128
+ return null;
129
+ // 过滤与 senderId 相关的承诺
130
+ const related = doc.active.filter((c) => {
131
+ const text = typeof c === 'string' ? c : (c.content ?? '');
132
+ return text.includes(senderId);
133
+ });
134
+ if (related.length === 0)
135
+ return null;
136
+ return related.map((c) => `- ${typeof c === 'string' ? c : (c.content ?? '')}`).join('\n');
137
+ }
138
+ catch {
139
+ return null;
140
+ }
141
+ }
142
+ async function readSelfReminders(workspacePath, taskType) {
143
+ try {
144
+ const filePath = join(workspacePath, 'memory', 'self', 'profile.yaml');
145
+ const content = await readFile(filePath, 'utf-8');
146
+ const doc = yaml.parse(content);
147
+ if (!doc?.entries)
148
+ return null;
149
+ let entries = doc.entries.filter((e) => !e.meta || e.meta.heat > 0);
150
+ // 如果有 taskType,优先匹配相关条目
151
+ if (taskType) {
152
+ const related = entries.filter((e) => {
153
+ const text = typeof e === 'string' ? e : (e.content ?? '');
154
+ return text.toLowerCase().includes(taskType.toLowerCase());
155
+ });
156
+ if (related.length > 0)
157
+ entries = related;
158
+ }
159
+ const recent = entries.slice(-3);
160
+ if (recent.length === 0)
161
+ return null;
162
+ return recent.map((e) => `- ${typeof e === 'string' ? e : (e.content ?? '')}`).join('\n');
163
+ }
164
+ catch {
165
+ return null;
166
+ }
167
+ }
168
+ //# sourceMappingURL=memory-brief.js.map
@@ -0,0 +1,124 @@
1
+ import { getTask, getAuditEventsByTask, getActiveCommitments, getOpenOpportunities, getAllTasks } from '@team-anya/db';
2
+ import { memorySearch } from './memory-search.js';
3
+ import { orgLookup } from './org-lookup.js';
4
+ // Token 预算(按字符数粗估,1 token ≈ 2 中文字符 / 4 英文字符)
5
+ const TOKEN_BUDGET = 4000;
6
+ /**
7
+ * 按场景获取预组装上下文
8
+ *
9
+ * 根据不同场景,按 required → recommended 顺序查询多种记忆源,
10
+ * 在 token 预算内拼装结构化文本供 Agent prompt 注入。
11
+ */
12
+ export async function memoryContext(db, workspacePath, input) {
13
+ const sources = [];
14
+ const sections = [];
15
+ let budgetUsed = 0;
16
+ const appendSection = (label, content, count) => {
17
+ const estimatedTokens = Math.ceil(content.length / 3);
18
+ if (budgetUsed + estimatedTokens > TOKEN_BUDGET) {
19
+ // 截断到预算
20
+ const remaining = (TOKEN_BUDGET - budgetUsed) * 3;
21
+ if (remaining > 100) {
22
+ sections.push(`## ${label}\n${content.slice(0, remaining)}…(已截断)`);
23
+ sources.push({ label, count });
24
+ budgetUsed = TOKEN_BUDGET;
25
+ }
26
+ return;
27
+ }
28
+ sections.push(`## ${label}\n${content}`);
29
+ sources.push({ label, count });
30
+ budgetUsed += estimatedTokens;
31
+ };
32
+ switch (input.scene) {
33
+ case 'task_execution': {
34
+ // 为 Yor 执行任务提供上下文
35
+ const taskId = input.vars.current_task;
36
+ if (taskId) {
37
+ const task = getTask(db, taskId);
38
+ if (task) {
39
+ appendSection('当前任务', `- ID: ${task.task_id}\n- 标题: ${task.title}\n- 状态: ${task.status}\n- 目标: ${task.objective ?? '未指定'}`, 1);
40
+ }
41
+ const events = getAuditEventsByTask(db, taskId);
42
+ if (events.length > 0) {
43
+ const recent = events.slice(-5).map(e => `- [${e.event_type}] ${e.summary}`).join('\n');
44
+ appendSection('最近事件', recent, events.length);
45
+ }
46
+ }
47
+ // 项目记忆
48
+ const projectId = input.vars.current_project;
49
+ if (projectId) {
50
+ const searchResult = await memorySearch(workspacePath, { query: projectId, project_id: projectId, limit: 3 });
51
+ if (searchResult.results.length > 0) {
52
+ const content = searchResult.results.map(r => `- [${r.type}] ${r.content.slice(0, 200)}`).join('\n');
53
+ appendSection('项目记忆', content, searchResult.results.length);
54
+ }
55
+ }
56
+ break;
57
+ }
58
+ case 'escalation': {
59
+ // 为升级场景提供组织信息和升级路径
60
+ const orgInfo = await orgLookup(db, workspacePath, {});
61
+ if (orgInfo.escalation_path && orgInfo.escalation_path.length > 0) {
62
+ const content = orgInfo.escalation_path.map(e => `- ${e.after_minutes}分钟后: ${e.action} → ${e.targets.join(', ')}`).join('\n');
63
+ appendSection('升级路径', content, orgInfo.escalation_path.length);
64
+ }
65
+ const taskId = input.vars.current_task;
66
+ if (taskId) {
67
+ const events = getAuditEventsByTask(db, taskId);
68
+ const blockerEvents = events.filter(e => e.event_type.includes('block') || e.event_type.includes('fail'));
69
+ if (blockerEvents.length > 0) {
70
+ const content = blockerEvents.slice(-5).map(e => `- [${e.event_type}] ${e.summary}`).join('\n');
71
+ appendSection('相关阻塞/失败事件', content, blockerEvents.length);
72
+ }
73
+ }
74
+ break;
75
+ }
76
+ case 'opportunity_eval': {
77
+ // 为机会评估提供活跃任务和承诺上下文
78
+ const tasks = getAllTasks(db);
79
+ const activeTasks = tasks.filter(t => !['DONE', 'CANCELLED'].includes(t.status));
80
+ if (activeTasks.length > 0) {
81
+ const content = activeTasks.slice(0, 10).map(t => `- [${t.task_id}] ${t.title} (${t.status})`).join('\n');
82
+ appendSection('活跃任务', content, activeTasks.length);
83
+ }
84
+ const commitments = getActiveCommitments(db);
85
+ if (commitments.length > 0) {
86
+ const content = commitments.map(c => `- [${c.task_id}] ${c.promise} (向 ${c.promised_to})`).join('\n');
87
+ appendSection('活跃承诺', content, commitments.length);
88
+ }
89
+ break;
90
+ }
91
+ case 'daily_report': {
92
+ // 为日报生成提供全面的状态概览
93
+ const tasks = getAllTasks(db);
94
+ const today = new Date().toISOString().slice(0, 10);
95
+ const doneTasks = tasks.filter(t => t.status === 'DONE' && t.updated_at?.startsWith(today));
96
+ const activeTasks = tasks.filter(t => ['IN_PROGRESS', 'READY', 'DELIVERING'].includes(t.status));
97
+ const blockedTasks = tasks.filter(t => t.status === 'BLOCKED');
98
+ if (doneTasks.length > 0) {
99
+ const content = doneTasks.map(t => `- [${t.task_id}] ${t.title}`).join('\n');
100
+ appendSection('今日完成', content, doneTasks.length);
101
+ }
102
+ if (activeTasks.length > 0) {
103
+ const content = activeTasks.map(t => `- [${t.task_id}] ${t.title} (${t.status})`).join('\n');
104
+ appendSection('进行中', content, activeTasks.length);
105
+ }
106
+ if (blockedTasks.length > 0) {
107
+ const content = blockedTasks.map(t => `- [${t.task_id}] ${t.title} — ${t.blocked_reason ?? '未知'}`).join('\n');
108
+ appendSection('阻塞项', content, blockedTasks.length);
109
+ }
110
+ const opportunities = getOpenOpportunities(db);
111
+ if (opportunities.length > 0) {
112
+ const content = opportunities.map(o => `- ${o.summary} (评分: ${o.total_score?.toFixed(2) ?? 'N/A'})`).join('\n');
113
+ appendSection('待处理机会', content, opportunities.length);
114
+ }
115
+ break;
116
+ }
117
+ }
118
+ return {
119
+ context: sections.join('\n\n'),
120
+ sources,
121
+ budget_used: budgetUsed,
122
+ };
123
+ }
124
+ //# sourceMappingURL=memory-context.js.map
@@ -0,0 +1,126 @@
1
+ import { memoryRemember } from './memory-remember.js';
2
+ const EXTRACTION_RULES = [
3
+ // 保留原有 3 条规则
4
+ {
5
+ patterns: [/fail/i, /失败/, /error/i, /错误/],
6
+ category: 'execution',
7
+ sub_type: 'failure',
8
+ importance: 0.8,
9
+ prefix: '失败记录',
10
+ },
11
+ {
12
+ patterns: [/decision/i, /决策/, /决定/],
13
+ category: 'project',
14
+ sub_type: 'decision',
15
+ importance: 0.6,
16
+ prefix: '决策记录',
17
+ },
18
+ {
19
+ patterns: [/block/i, /阻塞/, /卡住/, /stuck/i],
20
+ category: 'execution',
21
+ sub_type: 'failure',
22
+ importance: 0.7,
23
+ prefix: '阻塞经验',
24
+ },
25
+ // 新增:提取承诺类记忆
26
+ {
27
+ patterns: [/答应/, /承诺/, /保证/, /deadline/i, /截止/, /之前完成/],
28
+ category: 'commitment',
29
+ importance: 0.9,
30
+ prefix: '承诺记录',
31
+ },
32
+ // 新增:提取项目经验
33
+ {
34
+ patterns: [/注意/, /小心/, /别忘/, /踩坑/, /之前遇到/, /经验教训/, /切记/],
35
+ category: 'project',
36
+ sub_type: 'pitfall',
37
+ importance: 0.7,
38
+ prefix: '项目经验',
39
+ },
40
+ ];
41
+ /**
42
+ * 消化对话/日志,提取记忆(替代 memory.reflect)
43
+ *
44
+ * 当前实现:增强版规则提取(不依赖外部 LLM,保持自包含)。
45
+ * // TODO: 升级为 Haiku LLM 提取,实现更精确的语义理解
46
+ */
47
+ export async function memoryDigest(db, workspacePath, input) {
48
+ const entries = [];
49
+ const lines = input.conversation.split('\n').filter(l => l.trim());
50
+ // 基于规则提取
51
+ for (const line of lines) {
52
+ for (const rule of EXTRACTION_RULES) {
53
+ const matched = rule.patterns.some(p => p.test(line));
54
+ if (!matched)
55
+ continue;
56
+ entries.push({
57
+ content: `${rule.prefix}: ${line.trim()}`,
58
+ category: rule.category,
59
+ sub_type: rule.sub_type,
60
+ });
61
+ break; // 每行只匹配一条规则
62
+ }
63
+ }
64
+ // 去重
65
+ const seen = new Set();
66
+ const uniqueEntries = entries.filter(e => {
67
+ const key = `${e.category}:${e.content.slice(0, 50)}`;
68
+ if (seen.has(key))
69
+ return false;
70
+ seen.add(key);
71
+ return true;
72
+ });
73
+ // 写入记忆
74
+ for (const entry of uniqueEntries) {
75
+ const rule = EXTRACTION_RULES.find(r => r.prefix === entry.content.split(':')[0]);
76
+ await memoryRemember(db, workspacePath, {
77
+ category: entry.category,
78
+ target: entry.category === 'project' ? input.project_id : undefined,
79
+ content: entry.content,
80
+ sub_type: entry.sub_type,
81
+ importance: rule?.importance ?? 0.5,
82
+ source: input.task_id,
83
+ });
84
+ }
85
+ // 如果提供了 sender_id,额外提取沟通信号写入 people
86
+ if (input.sender_id) {
87
+ const commSignals = extractCommunicationSignals(input.conversation);
88
+ for (const signal of commSignals) {
89
+ await memoryRemember(db, workspacePath, {
90
+ category: 'people',
91
+ target: input.sender_id,
92
+ content: signal,
93
+ importance: 0.4,
94
+ source: input.task_id,
95
+ });
96
+ uniqueEntries.push({
97
+ content: signal,
98
+ category: 'people',
99
+ });
100
+ }
101
+ }
102
+ return {
103
+ memories_created: uniqueEntries.length,
104
+ entries: uniqueEntries,
105
+ };
106
+ }
107
+ /**
108
+ * 从对话中提取沟通信号(偏好、习惯、关注点)
109
+ * // TODO: 升级为 Haiku LLM 提取
110
+ */
111
+ function extractCommunicationSignals(conversation) {
112
+ const signals = [];
113
+ const lines = conversation.split('\n');
114
+ for (const line of lines) {
115
+ // 偏好表达
116
+ if (/喜欢|偏好|prefer|习惯/.test(line)) {
117
+ signals.push(`偏好观察: ${line.trim().slice(0, 100)}`);
118
+ }
119
+ // 不满/反馈
120
+ if (/不满|不好|不行|改进|问题/.test(line) && line.length > 10) {
121
+ signals.push(`反馈信号: ${line.trim().slice(0, 100)}`);
122
+ }
123
+ }
124
+ return signals.slice(0, 3); // 最多 3 条
125
+ }
126
+ //# sourceMappingURL=memory-digest.js.map