@keyou007/agent-bot 0.1.8 → 0.1.10
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/CHANGELOG.md +13 -0
- package/README.md +9 -1
- package/README.zh.md +9 -1
- package/dist/cli/FeishuAppConfiguration.js +87 -25
- package/dist/cli/FeishuAppConfiguration.js.map +1 -1
- package/dist/cli/FeishuAppRegistration.js +12 -9
- package/dist/cli/FeishuAppRegistration.js.map +1 -1
- package/dist/cli/Initializer.js +7 -6
- package/dist/cli/Initializer.js.map +1 -1
- package/dist/cli/LocalControlClient.js +3 -2
- package/dist/cli/LocalControlClient.js.map +1 -1
- package/dist/cli/LocalControlServer.js +2 -1
- package/dist/cli/LocalControlServer.js.map +1 -1
- package/dist/cli/OptionalAuthorizationSkip.js +27 -6
- package/dist/cli/OptionalAuthorizationSkip.js.map +1 -1
- package/dist/cli/ServerStarter.js +12 -3
- package/dist/cli/ServerStarter.js.map +1 -1
- package/dist/cli/SkillRegistry.js +5 -4
- package/dist/cli/SkillRegistry.js.map +1 -1
- package/dist/cli/VerificationOutput.js +2 -1
- package/dist/cli/VerificationOutput.js.map +1 -1
- package/dist/cli/help.js +48 -1
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/i18n.js +27 -0
- package/dist/cli/i18n.js.map +1 -0
- package/dist/cli/initOptions.js +5 -4
- package/dist/cli/initOptions.js.map +1 -1
- package/dist/cli/packageVersion.js +2 -1
- package/dist/cli/packageVersion.js.map +1 -1
- package/dist/cli/profile.js +4 -3
- package/dist/cli/profile.js.map +1 -1
- package/dist/cli/serverStatus.js +15 -14
- package/dist/cli/serverStatus.js.map +1 -1
- package/dist/cli/taskChatRoute.js +3 -2
- package/dist/cli/taskChatRoute.js.map +1 -1
- package/dist/cli.js +165 -107
- package/dist/cli.js.map +1 -1
- package/dist/commands/CommandRouter.js +49 -3
- package/dist/commands/CommandRouter.js.map +1 -1
- package/dist/proxy/ProxySessionController.js +81 -11
- package/dist/proxy/ProxySessionController.js.map +1 -1
- package/docs/technical-reference.md +16 -3
- package/docs/technical-reference.zh.md +16 -3
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/skills/agent-bot/SKILL.md +7 -7
- package/src/cli/FeishuAppConfiguration.ts +133 -21
- package/src/cli/FeishuAppRegistration.ts +24 -9
- package/src/cli/Initializer.ts +25 -6
- package/src/cli/LocalControlClient.ts +9 -2
- package/src/cli/LocalControlServer.ts +2 -1
- package/src/cli/OptionalAuthorizationSkip.ts +51 -6
- package/src/cli/ServerStarter.ts +20 -3
- package/src/cli/SkillRegistry.ts +17 -4
- package/src/cli/VerificationOutput.ts +4 -1
- package/src/cli/help.ts +50 -1
- package/src/cli/i18n.ts +38 -0
- package/src/cli/initOptions.ts +17 -4
- package/src/cli/packageVersion.ts +5 -1
- package/src/cli/profile.ts +13 -3
- package/src/cli/serverStatus.ts +19 -14
- package/src/cli/taskChatRoute.ts +9 -2
- package/src/cli.ts +290 -103
- package/src/commands/CommandRouter.ts +58 -3
- package/src/proxy/ProxySessionController.ts +147 -21
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
import type { Command } from "./commandTypes.js";
|
|
2
2
|
|
|
3
|
+
const COMMAND_NAMES = [
|
|
4
|
+
"agent",
|
|
5
|
+
"agents",
|
|
6
|
+
"ask",
|
|
7
|
+
"fork",
|
|
8
|
+
"forkgroup",
|
|
9
|
+
"goal",
|
|
10
|
+
"help",
|
|
11
|
+
"mode",
|
|
12
|
+
"model",
|
|
13
|
+
"modes",
|
|
14
|
+
"new",
|
|
15
|
+
"newgroup",
|
|
16
|
+
"nosteer",
|
|
17
|
+
"permissions",
|
|
18
|
+
"queue",
|
|
19
|
+
"restart",
|
|
20
|
+
"sessions",
|
|
21
|
+
"status",
|
|
22
|
+
"stop",
|
|
23
|
+
"switch",
|
|
24
|
+
"thinking",
|
|
25
|
+
"title",
|
|
26
|
+
"use",
|
|
27
|
+
] as const;
|
|
28
|
+
|
|
29
|
+
type CommandName = (typeof COMMAND_NAMES)[number];
|
|
30
|
+
|
|
31
|
+
const COMMAND_INITIALISMS: Partial<Record<CommandName, string>> = {
|
|
32
|
+
forkgroup: "fg",
|
|
33
|
+
newgroup: "ng",
|
|
34
|
+
nosteer: "ns",
|
|
35
|
+
};
|
|
36
|
+
|
|
3
37
|
export class CommandRouter {
|
|
4
38
|
parse(text: string): Command {
|
|
5
39
|
const trimmed = text.trim();
|
|
@@ -13,7 +47,7 @@ export class CommandRouter {
|
|
|
13
47
|
}
|
|
14
48
|
|
|
15
49
|
const [rawCommand, ...args] = splitArgs(trimmed);
|
|
16
|
-
const command = rawCommand
|
|
50
|
+
const command = resolveCommandName(rawCommand);
|
|
17
51
|
|
|
18
52
|
switch (command) {
|
|
19
53
|
case "agents":
|
|
@@ -86,12 +120,33 @@ export class CommandRouter {
|
|
|
86
120
|
}
|
|
87
121
|
case "help":
|
|
88
122
|
return { type: "help" };
|
|
89
|
-
default:
|
|
90
|
-
throw new Error(`未知命令:${rawCommand}。发送 /help 查看可用命令。`);
|
|
91
123
|
}
|
|
92
124
|
}
|
|
93
125
|
}
|
|
94
126
|
|
|
127
|
+
function resolveCommandName(rawCommand: string): CommandName {
|
|
128
|
+
const input = rawCommand.slice(1).toLowerCase();
|
|
129
|
+
if (!input) throw unknownCommand(rawCommand);
|
|
130
|
+
|
|
131
|
+
const exact = COMMAND_NAMES.find((command) => command === input);
|
|
132
|
+
if (exact) return exact;
|
|
133
|
+
|
|
134
|
+
const matches = COMMAND_NAMES.filter(
|
|
135
|
+
(command) => command.startsWith(input) || COMMAND_INITIALISMS[command] === input,
|
|
136
|
+
);
|
|
137
|
+
if (matches.length === 1) return matches[0]!;
|
|
138
|
+
if (matches.length > 1) {
|
|
139
|
+
throw new Error(
|
|
140
|
+
`命令前缀 ${rawCommand} 不唯一,可匹配:${matches.map((command) => `/${command}`).join("、")}。请输入更长的命令前缀。`,
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
throw unknownCommand(rawCommand);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function unknownCommand(rawCommand: string): Error {
|
|
147
|
+
return new Error(`未知命令:${rawCommand}。发送 /help 查看可用命令。`);
|
|
148
|
+
}
|
|
149
|
+
|
|
95
150
|
function requireArg<T>(value: string | undefined, name: string, create: (value: string) => T): T {
|
|
96
151
|
if (!value) {
|
|
97
152
|
throw new Error(`Missing ${name}.`);
|
|
@@ -82,6 +82,14 @@ interface SessionExecutionSettings {
|
|
|
82
82
|
permissionMode?: PermissionMode;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
interface ProjectSessionReference {
|
|
86
|
+
source?: SessionRecord;
|
|
87
|
+
agentName: string;
|
|
88
|
+
remoteSessionId: string;
|
|
89
|
+
cwd: string;
|
|
90
|
+
executionSettings: SessionExecutionSettings;
|
|
91
|
+
}
|
|
92
|
+
|
|
85
93
|
interface ForkSessionPlan {
|
|
86
94
|
source?: SessionRecord;
|
|
87
95
|
sourceLabel: string;
|
|
@@ -349,10 +357,18 @@ export class ProxySessionController {
|
|
|
349
357
|
const sessionId = String(scopedAction.value.sessionId ?? "");
|
|
350
358
|
await this.forkSessionReference(contextKey, sessionId);
|
|
351
359
|
await this.refreshSessionsCardFromAction(scopedAction);
|
|
360
|
+
} else if (kind === "session_fork_group") {
|
|
361
|
+
const sessionId = String(scopedAction.value.sessionId ?? "");
|
|
362
|
+
await this.forkSessionReferenceToFeishuGroup(contextKey, sessionId, scopedAction.userId);
|
|
363
|
+
await this.refreshSessionsCardFromAction(scopedAction);
|
|
352
364
|
} else if (kind === "session_new") {
|
|
353
365
|
const sessionId = String(scopedAction.value.sessionId ?? "");
|
|
354
366
|
await this.createProjectSessionFromReference(contextKey, sessionId);
|
|
355
367
|
await this.refreshSessionsCardFromAction(scopedAction);
|
|
368
|
+
} else if (kind === "session_new_group") {
|
|
369
|
+
const sessionId = String(scopedAction.value.sessionId ?? "");
|
|
370
|
+
await this.createFeishuGroupFromReference(contextKey, sessionId, scopedAction.userId);
|
|
371
|
+
await this.refreshSessionsCardFromAction(scopedAction);
|
|
356
372
|
} else if (kind === "session_stop") {
|
|
357
373
|
const sessionId = String(scopedAction.value.sessionId ?? "");
|
|
358
374
|
await this.stopSessionReference(contextKey, sessionId);
|
|
@@ -1301,6 +1317,32 @@ export class ProxySessionController {
|
|
|
1301
1317
|
}
|
|
1302
1318
|
|
|
1303
1319
|
private async createProjectSessionFromReference(contextKey: string, reference: string): Promise<void> {
|
|
1320
|
+
const resolved = await this.resolveProjectSessionReference(contextKey, reference);
|
|
1321
|
+
const created = await this.createSession(
|
|
1322
|
+
contextKey,
|
|
1323
|
+
resolved.agentName,
|
|
1324
|
+
resolved.cwd,
|
|
1325
|
+
true,
|
|
1326
|
+
false,
|
|
1327
|
+
undefined,
|
|
1328
|
+
undefined,
|
|
1329
|
+
undefined,
|
|
1330
|
+
resolved.executionSettings,
|
|
1331
|
+
);
|
|
1332
|
+
this.store.audit(contextKey, "project_session_created", {
|
|
1333
|
+
sourceLocalSessionId: resolved.source?.localSessionId,
|
|
1334
|
+
sourceRemoteSessionId: resolved.remoteSessionId,
|
|
1335
|
+
createdLocalSessionId: created.localSessionId,
|
|
1336
|
+
createdRemoteSessionId: created.remoteSessionId,
|
|
1337
|
+
cwd: resolved.cwd,
|
|
1338
|
+
...resolved.executionSettings,
|
|
1339
|
+
});
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
private async resolveProjectSessionReference(
|
|
1343
|
+
contextKey: string,
|
|
1344
|
+
reference: string,
|
|
1345
|
+
): Promise<ProjectSessionReference> {
|
|
1304
1346
|
const taskId = this.resolveSessionReference(contextKey, reference);
|
|
1305
1347
|
const direct = this.store.getSession(taskId);
|
|
1306
1348
|
if (direct?.status === "closed") {
|
|
@@ -1346,25 +1388,13 @@ export class ProxySessionController {
|
|
|
1346
1388
|
reasoningEffort: remote?.reasoningEffort ?? source?.reasoningEffort,
|
|
1347
1389
|
permissionMode: remote?.permissionMode ?? source?.permissionMode ?? "auto",
|
|
1348
1390
|
};
|
|
1349
|
-
|
|
1350
|
-
|
|
1391
|
+
return {
|
|
1392
|
+
source,
|
|
1351
1393
|
agentName,
|
|
1394
|
+
remoteSessionId,
|
|
1352
1395
|
cwd,
|
|
1353
|
-
true,
|
|
1354
|
-
false,
|
|
1355
|
-
undefined,
|
|
1356
|
-
undefined,
|
|
1357
|
-
undefined,
|
|
1358
1396
|
executionSettings,
|
|
1359
|
-
|
|
1360
|
-
this.store.audit(contextKey, "project_session_created", {
|
|
1361
|
-
sourceLocalSessionId: source?.localSessionId,
|
|
1362
|
-
sourceRemoteSessionId: remoteSessionId,
|
|
1363
|
-
createdLocalSessionId: created.localSessionId,
|
|
1364
|
-
createdRemoteSessionId: created.remoteSessionId,
|
|
1365
|
-
cwd,
|
|
1366
|
-
...executionSettings,
|
|
1367
|
-
});
|
|
1397
|
+
};
|
|
1368
1398
|
}
|
|
1369
1399
|
|
|
1370
1400
|
private async startTurn(
|
|
@@ -1473,8 +1503,6 @@ export class ProxySessionController {
|
|
|
1473
1503
|
): Promise<void> {
|
|
1474
1504
|
const source = this.currentSession(sourceContextKey);
|
|
1475
1505
|
const boundProjectCwd = this.currentProjectCwd(sourceContextKey);
|
|
1476
|
-
const explicitTitle = normalizeTaskTitle(requestedTitle);
|
|
1477
|
-
const taskTitle = explicitTitle ?? "新任务";
|
|
1478
1506
|
const executionSettings: SessionExecutionSettings = source?.agentName === agentName
|
|
1479
1507
|
? {
|
|
1480
1508
|
model: source.model,
|
|
@@ -1482,6 +1510,43 @@ export class ProxySessionController {
|
|
|
1482
1510
|
permissionMode: source.permissionMode,
|
|
1483
1511
|
}
|
|
1484
1512
|
: {};
|
|
1513
|
+
await this.createFeishuGroupWithTask(
|
|
1514
|
+
sourceContextKey,
|
|
1515
|
+
agentName,
|
|
1516
|
+
requestedTitle,
|
|
1517
|
+
userId,
|
|
1518
|
+
boundProjectCwd,
|
|
1519
|
+
executionSettings,
|
|
1520
|
+
);
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
private async createFeishuGroupFromReference(
|
|
1524
|
+
sourceContextKey: string,
|
|
1525
|
+
reference: string,
|
|
1526
|
+
userId: string | undefined,
|
|
1527
|
+
): Promise<void> {
|
|
1528
|
+
const resolved = await this.resolveProjectSessionReference(sourceContextKey, reference);
|
|
1529
|
+
const boundProjectCwd = detectProjectlessWorkspace(resolved.cwd) ? undefined : resolved.cwd;
|
|
1530
|
+
await this.createFeishuGroupWithTask(
|
|
1531
|
+
sourceContextKey,
|
|
1532
|
+
resolved.agentName,
|
|
1533
|
+
undefined,
|
|
1534
|
+
userId,
|
|
1535
|
+
boundProjectCwd,
|
|
1536
|
+
resolved.executionSettings,
|
|
1537
|
+
);
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
private async createFeishuGroupWithTask(
|
|
1541
|
+
sourceContextKey: string,
|
|
1542
|
+
agentName: string,
|
|
1543
|
+
requestedTitle: string | undefined,
|
|
1544
|
+
userId: string | undefined,
|
|
1545
|
+
boundProjectCwd: string | undefined,
|
|
1546
|
+
executionSettings: SessionExecutionSettings,
|
|
1547
|
+
): Promise<void> {
|
|
1548
|
+
const explicitTitle = normalizeTaskTitle(requestedTitle);
|
|
1549
|
+
const taskTitle = explicitTitle ?? "新任务";
|
|
1485
1550
|
const group = await this.createFeishuGroupContext(
|
|
1486
1551
|
sourceContextKey,
|
|
1487
1552
|
agentName,
|
|
@@ -1542,6 +1607,42 @@ export class ProxySessionController {
|
|
|
1542
1607
|
throw new Error("/forkgroup 只能由具有 open_id 的飞书用户消息触发。");
|
|
1543
1608
|
}
|
|
1544
1609
|
const prepared = await this.prepareForkGroupSession(sourceContextKey, requestedTitle, incomingMessage);
|
|
1610
|
+
await this.forkPreparedSessionToFeishuGroup(
|
|
1611
|
+
sourceContextKey,
|
|
1612
|
+
prepared,
|
|
1613
|
+
userId,
|
|
1614
|
+
incomingMessage?.threadContext ? prepared.sourceDescription : "当前任务",
|
|
1615
|
+
);
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
private async forkSessionReferenceToFeishuGroup(
|
|
1619
|
+
sourceContextKey: string,
|
|
1620
|
+
reference: string,
|
|
1621
|
+
userId: string | undefined,
|
|
1622
|
+
): Promise<void> {
|
|
1623
|
+
if (!userId?.startsWith("ou_")) {
|
|
1624
|
+
throw new Error("ForkGroup 只能由具有 open_id 的飞书用户触发。");
|
|
1625
|
+
}
|
|
1626
|
+
const plan = await this.prepareForkSession(sourceContextKey, reference);
|
|
1627
|
+
await this.forkPreparedSessionToFeishuGroup(
|
|
1628
|
+
sourceContextKey,
|
|
1629
|
+
{
|
|
1630
|
+
plan,
|
|
1631
|
+
sourceDescription: plan.forkedFromHistoricalTurn
|
|
1632
|
+
? "指定任务最近已完成轮次"
|
|
1633
|
+
: "指定任务最新轮次",
|
|
1634
|
+
},
|
|
1635
|
+
userId,
|
|
1636
|
+
"指定任务",
|
|
1637
|
+
);
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
private async forkPreparedSessionToFeishuGroup(
|
|
1641
|
+
sourceContextKey: string,
|
|
1642
|
+
prepared: ForkGroupSessionPlan,
|
|
1643
|
+
userId: string,
|
|
1644
|
+
sourceSummary: string,
|
|
1645
|
+
): Promise<void> {
|
|
1545
1646
|
const { plan } = prepared;
|
|
1546
1647
|
const boundProjectCwd = detectProjectlessWorkspace(plan.cwd) ? undefined : plan.cwd;
|
|
1547
1648
|
const group = await this.createFeishuGroupContext(
|
|
@@ -1574,13 +1675,14 @@ export class ProxySessionController {
|
|
|
1574
1675
|
`已从${prepared.sourceDescription}创建分支。`,
|
|
1575
1676
|
`当前任务:${taskDescription}`,
|
|
1576
1677
|
`当前 Project 目录:${boundProjectCwd ?? "未绑定(Projectless)"}`,
|
|
1678
|
+
`当前模型:${forked.session.model ?? "默认"}`,
|
|
1679
|
+
`思考强度:${forked.session.reasoningEffort ?? "自动"}`,
|
|
1680
|
+
`权限类型:${forked.session.permissionMode === "confirm" ? "执行前确认" : "自动执行"}`,
|
|
1577
1681
|
].join("\n"),
|
|
1578
1682
|
);
|
|
1579
1683
|
await this.outbound.sendText(
|
|
1580
1684
|
sourceContextKey,
|
|
1581
|
-
`已将${
|
|
1582
|
-
incomingMessage?.threadContext ? prepared.sourceDescription : "当前任务"
|
|
1583
|
-
} Fork 到飞书群:${group.name};新群当前任务为 ${taskDescription}。`,
|
|
1685
|
+
`已将${sourceSummary} Fork 到飞书群:${group.name};新群当前任务为 ${taskDescription}。`,
|
|
1584
1686
|
);
|
|
1585
1687
|
}
|
|
1586
1688
|
|
|
@@ -2277,6 +2379,16 @@ export class ProxySessionController {
|
|
|
2277
2379
|
contextKey,
|
|
2278
2380
|
},
|
|
2279
2381
|
});
|
|
2382
|
+
actions.push({
|
|
2383
|
+
text: "NewGroup",
|
|
2384
|
+
value: {
|
|
2385
|
+
action: "session_new_group",
|
|
2386
|
+
sessionId: entry.id,
|
|
2387
|
+
...(searchTerm ? { searchTerm } : {}),
|
|
2388
|
+
visibleCount: String(visibleCount),
|
|
2389
|
+
contextKey,
|
|
2390
|
+
},
|
|
2391
|
+
});
|
|
2280
2392
|
actions.push({
|
|
2281
2393
|
text: "Fork",
|
|
2282
2394
|
value: {
|
|
@@ -2287,6 +2399,16 @@ export class ProxySessionController {
|
|
|
2287
2399
|
contextKey,
|
|
2288
2400
|
},
|
|
2289
2401
|
});
|
|
2402
|
+
actions.push({
|
|
2403
|
+
text: "ForkGroup",
|
|
2404
|
+
value: {
|
|
2405
|
+
action: "session_fork_group",
|
|
2406
|
+
sessionId: entry.id,
|
|
2407
|
+
...(searchTerm ? { searchTerm } : {}),
|
|
2408
|
+
visibleCount: String(visibleCount),
|
|
2409
|
+
contextKey,
|
|
2410
|
+
},
|
|
2411
|
+
});
|
|
2290
2412
|
actions.push({
|
|
2291
2413
|
text: "Status",
|
|
2292
2414
|
value: {
|
|
@@ -2310,6 +2432,7 @@ export class ProxySessionController {
|
|
|
2310
2432
|
[
|
|
2311
2433
|
...(remoteHint ? [remoteHint] : []),
|
|
2312
2434
|
"点击 **New** 在对应任务的项目中创建新任务;点击 **Switch** 快速切换;点击 **Fork** 从任务最新已完成轮次创建分支;外部正在运行的任务显示 **Stop**,点击后发送 Interrupt 并变为 **Switch**。",
|
|
2435
|
+
"点击 **NewGroup** 在对应任务的项目中创建新群和新任务;点击 **ForkGroup** 从对应任务最新已完成轮次创建分支群。",
|
|
2313
2436
|
"也可发送 **/switch [序号或任务 ID]**;不带参数切回上一个任务。外部正在执行的回合不会被接管。",
|
|
2314
2437
|
"发送 **/fork [序号或任务 ID]**,可从当前或指定任务创建分支;任务运行中时使用最近已完成轮次。",
|
|
2315
2438
|
"点击 **Status**,或发送 **/status [序号或任务 ID]**,查看当前或指定任务状态。",
|
|
@@ -2707,6 +2830,9 @@ export class ProxySessionController {
|
|
|
2707
2830
|
{
|
|
2708
2831
|
lines: [
|
|
2709
2832
|
"直接发送消息即可继续当前任务;执行中发送的新消息会追加到本次任务。",
|
|
2833
|
+
"> 命令前缀示例:/sess 等同于 /sessions。",
|
|
2834
|
+
"> 命令缩写示例:/fg 等同于 /forkgroup。",
|
|
2835
|
+
"前缀或缩写匹配多个命令时,需要输入更长的形式。",
|
|
2710
2836
|
"**[参数]** 可选 **<参数>** 必填",
|
|
2711
2837
|
],
|
|
2712
2838
|
},
|