@keyou007/agent-bot 0.1.22 → 0.1.24-alpha.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/CHANGELOG.md +13 -0
- package/README.md +26 -2
- package/README.zh.md +26 -2
- package/config.example.yaml +5 -0
- package/dist/cli/controlProtocol.js.map +1 -1
- package/dist/cli/help.js +4 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/taskGroupOptions.js +27 -0
- package/dist/cli/taskGroupOptions.js.map +1 -1
- package/dist/cli.js +21 -1
- package/dist/cli.js.map +1 -1
- package/dist/codex/CodexProcessManager.js +19 -3
- package/dist/codex/CodexProcessManager.js.map +1 -1
- package/dist/codex/CodexRuntime.js +92 -9
- package/dist/codex/CodexRuntime.js.map +1 -1
- package/dist/commands/CommandRouter.js +27 -0
- package/dist/commands/CommandRouter.js.map +1 -1
- package/dist/config/loadConfig.js +4 -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 +31 -2
- package/dist/feishu/CardRenderer.js.map +1 -1
- package/dist/feishu/FeishuMessageClient.js +6 -3
- package/dist/feishu/FeishuMessageClient.js.map +1 -1
- package/dist/feishu/MergedForwardMessage.js +17 -7
- package/dist/feishu/MergedForwardMessage.js.map +1 -1
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -1
- package/dist/local-files/TurnPreviewPage.js +106 -87
- package/dist/local-files/TurnPreviewPage.js.map +1 -1
- package/dist/proxy/ConversationExport.js +41 -0
- package/dist/proxy/ConversationExport.js.map +1 -0
- package/dist/proxy/ProxySessionController.js +118 -7
- package/dist/proxy/ProxySessionController.js.map +1 -1
- package/dist/state/StateStore.js +65 -0
- package/dist/state/StateStore.js.map +1 -1
- package/dist/state/migrations.js +12 -0
- package/dist/state/migrations.js.map +1 -1
- package/dist/updates/AutomaticUpdatePreparer.js +66 -0
- package/dist/updates/AutomaticUpdatePreparer.js.map +1 -0
- package/dist/updates/DailyUpdateMonitor.js +261 -0
- package/dist/updates/DailyUpdateMonitor.js.map +1 -0
- package/dist/updates/PublishedRelease.js +43 -0
- package/dist/updates/PublishedRelease.js.map +1 -0
- package/dist/updates/types.js +2 -0
- package/dist/updates/types.js.map +1 -0
- package/docs/technical-reference.md +4 -0
- package/docs/technical-reference.zh.md +4 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/skills/agent-bot/SKILL.md +11 -0
- package/src/cli/controlProtocol.ts +9 -0
- package/src/cli/help.ts +4 -0
- package/src/cli/taskGroupOptions.ts +33 -3
- package/src/cli.ts +21 -0
- package/src/codex/CodexProcessManager.ts +21 -4
- package/src/codex/CodexRuntime.ts +104 -12
- package/src/commands/CommandRouter.ts +24 -0
- package/src/commands/commandTypes.ts +1 -0
- package/src/config/loadConfig.ts +4 -0
- package/src/config/schema.ts +4 -1
- package/src/feishu/CardRenderer.ts +34 -2
- package/src/feishu/FeishuMessageClient.ts +6 -2
- package/src/feishu/MergedForwardMessage.ts +29 -7
- package/src/feishu/types.ts +1 -1
- package/src/index.ts +49 -0
- package/src/local-files/TurnPreviewPage.ts +105 -88
- package/src/proxy/ConversationExport.ts +43 -0
- package/src/proxy/ProxySessionController.ts +166 -8
- package/src/runtime/types.ts +6 -0
- package/src/state/StateStore.ts +69 -0
- package/src/state/migrations.ts +12 -0
- package/src/updates/AutomaticUpdatePreparer.ts +76 -0
- package/src/updates/DailyUpdateMonitor.ts +252 -0
- package/src/updates/PublishedRelease.ts +44 -0
- package/src/updates/types.ts +19 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { compareSemver } from "../cli/SelfUpdater.js";
|
|
3
|
+
import { CardRenderer } from "../feishu/CardRenderer.js";
|
|
4
|
+
import { stableVersionSchema } from "./PublishedRelease.js";
|
|
5
|
+
export function scheduleDailyUpdate(now, random = Math.random) {
|
|
6
|
+
const start = new Date(now);
|
|
7
|
+
if (start.getHours() >= 17)
|
|
8
|
+
start.setDate(start.getDate() + 1);
|
|
9
|
+
start.setHours(10, 0, 0, 0);
|
|
10
|
+
const end = new Date(start);
|
|
11
|
+
end.setHours(17, 0, 0, 0);
|
|
12
|
+
const lower = Math.max(now, start.getTime());
|
|
13
|
+
const dueAt = lower + Math.floor(Math.min(0.999999999, Math.max(0, random())) * (end.getTime() - lower));
|
|
14
|
+
return { day: localDay(start.getTime()), dueAt, checked: false };
|
|
15
|
+
}
|
|
16
|
+
function localDay(now) {
|
|
17
|
+
const date = new Date(now);
|
|
18
|
+
return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
|
|
19
|
+
}
|
|
20
|
+
export class DailyUpdateMonitor {
|
|
21
|
+
options;
|
|
22
|
+
renderer = new CardRenderer();
|
|
23
|
+
now;
|
|
24
|
+
timer;
|
|
25
|
+
stopped = true;
|
|
26
|
+
work = Promise.resolve();
|
|
27
|
+
busy = false;
|
|
28
|
+
cardWrites = Promise.resolve();
|
|
29
|
+
lastCardState = new Map();
|
|
30
|
+
constructor(options) {
|
|
31
|
+
this.options = options;
|
|
32
|
+
this.now = options.now ?? Date.now;
|
|
33
|
+
}
|
|
34
|
+
async start() {
|
|
35
|
+
if (!this.stopped)
|
|
36
|
+
return;
|
|
37
|
+
this.stopped = false;
|
|
38
|
+
this.work = this.recover().catch((error) => this.logError(error));
|
|
39
|
+
await this.work;
|
|
40
|
+
if (this.stopped)
|
|
41
|
+
return;
|
|
42
|
+
this.timer = setInterval(() => this.poll(), 1_000);
|
|
43
|
+
this.timer.unref();
|
|
44
|
+
this.poll();
|
|
45
|
+
}
|
|
46
|
+
async stop() {
|
|
47
|
+
this.stopped = true;
|
|
48
|
+
clearInterval(this.timer);
|
|
49
|
+
await this.work;
|
|
50
|
+
await this.cardWrites;
|
|
51
|
+
}
|
|
52
|
+
async cancel(action) {
|
|
53
|
+
if (this.stopped)
|
|
54
|
+
throw new Error("自动更新已停止。");
|
|
55
|
+
const notice = this.options.store.getUpdateNotice(String(action.value.version ?? ""));
|
|
56
|
+
if (!notice || !action.messageId || action.userId !== notice.userOpenId
|
|
57
|
+
|| action.userId !== this.options.userOpenId() || action.value.token !== notice.token
|
|
58
|
+
|| (notice.messageId && notice.messageId !== action.messageId)) {
|
|
59
|
+
throw new Error("更新卡片已失效或无权操作。");
|
|
60
|
+
}
|
|
61
|
+
if (notice.status === "cancelled")
|
|
62
|
+
return;
|
|
63
|
+
if ((notice.status !== "countdown" && notice.status !== "announcing")
|
|
64
|
+
|| (notice.deadline !== undefined && this.now() >= notice.deadline)) {
|
|
65
|
+
throw new Error("取消倒计时已结束,请查看安全重启卡片中的更新状态。");
|
|
66
|
+
}
|
|
67
|
+
this.options.store.saveUpdateNotice({ ...notice, messageId: action.messageId, status: "cancelled" });
|
|
68
|
+
this.options.logger.info({ version: notice.version }, "Cancelled automatic Agent Bot update.");
|
|
69
|
+
await this.refreshCard(notice.version);
|
|
70
|
+
}
|
|
71
|
+
async cancelPreparedUpdate(version) {
|
|
72
|
+
const notice = this.options.store.getUpdateNotice(version);
|
|
73
|
+
if (!notice || (notice.status !== "preparing" && notice.status !== "scheduled"))
|
|
74
|
+
return;
|
|
75
|
+
this.options.store.saveUpdateNotice({ ...notice, status: "cancelled" });
|
|
76
|
+
await this.refreshCard(version).catch((error) => this.logError(error));
|
|
77
|
+
}
|
|
78
|
+
poll() {
|
|
79
|
+
if (this.stopped || this.busy)
|
|
80
|
+
return;
|
|
81
|
+
this.busy = true;
|
|
82
|
+
this.work = this.tick().catch((error) => this.logError(error)).finally(() => { this.busy = false; });
|
|
83
|
+
}
|
|
84
|
+
async tick() {
|
|
85
|
+
for (const notice of this.options.store.listPendingUpdateNotices()) {
|
|
86
|
+
if (this.stopped)
|
|
87
|
+
return;
|
|
88
|
+
if (notice.status !== "countdown")
|
|
89
|
+
continue;
|
|
90
|
+
if (notice.userOpenId !== this.options.userOpenId()) {
|
|
91
|
+
this.options.store.saveUpdateNotice({ ...notice, status: "cancelled" });
|
|
92
|
+
await this.refreshCard(notice.version);
|
|
93
|
+
}
|
|
94
|
+
else if (this.now() < notice.deadline) {
|
|
95
|
+
try {
|
|
96
|
+
await this.refreshCard(notice.version);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
await this.fail(notice.version, error);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
await this.apply(notice);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (this.stopped)
|
|
107
|
+
return;
|
|
108
|
+
const now = this.now();
|
|
109
|
+
let schedule = this.options.store.getUpdateCheckSchedule();
|
|
110
|
+
if (!schedule || schedule.day !== localDay(now)) {
|
|
111
|
+
// Keep tomorrow's persisted random slot when starting after the daily window.
|
|
112
|
+
if (!schedule || schedule.dueAt <= now) {
|
|
113
|
+
schedule = scheduleDailyUpdate(now, this.options.random);
|
|
114
|
+
this.options.store.saveUpdateCheckSchedule(schedule);
|
|
115
|
+
this.options.logger.info({ dueAt: new Date(schedule.dueAt).toISOString() }, "Scheduled daily Agent Bot update check.");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (schedule.checked || now < schedule.dueAt)
|
|
119
|
+
return;
|
|
120
|
+
const hour = new Date(now).getHours();
|
|
121
|
+
if (hour < 10 || hour >= 17)
|
|
122
|
+
return;
|
|
123
|
+
const owner = this.options.userOpenId();
|
|
124
|
+
if (!owner || this.options.hasPendingUpdate())
|
|
125
|
+
return;
|
|
126
|
+
this.options.store.saveUpdateCheckSchedule({ ...schedule, checked: true });
|
|
127
|
+
const version = stableVersionSchema.parse(await this.options.readLatest());
|
|
128
|
+
if (this.stopped || compareSemver(version, this.options.currentVersion) <= 0
|
|
129
|
+
|| this.options.store.getUpdateNotice(version))
|
|
130
|
+
return;
|
|
131
|
+
const notes = await this.options.readNotes(version);
|
|
132
|
+
if (this.stopped || owner !== this.options.userOpenId())
|
|
133
|
+
return;
|
|
134
|
+
if (!notes.trim())
|
|
135
|
+
throw new Error(`Release notes are unavailable for Agent Bot ${version}.`);
|
|
136
|
+
let supportError;
|
|
137
|
+
try {
|
|
138
|
+
await this.options.checkSupport();
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
supportError = error instanceof Error ? error.message : String(error);
|
|
142
|
+
}
|
|
143
|
+
if (this.stopped || owner !== this.options.userOpenId())
|
|
144
|
+
return;
|
|
145
|
+
await this.announce({
|
|
146
|
+
version, currentVersion: this.options.currentVersion, userOpenId: owner,
|
|
147
|
+
token: randomUUID(), notes, status: supportError ? "failed" : "announcing", error: supportError,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
async announce(notice) {
|
|
151
|
+
this.options.store.saveUpdateNotice(notice);
|
|
152
|
+
try {
|
|
153
|
+
const messageId = await this.options.outbound.sendInteractiveCard(`open_id:${notice.userOpenId}`, this.renderer.renderUpdateNotice(notice, this.now()), notice.token);
|
|
154
|
+
if (!messageId)
|
|
155
|
+
throw new Error("Update notification delivery was not confirmed; automatic update stopped.");
|
|
156
|
+
const current = this.options.store.getUpdateNotice(notice.version);
|
|
157
|
+
this.options.store.saveUpdateNotice({
|
|
158
|
+
...current, messageId, status: current.status === "announcing" ? "countdown" : current.status,
|
|
159
|
+
deadline: current.status === "announcing" ? this.now() + 60_000 : undefined,
|
|
160
|
+
});
|
|
161
|
+
this.options.logger.info({ version: notice.version }, "Delivered private Agent Bot update notice.");
|
|
162
|
+
if (!this.stopped)
|
|
163
|
+
await this.refreshCard(notice.version);
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
await this.fail(notice.version, error);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async apply(notice) {
|
|
170
|
+
if (this.stopped)
|
|
171
|
+
return;
|
|
172
|
+
const current = this.options.store.getUpdateNotice(notice.version);
|
|
173
|
+
if (current.status !== "countdown")
|
|
174
|
+
return;
|
|
175
|
+
this.options.store.saveUpdateNotice({ ...current, status: "preparing" });
|
|
176
|
+
try {
|
|
177
|
+
await this.refreshCard(current.version);
|
|
178
|
+
if (this.stopped)
|
|
179
|
+
return;
|
|
180
|
+
if (this.options.hasPendingUpdate())
|
|
181
|
+
throw new Error("已有更新或重启正在等待执行,本次自动更新已停止。");
|
|
182
|
+
await this.options.applyUpdate(current.version);
|
|
183
|
+
const latest = this.options.store.getUpdateNotice(current.version);
|
|
184
|
+
if (latest.status !== "cancelled")
|
|
185
|
+
this.options.store.saveUpdateNotice({ ...latest, status: "scheduled" });
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
await this.fail(current.version, error);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (!this.stopped)
|
|
192
|
+
await this.refreshCard(current.version).catch((error) => this.logError(error));
|
|
193
|
+
}
|
|
194
|
+
async recover() {
|
|
195
|
+
for (const notice of this.options.store.listPendingUpdateNotices()) {
|
|
196
|
+
if (this.stopped)
|
|
197
|
+
return;
|
|
198
|
+
let recovered;
|
|
199
|
+
if (compareSemver(this.options.currentVersion, notice.version) >= 0) {
|
|
200
|
+
recovered = { ...notice, status: "completed" };
|
|
201
|
+
}
|
|
202
|
+
else if (notice.userOpenId !== this.options.userOpenId()) {
|
|
203
|
+
recovered = { ...notice, status: "cancelled" };
|
|
204
|
+
}
|
|
205
|
+
else if (notice.status === "countdown" && notice.messageId) {
|
|
206
|
+
// Renew the cancellation window on the same card after downtime.
|
|
207
|
+
recovered = { ...notice, deadline: this.now() + 60_000 };
|
|
208
|
+
}
|
|
209
|
+
else if ((notice.status === "scheduled" || notice.status === "preparing") && this.options.pendingVersion() === notice.version) {
|
|
210
|
+
recovered = { ...notice, status: "scheduled" };
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
recovered = { ...notice, status: "failed", error: "上次自动更新被中断,未自动重试。" };
|
|
214
|
+
}
|
|
215
|
+
this.options.store.saveUpdateNotice(recovered);
|
|
216
|
+
try {
|
|
217
|
+
await this.refreshCard(recovered.version);
|
|
218
|
+
if (recovered.status === "countdown" && !this.stopped) {
|
|
219
|
+
const current = this.options.store.getUpdateNotice(recovered.version);
|
|
220
|
+
if (current.status === "countdown")
|
|
221
|
+
this.options.store.saveUpdateNotice({ ...current, deadline: this.now() + 60_000 });
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
if (recovered.status === "countdown")
|
|
226
|
+
await this.fail(recovered.version, error);
|
|
227
|
+
else
|
|
228
|
+
this.logError(error);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async fail(version, error) {
|
|
233
|
+
const notice = this.options.store.getUpdateNotice(version);
|
|
234
|
+
if (notice.status !== "cancelled") {
|
|
235
|
+
this.options.store.saveUpdateNotice({ ...notice, status: "failed", error: error instanceof Error ? error.message : String(error) });
|
|
236
|
+
}
|
|
237
|
+
this.logError(error);
|
|
238
|
+
if (!this.stopped)
|
|
239
|
+
await this.refreshCard(version).catch((cardError) => this.logError(cardError));
|
|
240
|
+
}
|
|
241
|
+
refreshCard(version) {
|
|
242
|
+
const write = this.cardWrites.then(async () => {
|
|
243
|
+
if (this.stopped)
|
|
244
|
+
return;
|
|
245
|
+
const notice = this.options.store.getUpdateNotice(version);
|
|
246
|
+
if (!notice.messageId)
|
|
247
|
+
return;
|
|
248
|
+
const key = `${notice.status}:${notice.status === "countdown" ? Math.ceil((notice.deadline - this.now()) / 5_000) : ""}`;
|
|
249
|
+
if (this.lastCardState.get(version) === key)
|
|
250
|
+
return;
|
|
251
|
+
await this.options.outbound.updateInteractiveCard(notice.messageId, this.renderer.renderUpdateNotice(notice, this.now()));
|
|
252
|
+
this.lastCardState.set(version, key);
|
|
253
|
+
});
|
|
254
|
+
this.cardWrites = write.catch(() => undefined);
|
|
255
|
+
return write;
|
|
256
|
+
}
|
|
257
|
+
logError(error) {
|
|
258
|
+
this.options.logger.warn({ error }, "Automatic Agent Bot update did not complete.");
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=DailyUpdateMonitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DailyUpdateMonitor.js","sourceRoot":"","sources":["../../src/updates/DailyUpdateMonitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { AGENT_BOT_PACKAGE_NAME } from "../cli/SelfUpdater.js";
|
|
3
|
+
export const stableVersionSchema = z.string().regex(/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/u);
|
|
4
|
+
export async function readLatestStableVersion() {
|
|
5
|
+
const text = await fetchText(`https://registry.npmjs.org/${encodeURIComponent(AGENT_BOT_PACKAGE_NAME)}/latest`, 256_000);
|
|
6
|
+
return z.object({ version: stableVersionSchema }).parse(JSON.parse(text)).version;
|
|
7
|
+
}
|
|
8
|
+
export async function readReleaseNotes(version) {
|
|
9
|
+
stableVersionSchema.parse(version);
|
|
10
|
+
const changelog = await fetchText(`https://raw.githubusercontent.com/keyou/agent-bot/v${version}/CHANGELOG.md`, 2_000_000);
|
|
11
|
+
return extractReleaseNotes(changelog, version);
|
|
12
|
+
}
|
|
13
|
+
export function extractReleaseNotes(changelog, version) {
|
|
14
|
+
const sections = changelog.split(/^## /mu).slice(1);
|
|
15
|
+
const section = sections.find((value) => value.split(/\r?\n/u, 1)[0]?.startsWith(`[${version}]`));
|
|
16
|
+
const notes = section?.includes("\n") ? section.slice(section.indexOf("\n") + 1).trim() : undefined;
|
|
17
|
+
if (!notes)
|
|
18
|
+
throw new Error(`Release notes are unavailable for Agent Bot ${version}.`);
|
|
19
|
+
return notes.length > 4_000 ? `${notes.slice(0, 3_900)}\n\n[完整更新日志](https://github.com/keyou/agent-bot/releases/tag/v${version})` : notes;
|
|
20
|
+
}
|
|
21
|
+
async function fetchText(url, maxBytes) {
|
|
22
|
+
const response = await fetch(url, { signal: AbortSignal.timeout(15_000) });
|
|
23
|
+
if (!response.ok || !response.body)
|
|
24
|
+
throw new Error(`Release request failed: HTTP ${response.status}.`);
|
|
25
|
+
const reader = response.body.getReader();
|
|
26
|
+
const chunks = [];
|
|
27
|
+
let size = 0;
|
|
28
|
+
try {
|
|
29
|
+
while (true) {
|
|
30
|
+
const { done, value } = await reader.read();
|
|
31
|
+
if (done)
|
|
32
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
33
|
+
size += value.byteLength;
|
|
34
|
+
if (size > maxBytes)
|
|
35
|
+
throw new Error("Release response exceeds the size limit.");
|
|
36
|
+
chunks.push(value);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
await reader.cancel();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=PublishedRelease.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PublishedRelease.js","sourceRoot":"","sources":["../../src/updates/PublishedRelease.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/updates/types.ts"],"names":[],"mappings":""}
|
|
@@ -54,6 +54,10 @@ Configuration path precedence:
|
|
|
54
54
|
|
|
55
55
|
The default `.env` is always loaded from the Agent Bot home. YAML values in the form `${NAME}` are expanded from the process environment after `.env` loading.
|
|
56
56
|
|
|
57
|
+
When the Worker constructs its runtimes at startup, each recognized Codex App Server Agent also reads `.env` from its own Codex home. The home is selected from `agents.<name>.env.CODEX_HOME`, then the Worker environment's `CODEX_HOME`, then `~/.codex`. Home-relative paths are expanded and relative paths resolve against the Profile directory, matching the child working directory. The resolved home is passed to the Codex process; a `CODEX_HOME` assignment inside that `.env` cannot redirect it.
|
|
58
|
+
|
|
59
|
+
Codex environment values have the lowest priority: explicit Agent `env` values win over the Worker environment (including the Profile `.env`), which wins over Codex `.env`. Empty explicit values remain explicit. The existing main/explicit-Profile environment precedence is unchanged. The same resolved values are available to Agent Bot's Provider `/models` authentication and the Codex child. This does not mutate `process.env`, affect YAML expansion, or load Codex credentials into other Agents. Reserved Agent Bot and Feishu variables are still filtered before spawning the child. Missing files are ignored; unreadable files produce a warning containing only the path and error code. Values are loaded once per Worker startup; safely restart after changes.
|
|
60
|
+
|
|
57
61
|
Relative `storage.sqlitePath` and `logging.path` values resolve against the directory containing the loaded configuration file. `defaults.cwd` resolves against the process startup directory.
|
|
58
62
|
|
|
59
63
|
## Initialization
|
|
@@ -54,6 +54,10 @@ CLI 通过 Node.js 国际化能力读取系统 Locale。以 `zh` 开头的 Local
|
|
|
54
54
|
|
|
55
55
|
默认 `.env` 始终从 Agent Bot 用户目录加载。加载 `.env` 后,YAML 中的 `${NAME}` 会使用进程环境变量展开。
|
|
56
56
|
|
|
57
|
+
Worker 启动并创建运行时时,还会为识别为 Codex 的 App Server Agent 读取各自 Codex 目录中的 `.env`。目录依次取 `agents.<name>.env.CODEX_HOME`、Worker 环境中的 `CODEX_HOME`、`~/.codex`。支持展开 `~`,相对路径按 Profile 目录解析,与子进程工作目录一致。解析后的目录会传给 Codex 进程,文件内的 `CODEX_HOME` 赋值不能改变该目录。
|
|
58
|
+
|
|
59
|
+
Codex `.env` 优先级最低:Agent 显式 `env` 优先于 Worker 环境(含 Profile `.env`),Worker 环境优先于 Codex `.env`;显式空值也不会被覆盖。主 Profile 与显式 Profile 原有的环境变量优先级不变。Agent Bot 查询 Provider `/models` 的鉴权和 Codex 子进程共用这些值,但不会修改 `process.env`、影响 YAML 变量展开或把 Codex 凭据加载到其他 Agent。启动子进程前仍会过滤 Agent Bot 和飞书保留变量。文件不存在时忽略,无法读取时只记录路径和错误码。每次 Worker 启动读取一次,修改后需安全重启。
|
|
60
|
+
|
|
57
61
|
相对形式的 `storage.sqlitePath` 和 `logging.path` 按配置文件所在目录解析;`defaults.cwd` 按进程启动目录解析。
|
|
58
62
|
|
|
59
63
|
## 初始化
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keyou007/agent-bot",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.24-alpha.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@keyou007/agent-bot",
|
|
9
|
-
"version": "0.1.
|
|
9
|
+
"version": "0.1.24-alpha.0",
|
|
10
10
|
"license": "GPL-3.0-only",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@agentclientprotocol/sdk": "1.2.1",
|
package/package.json
CHANGED
|
@@ -96,6 +96,15 @@ agentbot task forkgroup [title]
|
|
|
96
96
|
|
|
97
97
|
Choose `new` or `newgroup` for fresh context. Choose `fork` or `forkgroup` when the new task must retain conversation history through the latest completed Turn. Forking must not interrupt an active source turn.
|
|
98
98
|
|
|
99
|
+
For lightweight context transfer, including between different Agents:
|
|
100
|
+
|
|
101
|
+
```powershell
|
|
102
|
+
agentbot task clone [title] [--agent <name>]
|
|
103
|
+
agentbot task clonegroup [title] [--agent <name>]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
These commands export only user Prompts and final answers through the latest completed Turn to a local text file, then start a fresh task with instructions to read it, acknowledge, and wait. They do not copy tools, reasoning, images, or native session files, and never interrupt the source task. Without `--agent`, they use the conversation's default Agent, not necessarily the source Agent. Provider, model, and reasoning use the target Agent's saved defaults; project shape and permissions come from the source. `clone` switches the current conversation after import starts; `clonegroup` leaves it unchanged and creates a separate group. Both support `--json` and explicit `--task` targeting. Feishu equivalents are `/clone` and `/clonegroup` (`/cg`). ACP sources use only dialogue already saved by Agent Bot. The context file remains beside the Profile SQLite file under `context-transfers`; keep it available for the cloned task.
|
|
107
|
+
|
|
99
108
|
Feishu `/sessions [keyword]` lists and searches tasks across projects and all Providers, not just the App Server's current Provider. Switching Provider does not hide existing tasks; listing still uses paged metadata and the latest Turn summary only.
|
|
100
109
|
|
|
101
110
|
Fork creation stores source-task and branch-Turn references without synchronizing the full local Turn list. The Feishu Turn card reuses local records and loads only the summary pages needed for the requested page, not the entire history. `task turns` loads the first page if necessary and returns available local records. This does not change the Agent's inherited context. Retry listing Turns after a temporary history-read failure; unsupported summary pagination never falls back to downloading full history.
|
|
@@ -158,6 +167,8 @@ agentbot server stop
|
|
|
158
167
|
|
|
159
168
|
`update` is only for npm-installed Agent Bot packages. It verifies the new package, sends a safe-restart card, waits for active tasks, and restarts immediately when the service is already idle. It automatically restores the prior version if activation fails. It refuses source checkouts and `npm link` installations.
|
|
160
169
|
|
|
170
|
+
The Feishu service also checks stable npm `latest` once daily at a persisted random time between 10:00 and 17:00 (server local time). A new version sends the owner a private release-notes card with 60 seconds to cancel. If not cancelled, preparation runs in the background and activation waits for tasks, final deliveries, and the quiet inbound window before restarting. Each version is notified once per Profile; cancellation survives restarts. An interrupted countdown resumes with a fresh minute on the same card. No private recipient, unconfirmed notification delivery, or missing release notes means no automatic installation. Source/npm-link protections still apply. Set `updates.enabled: false` in the Profile config and safely restart to disable checks. Do not bypass the countdown or idle gate.
|
|
171
|
+
|
|
161
172
|
Autostart is Profile-specific. Use `server autostart enable` for login startup, `server autostart enable --linger` on Linux only when the user explicitly requests startup before login, and `server autostart disable` to remove registration without stopping the current Server. Disabling Agent Bot autostart must not disable Linux user lingering because other services may use it.
|
|
162
173
|
|
|
163
174
|
Use safe restart by default. Prefer `agentbot task restart` when hosted so the current task is resolved automatically. Use `--immediate` or `task restart --force` only when the user explicitly accepts interruption.
|
|
@@ -43,6 +43,7 @@ export type ControlRequest =
|
|
|
43
43
|
projectless?: boolean;
|
|
44
44
|
}
|
|
45
45
|
| { action: "task_fork"; localSessionId: string }
|
|
46
|
+
| { action: "task_clone" | "task_clone_group"; localSessionId: string; title?: string; agentName?: string }
|
|
46
47
|
| {
|
|
47
48
|
action: "task_switch";
|
|
48
49
|
localSessionId: string;
|
|
@@ -102,6 +103,14 @@ export interface TaskGroupControlData {
|
|
|
102
103
|
task: SessionRecord;
|
|
103
104
|
}
|
|
104
105
|
|
|
106
|
+
export interface TaskCloneControlData {
|
|
107
|
+
sourceLocalSessionId: string;
|
|
108
|
+
contextFile: string;
|
|
109
|
+
turnCount: number;
|
|
110
|
+
task: SessionRecord;
|
|
111
|
+
group?: TaskGroupControlData["group"];
|
|
112
|
+
}
|
|
113
|
+
|
|
105
114
|
export interface TaskDismissControlData {
|
|
106
115
|
localSessionId: string;
|
|
107
116
|
remoteSessionId: string;
|
package/src/cli/help.ts
CHANGED
|
@@ -30,6 +30,8 @@ export function renderCliHelp(version: string, language: CliLanguage = cliLangua
|
|
|
30
30
|
task newgroup [任务] [标题] 创建新群;支持 --agent、--dir、--nodir
|
|
31
31
|
task fork [任务] 从任务最近完成的 Turn 创建分支
|
|
32
32
|
task forkgroup [任务] [标题] 从任务 Fork 新群
|
|
33
|
+
task clone [任务] [标题] 用对话文件创建新任务;支持 --agent
|
|
34
|
+
task clonegroup [任务] [标题] 用对话文件创建新群;支持 --agent
|
|
33
35
|
task switch [任务] [目标任务] 切换会话任务;--previous 切回上一任务
|
|
34
36
|
task queue [任务] <提示词> 将提示词排队;nosteer 是别名
|
|
35
37
|
task agent [任务] [名称] 查看或设置该会话的新任务默认 Agent
|
|
@@ -123,6 +125,8 @@ Task commands:
|
|
|
123
125
|
task newgroup [task] [title] Create a group; supports --agent, --dir, --nodir
|
|
124
126
|
task fork [task] Fork the task's latest completed Turn
|
|
125
127
|
task forkgroup [task] [title] Fork a task into a new group
|
|
128
|
+
task clone [task] [title] Create a task from a conversation file; supports --agent
|
|
129
|
+
task clonegroup [task] [title] Create a group from a conversation file; supports --agent
|
|
126
130
|
task switch [task] [target] Switch the conversation task; --previous selects the prior task
|
|
127
131
|
task queue [task] <prompt> Queue a Prompt; nosteer is an alias
|
|
128
132
|
task agent [task] [name] Show or set the conversation's default Agent for new tasks
|
|
@@ -113,8 +113,38 @@ export function parseTaskForkGroupOptions(
|
|
|
113
113
|
};
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
export function parseTaskCloneOptions(
|
|
117
|
+
input: string[],
|
|
118
|
+
action: "clone" | "clonegroup",
|
|
119
|
+
language: CliLanguage = cliLanguage,
|
|
120
|
+
): TaskForkGroupOptions & { agentName?: string } {
|
|
121
|
+
const positionals: string[] = [];
|
|
122
|
+
let agentName: string | undefined;
|
|
123
|
+
let json = false;
|
|
124
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
125
|
+
const argument = input[index]!;
|
|
126
|
+
if (argument === "--json") {
|
|
127
|
+
json = true;
|
|
128
|
+
} else if (argument === "--agent") {
|
|
129
|
+
if (agentName !== undefined) throw optionError(action, "--agent", language);
|
|
130
|
+
const name = input[++index];
|
|
131
|
+
if (!name?.trim() || name.startsWith("--")) throw new Error(cliText(
|
|
132
|
+
`task ${action} requires an Agent name after --agent.`,
|
|
133
|
+
`task ${action} 需要在 --agent 后指定 Agent 名称。`, language,
|
|
134
|
+
));
|
|
135
|
+
agentName = name.trim();
|
|
136
|
+
} else {
|
|
137
|
+
if (argument.startsWith("--")) throw unsupportedOption(action, argument, language);
|
|
138
|
+
positionals.push(argument);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const [reference, ...title] = positionals;
|
|
142
|
+
requireTaskReference(action, reference, language);
|
|
143
|
+
return { reference, title: title.join(" ").trim() || undefined, agentName, json };
|
|
144
|
+
}
|
|
145
|
+
|
|
116
146
|
function requireTaskReference(
|
|
117
|
-
action: "new" | "newgroup" | "forkgroup",
|
|
147
|
+
action: "new" | "newgroup" | "forkgroup" | "clone" | "clonegroup",
|
|
118
148
|
reference: string | undefined,
|
|
119
149
|
language: CliLanguage,
|
|
120
150
|
): asserts reference is string {
|
|
@@ -127,7 +157,7 @@ function requireTaskReference(
|
|
|
127
157
|
}
|
|
128
158
|
|
|
129
159
|
function optionError(
|
|
130
|
-
action: "new" | "newgroup",
|
|
160
|
+
action: "new" | "newgroup" | "clone" | "clonegroup",
|
|
131
161
|
option: "--agent" | "--dir" | "--nodir",
|
|
132
162
|
language: CliLanguage,
|
|
133
163
|
): Error {
|
|
@@ -147,7 +177,7 @@ function conflictingProjectOptions(action: "new" | "newgroup", language: CliLang
|
|
|
147
177
|
}
|
|
148
178
|
|
|
149
179
|
function unsupportedOption(
|
|
150
|
-
action: "new" | "newgroup" | "forkgroup",
|
|
180
|
+
action: "new" | "newgroup" | "forkgroup" | "clone" | "clonegroup",
|
|
151
181
|
option: string,
|
|
152
182
|
language: CliLanguage,
|
|
153
183
|
): Error {
|
package/src/cli.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
controlEndpoint,
|
|
9
9
|
type ControlResponse,
|
|
10
10
|
type TaskAgentControlData,
|
|
11
|
+
type TaskCloneControlData,
|
|
11
12
|
type TaskDirectoryControlData,
|
|
12
13
|
type TaskDismissControlData,
|
|
13
14
|
type TaskForkControlData,
|
|
@@ -108,6 +109,7 @@ import {
|
|
|
108
109
|
import { isThreadContextKey } from "./feishu/contextKey.js";
|
|
109
110
|
import { refreshedSystemEnvironment } from "./supervision/systemEnvironment.js";
|
|
110
111
|
import {
|
|
112
|
+
parseTaskCloneOptions,
|
|
111
113
|
parseTaskForkGroupOptions,
|
|
112
114
|
parseTaskNewOptions,
|
|
113
115
|
parseTaskNewGroupOptions,
|
|
@@ -1593,6 +1595,25 @@ async function taskCommand(input: string[]): Promise<void> {
|
|
|
1593
1595
|
await serverCommand(["restart", "--task", target.session.localSessionId, ...translated]);
|
|
1594
1596
|
return;
|
|
1595
1597
|
}
|
|
1598
|
+
if (action === "clone" || action === "clonegroup") {
|
|
1599
|
+
const target = resolveTaskCommandTarget(allSessions, rest, action);
|
|
1600
|
+
const options = parseTaskCloneOptions([target.session.localSessionId, ...target.args], action);
|
|
1601
|
+
if (action === "clonegroup") requireCliGroupUser(config.feishu.userOpenId);
|
|
1602
|
+
const response = await sendControlRequest(controlEndpoint(config.storage.sqlitePath), {
|
|
1603
|
+
action: action === "clonegroup" ? "task_clone_group" : "task_clone",
|
|
1604
|
+
localSessionId: target.session.localSessionId,
|
|
1605
|
+
...(options.title ? { title: options.title } : {}),
|
|
1606
|
+
...(options.agentName ? { agentName: options.agentName } : {}),
|
|
1607
|
+
}, 120_000);
|
|
1608
|
+
if (!response.ok) throw new Error(response.message ?? cliText("Failed to clone the task.", "克隆任务失败。"));
|
|
1609
|
+
const result = response.data as TaskCloneControlData;
|
|
1610
|
+
if (options.json) printJson(result);
|
|
1611
|
+
else process.stdout.write(cliText(
|
|
1612
|
+
`Cloned task: ${result.task.title ?? result.task.localSessionId}\nAgent: ${result.task.agentName}\nContext: ${result.contextFile} (${result.turnCount} turns)\n${result.group ? `Group: ${result.group.name}\n` : ""}`,
|
|
1613
|
+
`克隆任务:${result.task.title ?? result.task.localSessionId}\nAgent:${result.task.agentName}\n上下文:${result.contextFile}(${result.turnCount} 轮)\n${result.group ? `群:${result.group.name}\n` : ""}`,
|
|
1614
|
+
));
|
|
1615
|
+
return;
|
|
1616
|
+
}
|
|
1596
1617
|
if (action === "newgroup") {
|
|
1597
1618
|
const target = resolveTaskCommandTarget(allSessions, rest, action);
|
|
1598
1619
|
const options = parseTaskNewGroupOptions([target.session.localSessionId, ...target.args]);
|
|
@@ -2,6 +2,7 @@ import type { ChildProcessWithoutNullStreams } from "node:child_process";
|
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import readline from "node:readline";
|
|
5
|
+
import { config as loadDotEnv } from "dotenv";
|
|
5
6
|
import type { Logger } from "pino";
|
|
6
7
|
import { AppServerConnection } from "./AppServerConnection.js";
|
|
7
8
|
import type { AppServerClient, AppServerClientProvider } from "./CodexRuntime.js";
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
import type { AgentProcessInfo } from "../runtime/types.js";
|
|
13
14
|
import { spawnStdioCommand } from "../utils/spawnCommand.js";
|
|
14
15
|
import { assertSupportedCodexVersion } from "./CodexVersion.js";
|
|
16
|
+
import { resolveUserPath } from "../config/paths.js";
|
|
15
17
|
|
|
16
18
|
export class CodexProcessManager implements AppServerClientProvider {
|
|
17
19
|
private static readonly RELEASE_TIMEOUT_MS = 5_000;
|
|
@@ -20,6 +22,7 @@ export class CodexProcessManager implements AppServerClientProvider {
|
|
|
20
22
|
private version?: string;
|
|
21
23
|
private agentFamily?: "codex" | "traex";
|
|
22
24
|
private initializing?: Promise<AppServerClient>;
|
|
25
|
+
private readonly codexEnvironment: Record<string, string> = {};
|
|
23
26
|
private readonly disconnectListeners = new Set<(error: Error) => void>();
|
|
24
27
|
|
|
25
28
|
constructor(
|
|
@@ -28,7 +31,17 @@ export class CodexProcessManager implements AppServerClientProvider {
|
|
|
28
31
|
private readonly env: Record<string, string>,
|
|
29
32
|
private readonly logger: Logger,
|
|
30
33
|
private readonly environmentContext: () => AgentEnvironmentContext = () => ({}),
|
|
31
|
-
) {
|
|
34
|
+
) {
|
|
35
|
+
if (this.getAgentFamily() !== "codex") return;
|
|
36
|
+
const envPath = path.join(this.getCodexHome(), ".env");
|
|
37
|
+
const result = loadDotEnv({ path: envPath, processEnv: this.codexEnvironment, quiet: true });
|
|
38
|
+
if (result.error && (result.error as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
39
|
+
this.logger.warn(
|
|
40
|
+
{ path: envPath, code: (result.error as NodeJS.ErrnoException).code },
|
|
41
|
+
"Could not load the Codex environment file; using configured and inherited values.",
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
32
45
|
|
|
33
46
|
async getClient(): Promise<AppServerClient> {
|
|
34
47
|
if (this.initializing) return this.initializing;
|
|
@@ -45,10 +58,12 @@ export class CodexProcessManager implements AppServerClientProvider {
|
|
|
45
58
|
private async startClient(): Promise<AppServerClient> {
|
|
46
59
|
this.version = undefined;
|
|
47
60
|
const environmentContext = this.environmentContext();
|
|
61
|
+
const agentEnvironment = { ...this.env };
|
|
62
|
+
if (this.getAgentFamily() === "codex") agentEnvironment.CODEX_HOME = this.getCodexHome();
|
|
48
63
|
const child = spawnStdioCommand(
|
|
49
64
|
this.command,
|
|
50
65
|
this.args,
|
|
51
|
-
agentBotEnvironment(
|
|
66
|
+
agentBotEnvironment({ ...this.codexEnvironment, ...process.env }, agentEnvironment, environmentContext),
|
|
52
67
|
environmentContext.profilePath ?? os.homedir(),
|
|
53
68
|
);
|
|
54
69
|
this.child = child;
|
|
@@ -108,11 +123,13 @@ export class CodexProcessManager implements AppServerClientProvider {
|
|
|
108
123
|
}
|
|
109
124
|
|
|
110
125
|
getCodexHome(): string {
|
|
111
|
-
|
|
126
|
+
const home = this.env.CODEX_HOME?.trim() || process.env.CODEX_HOME?.trim() || path.join(os.homedir(), ".codex");
|
|
127
|
+
return resolveUserPath(home, this.environmentContext().profilePath ?? os.homedir());
|
|
112
128
|
}
|
|
113
129
|
|
|
114
130
|
getEnvironmentVariable(name: string): string | undefined {
|
|
115
|
-
|
|
131
|
+
if (name === "CODEX_HOME" && this.getAgentFamily() === "codex") return this.getCodexHome();
|
|
132
|
+
return this.env[name] ?? process.env[name] ?? this.codexEnvironment[name];
|
|
116
133
|
}
|
|
117
134
|
|
|
118
135
|
close(): void {
|