team-anya 0.2.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 (145) hide show
  1. package/README.md +38 -0
  2. package/apps/server/dist/broker/cc-broker.js +267 -0
  3. package/apps/server/dist/cli.js +296 -0
  4. package/apps/server/dist/config.js +78 -0
  5. package/apps/server/dist/daemon.js +51 -0
  6. package/apps/server/dist/franky/context-builder.js +161 -0
  7. package/apps/server/dist/franky/franky-mcp-server.js +110 -0
  8. package/apps/server/dist/franky/franky-orchestrator.js +629 -0
  9. package/apps/server/dist/franky/index.js +5 -0
  10. package/apps/server/dist/franky/topic-router.js +16 -0
  11. package/apps/server/dist/gateway/chat-sync.js +135 -0
  12. package/apps/server/dist/gateway/command-router.js +116 -0
  13. package/apps/server/dist/gateway/commands/cancel.js +32 -0
  14. package/apps/server/dist/gateway/commands/help.js +16 -0
  15. package/apps/server/dist/gateway/commands/index.js +26 -0
  16. package/apps/server/dist/gateway/commands/restart.js +43 -0
  17. package/apps/server/dist/gateway/commands/status.js +34 -0
  18. package/apps/server/dist/gateway/commands/tasks.js +33 -0
  19. package/apps/server/dist/gateway/feishu-sender.js +508 -0
  20. package/apps/server/dist/gateway/feishu-ws.js +353 -0
  21. package/apps/server/dist/gateway/health-monitor.js +154 -0
  22. package/apps/server/dist/gateway/http.js +1064 -0
  23. package/apps/server/dist/gateway/media-downloader.js +182 -0
  24. package/apps/server/dist/gateway/message-events.js +10 -0
  25. package/apps/server/dist/gateway/message-intake.js +72 -0
  26. package/apps/server/dist/gateway/message-queue.js +118 -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 +121 -0
  30. package/apps/server/dist/loid/clarifier.js +162 -0
  31. package/apps/server/dist/loid/context-builder.js +462 -0
  32. package/apps/server/dist/loid/mcp-server.js +119 -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/project-registry.js +192 -0
  37. package/apps/server/dist/loid/reporter.js +148 -0
  38. package/apps/server/dist/loid/schemas.js +117 -0
  39. package/apps/server/dist/loid/self-calibrator.js +314 -0
  40. package/apps/server/dist/loid/session-manager.js +472 -0
  41. package/apps/server/dist/loid/session.js +276 -0
  42. package/apps/server/dist/main.js +528 -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 +107 -0
  47. package/apps/server/dist/yor/yor-orchestrator.js +248 -0
  48. package/apps/web/dist/assets/index-BiiEB0qZ.css +1 -0
  49. package/apps/web/dist/assets/index-Dnb9LGZd.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 +792 -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 +60 -0
  56. package/packages/core/dist/errors.js +35 -0
  57. package/packages/core/dist/index.js +9 -0
  58. package/packages/core/dist/office-init.js +190 -0
  59. package/packages/core/dist/repo-cache.js +70 -0
  60. package/packages/core/dist/scope/checker.js +114 -0
  61. package/packages/core/dist/scope/defaults.js +55 -0
  62. package/packages/core/dist/scope/index.js +3 -0
  63. package/packages/core/dist/state-machine.js +86 -0
  64. package/packages/core/dist/types/audit.js +12 -0
  65. package/packages/core/dist/types/backend.js +2 -0
  66. package/packages/core/dist/types/commitment.js +17 -0
  67. package/packages/core/dist/types/communication.js +18 -0
  68. package/packages/core/dist/types/index.js +9 -0
  69. package/packages/core/dist/types/opportunity.js +27 -0
  70. package/packages/core/dist/types/org.js +26 -0
  71. package/packages/core/dist/types/task.js +46 -0
  72. package/packages/core/dist/types/workspace.js +39 -0
  73. package/packages/core/dist/workspace-manager.js +314 -0
  74. package/packages/core/package.json +10 -0
  75. package/packages/db/dist/client.js +69 -0
  76. package/packages/db/dist/index.js +756 -0
  77. package/packages/db/dist/schema/audit-events.js +13 -0
  78. package/packages/db/dist/schema/cc-sessions.js +14 -0
  79. package/packages/db/dist/schema/chats.js +35 -0
  80. package/packages/db/dist/schema/commitments.js +18 -0
  81. package/packages/db/dist/schema/communication-events.js +14 -0
  82. package/packages/db/dist/schema/index.js +14 -0
  83. package/packages/db/dist/schema/message-log.js +20 -0
  84. package/packages/db/dist/schema/opportunities.js +23 -0
  85. package/packages/db/dist/schema/org.js +36 -0
  86. package/packages/db/dist/schema/projects.js +23 -0
  87. package/packages/db/dist/schema/tasks.js +51 -0
  88. package/packages/db/dist/schema/topics.js +22 -0
  89. package/packages/db/dist/schema/trace-spans.js +19 -0
  90. package/packages/db/dist/schema/workspaces.js +15 -0
  91. package/packages/db/package.json +12 -0
  92. package/packages/db/src/migrations/0000_baseline.sql +251 -0
  93. package/packages/db/src/migrations/0001_workspaces.sql +19 -0
  94. package/packages/db/src/migrations/0002_workspace_parent.sql +1 -0
  95. package/packages/db/src/migrations/0003_chat_context.sql +3 -0
  96. package/packages/db/src/migrations/meta/_journal.json +34 -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/franky/topic-checkpoint.js +43 -0
  117. package/packages/mcp-tools/dist/layer2/franky/topic-escalate.js +19 -0
  118. package/packages/mcp-tools/dist/layer2/loid/decision-log.js +15 -0
  119. package/packages/mcp-tools/dist/layer2/loid/decision-no-action.js +15 -0
  120. package/packages/mcp-tools/dist/layer2/loid/delivery-create-pr.js +30 -0
  121. package/packages/mcp-tools/dist/layer2/loid/delivery-share.js +12 -0
  122. package/packages/mcp-tools/dist/layer2/loid/delivery-submit.js +77 -0
  123. package/packages/mcp-tools/dist/layer2/loid/delivery-upload.js +18 -0
  124. package/packages/mcp-tools/dist/layer2/loid/project-remove.js +16 -0
  125. package/packages/mcp-tools/dist/layer2/loid/project-upsert.js +33 -0
  126. package/packages/mcp-tools/dist/layer2/loid/task-dispatch.js +206 -0
  127. package/packages/mcp-tools/dist/layer2/loid/task-escalate-to-topic.js +170 -0
  128. package/packages/mcp-tools/dist/layer2/loid/task-lookup.js +45 -0
  129. package/packages/mcp-tools/dist/layer2/loid/topic-close.js +22 -0
  130. package/packages/mcp-tools/dist/layer2/loid/topic-create.js +60 -0
  131. package/packages/mcp-tools/dist/layer2/loid/yor-approve.js +8 -0
  132. package/packages/mcp-tools/dist/layer2/loid/yor-kill.js +7 -0
  133. package/packages/mcp-tools/dist/layer2/loid/yor-rework.js +7 -0
  134. package/packages/mcp-tools/dist/layer2/loid/yor-spawn.js +28 -0
  135. package/packages/mcp-tools/dist/layer2/loid/yor-status.js +8 -0
  136. package/packages/mcp-tools/dist/layer2/yor/task-block.js +11 -0
  137. package/packages/mcp-tools/dist/layer2/yor/task-deliver.js +35 -0
  138. package/packages/mcp-tools/dist/layer2/yor/task-progress.js +21 -0
  139. package/packages/mcp-tools/dist/layer3/adapters/feishu-adapter.js +203 -0
  140. package/packages/mcp-tools/dist/layer3/adapters/types.js +28 -0
  141. package/packages/mcp-tools/dist/layer3/channel-receive.js +11 -0
  142. package/packages/mcp-tools/dist/layer3/channel-send.js +75 -0
  143. package/packages/mcp-tools/dist/layer3/file-upload.js +44 -0
  144. package/packages/mcp-tools/dist/registry.js +911 -0
  145. package/packages/mcp-tools/package.json +13 -0
@@ -0,0 +1,276 @@
1
+ import { insertCCSession, updateCCSessionEnded } from '@team-anya/db';
2
+ // ── 常量 ──
3
+ const DEFAULT_IDLE_TIMEOUT_MS = 2 * 60 * 60 * 1000; // 2 小时
4
+ const DEFAULT_MAX_TURNS = 50;
5
+ // ── LoidSession ──
6
+ export class LoidSession {
7
+ state = 'idle';
8
+ broker;
9
+ instanceId;
10
+ config;
11
+ callbacks;
12
+ pendingMessages = [];
13
+ turnCount = 0;
14
+ maxTurns;
15
+ idleTimer = null;
16
+ lastActivityAt = new Date();
17
+ connected = false;
18
+ cliSessionId = null;
19
+ /** Broker 事件监听器引用(用于 dispose 时清理) */
20
+ boundResultListener = null;
21
+ boundCrashListener = null;
22
+ boundExitedListener = null;
23
+ constructor(config, callbacks) {
24
+ this.config = config;
25
+ this.callbacks = callbacks;
26
+ this.maxTurns = config.maxTurns ?? DEFAULT_MAX_TURNS;
27
+ this.broker = config.broker;
28
+ this.instanceId = config.instanceId;
29
+ }
30
+ // ── 公开方法 ──
31
+ /**
32
+ * 通过 CCBroker 启动 CC 进程并建立连接
33
+ * @param resumeSessionId 传入则尝试 resume 到之前的 CC session
34
+ */
35
+ async connect(resumeSessionId) {
36
+ // 注册 broker 事件监听(过滤当前 instanceId)
37
+ this.boundResultListener = (id, _role, result) => {
38
+ if (id === this.instanceId) {
39
+ this.handleResult(result);
40
+ }
41
+ };
42
+ this.boundCrashListener = (id, _role, _error) => {
43
+ if (id === this.instanceId) {
44
+ this.handleCrash();
45
+ }
46
+ };
47
+ this.boundExitedListener = (id) => {
48
+ if (id === this.instanceId && this.connected) {
49
+ if (this.state !== 'disposed') {
50
+ this.config.logger?.error('[LoidSession] CC 进程异常退出,触发崩溃恢复');
51
+ this.handleCrash();
52
+ }
53
+ }
54
+ };
55
+ this.broker.on('instance.result', this.boundResultListener);
56
+ this.broker.on('instance.crash', this.boundCrashListener);
57
+ this.broker.on('instance.exited', this.boundExitedListener);
58
+ // 监听 CC session ID
59
+ const sessionIdListener = (id, cliSessionId) => {
60
+ if (id === this.instanceId && this.config.db) {
61
+ this.cliSessionId = cliSessionId;
62
+ insertCCSession(this.config.db, {
63
+ session_id: cliSessionId,
64
+ role: 'loid',
65
+ instance_id: this.instanceId,
66
+ chat_id: this.config.chatId,
67
+ project_path: this.config.backendConfig.workingDir,
68
+ });
69
+ this.config.logger?.info(`[LoidSession] 记录 CC session: ${cliSessionId}`);
70
+ // 一次性监听,获取后移除
71
+ this.broker.removeListener('instance.sessionId', sessionIdListener);
72
+ }
73
+ };
74
+ this.broker.on('instance.sessionId', sessionIdListener);
75
+ const backendConfig = resumeSessionId
76
+ ? { ...this.config.backendConfig, resumeSessionId }
77
+ : this.config.backendConfig;
78
+ await this.broker.spawn({
79
+ id: this.instanceId,
80
+ role: 'loid',
81
+ backendConfig,
82
+ logFile: this.config.logFile,
83
+ });
84
+ this.connected = true;
85
+ this.resetIdleTimer();
86
+ }
87
+ /**
88
+ * 投递消息:IDLE 时直接发送,EXECUTING 时缓冲
89
+ * 返回 false 表示 session 不接受消息(DISPOSED)
90
+ */
91
+ enqueue(msg) {
92
+ if (this.state === 'disposed') {
93
+ return false;
94
+ }
95
+ this.lastActivityAt = new Date();
96
+ if (this.state === 'idle') {
97
+ this.state = 'executing';
98
+ this.clearIdleTimer();
99
+ try {
100
+ this.broker.sendPrompt(this.instanceId, msg.prompt);
101
+ }
102
+ catch (err) {
103
+ this.config.logger?.error('[LoidSession] sendPrompt 失败:', err);
104
+ this.handleCrash();
105
+ }
106
+ }
107
+ else {
108
+ // EXECUTING → 缓冲
109
+ this.pendingMessages.push(msg);
110
+ }
111
+ return true;
112
+ }
113
+ /**
114
+ * 获取当前状态
115
+ */
116
+ getState() {
117
+ return this.state;
118
+ }
119
+ /**
120
+ * 获取当前轮次数
121
+ */
122
+ getTurnCount() {
123
+ return this.turnCount;
124
+ }
125
+ /**
126
+ * 获取缓冲区消息数
127
+ */
128
+ getPendingCount() {
129
+ return this.pendingMessages.length;
130
+ }
131
+ /**
132
+ * 获取最后活跃时间(供 LRU 淘汰使用)
133
+ */
134
+ getLastActivityAt() {
135
+ return this.lastActivityAt;
136
+ }
137
+ /**
138
+ * 销毁 session,释放资源
139
+ */
140
+ async dispose() {
141
+ if (this.state === 'disposed')
142
+ return;
143
+ this.state = 'disposed';
144
+ this.clearIdleTimer();
145
+ this.connected = false;
146
+ // 更新 cc_sessions.ended_at
147
+ if (this.cliSessionId && this.config.db) {
148
+ updateCCSessionEnded(this.config.db, this.cliSessionId);
149
+ }
150
+ this.removeBrokerListeners();
151
+ await this.broker.dispose(this.instanceId).catch(() => { });
152
+ }
153
+ // ── 私有方法 ──
154
+ /**
155
+ * CC 执行完一轮后的 drain loop
156
+ */
157
+ handleResult(result) {
158
+ this.callbacks.onResult?.(result);
159
+ this.turnCount++;
160
+ this.lastActivityAt = new Date();
161
+ if (this.state === 'disposed')
162
+ return;
163
+ // drain: 缓冲区有消息 → 合并发送
164
+ if (this.pendingMessages.length > 0) {
165
+ const buffered = this.pendingMessages.splice(0);
166
+ const prompt = this.formatBufferedMessages(buffered);
167
+ try {
168
+ this.broker.sendPrompt(this.instanceId, prompt);
169
+ }
170
+ catch (err) {
171
+ this.config.logger?.error('[LoidSession] drain sendPrompt 失败:', err);
172
+ this.handleCrash();
173
+ }
174
+ return;
175
+ }
176
+ // 达到硬上限 → 直接 dispose(不生成摘要)
177
+ if (this.turnCount >= this.maxTurns) {
178
+ this.config.logger?.info(`[LoidSession] 达到硬上限 (${this.maxTurns} 轮),销毁 session`);
179
+ this.disposeAndNotify();
180
+ return;
181
+ }
182
+ // 无待处理消息 → 回 IDLE,启动空闲计时器
183
+ this.state = 'idle';
184
+ this.resetIdleTimer();
185
+ }
186
+ /**
187
+ * 崩溃处理:交还未处理消息,标记 disposed
188
+ */
189
+ handleCrash() {
190
+ if (this.state === 'disposed')
191
+ return;
192
+ this.state = 'disposed';
193
+ this.clearIdleTimer();
194
+ this.connected = false;
195
+ const savedSessionId = this.cliSessionId;
196
+ this.removeBrokerListeners();
197
+ const orphans = this.pendingMessages.splice(0);
198
+ this.callbacks.onCrash(orphans, savedSessionId);
199
+ }
200
+ /**
201
+ * dispose 并通知回调
202
+ */
203
+ async disposeAndNotify() {
204
+ await this.dispose();
205
+ this.callbacks.onDisposed();
206
+ }
207
+ /**
208
+ * 重置空闲计时器
209
+ */
210
+ resetIdleTimer() {
211
+ this.clearIdleTimer();
212
+ const timeout = this.config.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
213
+ this.idleTimer = setTimeout(() => {
214
+ if (this.state === 'idle') {
215
+ this.config.logger?.info(`[LoidSession] 空闲超时 (${timeout}ms),销毁 session`);
216
+ this.disposeAndNotify();
217
+ }
218
+ }, timeout);
219
+ }
220
+ /**
221
+ * 清除空闲计时器
222
+ */
223
+ clearIdleTimer() {
224
+ if (this.idleTimer) {
225
+ clearTimeout(this.idleTimer);
226
+ this.idleTimer = null;
227
+ }
228
+ }
229
+ /**
230
+ * 移除 broker 事件监听器
231
+ */
232
+ removeBrokerListeners() {
233
+ if (this.boundResultListener) {
234
+ this.broker.removeListener('instance.result', this.boundResultListener);
235
+ this.boundResultListener = null;
236
+ }
237
+ if (this.boundCrashListener) {
238
+ this.broker.removeListener('instance.crash', this.boundCrashListener);
239
+ this.boundCrashListener = null;
240
+ }
241
+ if (this.boundExitedListener) {
242
+ this.broker.removeListener('instance.exited', this.boundExitedListener);
243
+ this.boundExitedListener = null;
244
+ }
245
+ }
246
+ /**
247
+ * 合并缓冲消息为单个 prompt
248
+ * 临时内联实现(正式版本由 context-builder 的 formatBufferedMessages 提供)
249
+ */
250
+ formatBufferedMessages(messages) {
251
+ if (messages.length === 1) {
252
+ return messages[0].prompt;
253
+ }
254
+ const lines = [];
255
+ lines.push(`你在处理上一件事的过程中,该对话又收到了 ${messages.length} 条新消息:`);
256
+ lines.push('');
257
+ for (let i = 0; i < messages.length; i++) {
258
+ const msg = messages[i];
259
+ const time = msg.enqueuedAt.toLocaleTimeString('zh-CN', {
260
+ hour: '2-digit',
261
+ minute: '2-digit',
262
+ second: '2-digit',
263
+ hour12: false,
264
+ });
265
+ const typeLabel = msg.type === 'delivery' ? ' [交付]'
266
+ : msg.type === 'recovery' ? ' [恢复]'
267
+ : '';
268
+ lines.push(`--- 消息 ${i + 1} (${time}${typeLabel}) ---`);
269
+ lines.push(msg.prompt);
270
+ lines.push('');
271
+ }
272
+ lines.push('请综合这些新消息,决定下一步行动。');
273
+ return lines.join('\n');
274
+ }
275
+ }
276
+ //# sourceMappingURL=session.js.map