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,135 @@
1
+ import { getChat, upsertChat, upsertChatMember, removeChatMembers, upsertOrgMember } from '@team-anya/db';
2
+ const SYNC_INTERVAL_MS = 60 * 60 * 1000; // 1 小时内不重复同步
3
+ export class ChatSyncService {
4
+ larkClient;
5
+ db;
6
+ syncing = new Set(); // 防并发重复同步
7
+ constructor(larkClient, db) {
8
+ this.larkClient = larkClient;
9
+ this.db = db;
10
+ }
11
+ /** 检查是否需要同步(不存在或超过同步间隔) */
12
+ needsSync(chatId) {
13
+ const chat = getChat(this.db, chatId);
14
+ if (!chat)
15
+ return true;
16
+ if (!chat.last_synced_at)
17
+ return true;
18
+ const elapsed = Date.now() - new Date(chat.last_synced_at).getTime();
19
+ return elapsed > SYNC_INTERVAL_MS;
20
+ }
21
+ /** 同步单个群信息 */
22
+ async syncChat(chatId) {
23
+ try {
24
+ const resp = await this.larkClient.im.chat.get({
25
+ path: { chat_id: chatId },
26
+ });
27
+ const chatData = resp?.data;
28
+ if (!chatData)
29
+ return;
30
+ upsertChat(this.db, {
31
+ chat_id: chatId,
32
+ platform: 'feishu',
33
+ name: chatData.name ?? null,
34
+ description: chatData.description ?? null,
35
+ avatar: chatData.avatar ?? null,
36
+ owner_id: chatData.owner_id ?? null,
37
+ chat_mode: chatData.chat_mode ?? null,
38
+ chat_type: chatData.chat_type ?? null,
39
+ chat_tag: chatData.chat_tag ?? null,
40
+ external: chatData.external ? 1 : 0,
41
+ tenant_key: chatData.tenant_key ?? null,
42
+ user_count: typeof chatData.user_count === 'string'
43
+ ? parseInt(chatData.user_count, 10)
44
+ : (chatData.user_count ?? null),
45
+ bot_count: typeof chatData.bot_count === 'string'
46
+ ? parseInt(chatData.bot_count, 10)
47
+ : (chatData.bot_count ?? null),
48
+ last_synced_at: new Date().toISOString(),
49
+ });
50
+ console.log(`[chat-sync] 群信息同步完成: ${chatId} (${chatData.name ?? 'unnamed'})`);
51
+ }
52
+ catch (err) {
53
+ console.warn(`[chat-sync] 同步群信息失败 (${chatId}):`, err);
54
+ }
55
+ }
56
+ /** 同步群成员(全量替换) */
57
+ async syncChatMembers(chatId) {
58
+ try {
59
+ // 清除旧成员数据
60
+ removeChatMembers(this.db, chatId);
61
+ let pageToken;
62
+ let memberCount = 0;
63
+ do {
64
+ const resp = await this.larkClient.im.chatMembers.get({
65
+ path: { chat_id: chatId },
66
+ params: {
67
+ member_id_type: 'open_id',
68
+ ...(pageToken ? { page_token: pageToken } : {}),
69
+ },
70
+ });
71
+ const items = resp?.data?.items ?? [];
72
+ for (const item of items) {
73
+ const openId = item.member_id;
74
+ if (!openId)
75
+ continue;
76
+ // 同步用户完整信息到 org_members
77
+ await this.resolveAndUpsertMember(openId);
78
+ // 写入 chat_members 关联
79
+ upsertChatMember(this.db, {
80
+ chat_id: chatId,
81
+ member_id: openId,
82
+ role: item.member_id_type === 'owner' ? 'owner' : 'member',
83
+ });
84
+ memberCount++;
85
+ }
86
+ pageToken = resp?.data?.page_token || undefined;
87
+ } while (pageToken);
88
+ console.log(`[chat-sync] 群成员同步完成: ${chatId}, 共 ${memberCount} 人`);
89
+ }
90
+ catch (err) {
91
+ console.warn(`[chat-sync] 同步群成员失败 (${chatId}):`, err);
92
+ }
93
+ }
94
+ /** 完整同步(群信息 + 成员) */
95
+ async syncChatFull(chatId) {
96
+ if (this.syncing.has(chatId))
97
+ return;
98
+ this.syncing.add(chatId);
99
+ try {
100
+ await this.syncChat(chatId);
101
+ await this.syncChatMembers(chatId);
102
+ }
103
+ finally {
104
+ this.syncing.delete(chatId);
105
+ }
106
+ }
107
+ /** 解析飞书用户完整信息并 upsert 到 org_members */
108
+ async resolveAndUpsertMember(openId) {
109
+ try {
110
+ const resp = await this.larkClient.contact.user.get({
111
+ path: { user_id: openId },
112
+ params: { user_id_type: 'open_id' },
113
+ });
114
+ const user = resp?.data?.user;
115
+ if (!user?.name)
116
+ return;
117
+ upsertOrgMember(this.db, {
118
+ member_id: openId,
119
+ name: user.name,
120
+ platform: 'feishu',
121
+ union_id: user.union_id ?? undefined,
122
+ user_id: user.user_id ?? undefined,
123
+ en_name: user.en_name ?? undefined,
124
+ email: user.email ?? undefined,
125
+ employee_no: user.employee_no ?? undefined,
126
+ avatar_url: user.avatar?.avatar_origin ?? user.avatar?.avatar_72 ?? undefined,
127
+ last_synced_at: new Date().toISOString(),
128
+ });
129
+ }
130
+ catch (err) {
131
+ console.warn(`[chat-sync] 解析用户信息失败 (${openId}):`, err);
132
+ }
133
+ }
134
+ }
135
+ //# sourceMappingURL=chat-sync.js.map
@@ -0,0 +1,114 @@
1
+ // ── CommandRouter ──
2
+ export class CommandRouter {
3
+ commands = new Map();
4
+ deps;
5
+ constructor(deps) {
6
+ this.deps = deps;
7
+ }
8
+ register(cmd) {
9
+ this.commands.set(cmd.name, cmd);
10
+ for (const alias of cmd.aliases) {
11
+ this.commands.set(alias, cmd);
12
+ }
13
+ }
14
+ getCommands() {
15
+ const seen = new Set();
16
+ const result = [];
17
+ for (const cmd of this.commands.values()) {
18
+ if (!seen.has(cmd.name)) {
19
+ seen.add(cmd.name);
20
+ result.push(cmd);
21
+ }
22
+ }
23
+ return result;
24
+ }
25
+ /**
26
+ * 尝试处理消息。返回 true 表示已拦截(不需要送 Loid)。
27
+ */
28
+ async tryHandle(message) {
29
+ const parsed = this.parseCommand(message);
30
+ if (!parsed)
31
+ return false;
32
+ const { commandName, args } = parsed;
33
+ const cmd = this.commands.get(commandName);
34
+ if (!cmd)
35
+ return false;
36
+ const logger = this.deps.logger;
37
+ logger?.info(`[CommandRouter] 匹配命令: /${cmd.name} (category: ${cmd.category})`);
38
+ // pass-through:标记 metadata 后继续送 Loid
39
+ if (cmd.category === 'pass-through') {
40
+ if (!message.metadata)
41
+ message.metadata = {};
42
+ message.metadata._command = cmd.name;
43
+ message.metadata._commandArgs = args;
44
+ return false;
45
+ }
46
+ // intercepted / control:执行 handler 并直接回复
47
+ try {
48
+ const ctx = {
49
+ message,
50
+ args,
51
+ db: this.deps.db,
52
+ broker: this.deps.broker,
53
+ router: this,
54
+ onRestart: this.deps.onRestart,
55
+ };
56
+ const result = await cmd.handler(ctx);
57
+ if (result) {
58
+ await this.sendResponse(message, result);
59
+ }
60
+ }
61
+ catch (err) {
62
+ logger?.error(`[CommandRouter] 命令执行失败 (/${cmd.name}):`, err);
63
+ await this.sendResponse(message, {
64
+ text: `命令执行出错: ${err instanceof Error ? err.message : String(err)}`,
65
+ });
66
+ }
67
+ return true;
68
+ }
69
+ /**
70
+ * 解析消息中的命令名和参数。
71
+ * 群聊需要 mentionsAnya,私聊直接匹配。
72
+ */
73
+ parseCommand(message) {
74
+ let text = message.content.trim();
75
+ // 群聊:需要 @Anya
76
+ if (!message.isDirectMessage) {
77
+ if (!message.mentionsAnya)
78
+ return null;
79
+ // 去掉 @mention 前缀(飞书格式通常是 @_user_1 或已被替换为空)
80
+ text = text.replace(/^@\S+\s*/, '').trim();
81
+ }
82
+ // 匹配 /command 格式
83
+ const slashMatch = text.match(/^\/(\S+)(?:\s+(.*))?$/s);
84
+ if (slashMatch) {
85
+ return { commandName: slashMatch[1].toLowerCase(), args: (slashMatch[2] ?? '').trim() };
86
+ }
87
+ // 裸词匹配:仅对已注册命令名/别名生效
88
+ const firstWord = text.split(/\s+/)[0]?.toLowerCase();
89
+ if (firstWord && this.commands.has(firstWord)) {
90
+ const rest = text.slice(firstWord.length).trim();
91
+ return { commandName: firstWord, args: rest };
92
+ }
93
+ return null;
94
+ }
95
+ async sendResponse(message, result) {
96
+ const sender = this.deps.feishuSender;
97
+ const messageId = message.metadata?.message_id;
98
+ try {
99
+ if (messageId) {
100
+ await sender.sendReply({ text: result.text, replyToMessageId: messageId });
101
+ }
102
+ else if (message.chatId) {
103
+ await sender.sendText({ receiveIdType: 'chat_id', receiveId: message.chatId, text: result.text });
104
+ }
105
+ else if (message.sender) {
106
+ await sender.sendText({ receiveIdType: 'open_id', receiveId: message.sender, text: result.text });
107
+ }
108
+ }
109
+ catch (err) {
110
+ this.deps.logger?.error('[CommandRouter] 发送回复失败:', err);
111
+ }
112
+ }
113
+ }
114
+ //# sourceMappingURL=command-router.js.map
@@ -0,0 +1,32 @@
1
+ import { getTask, updateTask, insertAuditEvent } from '@team-anya/db';
2
+ import { TaskStatus, validateTransition } from '@team-anya/core';
3
+ export const cancelCommand = {
4
+ name: 'cancel',
5
+ aliases: ['取消'],
6
+ category: 'control',
7
+ description: '取消任务(/cancel <task_id>)',
8
+ handler: async (ctx) => {
9
+ const taskId = ctx.args.trim();
10
+ if (!taskId) {
11
+ return { text: '请指定任务 ID,例如: /cancel ANYA-20260224-001' };
12
+ }
13
+ const task = getTask(ctx.db, taskId);
14
+ if (!task) {
15
+ return { text: `任务 ${taskId} 不存在` };
16
+ }
17
+ const currentStatus = task.status;
18
+ if (!validateTransition(currentStatus, TaskStatus.CANCELLED)) {
19
+ return { text: `任务 ${taskId} 当前状态为 ${currentStatus},无法取消` };
20
+ }
21
+ updateTask(ctx.db, taskId, { status: TaskStatus.CANCELLED });
22
+ insertAuditEvent(ctx.db, {
23
+ event_type: 'command_invoked',
24
+ actor: ctx.message.senderName ?? ctx.message.sender ?? 'unknown',
25
+ summary: `取消任务 ${taskId}`,
26
+ task_id: taskId,
27
+ detail: JSON.stringify({ command: 'cancel', from: currentStatus, to: TaskStatus.CANCELLED }),
28
+ });
29
+ return { text: `任务 ${taskId} 已取消(${currentStatus} → CANCELLED)` };
30
+ },
31
+ };
32
+ //# sourceMappingURL=cancel.js.map
@@ -0,0 +1,16 @@
1
+ export const helpCommand = {
2
+ name: 'help',
3
+ aliases: ['h', '帮助'],
4
+ category: 'intercepted',
5
+ description: '显示命令列表',
6
+ handler: async (ctx) => {
7
+ const commands = ctx.router.getCommands();
8
+ const lines = ['📋 可用命令:', ''];
9
+ for (const cmd of commands) {
10
+ const aliases = cmd.aliases.length > 0 ? ` (${cmd.aliases.join(', ')})` : '';
11
+ lines.push(`/${cmd.name}${aliases} — ${cmd.description}`);
12
+ }
13
+ return { text: lines.join('\n') };
14
+ },
15
+ };
16
+ //# sourceMappingURL=help.js.map
@@ -0,0 +1,26 @@
1
+ import { helpCommand } from './help.js';
2
+ import { statusCommand } from './status.js';
3
+ import { tasksCommand } from './tasks.js';
4
+ import { cancelCommand } from './cancel.js';
5
+ import { restartCommand } from './restart.js';
6
+ // pass-through 命令(仅标记 metadata,透传给 Loid)
7
+ const passThrough = (name, description) => ({
8
+ name,
9
+ aliases: [],
10
+ category: 'pass-through',
11
+ description,
12
+ handler: async () => null,
13
+ });
14
+ export function registerBuiltinCommands(router) {
15
+ // 直接处理
16
+ router.register(helpCommand);
17
+ router.register(statusCommand);
18
+ router.register(tasksCommand);
19
+ router.register(cancelCommand);
20
+ router.register(restartCommand);
21
+ // 透传 Loid
22
+ router.register(passThrough('task', '显式创建任务(透传 Loid)'));
23
+ router.register(passThrough('report', '生成报告(透传 Loid)'));
24
+ router.register(passThrough('review', '审核交付(透传 Loid)'));
25
+ }
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,34 @@
1
+ export const restartCommand = {
2
+ name: 'restart',
3
+ aliases: ['重启'],
4
+ category: 'control',
5
+ description: '重启所有 Claude Code 实例(安装 skills 后需要重启生效)',
6
+ handler: async (ctx) => {
7
+ if (!ctx.onRestart) {
8
+ return { text: '重启功能未配置' };
9
+ }
10
+ // 列出当前实例
11
+ const instances = ctx.broker.status();
12
+ const activeCount = instances.filter(i => i.state !== 'disposed').length;
13
+ if (activeCount === 0) {
14
+ return { text: '当前没有活跃的 CC 实例,无需重启' };
15
+ }
16
+ // 检查正在执行任务的 Yor 实例
17
+ const executingYor = instances.filter(i => i.role === 'yor' && i.state === 'executing');
18
+ let warning = '';
19
+ if (executingYor.length > 0) {
20
+ const taskIds = executingYor.map(i => i.taskId ?? i.id).join(', ');
21
+ warning = `\n\n⚠️ 注意: ${executingYor.length} 个 Yor 实例正在执行任务 (${taskIds}),已强制终止`;
22
+ }
23
+ const result = await ctx.onRestart();
24
+ const lines = [
25
+ '🔄 CC 实例已全部重启',
26
+ '',
27
+ `已释放实例: ${result.disposed} 个`,
28
+ 'Loid 会话将在下次收到消息时自动重建',
29
+ 'Yor 实例将在下次派工时重新创建',
30
+ ];
31
+ return { text: lines.join('\n') + warning };
32
+ },
33
+ };
34
+ //# sourceMappingURL=restart.js.map
@@ -0,0 +1,34 @@
1
+ import { getTaskCountByStatus } from '@team-anya/db';
2
+ export const statusCommand = {
3
+ name: 'status',
4
+ aliases: ['s', '状态'],
5
+ category: 'intercepted',
6
+ description: '系统状态概览',
7
+ handler: async (ctx) => {
8
+ const counts = getTaskCountByStatus(ctx.db);
9
+ const total = Object.values(counts).reduce((a, b) => a + b, 0);
10
+ const yorInstances = ctx.broker.getInstancesByRole('yor');
11
+ const activeYorCount = yorInstances.length;
12
+ const lines = ['📊 系统状态', ''];
13
+ lines.push(`任务总数: ${total}`);
14
+ if (total > 0) {
15
+ const statusLabels = {
16
+ NEW: '新建',
17
+ NEED_CLARIFICATION: '待澄清',
18
+ READY: '就绪',
19
+ IN_PROGRESS: '执行中',
20
+ DELIVERING: '交付中',
21
+ DONE: '已完成',
22
+ BLOCKED: '已阻塞',
23
+ CANCELLED: '已取消',
24
+ };
25
+ for (const [status, count] of Object.entries(counts)) {
26
+ const label = statusLabels[status] ?? status;
27
+ lines.push(` ${label}: ${count}`);
28
+ }
29
+ }
30
+ lines.push(`\n活跃 Yor 实例: ${activeYorCount}`);
31
+ return { text: lines.join('\n') };
32
+ },
33
+ };
34
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1,33 @@
1
+ import { getAllTasks, getTasksByChatId, getTasksByStatus } from '@team-anya/db';
2
+ const MAX_DISPLAY = 15;
3
+ export const tasksCommand = {
4
+ name: 'tasks',
5
+ aliases: ['t', '任务'],
6
+ category: 'intercepted',
7
+ description: '任务列表(支持状态过滤:/tasks in_progress)',
8
+ handler: async (ctx) => {
9
+ const statusFilter = ctx.args.toUpperCase().trim();
10
+ let taskList;
11
+ if (statusFilter) {
12
+ taskList = getTasksByStatus(ctx.db, statusFilter);
13
+ }
14
+ else if (!ctx.message.isDirectMessage && ctx.message.chatId) {
15
+ taskList = getTasksByChatId(ctx.db, ctx.message.chatId);
16
+ }
17
+ else {
18
+ taskList = getAllTasks(ctx.db);
19
+ }
20
+ if (taskList.length === 0) {
21
+ const hint = statusFilter ? `(状态: ${statusFilter})` : '';
22
+ return { text: `暂无任务${hint}` };
23
+ }
24
+ const displayed = taskList.slice(0, MAX_DISPLAY);
25
+ const lines = [`📝 任务列表(共 ${taskList.length} 条${taskList.length > MAX_DISPLAY ? `,显示前 ${MAX_DISPLAY} 条` : ''}):`, ''];
26
+ for (const task of displayed) {
27
+ const status = task.status.padEnd(18);
28
+ lines.push(`${task.task_id} ${status} ${task.title ?? '(无标题)'}`);
29
+ }
30
+ return { text: lines.join('\n') };
31
+ },
32
+ };
33
+ //# sourceMappingURL=tasks.js.map