@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.
- package/CHANGELOG.md +13 -0
- package/README.md +41 -44
- package/README.zh.md +41 -44
- package/config.example.yaml +4 -0
- package/dist/codex/CodexRuntime.js +8 -3
- package/dist/codex/CodexRuntime.js.map +1 -1
- package/dist/commands/CommandRouter.js +13 -0
- package/dist/commands/CommandRouter.js.map +1 -1
- package/dist/config/loadConfig.js +2 -0
- package/dist/config/loadConfig.js.map +1 -1
- package/dist/config/schema.js +2 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/console/ConsoleTurnPresenter.js +2 -0
- package/dist/console/ConsoleTurnPresenter.js.map +1 -1
- package/dist/feishu/CardRenderer.js +428 -9
- package/dist/feishu/CardRenderer.js.map +1 -1
- package/dist/feishu/FeishuConnector.js +29 -8
- package/dist/feishu/FeishuConnector.js.map +1 -1
- package/dist/feishu/FeishuMessageClient.js +43 -0
- package/dist/feishu/FeishuMessageClient.js.map +1 -1
- package/dist/feishu/FeishuTurnPresenter.js +29 -1
- package/dist/feishu/FeishuTurnPresenter.js.map +1 -1
- package/dist/feishu/ownerAccess.js +7 -0
- package/dist/feishu/ownerAccess.js.map +1 -0
- package/dist/index.js +14 -17
- package/dist/index.js.map +1 -1
- package/dist/presentation/OutboundRouter.js +19 -1
- package/dist/presentation/OutboundRouter.js.map +1 -1
- package/dist/proxy/ProxySessionController.js +1012 -58
- package/dist/proxy/ProxySessionController.js.map +1 -1
- package/dist/startup/StartupNotifier.js +65 -16
- package/dist/startup/StartupNotifier.js.map +1 -1
- package/dist/startup/startFeishu.js +2 -2
- package/dist/startup/startFeishu.js.map +1 -1
- package/dist/state/StateStore.js +250 -67
- package/dist/state/StateStore.js.map +1 -1
- package/dist/state/migrations.js +26 -0
- package/dist/state/migrations.js.map +1 -1
- package/dist/supervision/SafeRestartNotifier.js +17 -16
- package/dist/supervision/SafeRestartNotifier.js.map +1 -1
- package/dist/supervision/SafeRestartScheduler.js +12 -7
- package/dist/supervision/SafeRestartScheduler.js.map +1 -1
- package/dist/supervision/replacementSupervisor.js +45 -4
- package/dist/supervision/replacementSupervisor.js.map +1 -1
- package/dist/supervisor.js +30 -18
- package/dist/supervisor.js.map +1 -1
- package/docs/technical-reference.md +18 -5
- package/docs/technical-reference.zh.md +18 -5
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/skills/agent-bot/SKILL.md +8 -2
- package/src/codex/CodexRuntime.ts +9 -3
- package/src/commands/CommandRouter.ts +13 -0
- package/src/commands/commandTypes.ts +2 -0
- package/src/config/loadConfig.ts +2 -0
- package/src/config/schema.ts +2 -0
- package/src/console/ConsoleTurnPresenter.ts +4 -1
- package/src/feishu/CardRenderer.ts +533 -9
- package/src/feishu/FeishuConnector.ts +44 -10
- package/src/feishu/FeishuMessageClient.ts +58 -0
- package/src/feishu/FeishuTurnPresenter.ts +35 -2
- package/src/feishu/ownerAccess.ts +7 -0
- package/src/feishu/types.ts +7 -0
- package/src/index.ts +20 -20
- package/src/presentation/OutboundRouter.ts +28 -3
- package/src/proxy/ProxySessionController.ts +1177 -57
- package/src/startup/StartupNotifier.ts +67 -17
- package/src/startup/startFeishu.ts +5 -3
- package/src/state/StateStore.ts +394 -65
- package/src/state/migrations.ts +26 -0
- package/src/supervision/SafeRestartNotifier.ts +17 -17
- package/src/supervision/SafeRestartScheduler.ts +13 -6
- package/src/supervision/replacementSupervisor.ts +50 -4
- package/src/supervisor.ts +35 -16
|
@@ -1,24 +1,47 @@
|
|
|
1
|
+
import type { RestartNotificationTarget } from "./SafeRestartScheduler.js";
|
|
2
|
+
|
|
1
3
|
export const RESTART_GROUP_CONTEXTS_ENV = "AGENT_BOT_RESTART_GROUP_CONTEXTS";
|
|
4
|
+
export const RESTART_NOTIFICATION_TARGETS_ENV = "AGENT_BOT_RESTART_NOTIFICATION_TARGETS";
|
|
2
5
|
|
|
3
6
|
export function replacementSupervisorEnvironment(
|
|
4
7
|
restartReason: string,
|
|
5
8
|
environment: NodeJS.ProcessEnv = process.env,
|
|
6
|
-
|
|
9
|
+
restartNotificationTargets: readonly RestartNotificationTarget[] = [],
|
|
7
10
|
): NodeJS.ProcessEnv {
|
|
8
11
|
const result: NodeJS.ProcessEnv = {
|
|
9
12
|
...environment,
|
|
10
13
|
AGENT_BOT_START_DELAY_MS: "250",
|
|
11
14
|
AGENT_BOT_RESTART_REASON: restartReason,
|
|
12
15
|
};
|
|
13
|
-
const normalized =
|
|
16
|
+
const normalized = normalizedNotificationTargets(restartNotificationTargets);
|
|
14
17
|
if (normalized.length > 0) {
|
|
15
|
-
result[
|
|
18
|
+
result[RESTART_NOTIFICATION_TARGETS_ENV] = JSON.stringify(normalized);
|
|
16
19
|
} else {
|
|
17
|
-
delete result[
|
|
20
|
+
delete result[RESTART_NOTIFICATION_TARGETS_ENV];
|
|
18
21
|
}
|
|
22
|
+
delete result[RESTART_GROUP_CONTEXTS_ENV];
|
|
19
23
|
return result;
|
|
20
24
|
}
|
|
21
25
|
|
|
26
|
+
export function restartNotificationTargetsFromEnvironment(
|
|
27
|
+
value: string | undefined,
|
|
28
|
+
): RestartNotificationTarget[] {
|
|
29
|
+
if (!value?.trim()) return [];
|
|
30
|
+
try {
|
|
31
|
+
const parsed = JSON.parse(value) as unknown;
|
|
32
|
+
return Array.isArray(parsed)
|
|
33
|
+
? normalizedNotificationTargets(parsed.flatMap((entry) => {
|
|
34
|
+
if (!isRecord(entry)) return [];
|
|
35
|
+
const contextKey = typeof entry.contextKey === "string" ? entry.contextKey : "";
|
|
36
|
+
const replyMessageId = typeof entry.replyMessageId === "string" ? entry.replyMessageId : undefined;
|
|
37
|
+
return [{ contextKey, ...(replyMessageId ? { replyMessageId } : {}) }];
|
|
38
|
+
}))
|
|
39
|
+
: [];
|
|
40
|
+
} catch {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
22
45
|
export function restartGroupContextKeysFromEnvironment(value: string | undefined): string[] {
|
|
23
46
|
if (!value?.trim()) return [];
|
|
24
47
|
try {
|
|
@@ -34,3 +57,26 @@ export function restartGroupContextKeysFromEnvironment(value: string | undefined
|
|
|
34
57
|
function normalizedContextKeys(values: readonly string[]): string[] {
|
|
35
58
|
return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
|
|
36
59
|
}
|
|
60
|
+
|
|
61
|
+
function normalizedNotificationTargets(
|
|
62
|
+
values: readonly RestartNotificationTarget[],
|
|
63
|
+
): RestartNotificationTarget[] {
|
|
64
|
+
const targets = new Map<string, RestartNotificationTarget>();
|
|
65
|
+
for (const value of values) {
|
|
66
|
+
const contextKey = value.contextKey.trim();
|
|
67
|
+
if (!contextKey) continue;
|
|
68
|
+
const replyMessageId = value.replyMessageId?.trim();
|
|
69
|
+
const existing = targets.get(contextKey);
|
|
70
|
+
targets.set(contextKey, {
|
|
71
|
+
contextKey,
|
|
72
|
+
...(existing?.replyMessageId || replyMessageId
|
|
73
|
+
? { replyMessageId: existing?.replyMessageId ?? replyMessageId }
|
|
74
|
+
: {}),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return [...targets.values()];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
81
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
82
|
+
}
|
package/src/supervisor.ts
CHANGED
|
@@ -16,8 +16,11 @@ import { SupervisorDiagnostics, nodeDiagnosticReportArguments } from "./supervis
|
|
|
16
16
|
import { refreshedSystemEnvironment } from "./supervision/systemEnvironment.js";
|
|
17
17
|
import {
|
|
18
18
|
RESTART_GROUP_CONTEXTS_ENV,
|
|
19
|
+
RESTART_NOTIFICATION_TARGETS_ENV,
|
|
19
20
|
restartGroupContextKeysFromEnvironment,
|
|
21
|
+
restartNotificationTargetsFromEnvironment,
|
|
20
22
|
} from "./supervision/replacementSupervisor.js";
|
|
23
|
+
import type { RestartNotificationTarget } from "./supervision/SafeRestartScheduler.js";
|
|
21
24
|
|
|
22
25
|
const childEntry = fileURLToPath(new URL("./index.js", import.meta.url));
|
|
23
26
|
const config = loadConfig();
|
|
@@ -28,12 +31,14 @@ const diagnostics = new SupervisorDiagnostics(config);
|
|
|
28
31
|
diagnostics.initialize();
|
|
29
32
|
let child: ChildProcess | undefined;
|
|
30
33
|
let restartTimer: NodeJS.Timeout | undefined;
|
|
31
|
-
let
|
|
34
|
+
let restartNotificationTargetExpiryTimer: NodeJS.Timeout | undefined;
|
|
32
35
|
let stopping = false;
|
|
33
36
|
let consecutiveFailures = 0;
|
|
34
37
|
let nextStartReason = process.env.AGENT_BOT_RESTART_REASON?.trim() || "Supervisor 启动";
|
|
35
|
-
let
|
|
36
|
-
process.env[
|
|
38
|
+
let nextRestartNotificationTargets = mergeRestartNotificationTargets(
|
|
39
|
+
restartNotificationTargetsFromEnvironment(process.env[RESTART_NOTIFICATION_TARGETS_ENV]),
|
|
40
|
+
restartGroupContextKeysFromEnvironment(process.env[RESTART_GROUP_CONTEXTS_ENV])
|
|
41
|
+
.map((contextKey) => ({ contextKey })),
|
|
37
42
|
);
|
|
38
43
|
|
|
39
44
|
async function startChild(): Promise<void> {
|
|
@@ -45,7 +50,7 @@ async function startChild(): Promise<void> {
|
|
|
45
50
|
}
|
|
46
51
|
const startedAt = Date.now();
|
|
47
52
|
const restartReason = nextStartReason;
|
|
48
|
-
const
|
|
53
|
+
const restartNotificationTargets = nextRestartNotificationTargets;
|
|
49
54
|
nextStartReason = "Supervisor 重新拉起进程";
|
|
50
55
|
const workerStderr = diagnostics.openWorkerStderr();
|
|
51
56
|
const environmentRefresh = refreshedSystemEnvironment();
|
|
@@ -64,7 +69,7 @@ async function startChild(): Promise<void> {
|
|
|
64
69
|
...environmentRefresh.environment,
|
|
65
70
|
AGENT_BOT_SUPERVISED: "1",
|
|
66
71
|
AGENT_BOT_RESTART_REASON: restartReason,
|
|
67
|
-
},
|
|
72
|
+
}, restartNotificationTargets),
|
|
68
73
|
stdio: ["ignore", "ignore", workerStderr],
|
|
69
74
|
windowsHide: true,
|
|
70
75
|
});
|
|
@@ -75,7 +80,7 @@ async function startChild(): Promise<void> {
|
|
|
75
80
|
writeSupervisorLog("started", {
|
|
76
81
|
pid: child.pid,
|
|
77
82
|
restartReason,
|
|
78
|
-
|
|
83
|
+
restartNotificationTargets,
|
|
79
84
|
workerStderrPath: diagnostics.paths.workerStderrPath,
|
|
80
85
|
crashReportDirectory: diagnostics.paths.crashReportDirectory,
|
|
81
86
|
});
|
|
@@ -86,25 +91,26 @@ async function startChild(): Promise<void> {
|
|
|
86
91
|
child.once("exit", (code, signal) => {
|
|
87
92
|
void handleChildExit(code, signal, startedAt, workerPid);
|
|
88
93
|
});
|
|
89
|
-
if (
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
if (restartNotificationTargets.length > 0) {
|
|
95
|
+
if (restartNotificationTargetExpiryTimer) clearTimeout(restartNotificationTargetExpiryTimer);
|
|
96
|
+
restartNotificationTargetExpiryTimer = setTimeout(() => {
|
|
97
|
+
nextRestartNotificationTargets = [];
|
|
98
|
+
restartNotificationTargetExpiryTimer = undefined;
|
|
94
99
|
}, STABLE_UPTIME_MS);
|
|
95
100
|
}
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
function workerEnvironment(
|
|
99
104
|
environment: NodeJS.ProcessEnv,
|
|
100
|
-
|
|
105
|
+
restartNotificationTargets: readonly RestartNotificationTarget[],
|
|
101
106
|
): NodeJS.ProcessEnv {
|
|
102
107
|
const result = { ...environment };
|
|
103
|
-
if (
|
|
104
|
-
result[
|
|
108
|
+
if (restartNotificationTargets.length > 0) {
|
|
109
|
+
result[RESTART_NOTIFICATION_TARGETS_ENV] = JSON.stringify(restartNotificationTargets);
|
|
105
110
|
} else {
|
|
106
|
-
delete result[
|
|
111
|
+
delete result[RESTART_NOTIFICATION_TARGETS_ENV];
|
|
107
112
|
}
|
|
113
|
+
delete result[RESTART_GROUP_CONTEXTS_ENV];
|
|
108
114
|
return result;
|
|
109
115
|
}
|
|
110
116
|
|
|
@@ -164,7 +170,7 @@ function stop(signal: NodeJS.Signals): void {
|
|
|
164
170
|
if (stopping) return;
|
|
165
171
|
stopping = true;
|
|
166
172
|
if (restartTimer) clearTimeout(restartTimer);
|
|
167
|
-
if (
|
|
173
|
+
if (restartNotificationTargetExpiryTimer) clearTimeout(restartNotificationTargetExpiryTimer);
|
|
168
174
|
if (child && !child.killed) {
|
|
169
175
|
child.kill(signal);
|
|
170
176
|
return;
|
|
@@ -176,6 +182,19 @@ function writeSupervisorLog(event: string, data: Record<string, unknown>): void
|
|
|
176
182
|
diagnostics.writeEvent(event, data);
|
|
177
183
|
}
|
|
178
184
|
|
|
185
|
+
function mergeRestartNotificationTargets(
|
|
186
|
+
...targetGroups: RestartNotificationTarget[][]
|
|
187
|
+
): RestartNotificationTarget[] {
|
|
188
|
+
const targets = new Map<string, RestartNotificationTarget>();
|
|
189
|
+
for (const target of targetGroups.flat()) {
|
|
190
|
+
const existing = targets.get(target.contextKey);
|
|
191
|
+
if (!existing || (!existing.replyMessageId && target.replyMessageId)) {
|
|
192
|
+
targets.set(target.contextKey, { ...target });
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return [...targets.values()];
|
|
196
|
+
}
|
|
197
|
+
|
|
179
198
|
process.on("SIGINT", () => stop("SIGINT"));
|
|
180
199
|
process.on("SIGTERM", () => stop("SIGTERM"));
|
|
181
200
|
const initialDelayMs = Number(process.env.AGENT_BOT_START_DELAY_MS ?? 0);
|