@keyou007/agent-bot 0.1.14-alpha.0 → 0.1.14-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +41 -44
  3. package/README.zh.md +41 -44
  4. package/config.example.yaml +4 -0
  5. package/dist/codex/CodexRuntime.js +8 -3
  6. package/dist/codex/CodexRuntime.js.map +1 -1
  7. package/dist/commands/CommandRouter.js +13 -0
  8. package/dist/commands/CommandRouter.js.map +1 -1
  9. package/dist/config/loadConfig.js +2 -0
  10. package/dist/config/loadConfig.js.map +1 -1
  11. package/dist/config/schema.js +2 -0
  12. package/dist/config/schema.js.map +1 -1
  13. package/dist/console/ConsoleTurnPresenter.js +2 -0
  14. package/dist/console/ConsoleTurnPresenter.js.map +1 -1
  15. package/dist/feishu/CardRenderer.js +428 -9
  16. package/dist/feishu/CardRenderer.js.map +1 -1
  17. package/dist/feishu/FeishuConnector.js +29 -8
  18. package/dist/feishu/FeishuConnector.js.map +1 -1
  19. package/dist/feishu/FeishuMessageClient.js +43 -0
  20. package/dist/feishu/FeishuMessageClient.js.map +1 -1
  21. package/dist/feishu/FeishuTurnPresenter.js +29 -1
  22. package/dist/feishu/FeishuTurnPresenter.js.map +1 -1
  23. package/dist/feishu/ownerAccess.js +7 -0
  24. package/dist/feishu/ownerAccess.js.map +1 -0
  25. package/dist/index.js +14 -17
  26. package/dist/index.js.map +1 -1
  27. package/dist/presentation/OutboundRouter.js +19 -1
  28. package/dist/presentation/OutboundRouter.js.map +1 -1
  29. package/dist/proxy/ProxySessionController.js +1012 -58
  30. package/dist/proxy/ProxySessionController.js.map +1 -1
  31. package/dist/startup/StartupNotifier.js +65 -16
  32. package/dist/startup/StartupNotifier.js.map +1 -1
  33. package/dist/startup/startFeishu.js +2 -2
  34. package/dist/startup/startFeishu.js.map +1 -1
  35. package/dist/state/StateStore.js +250 -67
  36. package/dist/state/StateStore.js.map +1 -1
  37. package/dist/state/migrations.js +26 -0
  38. package/dist/state/migrations.js.map +1 -1
  39. package/dist/supervision/SafeRestartNotifier.js +17 -16
  40. package/dist/supervision/SafeRestartNotifier.js.map +1 -1
  41. package/dist/supervision/SafeRestartScheduler.js +12 -7
  42. package/dist/supervision/SafeRestartScheduler.js.map +1 -1
  43. package/dist/supervision/replacementSupervisor.js +45 -4
  44. package/dist/supervision/replacementSupervisor.js.map +1 -1
  45. package/dist/supervisor.js +30 -18
  46. package/dist/supervisor.js.map +1 -1
  47. package/docs/technical-reference.md +18 -5
  48. package/docs/technical-reference.zh.md +18 -5
  49. package/npm-shrinkwrap.json +2 -2
  50. package/package.json +1 -1
  51. package/skills/agent-bot/SKILL.md +8 -2
  52. package/src/codex/CodexRuntime.ts +9 -3
  53. package/src/commands/CommandRouter.ts +13 -0
  54. package/src/commands/commandTypes.ts +2 -0
  55. package/src/config/loadConfig.ts +2 -0
  56. package/src/config/schema.ts +2 -0
  57. package/src/console/ConsoleTurnPresenter.ts +4 -1
  58. package/src/feishu/CardRenderer.ts +533 -9
  59. package/src/feishu/FeishuConnector.ts +44 -10
  60. package/src/feishu/FeishuMessageClient.ts +58 -0
  61. package/src/feishu/FeishuTurnPresenter.ts +35 -2
  62. package/src/feishu/ownerAccess.ts +7 -0
  63. package/src/feishu/types.ts +7 -0
  64. package/src/index.ts +20 -20
  65. package/src/presentation/OutboundRouter.ts +28 -3
  66. package/src/proxy/ProxySessionController.ts +1177 -57
  67. package/src/startup/StartupNotifier.ts +67 -17
  68. package/src/startup/startFeishu.ts +5 -3
  69. package/src/state/StateStore.ts +394 -65
  70. package/src/state/migrations.ts +26 -0
  71. package/src/supervision/SafeRestartNotifier.ts +17 -17
  72. package/src/supervision/SafeRestartScheduler.ts +13 -6
  73. package/src/supervision/replacementSupervisor.ts +50 -4
  74. package/src/supervisor.ts +35 -16
@@ -4,6 +4,7 @@ import { CardRenderer } from "../feishu/CardRenderer.js";
4
4
  import { baseChatContextKey, isThreadContextKey } from "../feishu/contextKey.js";
5
5
  import type { FeishuOutbound } from "../feishu/types.js";
6
6
  import type { SessionRecord, StateStore, UserContextRecord } from "../state/StateStore.js";
7
+ import type { RestartNotificationTarget } from "../supervision/SafeRestartScheduler.js";
7
8
 
8
9
  export interface StartupNotificationOptions {
9
10
  agentBotVersion: string;
@@ -20,6 +21,7 @@ export interface StartupTaskMetadataHydrator {
20
21
 
21
22
  interface StartupNotificationTarget {
22
23
  contextKey: string;
24
+ replyMessageId?: string;
23
25
  context?: UserContextRecord;
24
26
  }
25
27
 
@@ -36,7 +38,7 @@ export class StartupNotifier {
36
38
  async notify(
37
39
  startedAt: Date,
38
40
  restartReason: string,
39
- restartGroupContextKeys: string[] = [],
41
+ restartTargets: RestartNotificationTarget[] = [],
40
42
  ): Promise<void> {
41
43
  let targets: StartupNotificationTarget[];
42
44
  try {
@@ -46,21 +48,58 @@ export class StartupNotifier {
46
48
  .filter((chat) => !isThreadContextKey(chat.contextKey))
47
49
  .map((chat) => [chat.contextKey, chat]),
48
50
  );
49
- const targetGroups = new Map(
50
- this.store.listRecentlyActiveChatContexts(activeGroupSince)
51
- .filter((chat) => chat.chatType === "group" && !isThreadContextKey(chat.contextKey))
52
- .map((chat) => [chat.contextKey, chat]),
53
- );
54
- for (const contextKey of restartGroupContextKeys) {
55
- const baseContextKey = baseChatContextKey(contextKey.trim());
56
- const group = knownGroups.get(baseContextKey);
57
- if (group) targetGroups.set(baseContextKey, group);
51
+ const targetsByContext = new Map<string, StartupNotificationTarget>();
52
+ for (const chat of this.store.listChatContexts("p2p")) {
53
+ targetsByContext.set(chat.contextKey, {
54
+ contextKey: chat.contextKey,
55
+ context: this.store.getUserContext(chat.contextKey),
56
+ });
57
+ }
58
+ const recentGroups = this.store.listRecentlyActiveChatContexts(activeGroupSince)
59
+ .filter((chat) => chat.chatType === "group" && !isThreadContextKey(chat.contextKey));
60
+ for (const chat of recentGroups) {
61
+ targetsByContext.set(chat.contextKey, {
62
+ contextKey: chat.contextKey,
63
+ context: this.store.getUserContext(chat.contextKey),
64
+ });
58
65
  }
59
- const chats = [...this.store.listChatContexts("p2p"), ...targetGroups.values()];
60
- targets = chats.map((chat) => ({
61
- contextKey: chat.contextKey,
62
- context: this.store.getUserContext(chat.contextKey),
63
- }));
66
+ const explicitBaseContextKeys = new Set(restartTargets
67
+ .map((target) => target.contextKey.trim())
68
+ .filter((contextKey) => contextKey && !isThreadContextKey(contextKey)));
69
+ for (const target of restartTargets) {
70
+ const contextKey = target.contextKey.trim();
71
+ if (!contextKey) continue;
72
+ if (isThreadContextKey(contextKey)) {
73
+ const baseContextKey = baseChatContextKey(contextKey);
74
+ if (!knownGroups.has(baseContextKey)) continue;
75
+ const replyMessageId = target.replyMessageId?.trim();
76
+ if (replyMessageId) {
77
+ if (!explicitBaseContextKeys.has(baseContextKey)) {
78
+ targetsByContext.delete(baseContextKey);
79
+ }
80
+ targetsByContext.set(contextKey, {
81
+ contextKey,
82
+ replyMessageId,
83
+ context: this.store.getUserContext(contextKey),
84
+ });
85
+ } else {
86
+ const group = knownGroups.get(baseContextKey)!;
87
+ targetsByContext.set(baseContextKey, {
88
+ contextKey: baseContextKey,
89
+ context: this.store.getUserContext(baseContextKey),
90
+ });
91
+ }
92
+ continue;
93
+ }
94
+ const group = knownGroups.get(contextKey);
95
+ if (group) {
96
+ targetsByContext.set(contextKey, {
97
+ contextKey,
98
+ context: this.store.getUserContext(contextKey),
99
+ });
100
+ }
101
+ }
102
+ targets = [...targetsByContext.values()];
64
103
  } catch (error) {
65
104
  this.logger.warn({ error }, "Failed to load startup notification targets.");
66
105
  throw new Error("Failed to load startup notification targets.", { cause: error });
@@ -72,7 +111,7 @@ export class StartupNotifier {
72
111
  targets = [{ contextKey: `open_id:${defaultUserOpenId}` }];
73
112
  }
74
113
 
75
- const deliveries = await Promise.all(targets.map(async ({ contextKey, context }) => {
114
+ const deliveries = await Promise.all(targets.map(async ({ contextKey, replyMessageId, context }) => {
76
115
  let session = context?.currentSessionId ? this.store.getSession(context.currentSessionId) : undefined;
77
116
  if (session && this.metadataHydrator) {
78
117
  try {
@@ -111,7 +150,18 @@ export class StartupNotifier {
111
150
  : undefined,
112
151
  });
113
152
  try {
114
- await this.outbound.sendInteractiveCard(contextKey, card);
153
+ if (replyMessageId) {
154
+ if (!this.outbound.replyInteractiveCard) {
155
+ throw new Error("The outbound transport cannot preserve the safe-restart topic.");
156
+ }
157
+ await this.outbound.replyInteractiveCard(
158
+ contextKey,
159
+ { messageId: replyMessageId, replyInThread: true },
160
+ card,
161
+ );
162
+ } else {
163
+ await this.outbound.sendInteractiveCard(contextKey, card);
164
+ }
115
165
  return true;
116
166
  } catch (error) {
117
167
  this.logger.warn(
@@ -1,9 +1,11 @@
1
+ import type { RestartNotificationTarget } from "../supervision/SafeRestartScheduler.js";
2
+
1
3
  export interface StartableFeishuConnector {
2
4
  start(): Promise<void>;
3
5
  }
4
6
 
5
7
  export interface StartupNotificationSender {
6
- notify(startedAt: Date, restartReason: string, restartGroupContextKeys?: string[]): Promise<void>;
8
+ notify(startedAt: Date, restartReason: string, restartTargets?: RestartNotificationTarget[]): Promise<void>;
7
9
  }
8
10
 
9
11
  export async function startFeishu(
@@ -13,10 +15,10 @@ export async function startFeishu(
13
15
  restartReason: string,
14
16
  prepare?: () => Promise<void>,
15
17
  onConnected?: () => void,
16
- restartGroupContextKeys: string[] = [],
18
+ restartTargets: RestartNotificationTarget[] = [],
17
19
  ): Promise<void> {
18
20
  await prepare?.();
19
21
  await connector.start();
20
- await notifier.notify(startedAt, restartReason, restartGroupContextKeys);
22
+ await notifier.notify(startedAt, restartReason, restartTargets);
21
23
  onConnected?.();
22
24
  }