@keyou007/agent-bot 0.1.7 → 0.1.9
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 +11 -0
- package/README.md +6 -0
- package/README.zh.md +6 -0
- package/config.example.yaml +2 -0
- package/dist/cli/FeishuAppConfiguration.js +3 -6
- package/dist/cli/FeishuAppConfiguration.js.map +1 -1
- package/dist/codex/CodexEventMapper.js +13 -0
- package/dist/codex/CodexEventMapper.js.map +1 -1
- package/dist/codex/CodexRuntime.js +33 -4
- package/dist/codex/CodexRuntime.js.map +1 -1
- package/dist/config/loadConfig.js +1 -0
- package/dist/config/loadConfig.js.map +1 -1
- package/dist/config/schema.js +1 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/feishu/CardRenderer.js +2 -2
- package/dist/feishu/CardRenderer.js.map +1 -1
- package/dist/feishu/FeishuBotIdentity.js +35 -0
- package/dist/feishu/FeishuBotIdentity.js.map +1 -0
- package/dist/feishu/FeishuConnector.js +20 -5
- package/dist/feishu/FeishuConnector.js.map +1 -1
- package/dist/presentation/TurnStateReducer.js +2 -1
- package/dist/presentation/TurnStateReducer.js.map +1 -1
- package/dist/proxy/ProxySessionController.js +80 -12
- package/dist/proxy/ProxySessionController.js.map +1 -1
- package/dist/utils/generatedImageMarkdown.js +11 -0
- package/dist/utils/generatedImageMarkdown.js.map +1 -0
- package/docs/technical-reference.md +7 -1
- package/docs/technical-reference.zh.md +7 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/skills/agent-bot/SKILL.md +6 -2
- package/src/cli/FeishuAppConfiguration.ts +3 -6
- package/src/codex/CodexEventMapper.ts +13 -0
- package/src/codex/CodexRuntime.ts +48 -5
- package/src/config/loadConfig.ts +1 -0
- package/src/config/schema.ts +1 -0
- package/src/feishu/CardRenderer.ts +2 -2
- package/src/feishu/FeishuBotIdentity.ts +55 -0
- package/src/feishu/FeishuConnector.ts +24 -4
- package/src/presentation/TurnStateReducer.ts +6 -1
- package/src/proxy/ProxySessionController.ts +145 -22
- package/src/utils/generatedImageMarkdown.ts +10 -0
|
@@ -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(
|
|
@@ -1578,9 +1679,7 @@ export class ProxySessionController {
|
|
|
1578
1679
|
);
|
|
1579
1680
|
await this.outbound.sendText(
|
|
1580
1681
|
sourceContextKey,
|
|
1581
|
-
`已将${
|
|
1582
|
-
incomingMessage?.threadContext ? prepared.sourceDescription : "当前任务"
|
|
1583
|
-
} Fork 到飞书群:${group.name};新群当前任务为 ${taskDescription}。`,
|
|
1682
|
+
`已将${sourceSummary} Fork 到飞书群:${group.name};新群当前任务为 ${taskDescription}。`,
|
|
1584
1683
|
);
|
|
1585
1684
|
}
|
|
1586
1685
|
|
|
@@ -2277,6 +2376,16 @@ export class ProxySessionController {
|
|
|
2277
2376
|
contextKey,
|
|
2278
2377
|
},
|
|
2279
2378
|
});
|
|
2379
|
+
actions.push({
|
|
2380
|
+
text: "NewGroup",
|
|
2381
|
+
value: {
|
|
2382
|
+
action: "session_new_group",
|
|
2383
|
+
sessionId: entry.id,
|
|
2384
|
+
...(searchTerm ? { searchTerm } : {}),
|
|
2385
|
+
visibleCount: String(visibleCount),
|
|
2386
|
+
contextKey,
|
|
2387
|
+
},
|
|
2388
|
+
});
|
|
2280
2389
|
actions.push({
|
|
2281
2390
|
text: "Fork",
|
|
2282
2391
|
value: {
|
|
@@ -2287,6 +2396,16 @@ export class ProxySessionController {
|
|
|
2287
2396
|
contextKey,
|
|
2288
2397
|
},
|
|
2289
2398
|
});
|
|
2399
|
+
actions.push({
|
|
2400
|
+
text: "ForkGroup",
|
|
2401
|
+
value: {
|
|
2402
|
+
action: "session_fork_group",
|
|
2403
|
+
sessionId: entry.id,
|
|
2404
|
+
...(searchTerm ? { searchTerm } : {}),
|
|
2405
|
+
visibleCount: String(visibleCount),
|
|
2406
|
+
contextKey,
|
|
2407
|
+
},
|
|
2408
|
+
});
|
|
2290
2409
|
actions.push({
|
|
2291
2410
|
text: "Status",
|
|
2292
2411
|
value: {
|
|
@@ -2310,6 +2429,7 @@ export class ProxySessionController {
|
|
|
2310
2429
|
[
|
|
2311
2430
|
...(remoteHint ? [remoteHint] : []),
|
|
2312
2431
|
"点击 **New** 在对应任务的项目中创建新任务;点击 **Switch** 快速切换;点击 **Fork** 从任务最新已完成轮次创建分支;外部正在运行的任务显示 **Stop**,点击后发送 Interrupt 并变为 **Switch**。",
|
|
2432
|
+
"点击 **NewGroup** 在对应任务的项目中创建新群和新任务;点击 **ForkGroup** 从对应任务最新已完成轮次创建分支群。",
|
|
2313
2433
|
"也可发送 **/switch [序号或任务 ID]**;不带参数切回上一个任务。外部正在执行的回合不会被接管。",
|
|
2314
2434
|
"发送 **/fork [序号或任务 ID]**,可从当前或指定任务创建分支;任务运行中时使用最近已完成轮次。",
|
|
2315
2435
|
"点击 **Status**,或发送 **/status [序号或任务 ID]**,查看当前或指定任务状态。",
|
|
@@ -3264,7 +3384,10 @@ function truncateTail(value: string, maxLength: number): string {
|
|
|
3264
3384
|
function parseAgentGroupName(value: string): { agentName: string; title: string } | undefined {
|
|
3265
3385
|
const match = /^\[([^[\]]+)\]\s+(.+)$/.exec(value.trim());
|
|
3266
3386
|
const agentName = match?.[1]?.trim();
|
|
3267
|
-
const
|
|
3387
|
+
const remainder = match?.[2]?.trim();
|
|
3388
|
+
if (!agentName || !remainder) return undefined;
|
|
3389
|
+
const projectPrefix = /^\[([^[\]]+)\](?:\s+(.+))?$/.exec(remainder);
|
|
3390
|
+
const title = projectPrefix ? projectPrefix[2]?.trim() : remainder;
|
|
3268
3391
|
return agentName && title ? { agentName, title } : undefined;
|
|
3269
3392
|
}
|
|
3270
3393
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function appendGeneratedImageMarkdown(finalResponse: string, imagePaths: string[]): string {
|
|
2
|
+
const text = finalResponse.trim();
|
|
3
|
+
const normalizedText = text.replaceAll("\\", "/");
|
|
4
|
+
const images = [...new Set(imagePaths.map((imagePath) => imagePath.trim().replaceAll("\\", "/")).filter(Boolean))]
|
|
5
|
+
.filter((imagePath) => !normalizedText.includes(imagePath));
|
|
6
|
+
if (images.length === 0) return text;
|
|
7
|
+
const imageMarkdown = images.map((imagePath, index) =>
|
|
8
|
+
``).join("\n\n");
|
|
9
|
+
return text ? `${text}\n\n${imageMarkdown}` : imageMarkdown;
|
|
10
|
+
}
|