feique 1.3.3 → 1.5.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.
- package/README.en.md +3 -2
- package/README.md +3 -2
- package/dist/backend/claude.d.ts +2 -0
- package/dist/backend/claude.js +57 -54
- package/dist/backend/claude.js.map +1 -1
- package/dist/backend/codex.d.ts +2 -0
- package/dist/backend/codex.js +27 -0
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/factory.d.ts +43 -0
- package/dist/backend/factory.js +109 -29
- package/dist/backend/factory.js.map +1 -1
- package/dist/backend/probe.d.ts +27 -0
- package/dist/backend/probe.js +85 -0
- package/dist/backend/probe.js.map +1 -0
- package/dist/backend/qwen.d.ts +59 -0
- package/dist/backend/qwen.js +372 -0
- package/dist/backend/qwen.js.map +1 -0
- package/dist/backend/registry.d.ts +58 -0
- package/dist/backend/registry.js +23 -0
- package/dist/backend/registry.js.map +1 -0
- package/dist/backend/types.d.ts +6 -1
- package/dist/bridge/admin-config.d.ts +47 -0
- package/dist/bridge/admin-config.js +141 -0
- package/dist/bridge/admin-config.js.map +1 -0
- package/dist/bridge/collab-commands.d.ts +42 -0
- package/dist/bridge/collab-commands.js +254 -0
- package/dist/bridge/collab-commands.js.map +1 -0
- package/dist/bridge/commands.d.ts +1 -1
- package/dist/bridge/commands.js +10 -6
- package/dist/bridge/commands.js.map +1 -1
- package/dist/bridge/feishu-commands.d.ts +27 -0
- package/dist/bridge/feishu-commands.js +462 -0
- package/dist/bridge/feishu-commands.js.map +1 -0
- package/dist/bridge/intent-classifier.d.ts +7 -2
- package/dist/bridge/intent-classifier.js +1 -1
- package/dist/bridge/intent-classifier.js.map +1 -1
- package/dist/bridge/lifecycle.d.ts +46 -0
- package/dist/bridge/lifecycle.js +228 -0
- package/dist/bridge/lifecycle.js.map +1 -0
- package/dist/bridge/memory-commands.d.ts +26 -0
- package/dist/bridge/memory-commands.js +330 -0
- package/dist/bridge/memory-commands.js.map +1 -0
- package/dist/bridge/reply-builders.d.ts +30 -0
- package/dist/bridge/reply-builders.js +72 -0
- package/dist/bridge/reply-builders.js.map +1 -0
- package/dist/bridge/run-pipeline.d.ts +86 -0
- package/dist/bridge/run-pipeline.js +453 -0
- package/dist/bridge/run-pipeline.js.map +1 -0
- package/dist/bridge/run-scheduler.d.ts +47 -0
- package/dist/bridge/run-scheduler.js +121 -0
- package/dist/bridge/run-scheduler.js.map +1 -0
- package/dist/bridge/service-utils.d.ts +47 -0
- package/dist/bridge/service-utils.js +309 -0
- package/dist/bridge/service-utils.js.map +1 -0
- package/dist/bridge/service.d.ts +114 -66
- package/dist/bridge/service.js +230 -2199
- package/dist/bridge/service.js.map +1 -1
- package/dist/config/load.js +1 -1
- package/dist/config/load.js.map +1 -1
- package/dist/config/paths.js +1 -20
- package/dist/config/paths.js.map +1 -1
- package/dist/config/schema.d.ts +50 -16
- package/dist/config/schema.js +41 -2
- package/dist/config/schema.js.map +1 -1
- package/dist/feishu/long-connection.js +1 -0
- package/dist/feishu/long-connection.js.map +1 -1
- package/dist/feishu/webhook.js +1 -0
- package/dist/feishu/webhook.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { BridgeConfig, ProjectConfig } from '../config/schema.js';
|
|
2
|
+
import type { IncomingMessageContext } from './types.js';
|
|
3
|
+
import type { ConfigHistoryStore } from '../state/config-history-store.js';
|
|
4
|
+
/**
|
|
5
|
+
* Minimal runtime control surface that the admin-config handler needs.
|
|
6
|
+
* Matches the shape of FeiqueService's internal RuntimeControl interface
|
|
7
|
+
* but is declared here so this module does not depend on service.ts.
|
|
8
|
+
*/
|
|
9
|
+
export interface AdminConfigRuntimeControl {
|
|
10
|
+
configPath?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Subset of FeiqueService that the admin config mutation flows need.
|
|
14
|
+
* Several fields are exposed because the shared helpers
|
|
15
|
+
* (snapshotConfigForAdminMutation, reloadRuntimeConfigFromDisk,
|
|
16
|
+
* appendAdminAudit) stay on FeiqueService — they are called from many
|
|
17
|
+
* admin paths including the WIP /admin project setup flow. Moving them
|
|
18
|
+
* here would create a tangle. Instead, this host interface just routes
|
|
19
|
+
* calls back into the service instance.
|
|
20
|
+
*/
|
|
21
|
+
export interface AdminConfigHost {
|
|
22
|
+
readonly config: BridgeConfig;
|
|
23
|
+
readonly runtimeControl?: AdminConfigRuntimeControl;
|
|
24
|
+
readonly configHistoryStore: ConfigHistoryStore;
|
|
25
|
+
sendTextReply(chatId: string, body: string, replyToMessageId?: string, originalText?: string): Promise<unknown>;
|
|
26
|
+
snapshotConfigForAdminMutation(context: IncomingMessageContext, action: string, summary?: string): Promise<{
|
|
27
|
+
id: string;
|
|
28
|
+
content: string;
|
|
29
|
+
}>;
|
|
30
|
+
reloadRuntimeConfigFromDisk(configPath: string): Promise<void>;
|
|
31
|
+
appendAdminAudit(event: {
|
|
32
|
+
type: string;
|
|
33
|
+
[key: string]: unknown;
|
|
34
|
+
}): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
export declare function handleAdminConfigCommand(host: AdminConfigHost, context: IncomingMessageContext, command: {
|
|
37
|
+
kind: 'admin';
|
|
38
|
+
resource: 'config';
|
|
39
|
+
action: 'history' | 'rollback';
|
|
40
|
+
value?: string;
|
|
41
|
+
}): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Resolve a list field patch with incremental add (+value) / remove (-value) support.
|
|
44
|
+
* Plain values (no prefix) replace the entire list for backward compatibility.
|
|
45
|
+
*/
|
|
46
|
+
export declare function resolveListPatch(config: BridgeConfig, field: string, value: string, projectAlias?: string): string[];
|
|
47
|
+
export declare function parseProjectPatch(config: BridgeConfig, field: string, value: string, projectAlias?: string): Partial<ProjectConfig> | null;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { writeUtf8Atomic } from '../utils/fs.js';
|
|
2
|
+
import { canAccessGlobalCapability } from '../security/access.js';
|
|
3
|
+
import { splitCommaSeparatedValues } from './service-utils.js';
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// /admin config history|rollback
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
export async function handleAdminConfigCommand(host, context, command) {
|
|
8
|
+
const canMutate = canAccessGlobalCapability(host.config, context.chat_id, 'config:mutate');
|
|
9
|
+
const canRead = canAccessGlobalCapability(host.config, context.chat_id, 'config:history') || canMutate;
|
|
10
|
+
if (command.action === 'history' && !canRead) {
|
|
11
|
+
await host.sendTextReply(context.chat_id, '当前 chat_id 无权查看配置历史。', context.message_id, context.text);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (command.action === 'rollback' && !canMutate) {
|
|
15
|
+
await host.sendTextReply(context.chat_id, '当前 chat_id 无权回滚配置。', context.message_id, context.text);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (!host.runtimeControl?.configPath) {
|
|
19
|
+
await host.sendTextReply(context.chat_id, '当前运行实例没有可写配置路径,无法执行配置历史操作。', context.message_id, context.text);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const configPath = host.runtimeControl.configPath;
|
|
23
|
+
if (command.action === 'history') {
|
|
24
|
+
const snapshots = await host.configHistoryStore.listSnapshots();
|
|
25
|
+
if (snapshots.length === 0) {
|
|
26
|
+
await host.sendTextReply(context.chat_id, '当前没有可回滚的配置快照。', context.message_id, context.text);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const lines = ['最近配置快照:'];
|
|
30
|
+
for (const snapshot of snapshots) {
|
|
31
|
+
lines.push(`- ${snapshot.id} | ${snapshot.at} | ${snapshot.action}${snapshot.summary ? ` | ${snapshot.summary}` : ''}`);
|
|
32
|
+
}
|
|
33
|
+
await host.sendTextReply(context.chat_id, lines.join('\n'), context.message_id, context.text);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const target = await host.configHistoryStore.getSnapshot(command.value);
|
|
37
|
+
if (!target) {
|
|
38
|
+
await host.sendTextReply(context.chat_id, '未找到指定配置快照。可先执行 `/admin config history`。', context.message_id, context.text);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const rollbackSnapshot = await host.snapshotConfigForAdminMutation(context, 'config.rollback', `rollback -> ${target.id}`);
|
|
42
|
+
const previousContent = rollbackSnapshot.content;
|
|
43
|
+
try {
|
|
44
|
+
await writeUtf8Atomic(configPath, target.content);
|
|
45
|
+
await host.reloadRuntimeConfigFromDisk(configPath);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
await writeUtf8Atomic(configPath, previousContent);
|
|
49
|
+
await host.reloadRuntimeConfigFromDisk(configPath);
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
await host.appendAdminAudit({
|
|
53
|
+
type: 'admin.config.rollback',
|
|
54
|
+
chat_id: context.chat_id,
|
|
55
|
+
actor_id: context.actor_id,
|
|
56
|
+
target_snapshot_id: target.id,
|
|
57
|
+
snapshot_id: rollbackSnapshot.id,
|
|
58
|
+
config_path: configPath,
|
|
59
|
+
});
|
|
60
|
+
await host.sendTextReply(context.chat_id, `已回滚配置。\n目标快照: ${target.id}\n回滚前快照: ${rollbackSnapshot.id}\n如需生效到某些运行时状态,请再执行 /admin service restart。`, context.message_id, context.text);
|
|
61
|
+
}
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
// /admin project set — field patch parsing
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
/**
|
|
66
|
+
* Resolve a list field patch with incremental add (+value) / remove (-value) support.
|
|
67
|
+
* Plain values (no prefix) replace the entire list for backward compatibility.
|
|
68
|
+
*/
|
|
69
|
+
export function resolveListPatch(config, field, value, projectAlias) {
|
|
70
|
+
const trimmed = value.trim();
|
|
71
|
+
// Incremental add: "+oc_xxx" or "+oc_xxx,oc_yyy"
|
|
72
|
+
if (trimmed.startsWith('+')) {
|
|
73
|
+
const toAdd = splitCommaSeparatedValues(trimmed.slice(1));
|
|
74
|
+
const existing = projectAlias ? (config.projects[projectAlias]?.[field] ?? []) : [];
|
|
75
|
+
return Array.from(new Set([...existing, ...toAdd]));
|
|
76
|
+
}
|
|
77
|
+
// Incremental remove: "-oc_xxx" or "-oc_xxx,oc_yyy"
|
|
78
|
+
if (trimmed.startsWith('-')) {
|
|
79
|
+
const toRemove = new Set(splitCommaSeparatedValues(trimmed.slice(1)));
|
|
80
|
+
const existing = projectAlias ? (config.projects[projectAlias]?.[field] ?? []) : [];
|
|
81
|
+
return existing.filter((id) => !toRemove.has(id));
|
|
82
|
+
}
|
|
83
|
+
// Replace: "oc_xxx,oc_yyy"
|
|
84
|
+
return splitCommaSeparatedValues(value);
|
|
85
|
+
}
|
|
86
|
+
export function parseProjectPatch(config, field, value, projectAlias) {
|
|
87
|
+
switch (field) {
|
|
88
|
+
case 'root':
|
|
89
|
+
return { root: value };
|
|
90
|
+
case 'profile':
|
|
91
|
+
return { profile: value };
|
|
92
|
+
case 'sandbox':
|
|
93
|
+
if (value === 'read-only' || value === 'workspace-write' || value === 'danger-full-access') {
|
|
94
|
+
return { sandbox: value };
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
case 'session_scope':
|
|
98
|
+
if (value === 'chat' || value === 'chat-user') {
|
|
99
|
+
return { session_scope: value };
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
case 'mention_required':
|
|
103
|
+
if (value === 'true' || value === 'false') {
|
|
104
|
+
return { mention_required: value === 'true' };
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
case 'description':
|
|
108
|
+
return { description: value };
|
|
109
|
+
case 'viewer_chat_ids':
|
|
110
|
+
case 'operator_chat_ids':
|
|
111
|
+
case 'admin_chat_ids':
|
|
112
|
+
case 'session_operator_chat_ids':
|
|
113
|
+
case 'run_operator_chat_ids':
|
|
114
|
+
case 'config_admin_chat_ids':
|
|
115
|
+
case 'notification_chat_ids':
|
|
116
|
+
return { [field]: resolveListPatch(config, field, value, projectAlias) };
|
|
117
|
+
case 'download_dir':
|
|
118
|
+
return { download_dir: value };
|
|
119
|
+
case 'temp_dir':
|
|
120
|
+
return { temp_dir: value };
|
|
121
|
+
case 'cache_dir':
|
|
122
|
+
return { cache_dir: value };
|
|
123
|
+
case 'log_dir':
|
|
124
|
+
return { log_dir: value };
|
|
125
|
+
case 'run_priority': {
|
|
126
|
+
const parsed = Number(value);
|
|
127
|
+
return Number.isInteger(parsed) && parsed >= 1 && parsed <= 1000 ? { run_priority: parsed } : null;
|
|
128
|
+
}
|
|
129
|
+
case 'chat_rate_limit_window_seconds': {
|
|
130
|
+
const parsed = Number(value);
|
|
131
|
+
return Number.isInteger(parsed) && parsed > 0 ? { chat_rate_limit_window_seconds: parsed } : null;
|
|
132
|
+
}
|
|
133
|
+
case 'chat_rate_limit_max_runs': {
|
|
134
|
+
const parsed = Number(value);
|
|
135
|
+
return Number.isInteger(parsed) && parsed > 0 ? { chat_rate_limit_max_runs: parsed } : null;
|
|
136
|
+
}
|
|
137
|
+
default:
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=admin-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-config.js","sourceRoot":"","sources":["../../src/bridge/admin-config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAuC/D,8EAA8E;AAC9E,iCAAiC;AACjC,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,IAAqB,EACrB,OAA+B,EAC/B,OAA8F;IAE9F,MAAM,SAAS,GAAG,yBAAyB,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAC3F,MAAM,OAAO,GAAG,yBAAyB,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,gBAAgB,CAAC,IAAI,SAAS,CAAC;IAEvG,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;QAC7C,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,sBAAsB,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACpG,OAAO;IACT,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,SAAS,EAAE,CAAC;QAChD,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,oBAAoB,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAClG,OAAO;IACT,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,EAAE,CAAC;QACrC,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,4BAA4B,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1G,OAAO;IACT,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC;IAElD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,CAAC;QAChE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;YAC7F,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,KAAK,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,EAAE,MAAM,QAAQ,CAAC,EAAE,MAAM,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1H,CAAC;QACD,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC9F,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACxE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,yCAAyC,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACvH,OAAO;IACT,CAAC;IAED,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,8BAA8B,CAAC,OAAO,EAAE,iBAAiB,EAAE,eAAe,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3H,MAAM,eAAe,GAAG,gBAAgB,CAAC,OAAO,CAAC;IACjD,IAAI,CAAC;QACH,MAAM,eAAe,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,IAAI,CAAC,2BAA2B,CAAC,UAAU,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,eAAe,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;QACnD,MAAM,IAAI,CAAC,2BAA2B,CAAC,UAAU,CAAC,CAAC;QACnD,MAAM,KAAK,CAAC;IACd,CAAC;IACD,MAAM,IAAI,CAAC,gBAAgB,CAAC;QAC1B,IAAI,EAAE,uBAAuB;QAC7B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,kBAAkB,EAAE,MAAM,CAAC,EAAE;QAC7B,WAAW,EAAE,gBAAgB,CAAC,EAAE;QAChC,WAAW,EAAE,UAAU;KACxB,CAAC,CAAC;IACH,MAAM,IAAI,CAAC,aAAa,CACtB,OAAO,CAAC,OAAO,EACf,iBAAiB,MAAM,CAAC,EAAE,YAAY,gBAAgB,CAAC,EAAE,6CAA6C,EACtG,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,IAAI,CACb,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,2CAA2C;AAC3C,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAoB,EACpB,KAAa,EACb,KAAa,EACb,YAAqB;IAErB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAE7B,iDAAiD;IACjD,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,yBAAyB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAA4B,CAAa,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvH,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,oDAAoD;IACpD,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,yBAAyB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAA4B,CAAa,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvH,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,2BAA2B;IAC3B,OAAO,yBAAyB,CAAC,KAAK,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,MAAoB,EACpB,KAAa,EACb,KAAa,EACb,YAAqB;IAErB,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,MAAM;YACT,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACzB,KAAK,SAAS;YACZ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC5B,KAAK,SAAS;YACZ,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,iBAAiB,IAAI,KAAK,KAAK,oBAAoB,EAAE,CAAC;gBAC3F,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAC5B,CAAC;YACD,OAAO,IAAI,CAAC;QACd,KAAK,eAAe;YAClB,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;gBAC9C,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;YAClC,CAAC;YACD,OAAO,IAAI,CAAC;QACd,KAAK,kBAAkB;YACrB,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;gBAC1C,OAAO,EAAE,gBAAgB,EAAE,KAAK,KAAK,MAAM,EAAE,CAAC;YAChD,CAAC;YACD,OAAO,IAAI,CAAC;QACd,KAAK,aAAa;YAChB,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QAChC,KAAK,iBAAiB,CAAC;QACvB,KAAK,mBAAmB,CAAC;QACzB,KAAK,gBAAgB,CAAC;QACtB,KAAK,2BAA2B,CAAC;QACjC,KAAK,uBAAuB,CAAC;QAC7B,KAAK,uBAAuB,CAAC;QAC7B,KAAK,uBAAuB;YAC1B,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE,CAAC;QAC3E,KAAK,cAAc;YACjB,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;QACjC,KAAK,UAAU;YACb,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC7B,KAAK,WAAW;YACd,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QAC9B,KAAK,SAAS;YACZ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC5B,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC7B,OAAO,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACrG,CAAC;QACD,KAAK,gCAAgC,CAAC,CAAC,CAAC;YACtC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC7B,OAAO,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,8BAA8B,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACpG,CAAC;QACD,KAAK,0BAA0B,CAAC,CAAC,CAAC;YAChC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC7B,OAAO,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,wBAAwB,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9F,CAAC;QACD;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { BridgeConfig, ProjectConfig } from '../config/schema.js';
|
|
2
|
+
import type { IncomingMessageContext } from './types.js';
|
|
3
|
+
import type { AuditLog } from '../state/audit-log.js';
|
|
4
|
+
import type { SessionStore } from '../state/session-store.js';
|
|
5
|
+
import type { MemoryStore } from '../state/memory-store.js';
|
|
6
|
+
import type { RunStateStore } from '../state/run-state-store.js';
|
|
7
|
+
import type { HandoffStore } from '../state/handoff-store.js';
|
|
8
|
+
import type { TrustStore } from '../state/trust-store.js';
|
|
9
|
+
import type { MetricsRegistry } from '../observability/metrics.js';
|
|
10
|
+
/**
|
|
11
|
+
* Subset of FeiqueService that the collaboration command handlers
|
|
12
|
+
* (/learn, /recall, /handoff, /pickup, /review, /approve, /reject,
|
|
13
|
+
* /insights, /trust, /digest, /gaps, /timeline) need access to.
|
|
14
|
+
*/
|
|
15
|
+
export interface CollabCommandHost {
|
|
16
|
+
readonly config: BridgeConfig;
|
|
17
|
+
readonly auditLog: AuditLog;
|
|
18
|
+
readonly sessionStore: SessionStore;
|
|
19
|
+
readonly memoryStore: MemoryStore;
|
|
20
|
+
readonly runStateStore: RunStateStore;
|
|
21
|
+
readonly handoffStore: HandoffStore;
|
|
22
|
+
readonly trustStore: TrustStore;
|
|
23
|
+
readonly metrics?: MetricsRegistry;
|
|
24
|
+
sendTextReply(chatId: string, body: string, replyToMessageId?: string, originalText?: string): Promise<unknown>;
|
|
25
|
+
}
|
|
26
|
+
export interface CollabProjectContext {
|
|
27
|
+
projectAlias: string;
|
|
28
|
+
project: ProjectConfig;
|
|
29
|
+
sessionKey: string;
|
|
30
|
+
}
|
|
31
|
+
export declare function handleLearnCommand(host: CollabCommandHost, context: IncomingMessageContext, projectContext: CollabProjectContext, value: string): Promise<void>;
|
|
32
|
+
export declare function handleRecallCommand(host: CollabCommandHost, context: IncomingMessageContext, projectContext: CollabProjectContext, query: string): Promise<void>;
|
|
33
|
+
export declare function handleHandoffCommand(host: CollabCommandHost, context: IncomingMessageContext, projectContext: CollabProjectContext, summary?: string): Promise<void>;
|
|
34
|
+
export declare function handlePickupCommand(host: CollabCommandHost, context: IncomingMessageContext, projectContext: CollabProjectContext, id?: string): Promise<void>;
|
|
35
|
+
export declare function handleReviewCommand(host: CollabCommandHost, context: IncomingMessageContext, projectContext: CollabProjectContext): Promise<void>;
|
|
36
|
+
export declare function handleApproveCommand(host: CollabCommandHost, context: IncomingMessageContext, comment?: string): Promise<void>;
|
|
37
|
+
export declare function handleRejectCommand(host: CollabCommandHost, context: IncomingMessageContext, reason?: string): Promise<void>;
|
|
38
|
+
export declare function handleInsightsCommand(host: CollabCommandHost, context: IncomingMessageContext): Promise<void>;
|
|
39
|
+
export declare function handleTrustCommand(host: CollabCommandHost, context: IncomingMessageContext, projectContext: CollabProjectContext, action?: 'set', level?: string): Promise<void>;
|
|
40
|
+
export declare function handleDigestCommand(host: CollabCommandHost, context: IncomingMessageContext): Promise<void>;
|
|
41
|
+
export declare function handleGapsCommand(host: CollabCommandHost, context: IncomingMessageContext): Promise<void>;
|
|
42
|
+
export declare function handleTimelineCommand(host: CollabCommandHost, context: IncomingMessageContext, projectContext: CollabProjectContext, projectArg?: string): Promise<void>;
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { buildLearnInput, formatRecallResults } from '../collaboration/knowledge.js';
|
|
2
|
+
import { createHandoff, acceptHandoff, createReview, resolveReview, formatHandoff, formatReview, formatReviewResult } from '../collaboration/handoff.js';
|
|
3
|
+
import { analyzeTeamHealth, formatInsightsReport } from '../collaboration/insights.js';
|
|
4
|
+
import { formatTrustState } from '../collaboration/trust.js';
|
|
5
|
+
import { buildProjectTimeline, formatTimeline } from '../collaboration/timeline.js';
|
|
6
|
+
import { buildTeamDigest, formatTeamDigest, createDigestPeriod } from '../collaboration/digest.js';
|
|
7
|
+
import { detectKnowledgeGaps, formatKnowledgeGaps } from '../collaboration/knowledge-gaps.js';
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// /learn /recall — knowledge capture and retrieval
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
export async function handleLearnCommand(host, context, projectContext, value) {
|
|
12
|
+
const input = buildLearnInput(value, projectContext.projectAlias, context.actor_id, context.chat_id);
|
|
13
|
+
await host.memoryStore.saveProjectMemory({
|
|
14
|
+
project_alias: input.project_alias,
|
|
15
|
+
title: input.title,
|
|
16
|
+
content: input.content,
|
|
17
|
+
tags: input.tags,
|
|
18
|
+
source: input.source,
|
|
19
|
+
created_by: context.actor_id,
|
|
20
|
+
});
|
|
21
|
+
await host.auditLog.append({
|
|
22
|
+
type: 'collaboration.knowledge.learned',
|
|
23
|
+
project_alias: input.project_alias,
|
|
24
|
+
actor_id: context.actor_id,
|
|
25
|
+
title: input.title,
|
|
26
|
+
});
|
|
27
|
+
await host.sendTextReply(context.chat_id, `💡 团队知识已记录: "${input.title}"\n项目: ${input.project_alias}`, context.message_id, context.text);
|
|
28
|
+
}
|
|
29
|
+
export async function handleRecallCommand(host, context, projectContext, query) {
|
|
30
|
+
const memories = await host.memoryStore.searchMemories({ scope: 'project', project_alias: projectContext.projectAlias }, query, 10);
|
|
31
|
+
const text = formatRecallResults(memories, query);
|
|
32
|
+
await host.sendTextReply(context.chat_id, text, context.message_id, context.text);
|
|
33
|
+
}
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// /handoff /pickup — session handoff
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
export async function handleHandoffCommand(host, context, projectContext, summary) {
|
|
38
|
+
const conversation = await host.sessionStore.getConversation(projectContext.sessionKey);
|
|
39
|
+
const projectState = conversation?.projects[projectContext.projectAlias];
|
|
40
|
+
const record = createHandoff({
|
|
41
|
+
from_actor_id: context.actor_id ?? 'unknown',
|
|
42
|
+
from_actor_name: context.actor_name,
|
|
43
|
+
project_alias: projectContext.projectAlias,
|
|
44
|
+
conversation_key: projectContext.sessionKey,
|
|
45
|
+
thread_id: projectState?.active_thread_id ?? projectState?.thread_id,
|
|
46
|
+
summary: summary ?? '会话交接',
|
|
47
|
+
last_prompt: projectState?.last_prompt,
|
|
48
|
+
last_response_excerpt: projectState?.last_response_excerpt,
|
|
49
|
+
});
|
|
50
|
+
await host.handoffStore.addHandoff(record);
|
|
51
|
+
await host.auditLog.append({
|
|
52
|
+
type: 'collaboration.handoff.created',
|
|
53
|
+
handoff_id: record.id,
|
|
54
|
+
from_actor_id: record.from_actor_id,
|
|
55
|
+
project_alias: record.project_alias,
|
|
56
|
+
});
|
|
57
|
+
await host.sendTextReply(context.chat_id, formatHandoff(record), context.message_id, context.text);
|
|
58
|
+
}
|
|
59
|
+
export async function handlePickupCommand(host, context, projectContext, id) {
|
|
60
|
+
let handoff = id
|
|
61
|
+
? await host.handoffStore.updateHandoff(id, {})
|
|
62
|
+
: await host.handoffStore.getPendingHandoffForActor(context.actor_id ?? '', undefined);
|
|
63
|
+
if (id) {
|
|
64
|
+
handoff = await host.handoffStore.getPendingHandoff();
|
|
65
|
+
if (handoff && !handoff.id.startsWith(id)) {
|
|
66
|
+
handoff = null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (!handoff || handoff.status !== 'pending') {
|
|
70
|
+
await host.sendTextReply(context.chat_id, '没有找到待接手的交接任务。', context.message_id, context.text);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const accepted = acceptHandoff(handoff, context.actor_id ?? 'unknown');
|
|
74
|
+
await host.handoffStore.updateHandoff(handoff.id, {
|
|
75
|
+
status: 'accepted',
|
|
76
|
+
accepted_at: accepted.accepted_at,
|
|
77
|
+
accepted_by: accepted.accepted_by,
|
|
78
|
+
});
|
|
79
|
+
// Adopt the session if there's a thread_id
|
|
80
|
+
if (handoff.thread_id) {
|
|
81
|
+
await host.sessionStore.setActiveProjectSession(projectContext.sessionKey, handoff.project_alias, handoff.thread_id);
|
|
82
|
+
}
|
|
83
|
+
await host.auditLog.append({
|
|
84
|
+
type: 'collaboration.handoff.accepted',
|
|
85
|
+
handoff_id: handoff.id,
|
|
86
|
+
accepted_by: context.actor_id,
|
|
87
|
+
project_alias: handoff.project_alias,
|
|
88
|
+
});
|
|
89
|
+
await host.sendTextReply(context.chat_id, `✅ 已接手 ${handoff.from_actor_name ?? handoff.from_actor_id} 的交接任务 [${handoff.project_alias}]\n摘要: ${handoff.summary}`, context.message_id, context.text);
|
|
90
|
+
}
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// /review /approve /reject — review workflow
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
export async function handleReviewCommand(host, context, projectContext) {
|
|
95
|
+
const runs = await host.runStateStore.listRuns();
|
|
96
|
+
const latestRun = runs.find((r) => r.project_alias === projectContext.projectAlias && (r.status === 'success' || r.status === 'failure'));
|
|
97
|
+
if (!latestRun) {
|
|
98
|
+
await host.sendTextReply(context.chat_id, '没有找到最近的运行结果可供评审。', context.message_id, context.text);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const review = createReview({
|
|
102
|
+
run_id: latestRun.run_id,
|
|
103
|
+
project_alias: projectContext.projectAlias,
|
|
104
|
+
chat_id: context.chat_id,
|
|
105
|
+
actor_id: context.actor_id ?? 'unknown',
|
|
106
|
+
content_excerpt: latestRun.prompt_excerpt,
|
|
107
|
+
});
|
|
108
|
+
await host.handoffStore.addReview(review);
|
|
109
|
+
await host.auditLog.append({
|
|
110
|
+
type: 'collaboration.review.created',
|
|
111
|
+
review_id: review.id,
|
|
112
|
+
run_id: review.run_id,
|
|
113
|
+
project_alias: review.project_alias,
|
|
114
|
+
});
|
|
115
|
+
await host.sendTextReply(context.chat_id, formatReview(review), context.message_id, context.text);
|
|
116
|
+
}
|
|
117
|
+
export async function handleApproveCommand(host, context, comment) {
|
|
118
|
+
const pending = await host.handoffStore.getPendingReview(context.chat_id);
|
|
119
|
+
if (!pending) {
|
|
120
|
+
await host.sendTextReply(context.chat_id, '当前没有待评审的内容。', context.message_id, context.text);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const resolved = resolveReview(pending, 'approved', context.actor_id ?? 'unknown', comment);
|
|
124
|
+
await host.handoffStore.updateReview(pending.id, {
|
|
125
|
+
status: 'approved',
|
|
126
|
+
reviewer_id: resolved.reviewer_id,
|
|
127
|
+
review_comment: resolved.review_comment,
|
|
128
|
+
resolved_at: resolved.resolved_at,
|
|
129
|
+
});
|
|
130
|
+
await host.auditLog.append({
|
|
131
|
+
type: 'collaboration.review.approved',
|
|
132
|
+
review_id: pending.id,
|
|
133
|
+
reviewer_id: context.actor_id,
|
|
134
|
+
});
|
|
135
|
+
await host.sendTextReply(context.chat_id, formatReviewResult(resolved), context.message_id, context.text);
|
|
136
|
+
}
|
|
137
|
+
export async function handleRejectCommand(host, context, reason) {
|
|
138
|
+
const pending = await host.handoffStore.getPendingReview(context.chat_id);
|
|
139
|
+
if (!pending) {
|
|
140
|
+
await host.sendTextReply(context.chat_id, '当前没有待评审的内容。', context.message_id, context.text);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const resolved = resolveReview(pending, 'rejected', context.actor_id ?? 'unknown', reason);
|
|
144
|
+
await host.handoffStore.updateReview(pending.id, {
|
|
145
|
+
status: 'rejected',
|
|
146
|
+
reviewer_id: resolved.reviewer_id,
|
|
147
|
+
review_comment: resolved.review_comment,
|
|
148
|
+
resolved_at: resolved.resolved_at,
|
|
149
|
+
});
|
|
150
|
+
await host.auditLog.append({
|
|
151
|
+
type: 'collaboration.review.rejected',
|
|
152
|
+
review_id: pending.id,
|
|
153
|
+
reviewer_id: context.actor_id,
|
|
154
|
+
reason,
|
|
155
|
+
});
|
|
156
|
+
await host.sendTextReply(context.chat_id, formatReviewResult(resolved), context.message_id, context.text);
|
|
157
|
+
}
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
// /insights — team health
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
export async function handleInsightsCommand(host, context) {
|
|
162
|
+
const runs = await host.runStateStore.listRuns();
|
|
163
|
+
const auditEvents = await host.auditLog.tail(500);
|
|
164
|
+
const insights = analyzeTeamHealth(runs, auditEvents);
|
|
165
|
+
const text = formatInsightsReport(insights);
|
|
166
|
+
await host.sendTextReply(context.chat_id, text, context.message_id, context.text);
|
|
167
|
+
}
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
// /trust — trust level
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
export async function handleTrustCommand(host, context, projectContext, action, level) {
|
|
172
|
+
if (action === 'set' && level) {
|
|
173
|
+
const TRUST_ORDER = ['observe', 'suggest', 'execute', 'autonomous'];
|
|
174
|
+
const validLevels = [...TRUST_ORDER];
|
|
175
|
+
const state = await host.trustStore.getOrCreate(projectContext.projectAlias);
|
|
176
|
+
// Handle relative promote/demote from natural language
|
|
177
|
+
let resolvedLevel = level;
|
|
178
|
+
if (level === '_promote') {
|
|
179
|
+
const idx = TRUST_ORDER.indexOf(state.current_level);
|
|
180
|
+
if (idx >= TRUST_ORDER.length - 1) {
|
|
181
|
+
await host.sendTextReply(context.chat_id, `已经是最高信任等级 (${state.current_level}),无法继续提升。`, context.message_id, context.text);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
resolvedLevel = TRUST_ORDER[idx + 1];
|
|
185
|
+
}
|
|
186
|
+
else if (level === '_demote') {
|
|
187
|
+
const idx = TRUST_ORDER.indexOf(state.current_level);
|
|
188
|
+
if (idx <= 0) {
|
|
189
|
+
await host.sendTextReply(context.chat_id, `已经是最低信任等级 (${state.current_level}),无法继续降低。`, context.message_id, context.text);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
resolvedLevel = TRUST_ORDER[idx - 1];
|
|
193
|
+
}
|
|
194
|
+
if (!validLevels.includes(resolvedLevel)) {
|
|
195
|
+
await host.sendTextReply(context.chat_id, `无效的信任等级。有效值: ${validLevels.join(', ')}`, context.message_id, context.text);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
state.current_level = resolvedLevel;
|
|
199
|
+
state.last_evaluated_at = new Date().toISOString();
|
|
200
|
+
await host.trustStore.update(projectContext.projectAlias, state);
|
|
201
|
+
host.metrics?.recordTrustLevel(projectContext.projectAlias, resolvedLevel);
|
|
202
|
+
await host.auditLog.append({
|
|
203
|
+
type: 'collaboration.trust.set',
|
|
204
|
+
project_alias: projectContext.projectAlias,
|
|
205
|
+
actor_id: context.actor_id,
|
|
206
|
+
level,
|
|
207
|
+
});
|
|
208
|
+
await host.sendTextReply(context.chat_id, `🛡️ 项目 ${projectContext.projectAlias} 的信任等级已设置为: ${level}`, context.message_id, context.text);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
const state = await host.trustStore.getOrCreate(projectContext.projectAlias);
|
|
212
|
+
await host.sendTextReply(context.chat_id, formatTrustState(state), context.message_id, context.text);
|
|
213
|
+
}
|
|
214
|
+
// ---------------------------------------------------------------------------
|
|
215
|
+
// /digest — periodic team digest (manual trigger)
|
|
216
|
+
// ---------------------------------------------------------------------------
|
|
217
|
+
export async function handleDigestCommand(host, context) {
|
|
218
|
+
const period = createDigestPeriod(host.config.service.team_digest_interval_hours);
|
|
219
|
+
const runs = await host.runStateStore.listRuns();
|
|
220
|
+
const memories = host.config.service.memory_enabled
|
|
221
|
+
? await host.memoryStore.listRecentMemories({ scope: 'project', project_alias: '' }, 100)
|
|
222
|
+
: [];
|
|
223
|
+
const auditEvents = await host.auditLog.tail(500);
|
|
224
|
+
const digest = buildTeamDigest(runs, memories, auditEvents, period);
|
|
225
|
+
const text = formatTeamDigest(digest);
|
|
226
|
+
await host.sendTextReply(context.chat_id, text, context.message_id, context.text);
|
|
227
|
+
}
|
|
228
|
+
// ---------------------------------------------------------------------------
|
|
229
|
+
// /gaps — knowledge gaps
|
|
230
|
+
// ---------------------------------------------------------------------------
|
|
231
|
+
export async function handleGapsCommand(host, context) {
|
|
232
|
+
const runs = await host.runStateStore.listRuns();
|
|
233
|
+
const memories = host.config.service.memory_enabled
|
|
234
|
+
? await host.memoryStore.listRecentMemories({ scope: 'project', project_alias: '' }, 200)
|
|
235
|
+
: [];
|
|
236
|
+
const gaps = detectKnowledgeGaps(runs, memories);
|
|
237
|
+
const text = formatKnowledgeGaps(gaps);
|
|
238
|
+
await host.sendTextReply(context.chat_id, text, context.message_id, context.text);
|
|
239
|
+
}
|
|
240
|
+
// ---------------------------------------------------------------------------
|
|
241
|
+
// /timeline — project activity timeline
|
|
242
|
+
// ---------------------------------------------------------------------------
|
|
243
|
+
export async function handleTimelineCommand(host, context, projectContext, projectArg) {
|
|
244
|
+
const projectAlias = projectArg ?? projectContext.projectAlias;
|
|
245
|
+
const runs = await host.runStateStore.listRuns();
|
|
246
|
+
const auditEvents = await host.auditLog.tail(200);
|
|
247
|
+
const memories = host.config.service.memory_enabled
|
|
248
|
+
? await host.memoryStore.listRecentMemories({ scope: 'project', project_alias: projectAlias }, 20)
|
|
249
|
+
: [];
|
|
250
|
+
const timeline = buildProjectTimeline(runs, memories, auditEvents, projectAlias, 20);
|
|
251
|
+
const text = formatTimeline(timeline);
|
|
252
|
+
await host.sendTextReply(context.chat_id, text, context.message_id, context.text);
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=collab-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collab-commands.js","sourceRoot":"","sources":["../../src/bridge/collab-commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@ export interface MemoryCommandFilters {
|
|
|
6
6
|
}
|
|
7
7
|
export type AdminResource = 'viewer' | 'operator' | 'admin' | 'service-observer' | 'service-restart' | 'config-admin' | 'group' | 'chat' | 'project' | 'service' | 'config';
|
|
8
8
|
export type AdminListAction = 'status' | 'list' | 'add' | 'remove';
|
|
9
|
-
export type AdminProjectAction = 'add' | 'create' | 'remove' | 'set' | 'list';
|
|
9
|
+
export type AdminProjectAction = 'add' | 'create' | 'remove' | 'set' | 'list' | 'setup';
|
|
10
10
|
export type AdminConfigAction = 'history' | 'rollback';
|
|
11
11
|
export type BridgeCommand = {
|
|
12
12
|
kind: 'help';
|
package/dist/bridge/commands.js
CHANGED
|
@@ -85,7 +85,7 @@ export function buildHelpText() {
|
|
|
85
85
|
'/projects 查看可用项目',
|
|
86
86
|
'/project <名称> 切换项目',
|
|
87
87
|
'/status 查看当前状态',
|
|
88
|
-
'/backend codex|claude 切换后端',
|
|
88
|
+
'/backend codex|claude|qwen 切换后端',
|
|
89
89
|
'/team 查看团队成员活动',
|
|
90
90
|
'/learn <内容> 记录团队知识',
|
|
91
91
|
'/recall <关键词> 检索知识',
|
|
@@ -115,6 +115,7 @@ export function buildFullHelpText() {
|
|
|
115
115
|
'/backend 查看当前项目的活跃后端',
|
|
116
116
|
'/backend codex 切换当前项目到 Codex 后端',
|
|
117
117
|
'/backend claude 切换当前项目到 Claude Code 后端',
|
|
118
|
+
'/backend qwen 切换当前项目到 Qwen Code 后端',
|
|
118
119
|
'',
|
|
119
120
|
'会话管理',
|
|
120
121
|
'/session list 列出当前项目保存过的会话',
|
|
@@ -498,17 +499,17 @@ function parseNaturalLanguageCommand(input) {
|
|
|
498
499
|
}
|
|
499
500
|
// ── /backend: 后端切换(必须在项目切换之前,否则 "切到 claude" 会被误判为切换项目)──
|
|
500
501
|
// Pattern 1: 带"后端"关键词 — "切换后端到 claude" / "后端换成 codex"
|
|
501
|
-
const backendWithKeyword = normalized.match(/^(?:切换(?:到|为)?|使用|换(?:到|成)?|改(?:到|为|用)?)?\s*(?:后端(?:(?:切换)?(?:到|为)?)?)\s*(codex|claude)\s*(?:后端)?$/i);
|
|
502
|
+
const backendWithKeyword = normalized.match(/^(?:切换(?:到|为)?|使用|换(?:到|成)?|改(?:到|为|用)?)?\s*(?:后端(?:(?:切换)?(?:到|为)?)?)\s*(codex|claude|qwen)\s*(?:后端)?$/i);
|
|
502
503
|
if (backendWithKeyword) {
|
|
503
504
|
return { kind: 'backend', name: backendWithKeyword[1].toLowerCase() };
|
|
504
505
|
}
|
|
505
506
|
// Pattern 2: 不带"后端"— "用 claude" / "换成 codex" / "切到 claude" / "改用 codex"
|
|
506
|
-
const backendDirect = normalized.match(/^(?:用|使用|换(?:成|到)?|切(?:换?(?:到|成)?)?|改(?:用|成|到)?|转(?:到|成)?)\s*(codex|claude)(?:\s*(?:吧|看看|试试|帮我|来))?$/i);
|
|
507
|
+
const backendDirect = normalized.match(/^(?:用|使用|换(?:成|到)?|切(?:换?(?:到|成)?)?|改(?:用|成|到)?|转(?:到|成)?)\s*(codex|claude|qwen)(?:\s*(?:吧|看看|试试|帮我|来))?$/i);
|
|
507
508
|
if (backendDirect) {
|
|
508
509
|
return { kind: 'backend', name: backendDirect[1].toLowerCase() };
|
|
509
510
|
}
|
|
510
511
|
// Pattern 3: "codex/claude + 动词" — "claude 来" / "codex 帮我"
|
|
511
|
-
const backendNameFirst = normalized.match(/^(codex|claude)\s*(?:来(?:吧)?|帮我|试试|处理|干活|上)$/i);
|
|
512
|
+
const backendNameFirst = normalized.match(/^(codex|claude|qwen)\s*(?:来(?:吧)?|帮我|试试|处理|干活|上)$/i);
|
|
512
513
|
if (backendNameFirst) {
|
|
513
514
|
return { kind: 'backend', name: backendNameFirst[1].toLowerCase() };
|
|
514
515
|
}
|
|
@@ -521,12 +522,12 @@ function parseNaturalLanguageCommand(input) {
|
|
|
521
522
|
return { kind: 'backend' };
|
|
522
523
|
}
|
|
523
524
|
// Pattern 6: English — "switch to claude" / "use codex" / "change to claude"
|
|
524
|
-
const backendEnglish = normalized.match(/^(?:switch(?:\s+backend)?(?:\s+to)?|use|change(?:\s+backend)?(?:\s+to)?|backend)\s+(codex|claude)$/i);
|
|
525
|
+
const backendEnglish = normalized.match(/^(?:switch(?:\s+backend)?(?:\s+to)?|use|change(?:\s+backend)?(?:\s+to)?|backend)\s+(codex|claude|qwen)$/i);
|
|
525
526
|
if (backendEnglish) {
|
|
526
527
|
return { kind: 'backend', name: backendEnglish[1].toLowerCase() };
|
|
527
528
|
}
|
|
528
529
|
// Pattern 7: English name-first — "claude please" / "codex go"
|
|
529
|
-
const backendEnglishNameFirst = normalized.match(/^(codex|claude)\s+(?:please|go|now|backend)$/i);
|
|
530
|
+
const backendEnglishNameFirst = normalized.match(/^(codex|claude|qwen)\s+(?:please|go|now|backend)$/i);
|
|
530
531
|
if (backendEnglishNameFirst) {
|
|
531
532
|
return { kind: 'backend', name: backendEnglishNameFirst[1].toLowerCase() };
|
|
532
533
|
}
|
|
@@ -688,6 +689,9 @@ function parseAdminCommand(argument) {
|
|
|
688
689
|
value: rest.slice(2).join(' ').trim() || undefined,
|
|
689
690
|
};
|
|
690
691
|
}
|
|
692
|
+
if (action === 'setup') {
|
|
693
|
+
return { kind: 'admin', resource: 'project', action: 'setup', alias: rest[0], value: rest.slice(1).join(' ').trim() || undefined };
|
|
694
|
+
}
|
|
691
695
|
return { kind: 'prompt', prompt: `/admin${argument ? ` ${argument}` : ''}`.trim() };
|
|
692
696
|
}
|
|
693
697
|
if (resource === 'viewer' ||
|