tellrun 1.0.1 → 1.1.2
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/LICENSE +21 -0
- package/README.md +144 -108
- package/README.zh-CN.md +207 -0
- package/dist/agents/codex.js +225 -80
- package/dist/agents/codex.js.map +1 -1
- package/dist/cli.js +39 -39
- package/dist/cli.js.map +1 -1
- package/dist/config.js +3 -3
- package/dist/config.js.map +1 -1
- package/dist/core/relay.js +80 -44
- package/dist/core/relay.js.map +1 -1
- package/dist/im/telegram.js +90 -14
- package/dist/im/telegram.js.map +1 -1
- package/dist/logger.js +1 -1
- package/dist/logger.js.map +1 -1
- package/dist/main.js +12 -12
- package/dist/main.js.map +1 -1
- package/dist/storage/schema.js +8 -1
- package/dist/storage/schema.js.map +1 -1
- package/dist/storage/store.js +88 -21
- package/dist/storage/store.js.map +1 -1
- package/dist/systemd.js +17 -17
- package/dist/systemd.js.map +1 -1
- package/docs/architecture.md +32 -18
- package/docs/prd.md +9 -9
- package/package.json +32 -5
package/dist/im/telegram.js
CHANGED
|
@@ -16,15 +16,30 @@ export function createTelegramConnection(config, handleMessage, store, logger) {
|
|
|
16
16
|
const bot = new Bot(config.token, {
|
|
17
17
|
client: { timeoutSeconds: 35, baseFetchConfig: { agent } },
|
|
18
18
|
});
|
|
19
|
-
/**
|
|
19
|
+
/** 中断初始化、拉取和输入提示;正在处理的消息由 start 等待完成。 */
|
|
20
20
|
const polling = new AbortController();
|
|
21
21
|
let started = false;
|
|
22
|
-
|
|
22
|
+
/** 输入提示与流式草稿只发送最新状态,避免自动重发已过期的内容。 */
|
|
23
|
+
bot.api.config.use((prev, method, payload, signal) => ["sendChatAction", "sendMessageDraft"].includes(method)
|
|
24
|
+
? prev(method, payload, signal)
|
|
25
|
+
: autoRetry({ maxRetryAttempts: 2, maxDelaySeconds: 5, rethrowHttpErrors: true })(prev, method, payload, signal));
|
|
23
26
|
/** 超时覆盖整次调用及重试;grammY 的旧 signal 类型与 Node 原生接口兼容。 */
|
|
24
27
|
bot.api.config.use((prev, method, payload, signal) => prev(method, payload, signal ??
|
|
25
28
|
AbortSignal.any([
|
|
26
|
-
AbortSignal.timeout(method === "getUpdates"
|
|
27
|
-
|
|
29
|
+
AbortSignal.timeout(method === "getUpdates"
|
|
30
|
+
? 40_000
|
|
31
|
+
: ["sendChatAction", "sendMessageDraft"].includes(method)
|
|
32
|
+
? 4_000
|
|
33
|
+
: 15_000),
|
|
34
|
+
...([
|
|
35
|
+
"getMe",
|
|
36
|
+
"getWebhookInfo",
|
|
37
|
+
"getUpdates",
|
|
38
|
+
"sendChatAction",
|
|
39
|
+
"sendMessageDraft",
|
|
40
|
+
].includes(method)
|
|
41
|
+
? [polling.signal]
|
|
42
|
+
: []),
|
|
28
43
|
])));
|
|
29
44
|
/** 身份与私聊范围校验必须先于核心层调用。 */
|
|
30
45
|
bot.use(async (ctx, next) => {
|
|
@@ -74,10 +89,10 @@ export function createTelegramConnection(config, handleMessage, store, logger) {
|
|
|
74
89
|
? cause.code
|
|
75
90
|
: undefined,
|
|
76
91
|
}, cause instanceof GrammyError && cause.error_code === 409
|
|
77
|
-
? "Telegram
|
|
92
|
+
? "Telegram polling conflict. Check other instances or webhook."
|
|
78
93
|
: cause instanceof GrammyError && cause.error_code === 401
|
|
79
|
-
? "Telegram
|
|
80
|
-
: "Telegram
|
|
94
|
+
? "Telegram authentication failed. Check bot token."
|
|
95
|
+
: "Telegram or storage error. Stopping service.");
|
|
81
96
|
}
|
|
82
97
|
return {
|
|
83
98
|
/** 核实机器人身份后才启动任务,初始化不消费 Telegram 消息。 */
|
|
@@ -87,8 +102,8 @@ export function createTelegramConnection(config, handleMessage, store, logger) {
|
|
|
87
102
|
if (polling.signal.aborted)
|
|
88
103
|
return;
|
|
89
104
|
if ((await bot.api.getWebhookInfo()).url) {
|
|
90
|
-
logger.error("
|
|
91
|
-
throw new Error("Bot
|
|
105
|
+
logger.error("Webhook configured. Remove it before starting long polling.");
|
|
106
|
+
throw new Error("Bot has an active webhook.");
|
|
92
107
|
}
|
|
93
108
|
return {
|
|
94
109
|
platform: "telegram",
|
|
@@ -103,14 +118,14 @@ export function createTelegramConnection(config, handleMessage, store, logger) {
|
|
|
103
118
|
throw error;
|
|
104
119
|
}
|
|
105
120
|
},
|
|
106
|
-
/**
|
|
121
|
+
/** 接收、回复与输入提示独立运行,慢请求不会阻塞 /stop 的入站处理。 */
|
|
107
122
|
async start() {
|
|
108
123
|
started = true;
|
|
109
124
|
const workers = [];
|
|
110
125
|
try {
|
|
111
126
|
if (polling.signal.aborted)
|
|
112
127
|
return;
|
|
113
|
-
logger.info({ botId: bot.botInfo.id }, "Telegram
|
|
128
|
+
logger.info({ botId: bot.botInfo.id }, "Telegram polling started");
|
|
114
129
|
workers.push((async () => {
|
|
115
130
|
/** 只有入站状态保存成功才推进确认位置;重投按已保存的事件标识去重。 */
|
|
116
131
|
let offset = 0;
|
|
@@ -127,15 +142,53 @@ export function createTelegramConnection(config, handleMessage, store, logger) {
|
|
|
127
142
|
}
|
|
128
143
|
}
|
|
129
144
|
})(), (async () => {
|
|
145
|
+
/** 草稿最多每秒更新一次;无新内容时每 20 秒续期,最终回复与草稿串行发送。 */
|
|
146
|
+
let nextDraftAt = 0;
|
|
147
|
+
let sentDraft;
|
|
130
148
|
while (!polling.signal.aborted) {
|
|
131
149
|
const reply = store.pendingReply(String(bot.botInfo.id), String(config.ownerId));
|
|
132
150
|
if (!reply) {
|
|
133
|
-
|
|
151
|
+
const draft = store.pendingDraft(String(bot.botInfo.id), String(config.ownerId));
|
|
152
|
+
if (draft &&
|
|
153
|
+
Date.now() >= nextDraftAt &&
|
|
154
|
+
(draft.taskId !== sentDraft?.taskId ||
|
|
155
|
+
draft.text !== sentDraft.text ||
|
|
156
|
+
Date.now() - sentDraft.at >= 20_000)) {
|
|
157
|
+
nextDraftAt = Date.now() + 1000;
|
|
158
|
+
try {
|
|
159
|
+
await bot.api.sendMessageDraft(Number(draft.chatId), draft.taskId, draft.text);
|
|
160
|
+
sentDraft = { ...draft, at: Date.now() };
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
if (polling.signal.aborted)
|
|
164
|
+
return;
|
|
165
|
+
if (!(error instanceof HttpError || error instanceof GrammyError))
|
|
166
|
+
throw error;
|
|
167
|
+
if (error instanceof GrammyError && error.error_code === 401)
|
|
168
|
+
throw error;
|
|
169
|
+
nextDraftAt =
|
|
170
|
+
error instanceof GrammyError &&
|
|
171
|
+
error.error_code >= 400 &&
|
|
172
|
+
error.error_code < 500 &&
|
|
173
|
+
error.error_code !== 429
|
|
174
|
+
? Number.POSITIVE_INFINITY
|
|
175
|
+
: Date.now() +
|
|
176
|
+
(error instanceof GrammyError ? (error.parameters.retry_after ?? 5) : 5) *
|
|
177
|
+
1000;
|
|
178
|
+
logger.warn({
|
|
179
|
+
errorType: error.name,
|
|
180
|
+
errorCode: error instanceof GrammyError ? error.error_code : undefined,
|
|
181
|
+
}, "Telegram preview failed; final reply delivery continues");
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
await setTimeout(100);
|
|
134
185
|
continue;
|
|
135
186
|
}
|
|
136
187
|
try {
|
|
137
188
|
await bot.api.sendMessage(reply.chatId, reply.text);
|
|
138
189
|
store.removeReply(reply.id);
|
|
190
|
+
/** 普通消息会清除客户端草稿;任务仍执行时允许再次显示最新内容。 */
|
|
191
|
+
sentDraft = undefined;
|
|
139
192
|
}
|
|
140
193
|
catch (error) {
|
|
141
194
|
if (!(error instanceof HttpError || error instanceof GrammyError))
|
|
@@ -153,10 +206,33 @@ export function createTelegramConnection(config, handleMessage, store, logger) {
|
|
|
153
206
|
? error.parameters.retry_after
|
|
154
207
|
: Math.min(60, 2 ** Math.min(reply.attempts, 6)));
|
|
155
208
|
logger.warn({ outboxId: reply.id, permanent, errorType: error.name }, permanent
|
|
156
|
-
? "Telegram
|
|
157
|
-
: "Telegram
|
|
209
|
+
? "Telegram rejected reply permanently; removed from queue. Result kept."
|
|
210
|
+
: "Telegram reply failed; saved for retry");
|
|
158
211
|
}
|
|
159
212
|
}
|
|
213
|
+
})(), (async () => {
|
|
214
|
+
/** 输入提示最多持续 5 秒,每 4 秒刷新;仅当前实例已派发的任务显示。 */
|
|
215
|
+
let nextTypingAt = 0;
|
|
216
|
+
while (!polling.signal.aborted) {
|
|
217
|
+
if (Date.now() >= nextTypingAt &&
|
|
218
|
+
["dispatching", "running"].includes(store.activeTask()?.status ?? "")) {
|
|
219
|
+
nextTypingAt = Date.now() + 4_000;
|
|
220
|
+
try {
|
|
221
|
+
await bot.api.sendChatAction(config.ownerId, "typing");
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
if (polling.signal.aborted)
|
|
225
|
+
return;
|
|
226
|
+
if (error instanceof GrammyError && error.parameters.retry_after !== undefined)
|
|
227
|
+
nextTypingAt = Math.max(nextTypingAt, Date.now() + error.parameters.retry_after * 1_000);
|
|
228
|
+
logger.warn({
|
|
229
|
+
errorType: error instanceof Error ? error.name : "UnknownError",
|
|
230
|
+
errorCode: error instanceof GrammyError ? error.error_code : undefined,
|
|
231
|
+
}, "Telegram typing update failed; task continues");
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
await setTimeout(250);
|
|
235
|
+
}
|
|
160
236
|
})());
|
|
161
237
|
await Promise.all(workers);
|
|
162
238
|
}
|
package/dist/im/telegram.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/im/telegram.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAM/D,6CAA6C;AAC7C,MAAM,UAAU,wBAAwB,CACtC,MAA0B,EAC1B,aAA6B,EAC7B,KAAY,EACZ,MAAc;IAEd,gDAAgD;IAChD,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACtB,SAAS,EAAE,IAAI;QACf,QAAQ,EACN,MAAM,CAAC,QAAQ,KAAK,SAAS;YAC3B,CAAC,CAAC,OAAO,CAAC,GAAG;YACb,CAAC,CAAC,MAAM,CAAC,QAAQ;gBACf,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE;gBAClD,CAAC,CAAC,EAAE;KACX,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE;QAChC,MAAM,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE,KAAK,EAAE,EAAE;KAC3D,CAAC,CAAC;IACH,
|
|
1
|
+
{"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/im/telegram.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.js
CHANGED
package/dist/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,8CAA8C;AAC9C,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC;QACV,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,MAAM;QACb,MAAM,EAAE;YACN,KAAK,EAAE;gBACL,eAAe;gBACf,OAAO;gBACP,oBAAoB;gBACpB,eAAe;gBACf,QAAQ;gBACR,iBAAiB;gBACjB,SAAS;gBACT,sBAAsB;gBACtB,iBAAiB;gBACjB,UAAU;aACX;YACD,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,8CAA8C;AAC9C,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC;QACV,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,MAAM;QACb,MAAM,EAAE;YACN,KAAK,EAAE;gBACL,eAAe;gBACf,OAAO;gBACP,oBAAoB;gBACpB,eAAe;gBACf,QAAQ;gBACR,iBAAiB;gBACjB,SAAS;gBACT,sBAAsB;gBACtB,iBAAiB;gBACjB,UAAU;aACX;YACD,MAAM,EAAE,YAAY;SACrB;KACF,CAAC,CAAC;AACL,CAAC"}
|
package/dist/main.js
CHANGED
|
@@ -12,14 +12,14 @@ let store;
|
|
|
12
12
|
let im;
|
|
13
13
|
let relay;
|
|
14
14
|
let running = [];
|
|
15
|
-
let phase = "
|
|
15
|
+
let phase = "Loading config";
|
|
16
16
|
let stopping = false;
|
|
17
17
|
/** 两种退出信号共用关停入口;主流程等待消息处理和 Agent 退出后释放状态锁。 */
|
|
18
18
|
function stop() {
|
|
19
19
|
if (stopping)
|
|
20
20
|
return;
|
|
21
21
|
stopping = true;
|
|
22
|
-
logger.info("
|
|
22
|
+
logger.info("Stopping service");
|
|
23
23
|
im?.stop();
|
|
24
24
|
relay?.stop();
|
|
25
25
|
}
|
|
@@ -27,25 +27,25 @@ process.once("SIGINT", stop);
|
|
|
27
27
|
process.once("SIGTERM", stop);
|
|
28
28
|
try {
|
|
29
29
|
const config = loadConfig();
|
|
30
|
-
phase = "
|
|
30
|
+
phase = "Loading state";
|
|
31
31
|
store = openStore();
|
|
32
|
-
phase = "
|
|
32
|
+
phase = "Checking agent";
|
|
33
33
|
const agent = await createCodexAgent(config.codexPath);
|
|
34
|
-
logger.info({ agent: agent.name, version: agent.version }, "Agent CLI
|
|
34
|
+
logger.info({ agent: agent.name, version: agent.version }, "Agent CLI ready");
|
|
35
35
|
if (!stopping) {
|
|
36
36
|
relay = createRelayService({ store, agent, logger });
|
|
37
37
|
im = createTelegramConnection(config.telegram, relay.handleMessage, store, logger);
|
|
38
|
-
phase = "
|
|
38
|
+
phase = "Connecting Telegram";
|
|
39
39
|
const source = await im.initialize();
|
|
40
40
|
if (source && !stopping) {
|
|
41
41
|
/** systemctl start 等待实际初始化成功,避免把进程创建误报为服务就绪。 */
|
|
42
42
|
if (process.env.NOTIFY_SOCKET) {
|
|
43
|
-
phase = "
|
|
44
|
-
await promisify(execFile)("systemd-notify", ["--ready", "--status=Telegram
|
|
43
|
+
phase = "Notifying systemd";
|
|
44
|
+
await promisify(execFile)("systemd-notify", ["--ready", "--status=Telegram connected"], {
|
|
45
45
|
timeout: 5_000,
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
|
-
phase = "
|
|
48
|
+
phase = "Processing messages";
|
|
49
49
|
running = [im.start(), relay.run(source)];
|
|
50
50
|
await Promise.all(running);
|
|
51
51
|
}
|
|
@@ -61,9 +61,9 @@ catch (error) {
|
|
|
61
61
|
(typeof error.code === "string" || typeof error.code === "number")
|
|
62
62
|
? error.code
|
|
63
63
|
: undefined,
|
|
64
|
-
}, (phase === "
|
|
64
|
+
}, (phase === "Loading config" || phase === "Loading state") && error instanceof Error
|
|
65
65
|
? error.message
|
|
66
|
-
: "
|
|
66
|
+
: "Service failed");
|
|
67
67
|
}
|
|
68
68
|
finally {
|
|
69
69
|
im?.stop();
|
|
@@ -72,6 +72,6 @@ finally {
|
|
|
72
72
|
store?.close();
|
|
73
73
|
process.removeListener("SIGINT", stop);
|
|
74
74
|
process.removeListener("SIGTERM", stop);
|
|
75
|
-
logger.info("Tellrun
|
|
75
|
+
logger.info("Tellrun stopped");
|
|
76
76
|
}
|
|
77
77
|
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAc,MAAM,oBAAoB,CAAC;AAE3D,gCAAgC;AAChC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;AAC9B,IAAI,KAAwB,CAAC;AAC7B,IAAI,EAA2D,CAAC;AAChE,IAAI,KAAwD,CAAC;AAC7D,IAAI,OAAO,GAAoB,EAAE,CAAC;AAClC,IAAI,KAAK,GAAG,
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
|
package/dist/storage/schema.js
CHANGED
|
@@ -33,6 +33,13 @@ export const stateSchema = z
|
|
|
33
33
|
cwd: z.string(),
|
|
34
34
|
sessionId: z.string().nullable(),
|
|
35
35
|
prompt: z.string(),
|
|
36
|
+
/** 旧状态文件没有补充输入;发送中记录用于重启后避免不确定重放。 */
|
|
37
|
+
inputs: z
|
|
38
|
+
.array(z.strictObject({
|
|
39
|
+
text: z.string(),
|
|
40
|
+
status: z.enum(["pending", "sending", "accepted", "failed"]),
|
|
41
|
+
}))
|
|
42
|
+
.default([]),
|
|
36
43
|
status: z.enum([
|
|
37
44
|
"queued",
|
|
38
45
|
"dispatching",
|
|
@@ -63,5 +70,5 @@ export const stateSchema = z
|
|
|
63
70
|
state.tasks.every((row) => channels.has(row.channelId)) &&
|
|
64
71
|
state.outbox.every((row) => channels.has(row.channelId)) &&
|
|
65
72
|
state.tasks.filter((row) => activeTaskStatuses.has(row.status)).length <= 1);
|
|
66
|
-
}, "
|
|
73
|
+
}, "Invalid state IDs, references, or active task count.");
|
|
67
74
|
//# sourceMappingURL=schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/storage/schema.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/storage/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/storage/store.js
CHANGED
|
@@ -14,6 +14,8 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
14
14
|
let owned = false;
|
|
15
15
|
let usable = true;
|
|
16
16
|
let updating = false;
|
|
17
|
+
/** 流式预览只保留内存中的最新片段,不为每个文本增量写磁盘。 */
|
|
18
|
+
let draft;
|
|
17
19
|
/** 只删除本实例的所有权文件;非空目录不能被另一个退出中的实例移除。 */
|
|
18
20
|
function release() {
|
|
19
21
|
if (!owned)
|
|
@@ -38,7 +40,7 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
38
40
|
writeFileSync(join(lock, owner), "", { flag: "wx", mode: 0o600 });
|
|
39
41
|
owned = true;
|
|
40
42
|
if (readdirSync(lock).length !== 1)
|
|
41
|
-
throw new Error("
|
|
43
|
+
throw new Error("State lock busy. Try again.");
|
|
42
44
|
}
|
|
43
45
|
catch (error) {
|
|
44
46
|
if (owned || !(error instanceof Error && "code" in error && error.code === "EEXIST"))
|
|
@@ -52,7 +54,7 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
52
54
|
const previous = owners.length === 1 ? owners[0] : undefined;
|
|
53
55
|
const pid = previous?.match(/^([1-9]\d*)-[0-9a-f-]+$/)?.[1];
|
|
54
56
|
if (!previous || !pid)
|
|
55
|
-
throw new Error("
|
|
57
|
+
throw new Error("State lock initializing or invalid. Check for another instance.");
|
|
56
58
|
try {
|
|
57
59
|
process.kill(Number(pid), 0);
|
|
58
60
|
}
|
|
@@ -64,7 +66,7 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
64
66
|
rmdirSync(lock);
|
|
65
67
|
continue;
|
|
66
68
|
}
|
|
67
|
-
throw new Error("
|
|
69
|
+
throw new Error("Another Tellrun instance is running. Stop it first.");
|
|
68
70
|
}
|
|
69
71
|
catch (error) {
|
|
70
72
|
if (!(error instanceof Error &&
|
|
@@ -75,7 +77,7 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
79
|
if (!owned)
|
|
78
|
-
throw new Error("
|
|
80
|
+
throw new Error("Cannot acquire state lock. Try again.");
|
|
79
81
|
let state;
|
|
80
82
|
try {
|
|
81
83
|
const contents = readFileSync(path, "utf8");
|
|
@@ -83,7 +85,7 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
83
85
|
state = stateSchema.parse(JSON.parse(contents));
|
|
84
86
|
}
|
|
85
87
|
catch {
|
|
86
|
-
throw new Error("state.json
|
|
88
|
+
throw new Error("Invalid state.json; file unchanged. Check it or restore a backup.");
|
|
87
89
|
}
|
|
88
90
|
chmodSync(path, 0o600);
|
|
89
91
|
}
|
|
@@ -96,7 +98,7 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
96
98
|
/** 一次业务操作只保存一个快照;嵌套操作合并写入,失败时回滚内存并停止后续写入。 */
|
|
97
99
|
function update(action) {
|
|
98
100
|
if (!usable)
|
|
99
|
-
throw new Error("
|
|
101
|
+
throw new Error("State storage unavailable. Restart the service.");
|
|
100
102
|
if (updating)
|
|
101
103
|
return action();
|
|
102
104
|
const previous = state;
|
|
@@ -109,7 +111,7 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
109
111
|
}
|
|
110
112
|
catch (error) {
|
|
111
113
|
usable = false;
|
|
112
|
-
throw Object.assign(new Error("
|
|
114
|
+
throw Object.assign(new Error("Cannot save state. Check disk space and permissions.", { cause: error }), { code: "STATE_WRITE_FAILED" });
|
|
113
115
|
}
|
|
114
116
|
return structuredClone(result);
|
|
115
117
|
}
|
|
@@ -121,14 +123,16 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
121
123
|
updating = false;
|
|
122
124
|
}
|
|
123
125
|
}
|
|
124
|
-
/**
|
|
126
|
+
/** 无回复时跳过入队;其余按 Unicode 字符拆分,和触发它的状态变更一起保存。 */
|
|
125
127
|
function enqueueReply(channelId, text) {
|
|
126
|
-
|
|
128
|
+
if (text === undefined)
|
|
129
|
+
return;
|
|
130
|
+
const parts = text.match(/[\s\S]{1,2000}/gu) ?? ["(No text reply)"];
|
|
127
131
|
for (const [index, part] of parts.entries()) {
|
|
128
132
|
state.outbox.push({
|
|
129
133
|
id: state.outbox.reduce((max, item) => Math.max(max, item.id), 0) + 1,
|
|
130
134
|
channelId,
|
|
131
|
-
text: parts.length > 1 ?
|
|
135
|
+
text: parts.length > 1 ? `(${index + 1}/${parts.length})\n${part}` : part,
|
|
132
136
|
attempts: 0,
|
|
133
137
|
retryAt: Date.now(),
|
|
134
138
|
});
|
|
@@ -141,23 +145,31 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
141
145
|
update(() => {
|
|
142
146
|
const task = state.tasks.find((task) => task.id === id);
|
|
143
147
|
if (!task)
|
|
144
|
-
throw new Error("
|
|
148
|
+
throw new Error("Task not found.");
|
|
145
149
|
Object.assign(task, { status: result.status, result: result.text });
|
|
146
150
|
if (result.status === "interrupted") {
|
|
147
151
|
const channel = state.channels.find((channel) => channel.id === task.channelId);
|
|
148
152
|
if (channel)
|
|
149
153
|
channel.paused = true;
|
|
150
154
|
}
|
|
151
|
-
enqueueReply(task.channelId,
|
|
152
|
-
completed: "
|
|
153
|
-
failed: "
|
|
154
|
-
cancelled: "
|
|
155
|
-
interrupted: "
|
|
155
|
+
enqueueReply(task.channelId, `Task #${id} ${{
|
|
156
|
+
completed: "Completed",
|
|
157
|
+
failed: "Failed",
|
|
158
|
+
cancelled: "Stopped",
|
|
159
|
+
interrupted: "Unconfirmed",
|
|
156
160
|
}[result.status]}\n${result.text}`);
|
|
161
|
+
for (const [index, input] of task.inputs.entries()) {
|
|
162
|
+
if (input.status !== "pending" && input.status !== "sending")
|
|
163
|
+
continue;
|
|
164
|
+
enqueueReply(task.channelId, `Task #${id}, message ${index + 1}: ${input.status === "pending" ? "not sent" : "delivery unconfirmed"}. Task ended; not retried. Check the session before resending.`);
|
|
165
|
+
input.status = "failed";
|
|
166
|
+
}
|
|
157
167
|
});
|
|
168
|
+
if (draft?.taskId === id)
|
|
169
|
+
draft = undefined;
|
|
158
170
|
}
|
|
159
171
|
return {
|
|
160
|
-
/**
|
|
172
|
+
/** 去重标识、任务和必要回复合并保存,成功返回后才能确认入站事件。 */
|
|
161
173
|
accept(message, handle) {
|
|
162
174
|
const existing = state.channels.find((channel) => channel.platform === message.channel.platform &&
|
|
163
175
|
channel.accountId === message.channel.accountId &&
|
|
@@ -205,6 +217,22 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
205
217
|
activeTask() {
|
|
206
218
|
return structuredClone(state.tasks.find((task) => activeTaskStatuses.has(task.status)));
|
|
207
219
|
},
|
|
220
|
+
/** 限制预览为末尾 2000 个 Unicode 字符,完整结果仍由最终回复保存。 */
|
|
221
|
+
setDraft(id, text) {
|
|
222
|
+
if (state.tasks.some((task) => task.id === id && task.status === "running"))
|
|
223
|
+
draft = { taskId: id, text: [...text].slice(-2000).join("") };
|
|
224
|
+
},
|
|
225
|
+
/** 仅向当前机器人与授权用户返回执行中的草稿,停止后不再刷新。 */
|
|
226
|
+
pendingDraft(accountId, userId) {
|
|
227
|
+
if (!draft?.text.trim())
|
|
228
|
+
return;
|
|
229
|
+
const task = state.tasks.find((task) => task.id === draft?.taskId && task.status === "running");
|
|
230
|
+
const channel = state.channels.find((channel) => channel.id === task?.channelId);
|
|
231
|
+
if (channel?.platform === "telegram" &&
|
|
232
|
+
channel.accountId === accountId &&
|
|
233
|
+
channel.userId === userId)
|
|
234
|
+
return { ...draft, chatId: channel.chatId };
|
|
235
|
+
},
|
|
208
236
|
/** 最近结果按聊天隔离,供 /last 再次查看。 */
|
|
209
237
|
lastTask(channelId) {
|
|
210
238
|
return structuredClone(state.tasks.findLast((task) => task.channelId === channelId));
|
|
@@ -213,15 +241,16 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
213
241
|
createTask(channel, prompt) {
|
|
214
242
|
return update(() => {
|
|
215
243
|
if (!channel.cwd)
|
|
216
|
-
throw new Error("
|
|
244
|
+
throw new Error("Set a working directory first.");
|
|
217
245
|
if (state.tasks.some((task) => activeTaskStatuses.has(task.status)))
|
|
218
|
-
throw new Error("
|
|
246
|
+
throw new Error("A task is already running.");
|
|
219
247
|
const task = {
|
|
220
248
|
id: state.tasks.reduce((max, item) => Math.max(max, item.id), 0) + 1,
|
|
221
249
|
channelId: channel.id,
|
|
222
250
|
cwd: channel.cwd,
|
|
223
251
|
sessionId: channel.sessionId,
|
|
224
252
|
prompt,
|
|
253
|
+
inputs: [],
|
|
225
254
|
status: "queued",
|
|
226
255
|
result: null,
|
|
227
256
|
};
|
|
@@ -229,6 +258,44 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
229
258
|
return task;
|
|
230
259
|
});
|
|
231
260
|
},
|
|
261
|
+
/** 尚未派发时合并首条输入;执行中的补充输入与入站去重标识一起保存。 */
|
|
262
|
+
appendTaskInput(id, text) {
|
|
263
|
+
update(() => {
|
|
264
|
+
const task = state.tasks.find((task) => task.id === id);
|
|
265
|
+
if (!task || !["queued", "dispatching", "running"].includes(task.status))
|
|
266
|
+
throw new Error("Task cannot accept more input.");
|
|
267
|
+
if (task.status === "queued")
|
|
268
|
+
task.prompt += `\n\n${text}`;
|
|
269
|
+
else
|
|
270
|
+
task.inputs.push({ text, status: "pending" });
|
|
271
|
+
});
|
|
272
|
+
},
|
|
273
|
+
/** 取得当前轮次后按接收顺序派发,先落盘 sending,不能自动重试不确定输入。 */
|
|
274
|
+
claimTaskInput(id) {
|
|
275
|
+
const task = state.tasks.find((task) => task.id === id && task.status === "running");
|
|
276
|
+
const index = task?.inputs.findIndex((input) => input.status === "pending") ?? -1;
|
|
277
|
+
if (!task || index < 0)
|
|
278
|
+
return;
|
|
279
|
+
return update(() => {
|
|
280
|
+
const input = state.tasks.find((task) => task.id === id)?.inputs[index];
|
|
281
|
+
if (!input)
|
|
282
|
+
throw new Error("Input not found.");
|
|
283
|
+
input.status = "sending";
|
|
284
|
+
return { index, text: input.text };
|
|
285
|
+
});
|
|
286
|
+
},
|
|
287
|
+
/** 成功补充不产生固定回执,失败提示和输入状态原子保存。 */
|
|
288
|
+
finishTaskInput(id, index, error) {
|
|
289
|
+
update(() => {
|
|
290
|
+
const task = state.tasks.find((task) => task.id === id);
|
|
291
|
+
const input = task?.inputs[index];
|
|
292
|
+
if (!task || input?.status !== "sending")
|
|
293
|
+
return;
|
|
294
|
+
input.status = error === undefined ? "accepted" : "failed";
|
|
295
|
+
if (error !== undefined)
|
|
296
|
+
enqueueReply(task.channelId, `Task #${id}, message ${index + 1}: ${error}`);
|
|
297
|
+
});
|
|
298
|
+
},
|
|
232
299
|
/** 先保存派发状态再调用 Agent;空闲时仅查询,不反复写文件。 */
|
|
233
300
|
claimTask(source) {
|
|
234
301
|
const index = state.tasks.findIndex((task) => task.status === "queued");
|
|
@@ -270,7 +337,7 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
270
337
|
/** 未派发任务直接取消;其余等待 Agent 确认终态。 */
|
|
271
338
|
cancelTask(id) {
|
|
272
339
|
if (state.tasks.find((task) => task.id === id)?.status === "queued") {
|
|
273
|
-
finishTask(id, { status: "cancelled", text: "
|
|
340
|
+
finishTask(id, { status: "cancelled", text: "Cancelled before starting." });
|
|
274
341
|
}
|
|
275
342
|
else
|
|
276
343
|
update(() => {
|
|
@@ -285,7 +352,7 @@ export function openStore(path = join(appDirectory, "state.json")) {
|
|
|
285
352
|
for (const task of state.tasks.filter((task) => activeTaskStatuses.has(task.status) && task.status !== "queued")) {
|
|
286
353
|
finishTask(task.id, {
|
|
287
354
|
status: "interrupted",
|
|
288
|
-
text: "
|
|
355
|
+
text: "Service restarted; task result unknown. Check the project, then /resume and send a new task.",
|
|
289
356
|
});
|
|
290
357
|
}
|
|
291
358
|
},
|