team-anya 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.
Potentially problematic release.
This version of team-anya might be problematic. Click here for more details.
- package/README.md +38 -0
- package/anya/prompts/execution-guides/git-delivery.md +38 -0
- package/anya/prompts/execution-guides/testing-and-self-heal.md +28 -0
- package/anya/prompts/protocols/brief-assembly.md +55 -0
- package/anya/prompts/protocols/report.md +175 -0
- package/anya/prompts/protocols/review.md +90 -0
- package/anya/prompts/task-claude-md.template.md +32 -0
- package/apps/server/dist/broker/cc-broker.js +257 -0
- package/apps/server/dist/cli.js +296 -0
- package/apps/server/dist/config.js +76 -0
- package/apps/server/dist/daemon.js +51 -0
- package/apps/server/dist/gateway/chat-sync.js +135 -0
- package/apps/server/dist/gateway/command-router.js +114 -0
- package/apps/server/dist/gateway/commands/cancel.js +32 -0
- package/apps/server/dist/gateway/commands/help.js +16 -0
- package/apps/server/dist/gateway/commands/index.js +26 -0
- package/apps/server/dist/gateway/commands/restart.js +34 -0
- package/apps/server/dist/gateway/commands/status.js +34 -0
- package/apps/server/dist/gateway/commands/tasks.js +33 -0
- package/apps/server/dist/gateway/feishu-sender.js +346 -0
- package/apps/server/dist/gateway/feishu-ws.js +254 -0
- package/apps/server/dist/gateway/http.js +994 -0
- package/apps/server/dist/gateway/media-downloader.js +149 -0
- package/apps/server/dist/gateway/message-events.js +10 -0
- package/apps/server/dist/gateway/message-intake.js +50 -0
- package/apps/server/dist/gateway/message-queue.js +104 -0
- package/apps/server/dist/gateway/session-reader.js +142 -0
- package/apps/server/dist/gateway/ws-push.js +115 -0
- package/apps/server/dist/loid/brain.js +104 -0
- package/apps/server/dist/loid/brief-assembler.js +156 -0
- package/apps/server/dist/loid/clarifier.js +162 -0
- package/apps/server/dist/loid/commitment-tracker.js +236 -0
- package/apps/server/dist/loid/context-builder.js +413 -0
- package/apps/server/dist/loid/dispatcher.js +544 -0
- package/apps/server/dist/loid/intent-classifier.js +158 -0
- package/apps/server/dist/loid/mcp-server.js +104 -0
- package/apps/server/dist/loid/memory-settler.js +189 -0
- package/apps/server/dist/loid/opportunity-manager.js +148 -0
- package/apps/server/dist/loid/process-manager.js +186 -0
- package/apps/server/dist/loid/profile-updater.js +179 -0
- package/apps/server/dist/loid/reporter.js +148 -0
- package/apps/server/dist/loid/schemas.js +117 -0
- package/apps/server/dist/loid/self-calibrator.js +314 -0
- package/apps/server/dist/loid/session-manager.js +217 -0
- package/apps/server/dist/loid/session.js +271 -0
- package/apps/server/dist/loid/worktree-manager.js +191 -0
- package/apps/server/dist/main.js +337 -0
- package/apps/server/dist/tracing/index.js +2 -0
- package/apps/server/dist/tracing/trace-context.js +92 -0
- package/apps/server/dist/types/message.js +2 -0
- package/apps/server/dist/yor/yor-mcp-server.js +104 -0
- package/apps/server/dist/yor/yor-orchestrator.js +233 -0
- package/apps/web/dist/assets/index-CHIT0Dya.css +1 -0
- package/apps/web/dist/assets/index-CJzAjoVH.js +798 -0
- package/apps/web/dist/index.html +13 -0
- package/package.json +42 -0
- package/packages/cc-client/dist/claude-code-backend.js +664 -0
- package/packages/cc-client/dist/index.js +2 -0
- package/packages/cc-client/package.json +11 -0
- package/packages/core/dist/constants.js +59 -0
- package/packages/core/dist/errors.js +35 -0
- package/packages/core/dist/index.js +7 -0
- package/packages/core/dist/office-init.js +97 -0
- package/packages/core/dist/scope/checker.js +114 -0
- package/packages/core/dist/scope/defaults.js +40 -0
- package/packages/core/dist/scope/index.js +3 -0
- package/packages/core/dist/state-machine.js +85 -0
- package/packages/core/dist/types/audit.js +12 -0
- package/packages/core/dist/types/backend.js +2 -0
- package/packages/core/dist/types/commitment.js +17 -0
- package/packages/core/dist/types/communication.js +18 -0
- package/packages/core/dist/types/index.js +8 -0
- package/packages/core/dist/types/opportunity.js +27 -0
- package/packages/core/dist/types/org.js +26 -0
- package/packages/core/dist/types/task.js +46 -0
- package/packages/core/package.json +10 -0
- package/packages/db/dist/client.js +69 -0
- package/packages/db/dist/index.js +603 -0
- package/packages/db/dist/schema/audit-events.js +13 -0
- package/packages/db/dist/schema/cc-sessions.js +14 -0
- package/packages/db/dist/schema/chats.js +33 -0
- package/packages/db/dist/schema/commitments.js +18 -0
- package/packages/db/dist/schema/communication-events.js +14 -0
- package/packages/db/dist/schema/index.js +12 -0
- package/packages/db/dist/schema/message-log.js +20 -0
- package/packages/db/dist/schema/opportunities.js +23 -0
- package/packages/db/dist/schema/org.js +36 -0
- package/packages/db/dist/schema/projects.js +23 -0
- package/packages/db/dist/schema/tasks.js +46 -0
- package/packages/db/dist/schema/trace-spans.js +19 -0
- package/packages/db/package.json +12 -0
- package/packages/db/src/migrations/0000_simple_magneto.sql +148 -0
- package/packages/db/src/migrations/0001_nifty_morph.sql +42 -0
- package/packages/db/src/migrations/0002_common_joshua_kane.sql +20 -0
- package/packages/db/src/migrations/0003_add_cc_sessions.sql +13 -0
- package/packages/db/src/migrations/0004_jittery_triathlon.sql +1 -0
- package/packages/db/src/migrations/meta/0000_snapshot.json +987 -0
- package/packages/db/src/migrations/meta/0001_snapshot.json +1280 -0
- package/packages/db/src/migrations/meta/0002_snapshot.json +1417 -0
- package/packages/db/src/migrations/meta/0004_snapshot.json +1505 -0
- package/packages/db/src/migrations/meta/_journal.json +41 -0
- package/packages/mcp-tools/dist/index.js +41 -0
- package/packages/mcp-tools/dist/layer1/audit-append.js +38 -0
- package/packages/mcp-tools/dist/layer1/audit-query.js +51 -0
- package/packages/mcp-tools/dist/layer1/memory-brief.js +168 -0
- package/packages/mcp-tools/dist/layer1/memory-context.js +124 -0
- package/packages/mcp-tools/dist/layer1/memory-digest.js +126 -0
- package/packages/mcp-tools/dist/layer1/memory-forget.js +108 -0
- package/packages/mcp-tools/dist/layer1/memory-learn.js +63 -0
- package/packages/mcp-tools/dist/layer1/memory-recall.js +287 -0
- package/packages/mcp-tools/dist/layer1/memory-reflect.js +80 -0
- package/packages/mcp-tools/dist/layer1/memory-remember.js +119 -0
- package/packages/mcp-tools/dist/layer1/memory-search.js +263 -0
- package/packages/mcp-tools/dist/layer1/memory-write.js +21 -0
- package/packages/mcp-tools/dist/layer1/org-lookup.js +47 -0
- package/packages/mcp-tools/dist/layer1/project-get.js +28 -0
- package/packages/mcp-tools/dist/layer1/project-list.js +20 -0
- package/packages/mcp-tools/dist/layer1/report-daily.js +68 -0
- package/packages/mcp-tools/dist/layer1/task-get.js +29 -0
- package/packages/mcp-tools/dist/layer1/task-update.js +34 -0
- package/packages/mcp-tools/dist/layer2/loid/decision-log.js +15 -0
- package/packages/mcp-tools/dist/layer2/loid/decision-no-action.js +15 -0
- package/packages/mcp-tools/dist/layer2/loid/delivery-create-pr.js +30 -0
- package/packages/mcp-tools/dist/layer2/loid/delivery-share.js +12 -0
- package/packages/mcp-tools/dist/layer2/loid/delivery-submit.js +77 -0
- package/packages/mcp-tools/dist/layer2/loid/delivery-upload.js +18 -0
- package/packages/mcp-tools/dist/layer2/loid/project-remove.js +16 -0
- package/packages/mcp-tools/dist/layer2/loid/project-upsert.js +33 -0
- package/packages/mcp-tools/dist/layer2/loid/task-dispatch.js +177 -0
- package/packages/mcp-tools/dist/layer2/loid/task-lookup.js +38 -0
- package/packages/mcp-tools/dist/layer2/loid/task-review.js +151 -0
- package/packages/mcp-tools/dist/layer2/loid/workspace-cleanup.js +7 -0
- package/packages/mcp-tools/dist/layer2/loid/workspace-info.js +31 -0
- package/packages/mcp-tools/dist/layer2/loid/workspace-prepare.js +12 -0
- package/packages/mcp-tools/dist/layer2/loid/yor-approve.js +8 -0
- package/packages/mcp-tools/dist/layer2/loid/yor-kill.js +7 -0
- package/packages/mcp-tools/dist/layer2/loid/yor-rework.js +7 -0
- package/packages/mcp-tools/dist/layer2/loid/yor-spawn.js +15 -0
- package/packages/mcp-tools/dist/layer2/loid/yor-status.js +8 -0
- package/packages/mcp-tools/dist/layer2/yor/code-lint.js +47 -0
- package/packages/mcp-tools/dist/layer2/yor/code-test.js +52 -0
- package/packages/mcp-tools/dist/layer2/yor/git-add.js +24 -0
- package/packages/mcp-tools/dist/layer2/yor/git-commit.js +24 -0
- package/packages/mcp-tools/dist/layer2/yor/git-push.js +64 -0
- package/packages/mcp-tools/dist/layer2/yor/task-block.js +11 -0
- package/packages/mcp-tools/dist/layer2/yor/task-deliver.js +35 -0
- package/packages/mcp-tools/dist/layer2/yor/task-progress.js +21 -0
- package/packages/mcp-tools/dist/layer3/adapters/feishu-adapter.js +191 -0
- package/packages/mcp-tools/dist/layer3/adapters/types.js +28 -0
- package/packages/mcp-tools/dist/layer3/channel-receive.js +11 -0
- package/packages/mcp-tools/dist/layer3/channel-send.js +90 -0
- package/packages/mcp-tools/dist/layer3/file-upload.js +44 -0
- package/packages/mcp-tools/dist/registry.js +779 -0
- package/packages/mcp-tools/package.json +13 -0
- package/workspace/.claude/settings.local.json +9 -0
- package/workspace/.mcp.json +12 -0
- package/workspace/CHARTER.md +73 -0
- package/workspace/CLAUDE.md +49 -0
- package/workspace/PROTOCOL.md +126 -0
- package/workspace/TOOLS.md +464 -0
- package/workspace/audit/.gitkeep +0 -0
- package/workspace/loid/CLAUDE.md +12 -0
- package/workspace/loid/PLAYBOOK.md +198 -0
- package/workspace/loid/PROFILE.md +78 -0
- package/workspace/memory/commitments/.gitkeep +0 -0
- package/workspace/memory/execution/.gitkeep +0 -0
- package/workspace/memory/people/.gitkeep +0 -0
- package/workspace/memory/projects/.gitkeep +0 -0
- package/workspace/memory/self/.gitkeep +0 -0
- package/workspace/reference/identity/.gitkeep +0 -0
- package/workspace/reference/org/escalation.yaml +24 -0
- package/workspace/reference/org/ownership.yaml +28 -0
- package/workspace/reports/.gitkeep +0 -0
- package/workspace/yor/CLAUDE.md +22 -0
- package/workspace/yor/PLAYBOOK.md +73 -0
- package/workspace/yor/PROFILE.md +52 -0
- package/workspace/yor/SELF-HEAL.md +39 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// ── ProfileUpdater ──
|
|
2
|
+
/**
|
|
3
|
+
* 协作者画像自动更新
|
|
4
|
+
*
|
|
5
|
+
* 从任务交互中提取协作者特征,增量更新 memory/org/people/{person}.md
|
|
6
|
+
*
|
|
7
|
+
* 提取维度:
|
|
8
|
+
* - 响应速度:从 clarification_response 中统计平均响应时间
|
|
9
|
+
* - 沟通风格:从交互标签中聚合
|
|
10
|
+
* - 技术偏好:从 review_feedback 标签中提取
|
|
11
|
+
* - Review 反馈模式:统计 review 次数和情感倾向
|
|
12
|
+
*/
|
|
13
|
+
export class ProfileUpdater {
|
|
14
|
+
deps;
|
|
15
|
+
constructor(deps) {
|
|
16
|
+
this.deps = deps;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 更新单人画像
|
|
20
|
+
*/
|
|
21
|
+
async updateProfile(personId, interactions) {
|
|
22
|
+
const profile = { personId };
|
|
23
|
+
if (interactions.length === 0) {
|
|
24
|
+
return profile;
|
|
25
|
+
}
|
|
26
|
+
// 读取已有画像
|
|
27
|
+
const existingContent = await this.deps.readFile(`memory/people/${personId}.md`);
|
|
28
|
+
const existingProfile = existingContent ? this.parseExistingProfile(existingContent) : null;
|
|
29
|
+
// 提取响应速度
|
|
30
|
+
const responseTimes = interactions
|
|
31
|
+
.filter(i => i.type === 'clarification_response' && i.responseTimeMinutes !== undefined)
|
|
32
|
+
.map(i => i.responseTimeMinutes);
|
|
33
|
+
if (responseTimes.length > 0) {
|
|
34
|
+
const newAvg = responseTimes.reduce((a, b) => a + b, 0) / responseTimes.length;
|
|
35
|
+
const newCount = responseTimes.length;
|
|
36
|
+
if (existingProfile?.responseSpeed) {
|
|
37
|
+
// 合并历史数据
|
|
38
|
+
const oldTotal = existingProfile.responseSpeed.avgMinutes * existingProfile.responseSpeed.sampleCount;
|
|
39
|
+
const newTotal = newAvg * newCount;
|
|
40
|
+
const totalCount = existingProfile.responseSpeed.sampleCount + newCount;
|
|
41
|
+
profile.responseSpeed = {
|
|
42
|
+
avgMinutes: (oldTotal + newTotal) / totalCount,
|
|
43
|
+
sampleCount: totalCount,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
profile.responseSpeed = {
|
|
48
|
+
avgMinutes: newAvg,
|
|
49
|
+
sampleCount: newCount,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// 提取沟通风格
|
|
54
|
+
const styleTags = interactions
|
|
55
|
+
.filter(i => i.tags && i.tags.length > 0)
|
|
56
|
+
.flatMap(i => i.tags);
|
|
57
|
+
if (styleTags.length > 0) {
|
|
58
|
+
profile.communicationStyle = [...new Set(styleTags)];
|
|
59
|
+
}
|
|
60
|
+
// 提取技术偏好
|
|
61
|
+
const techInteractions = interactions.filter(i => i.type === 'review_feedback');
|
|
62
|
+
const techPrefs = [];
|
|
63
|
+
for (const interaction of techInteractions) {
|
|
64
|
+
if (interaction.detail) {
|
|
65
|
+
techPrefs.push(interaction.detail);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (techPrefs.length > 0) {
|
|
69
|
+
profile.technicalPreferences = techPrefs;
|
|
70
|
+
}
|
|
71
|
+
// Review 反馈模式
|
|
72
|
+
const reviews = interactions.filter(i => i.type === 'review_feedback');
|
|
73
|
+
if (reviews.length > 0) {
|
|
74
|
+
const sentiments = {};
|
|
75
|
+
for (const r of reviews) {
|
|
76
|
+
const s = r.sentiment ?? 'neutral';
|
|
77
|
+
sentiments[s] = (sentiments[s] ?? 0) + 1;
|
|
78
|
+
}
|
|
79
|
+
profile.reviewPatterns = {
|
|
80
|
+
totalReviews: reviews.length,
|
|
81
|
+
sentiments,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// 构建历史记录
|
|
85
|
+
profile.history = interactions.map(i => {
|
|
86
|
+
const date = i.timestamp.slice(0, 10);
|
|
87
|
+
return `- ${date}: [${i.taskId}] ${i.type}${i.detail ? ` - ${i.detail}` : ''}`;
|
|
88
|
+
});
|
|
89
|
+
// 渲染并写入
|
|
90
|
+
const rendered = this.renderProfile(profile, existingContent);
|
|
91
|
+
try {
|
|
92
|
+
await this.deps.memoryRemember({
|
|
93
|
+
category: 'people',
|
|
94
|
+
target: personId,
|
|
95
|
+
content: rendered,
|
|
96
|
+
importance: 0.5,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// 写入失败不影响返回
|
|
101
|
+
}
|
|
102
|
+
return profile;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* 批量更新多人画像
|
|
106
|
+
*/
|
|
107
|
+
async updateProfiles(interactions) {
|
|
108
|
+
// 按 personId 分组
|
|
109
|
+
const grouped = new Map();
|
|
110
|
+
for (const interaction of interactions) {
|
|
111
|
+
const existing = grouped.get(interaction.personId) ?? [];
|
|
112
|
+
existing.push(interaction);
|
|
113
|
+
grouped.set(interaction.personId, existing);
|
|
114
|
+
}
|
|
115
|
+
const results = {};
|
|
116
|
+
for (const [personId, personInteractions] of grouped) {
|
|
117
|
+
results[personId] = await this.updateProfile(personId, personInteractions);
|
|
118
|
+
}
|
|
119
|
+
return results;
|
|
120
|
+
}
|
|
121
|
+
// ── 内部方法 ──
|
|
122
|
+
parseExistingProfile(content) {
|
|
123
|
+
const profile = {};
|
|
124
|
+
// 解析响应速度
|
|
125
|
+
const avgMatch = /平均响应:\s*(\d+(?:\.\d+)?)\s*分钟/.exec(content);
|
|
126
|
+
const countMatch = /样本数:\s*(\d+)/.exec(content);
|
|
127
|
+
if (avgMatch && countMatch) {
|
|
128
|
+
profile.responseSpeed = {
|
|
129
|
+
avgMinutes: parseFloat(avgMatch[1]),
|
|
130
|
+
sampleCount: parseInt(countMatch[1], 10),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return profile;
|
|
134
|
+
}
|
|
135
|
+
renderProfile(profile, existingContent) {
|
|
136
|
+
const sections = [];
|
|
137
|
+
sections.push(`# ${profile.personId}`);
|
|
138
|
+
// 保留已有的基本信息 section
|
|
139
|
+
if (existingContent) {
|
|
140
|
+
const basicInfoMatch = /## 基本信息\n([\s\S]*?)(?=\n##\s|$)/.exec(existingContent);
|
|
141
|
+
if (basicInfoMatch) {
|
|
142
|
+
sections.push(`\n## 基本信息\n${basicInfoMatch[1].trimEnd()}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// 响应速度
|
|
146
|
+
if (profile.responseSpeed) {
|
|
147
|
+
sections.push(`\n## 响应速度\n- 平均响应: ${Math.round(profile.responseSpeed.avgMinutes * 10) / 10} 分钟\n- 样本数: ${profile.responseSpeed.sampleCount}`);
|
|
148
|
+
}
|
|
149
|
+
// 沟通风格
|
|
150
|
+
if (profile.communicationStyle && profile.communicationStyle.length > 0) {
|
|
151
|
+
sections.push(`\n## 沟通风格\n${profile.communicationStyle.map(s => `- ${s}`).join('\n')}`);
|
|
152
|
+
}
|
|
153
|
+
// 技术偏好
|
|
154
|
+
if (profile.technicalPreferences && profile.technicalPreferences.length > 0) {
|
|
155
|
+
sections.push(`\n## 技术偏好\n${profile.technicalPreferences.map(p => `- ${p}`).join('\n')}`);
|
|
156
|
+
}
|
|
157
|
+
// Review 模式
|
|
158
|
+
if (profile.reviewPatterns) {
|
|
159
|
+
const sentimentStr = Object.entries(profile.reviewPatterns.sentiments)
|
|
160
|
+
.map(([k, v]) => `${k}: ${v}`)
|
|
161
|
+
.join(', ');
|
|
162
|
+
sections.push(`\n## Review 模式\n- 总 Review 数: ${profile.reviewPatterns.totalReviews}\n- 情感分布: ${sentimentStr}`);
|
|
163
|
+
}
|
|
164
|
+
// 历史记录
|
|
165
|
+
if (profile.history && profile.history.length > 0) {
|
|
166
|
+
// 保留已有历史
|
|
167
|
+
let existingHistory = '';
|
|
168
|
+
if (existingContent) {
|
|
169
|
+
const historyMatch = /## 历史记录\n([\s\S]*?)(?=\n##\s|$)/.exec(existingContent);
|
|
170
|
+
if (historyMatch) {
|
|
171
|
+
existingHistory = historyMatch[1].trimEnd() + '\n';
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
sections.push(`\n## 历史记录\n${existingHistory}${profile.history.join('\n')}`);
|
|
175
|
+
}
|
|
176
|
+
return sections.join('\n') + '\n';
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=profile-updater.js.map
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
// ── 进行中状态集合 ──
|
|
3
|
+
const IN_PROGRESS_STATUSES = new Set(['IN_PROGRESS', 'TESTING', 'FIXING']);
|
|
4
|
+
const PR_STATUSES = new Set(['PR_OPEN', 'WAITING_REVIEW']);
|
|
5
|
+
// ── Reporter ──
|
|
6
|
+
export class Reporter {
|
|
7
|
+
deps;
|
|
8
|
+
config;
|
|
9
|
+
constructor(deps, config) {
|
|
10
|
+
this.deps = deps;
|
|
11
|
+
this.config = config;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 生成日报 Markdown 内容
|
|
15
|
+
*/
|
|
16
|
+
async generateDailyReport(date) {
|
|
17
|
+
const allTasks = this.deps.getAllTasks();
|
|
18
|
+
const commitments = this.deps.getActiveCommitments();
|
|
19
|
+
const opportunities = this.deps.getOpenOpportunities();
|
|
20
|
+
const auditEvents = this.deps.getAuditEventsByDate(date);
|
|
21
|
+
const lines = [];
|
|
22
|
+
const done = allTasks.filter((t) => t.status === 'DONE' && t.updated_at?.startsWith(date));
|
|
23
|
+
const prOpen = allTasks.filter((t) => PR_STATUSES.has(t.status));
|
|
24
|
+
const inProgress = allTasks.filter((t) => IN_PROGRESS_STATUSES.has(t.status));
|
|
25
|
+
const blocked = allTasks.filter((t) => t.status === 'BLOCKED');
|
|
26
|
+
// 开头一句话总结
|
|
27
|
+
const totalActive = inProgress.length + prOpen.length;
|
|
28
|
+
if (done.length > 0 && blocked.length === 0) {
|
|
29
|
+
lines.push(`今天完成了 ${done.length} 个任务${totalActive > 0 ? `,还有 ${totalActive} 个在跑` : ''}。\n`);
|
|
30
|
+
}
|
|
31
|
+
else if (done.length > 0 && blocked.length > 0) {
|
|
32
|
+
lines.push(`今天完成了 ${done.length} 个任务,但有 ${blocked.length} 个卡住了。\n`);
|
|
33
|
+
}
|
|
34
|
+
else if (blocked.length > 0) {
|
|
35
|
+
lines.push(`有 ${blocked.length} 个任务卡住了,需要关注。\n`);
|
|
36
|
+
}
|
|
37
|
+
else if (totalActive > 0) {
|
|
38
|
+
lines.push(`${totalActive} 个任务进行中。\n`);
|
|
39
|
+
}
|
|
40
|
+
// 完成的
|
|
41
|
+
if (done.length > 0) {
|
|
42
|
+
lines.push('**已完成**');
|
|
43
|
+
for (const t of done) {
|
|
44
|
+
const pr = t.pr_url ? ` → ${t.pr_url}` : '';
|
|
45
|
+
lines.push(`- ${t.title} (${t.task_id})${pr}`);
|
|
46
|
+
}
|
|
47
|
+
lines.push('');
|
|
48
|
+
}
|
|
49
|
+
// 等 Review 的
|
|
50
|
+
if (prOpen.length > 0) {
|
|
51
|
+
lines.push('**等 Review**');
|
|
52
|
+
for (const t of prOpen) {
|
|
53
|
+
const pr = t.pr_url ? ` → ${t.pr_url}` : '';
|
|
54
|
+
lines.push(`- ${t.title} (${t.task_id})${pr}`);
|
|
55
|
+
}
|
|
56
|
+
lines.push('');
|
|
57
|
+
}
|
|
58
|
+
// 进行中的
|
|
59
|
+
if (inProgress.length > 0) {
|
|
60
|
+
lines.push('**进行中**');
|
|
61
|
+
for (const t of inProgress) {
|
|
62
|
+
lines.push(`- ${t.title} (${t.task_id})`);
|
|
63
|
+
}
|
|
64
|
+
lines.push('');
|
|
65
|
+
}
|
|
66
|
+
// 卡住的(重点标出)
|
|
67
|
+
if (blocked.length > 0) {
|
|
68
|
+
lines.push('**卡住了**');
|
|
69
|
+
for (const t of blocked) {
|
|
70
|
+
lines.push(`- ${t.title} (${t.task_id}) — ${t.blocked_reason ?? '原因待查'}`);
|
|
71
|
+
}
|
|
72
|
+
lines.push('');
|
|
73
|
+
}
|
|
74
|
+
// 承诺追踪
|
|
75
|
+
if (commitments.length > 0) {
|
|
76
|
+
lines.push('**还欠着的**');
|
|
77
|
+
for (const c of commitments) {
|
|
78
|
+
const deadline = c.deadline ? `,截止 ${c.deadline}` : '';
|
|
79
|
+
lines.push(`- ${c.promise} (答应 ${c.promised_to} 的${deadline})`);
|
|
80
|
+
}
|
|
81
|
+
lines.push('');
|
|
82
|
+
}
|
|
83
|
+
// 机会
|
|
84
|
+
if (opportunities.length > 0) {
|
|
85
|
+
lines.push('**发现了几个可以做的事**');
|
|
86
|
+
for (const o of opportunities) {
|
|
87
|
+
lines.push(`- ${o.summary}`);
|
|
88
|
+
}
|
|
89
|
+
lines.push('');
|
|
90
|
+
}
|
|
91
|
+
return lines.join('\n');
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* 将日报写入文件
|
|
95
|
+
*/
|
|
96
|
+
async saveDailyReport(date, content) {
|
|
97
|
+
const reportsDir = join(this.config.workspacePath, 'reports');
|
|
98
|
+
await this.deps.mkdirp(reportsDir);
|
|
99
|
+
const filePath = join(reportsDir, `daily-${date}.md`);
|
|
100
|
+
await this.deps.writeFile(filePath, content);
|
|
101
|
+
return filePath;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 端到端:生成 + 写文件 + 飞书推送
|
|
105
|
+
*/
|
|
106
|
+
async publishDailyReport(date) {
|
|
107
|
+
const content = await this.generateDailyReport(date);
|
|
108
|
+
// 写文件(总是执行)
|
|
109
|
+
await this.saveDailyReport(date, content);
|
|
110
|
+
// 飞书推送(可选,失败不影响文件写入)
|
|
111
|
+
if (this.config.feishuDailyReportChatId) {
|
|
112
|
+
try {
|
|
113
|
+
await this.deps.sendDailyReport({
|
|
114
|
+
chatId: this.config.feishuDailyReportChatId,
|
|
115
|
+
reportContent: content,
|
|
116
|
+
date,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// 飞书发送失败不影响日报文件保存
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* 实时告警:任务 BLOCKED
|
|
126
|
+
*/
|
|
127
|
+
async notifyBlocked(params) {
|
|
128
|
+
await this.deps.sendBlockedAlert({
|
|
129
|
+
targetUserIds: params.targetUserIds,
|
|
130
|
+
taskId: params.taskId,
|
|
131
|
+
reason: params.reason,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* 任务完成通知
|
|
136
|
+
*/
|
|
137
|
+
async notifyTaskDone(params) {
|
|
138
|
+
if (!params.chatId)
|
|
139
|
+
return;
|
|
140
|
+
await this.deps.sendTaskDone({
|
|
141
|
+
chatId: params.chatId,
|
|
142
|
+
taskId: params.taskId,
|
|
143
|
+
prUrl: params.prUrl,
|
|
144
|
+
summary: params.summary,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=reporter.js.map
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
// ── Loid 行动工具 Input Schemas ──
|
|
3
|
+
export const DispatchTaskInputSchema = z.object({
|
|
4
|
+
title: z.string().describe('任务标题'),
|
|
5
|
+
brief: z.string().describe('执行 brief(Markdown 格式,只写做什么和标准,不写怎么做)'),
|
|
6
|
+
project_id: z.string().optional().describe('目标项目/仓库 ID'),
|
|
7
|
+
objective: z.string().describe('任务目标(一句话概括要达成什么)'),
|
|
8
|
+
acceptance_criteria: z.array(z.string()).describe('验收标准列表(至少一条可验证的完成条件)'),
|
|
9
|
+
context: z.string().optional().describe('背景信息(业务上下文、技术约束等)'),
|
|
10
|
+
conversation_id: z.string().optional().describe('关联的对话 ID(用于后续回复)'),
|
|
11
|
+
source_message_id: z.string().optional().describe('触发消息 ID'),
|
|
12
|
+
created_by: z.string().optional().describe('任务创建者(从当前事件的 sender_name 或 sender_id 提取)'),
|
|
13
|
+
source_chat_id: z.string().optional().describe('触发任务的聊天 ID(从当前对话的 chat_id 提取)'),
|
|
14
|
+
});
|
|
15
|
+
export const AskHumanInputSchema = z.object({
|
|
16
|
+
message: z.string().describe('要发送给人类的消息内容'),
|
|
17
|
+
chat_id: z.string().optional().describe('目标群聊 ID'),
|
|
18
|
+
reply_to_message_id: z.string().optional().describe('回复的消息 ID'),
|
|
19
|
+
task_id: z.string().optional().describe('关联任务 ID'),
|
|
20
|
+
intent: z.enum(['clarification', 'report', 'notification']).describe('消息意图'),
|
|
21
|
+
});
|
|
22
|
+
export const ApproveDeliveryInputSchema = z.object({
|
|
23
|
+
task_id: z.string().describe('要验收的任务 ID'),
|
|
24
|
+
summary: z.string().optional().describe('验收通过的简评'),
|
|
25
|
+
notify_human: z.boolean().default(true).describe('是否通知人类'),
|
|
26
|
+
});
|
|
27
|
+
export const RejectDeliveryInputSchema = z.object({
|
|
28
|
+
task_id: z.string().describe('要打回的任务 ID'),
|
|
29
|
+
reason: z.string().describe('打回原因'),
|
|
30
|
+
feedback: z.string().describe('给执行者的修改意见'),
|
|
31
|
+
});
|
|
32
|
+
export const LookupTaskInputSchema = z.object({
|
|
33
|
+
task_id: z.string().optional().describe('指定任务 ID'),
|
|
34
|
+
status: z.string().optional().describe('按状态过滤'),
|
|
35
|
+
});
|
|
36
|
+
export const LogDecisionInputSchema = z.object({
|
|
37
|
+
decision: z.string().describe('决策内容'),
|
|
38
|
+
reasoning: z.string().describe('决策理由'),
|
|
39
|
+
task_id: z.string().optional().describe('关联任务 ID'),
|
|
40
|
+
});
|
|
41
|
+
export const NoActionInputSchema = z.object({
|
|
42
|
+
reason: z.string().describe('不处理的原因'),
|
|
43
|
+
});
|
|
44
|
+
// ── Output Schemas(工具执行后返回给 Loid 的结果)──
|
|
45
|
+
export const DispatchTaskOutputSchema = z.object({
|
|
46
|
+
task_id: z.string(),
|
|
47
|
+
status: z.literal('dispatched'),
|
|
48
|
+
});
|
|
49
|
+
export const AskHumanOutputSchema = z.object({
|
|
50
|
+
sent: z.boolean(),
|
|
51
|
+
message_id: z.string().optional(),
|
|
52
|
+
});
|
|
53
|
+
export const ApproveDeliveryOutputSchema = z.object({
|
|
54
|
+
approved: z.boolean(),
|
|
55
|
+
task_id: z.string(),
|
|
56
|
+
});
|
|
57
|
+
export const RejectDeliveryOutputSchema = z.object({
|
|
58
|
+
rejected: z.boolean(),
|
|
59
|
+
task_id: z.string(),
|
|
60
|
+
retry_count: z.number(),
|
|
61
|
+
max_retries: z.number(),
|
|
62
|
+
});
|
|
63
|
+
export const LookupTaskOutputSchema = z.object({
|
|
64
|
+
tasks: z.array(z.object({
|
|
65
|
+
task_id: z.string(),
|
|
66
|
+
title: z.string(),
|
|
67
|
+
status: z.string(),
|
|
68
|
+
assignee: z.string().nullable(),
|
|
69
|
+
created_at: z.string().nullable(),
|
|
70
|
+
pr_url: z.string().nullable().optional(),
|
|
71
|
+
})),
|
|
72
|
+
});
|
|
73
|
+
export const LogDecisionOutputSchema = z.object({
|
|
74
|
+
logged: z.boolean(),
|
|
75
|
+
});
|
|
76
|
+
export const NoActionOutputSchema = z.object({
|
|
77
|
+
acknowledged: z.boolean(),
|
|
78
|
+
});
|
|
79
|
+
// ── Tool 注册表 ──
|
|
80
|
+
export const LOID_TOOL_REGISTRY = {
|
|
81
|
+
dispatch_task: {
|
|
82
|
+
description: '派工给执行者(Yor)。创建任务、写入 brief、启动执行。',
|
|
83
|
+
inputSchema: DispatchTaskInputSchema,
|
|
84
|
+
outputSchema: DispatchTaskOutputSchema,
|
|
85
|
+
},
|
|
86
|
+
ask_human: {
|
|
87
|
+
description: '向人类发送消息(提问、汇报结果、通知)。',
|
|
88
|
+
inputSchema: AskHumanInputSchema,
|
|
89
|
+
outputSchema: AskHumanOutputSchema,
|
|
90
|
+
},
|
|
91
|
+
approve_delivery: {
|
|
92
|
+
description: '验收通过执行者的交付成果。标记任务完成,可选通知人类。',
|
|
93
|
+
inputSchema: ApproveDeliveryInputSchema,
|
|
94
|
+
outputSchema: ApproveDeliveryOutputSchema,
|
|
95
|
+
},
|
|
96
|
+
reject_delivery: {
|
|
97
|
+
description: '打回执行者的交付,附带修改意见并重新派工。最多返工 3 次。',
|
|
98
|
+
inputSchema: RejectDeliveryInputSchema,
|
|
99
|
+
outputSchema: RejectDeliveryOutputSchema,
|
|
100
|
+
},
|
|
101
|
+
lookup_task: {
|
|
102
|
+
description: '查询任务状态和历史。可按 task_id 或 status 过滤。',
|
|
103
|
+
inputSchema: LookupTaskInputSchema,
|
|
104
|
+
outputSchema: LookupTaskOutputSchema,
|
|
105
|
+
},
|
|
106
|
+
log_decision: {
|
|
107
|
+
description: '记录决策理由到审计日志。',
|
|
108
|
+
inputSchema: LogDecisionInputSchema,
|
|
109
|
+
outputSchema: LogDecisionOutputSchema,
|
|
110
|
+
},
|
|
111
|
+
no_action: {
|
|
112
|
+
description: '明确表示不处理此消息。记录原因到日志。',
|
|
113
|
+
inputSchema: NoActionInputSchema,
|
|
114
|
+
outputSchema: NoActionOutputSchema,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=schemas.js.map
|