@geminixiang/mikan 1.5.0 → 1.5.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 +23 -0
- package/dist/adapters/messages.d.ts +1 -2
- package/dist/adapters/messages.d.ts.map +1 -1
- package/dist/adapters/messages.js +2 -5
- package/dist/adapters/messages.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +2 -2
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +36 -50
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/harness/continued-run.d.ts +3 -0
- package/dist/harness/continued-run.d.ts.map +1 -0
- package/dist/harness/continued-run.js +8 -0
- package/dist/harness/continued-run.js.map +1 -0
- package/dist/harness/prompt.d.ts.map +1 -1
- package/dist/harness/prompt.js +1 -0
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +14 -7
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/session.d.ts +3 -0
- package/dist/harness/session.d.ts.map +1 -1
- package/dist/harness/session.js +14 -1
- package/dist/harness/session.js.map +1 -1
- package/dist/harness/tools/codemode.js +1 -1
- package/dist/harness/tools/codemode.js.map +1 -1
- package/dist/harness/tools/jev-browser.d.ts.map +1 -1
- package/dist/harness/tools/jev-browser.js +31 -6
- package/dist/harness/tools/jev-browser.js.map +1 -1
- package/dist/harness/tools/task.d.ts +0 -2
- package/dist/harness/tools/task.d.ts.map +1 -1
- package/dist/harness/tools/task.js +1 -6
- package/dist/harness/tools/task.js.map +1 -1
- package/dist/runtime/conversation-runtime.d.ts.map +1 -1
- package/dist/runtime/conversation-runtime.js +6 -3
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/sessions/session-store.d.ts +4 -3
- package/dist/sessions/session-store.d.ts.map +1 -1
- package/dist/sessions/session-store.js +92 -47
- package/dist/sessions/session-store.js.map +1 -1
- package/dist/sessions/types.d.ts +0 -1
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,29 @@ change in a minor release.
|
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
+
## [1.5.1] - 2026-10-14
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- A Slack reply or task that a restart interrupts now continues after the restart instead of
|
|
19
|
+
stopping with its progress message stuck: mikan posts "Restarted for an update; continuing." and
|
|
20
|
+
pi-durable continues the same turn, telling the model which step was interrupted. A deploy no
|
|
21
|
+
longer waits up to five minutes for Slack runs to finish. Tasks continue the same way, without the
|
|
22
|
+
earlier limit of two automatic resumes. Other platforms keep the five-minute drain.
|
|
23
|
+
- A codemode script has no deadline unless it sets `timeout_ms`, as in Pi. Before, mikan stopped
|
|
24
|
+
every script after 60 seconds, which cut off scripts that call slow tools such as
|
|
25
|
+
`jev_browser`'s goal loop. A stuck script now runs until the conversation is stopped, or until
|
|
26
|
+
the run's budget ends it where one is set, as for scheduled events.
|
|
27
|
+
- `jev_browser` with only `url` opens the page and returns its final URL and title, for example to
|
|
28
|
+
show it on the office desktop. Before, it refused the call, and models made up a goal that ran the
|
|
29
|
+
slower goal loop.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- `jev_browser` no longer refuses a call because the model filled `handOff` with an empty string,
|
|
34
|
+
as models that fill every optional field do; an empty `handOff` and `frame: "main"` count as not
|
|
35
|
+
given.
|
|
36
|
+
|
|
14
37
|
## [1.5.0] - 2026-10-13
|
|
15
38
|
|
|
16
39
|
### Added
|
|
@@ -5,8 +5,7 @@ export declare function formatNothingRunning(source: PlatformSource): string;
|
|
|
5
5
|
export declare function formatStopping(source: PlatformSource): string;
|
|
6
6
|
export declare function formatStopped(source: PlatformSource): string;
|
|
7
7
|
export declare function formatRestarting(source: PlatformSource): string;
|
|
8
|
-
export declare function
|
|
9
|
-
export declare function formatTaskResumesExhausted(source: PlatformSource): string;
|
|
8
|
+
export declare function formatContinuingRun(source: PlatformSource): string;
|
|
10
9
|
export declare function formatAlreadyWorking(source: PlatformSource, stopCommand: string, options?: {
|
|
11
10
|
scope?: "thread";
|
|
12
11
|
}): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/adapters/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE/D,eAAO,MAAM,YAAY,UAAU,CAAC;AAEpC,KAAK,cAAc,GAAG,YAAY,GAAG,aAAa,GAAG,MAAM,CAAC;AAoB5D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAEnE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAE7D;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAE5D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAK/D;AAED,wBAAgB,
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/adapters/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE/D,eAAO,MAAM,YAAY,UAAU,CAAC;AAEpC,KAAK,cAAc,GAAG,YAAY,GAAG,aAAa,GAAG,MAAM,CAAC;AAoB5D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAEnE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAE7D;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAE5D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAK/D;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAElE;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,QAAQ,CAAA;CAAE,GAC7B,MAAM,CAMR"}
|
|
@@ -27,11 +27,8 @@ export function formatStopped(source) {
|
|
|
27
27
|
export function formatRestarting(source) {
|
|
28
28
|
return formatItalic(resolvePlatformName(source), "Restarting for an update; this reply was interrupted. Please send your message again.");
|
|
29
29
|
}
|
|
30
|
-
export function
|
|
31
|
-
return formatItalic(resolvePlatformName(source), "Restarted for an update; continuing
|
|
32
|
-
}
|
|
33
|
-
export function formatTaskResumesExhausted(source) {
|
|
34
|
-
return formatItalic(resolvePlatformName(source), "Interrupted again after two automatic restarts; not continuing this task. Ask me to continue when you are ready.");
|
|
30
|
+
export function formatContinuingRun(source) {
|
|
31
|
+
return formatItalic(resolvePlatformName(source), "Restarted for an update; continuing.");
|
|
35
32
|
}
|
|
36
33
|
export function formatAlreadyWorking(source, stopCommand, options) {
|
|
37
34
|
const platformName = resolvePlatformName(source);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/adapters/messages.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC;AAIpC,SAAS,mBAAmB,CAAC,MAAsB;IACjD,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,kBAAkB,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,gBAAgB,EAAE,CAAC,IAAI,CAAC;IACxE,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,SAAS,sBAAsB,CAAC,YAAoB;IAClD,OAAO,YAAY,KAAK,UAAU,CAAC;AACrC,CAAC;AAED,SAAS,YAAY,CAAC,YAAoB,EAAE,IAAY;IACtD,OAAO,sBAAsB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC;AACnE,CAAC;AAED,SAAS,UAAU,CAAC,YAAoB,EAAE,IAAY;IACpD,OAAO,sBAAsB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC;AACvF,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAsB;IACzD,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAsB;IACnD,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAsB;IAClD,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,OAAO,YAAY,CACjB,mBAAmB,CAAC,MAAM,CAAC,EAC3B,uFAAuF,CACxF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/adapters/messages.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC;AAIpC,SAAS,mBAAmB,CAAC,MAAsB;IACjD,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,kBAAkB,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,gBAAgB,EAAE,CAAC,IAAI,CAAC;IACxE,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,SAAS,sBAAsB,CAAC,YAAoB;IAClD,OAAO,YAAY,KAAK,UAAU,CAAC;AACrC,CAAC;AAED,SAAS,YAAY,CAAC,YAAoB,EAAE,IAAY;IACtD,OAAO,sBAAsB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC;AACnE,CAAC;AAED,SAAS,UAAU,CAAC,YAAoB,EAAE,IAAY;IACpD,OAAO,sBAAsB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC;AACvF,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAsB;IACzD,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAsB;IACnD,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAsB;IAClD,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,OAAO,YAAY,CACjB,mBAAmB,CAAC,MAAM,CAAC,EAC3B,uFAAuF,CACxF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAsB;IACxD,OAAO,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,sCAAsC,CAAC,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,MAAsB,EACtB,WAAmB,EACnB,OAA8B;IAE9B,MAAM,YAAY,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,UAAU,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACtD,MAAM,MAAM,GACV,OAAO,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,kBAAkB,CAAC;IACvF,OAAO,YAAY,CAAC,YAAY,EAAE,GAAG,MAAM,SAAS,OAAO,aAAa,CAAC,CAAC;AAC5E,CAAC","sourcesContent":["import type { MessagingBot, MessagingInfo } from \"../types.js\";\n\nexport const PRODUCT_NAME = \"mikan\";\n\ntype PlatformSource = MessagingBot | MessagingInfo | string;\n\nfunction resolvePlatformName(source: PlatformSource): string {\n if (typeof source === \"string\") return source;\n if (\"getMessagingInfo\" in source) return source.getMessagingInfo().name;\n return source.name;\n}\n\nfunction supportsHtmlFormatting(platformName: string): boolean {\n return platformName === \"telegram\";\n}\n\nfunction formatItalic(platformName: string, text: string): string {\n return supportsHtmlFormatting(platformName) ? text : `_${text}_`;\n}\n\nfunction formatCode(platformName: string, text: string): string {\n return supportsHtmlFormatting(platformName) ? `<code>${text}</code>` : `\\`${text}\\``;\n}\n\nexport function formatNothingRunning(source: PlatformSource): string {\n return formatItalic(resolvePlatformName(source), \"Nothing running.\");\n}\n\nexport function formatStopping(source: PlatformSource): string {\n return formatItalic(resolvePlatformName(source), \"Stopping…\");\n}\n\nexport function formatStopped(source: PlatformSource): string {\n return formatItalic(resolvePlatformName(source), \"Stopped.\");\n}\n\nexport function formatRestarting(source: PlatformSource): string {\n return formatItalic(\n resolvePlatformName(source),\n \"Restarting for an update; this reply was interrupted. Please send your message again.\",\n );\n}\n\nexport function formatContinuingRun(source: PlatformSource): string {\n return formatItalic(resolvePlatformName(source), \"Restarted for an update; continuing.\");\n}\n\nexport function formatAlreadyWorking(\n source: PlatformSource,\n stopCommand: string,\n options?: { scope?: \"thread\" },\n): string {\n const platformName = resolvePlatformName(source);\n const command = formatCode(platformName, stopCommand);\n const prefix =\n options?.scope === \"thread\" ? \"Already working in this thread.\" : \"Already working.\";\n return formatItalic(platformName, `${prefix} Send ${command} to cancel.`);\n}\n"]}
|
|
@@ -26,7 +26,6 @@ export declare class SlackMessagingBot implements MessagingBot {
|
|
|
26
26
|
private streamStarts;
|
|
27
27
|
private stopped;
|
|
28
28
|
private queues;
|
|
29
|
-
private readonly taskQueueKeys;
|
|
30
29
|
private intake;
|
|
31
30
|
private readonly recentMessageKeys;
|
|
32
31
|
private agentSurfaceUnavailable;
|
|
@@ -83,7 +82,8 @@ export declare class SlackMessagingBot implements MessagingBot {
|
|
|
83
82
|
private getQueue;
|
|
84
83
|
private resolveQueueKey;
|
|
85
84
|
private enqueueTaskRun;
|
|
86
|
-
private
|
|
85
|
+
private continueInterruptedRuns;
|
|
86
|
+
private enqueueContinuation;
|
|
87
87
|
private isTaskThread;
|
|
88
88
|
private hasRunningTaskThread;
|
|
89
89
|
private hasKnownThreadSession;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../../../src/adapters/slack/bot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../../../src/adapters/slack/bot.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { appendBotResponseLog, appendOfficeLog, readOfficeLog } from "../../office/log.js";
|
|
2
2
|
import { SessionStore } from "../../sessions/session-store.js";
|
|
3
|
-
import {
|
|
3
|
+
import { taskRunId } from "../../harness/tools/task.js";
|
|
4
|
+
import { continuedRunId } from "../../harness/continued-run.js";
|
|
4
5
|
import { SocketModeClient } from "@slack/socket-mode";
|
|
5
6
|
import { WebAPIRateLimitedError, WebClient } from "@slack/web-api";
|
|
6
7
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -12,7 +13,7 @@ import { evaluateWithJev, JevNotConfiguredError } from "../../harness/jev.js";
|
|
|
12
13
|
import * as log from "../../log.js";
|
|
13
14
|
import { SlackSocketAgent } from "./socket-agent.js";
|
|
14
15
|
import { readTextFileNoFollowIfExists } from "../../file-guards.js";
|
|
15
|
-
import {
|
|
16
|
+
import { formatContinuingRun } from "../messages.js";
|
|
16
17
|
import { MessagingEventQueue, MessagingIntakeTracker, AttachmentRejectedError, saveIncomingAttachments, writeResponseToFile, withRetry, } from "../shared.js";
|
|
17
18
|
import { matchMagicWord, processMessageIntake } from "../intake.js";
|
|
18
19
|
import { readPlatformChannelKind, recordPlatformChannelKind } from "../../office/projection.js";
|
|
@@ -29,8 +30,6 @@ import { buildTaskIntentState, classifyTaskIntent } from "./task-intent.js";
|
|
|
29
30
|
import { StreamStartLimiter } from "./stream-limits.js";
|
|
30
31
|
import { errorMessage, isRecord } from "../../unknown-values.js";
|
|
31
32
|
const SLACK_EVENT_ANCHOR_TEXT = "Working on it...";
|
|
32
|
-
const TASK_RESUME_WINDOW_MS = 24 * 60 * 60 * 1000;
|
|
33
|
-
const MAX_TASK_RESUMES = 2;
|
|
34
33
|
function hasMessageContent(message, includeBlocks = true) {
|
|
35
34
|
const content = [message.text, message.files];
|
|
36
35
|
if (includeBlocks)
|
|
@@ -220,7 +219,6 @@ export class SlackMessagingBot {
|
|
|
220
219
|
this.streamStarts = new StreamStartLimiter();
|
|
221
220
|
this.stopped = false;
|
|
222
221
|
this.queues = new Map();
|
|
223
|
-
this.taskQueueKeys = new Set();
|
|
224
222
|
this.intake = new MessagingIntakeTracker("Slack");
|
|
225
223
|
this.recentMessageKeys = new Set();
|
|
226
224
|
this.agentSurfaceUnavailable = false;
|
|
@@ -259,6 +257,9 @@ export class SlackMessagingBot {
|
|
|
259
257
|
log.logInfo(`Loaded ${this.channels.size} channels, ${this.users.size} users`);
|
|
260
258
|
this.backfillChannelKinds();
|
|
261
259
|
this.startupTs = (Date.now() / 1000).toFixed(6);
|
|
260
|
+
await this.continueInterruptedRuns().catch((error) => {
|
|
261
|
+
log.logWarning("Could not continue interrupted runs", errorMessage(error));
|
|
262
|
+
});
|
|
262
263
|
this.setupEventHandlers();
|
|
263
264
|
try {
|
|
264
265
|
await this.socketClient.start();
|
|
@@ -269,9 +270,6 @@ export class SlackMessagingBot {
|
|
|
269
270
|
throw error;
|
|
270
271
|
}
|
|
271
272
|
log.logConnected("Slack");
|
|
272
|
-
void this.resumeInterruptedTasks().catch((error) => {
|
|
273
|
-
log.logWarning("Could not resume interrupted tasks", String(error));
|
|
274
|
-
});
|
|
275
273
|
void this.backfillAllChannels(this.startupTs).catch((error) => {
|
|
276
274
|
log.logWarning("Slack backfill failed", String(error));
|
|
277
275
|
});
|
|
@@ -283,11 +281,8 @@ export class SlackMessagingBot {
|
|
|
283
281
|
}
|
|
284
282
|
finally {
|
|
285
283
|
await this.intake.close();
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
closed: queue.close(),
|
|
289
|
-
}));
|
|
290
|
-
await Promise.all(closing.filter(({ waits }) => waits).map(({ closed }) => closed));
|
|
284
|
+
for (const queue of this.queues.values())
|
|
285
|
+
void queue.close();
|
|
291
286
|
}
|
|
292
287
|
}
|
|
293
288
|
getUser(userId) {
|
|
@@ -575,6 +570,7 @@ export class SlackMessagingBot {
|
|
|
575
570
|
name: "slack",
|
|
576
571
|
workspaceId: this.teamId || undefined,
|
|
577
572
|
trustModel: "membership",
|
|
573
|
+
continuesInterruptedRuns: true,
|
|
578
574
|
formattingGuide: "## Slack Formatting\nWrite standard Markdown/GFM: **bold**, _italic_, ~~strike~~, `code`, fenced code blocks, [links](url), lists, and pipe tables (rendered as native Slack tables).\nDo NOT use Slack mrkdwn syntax like *single-asterisk bold* or <url|label> links.",
|
|
579
575
|
channels: this.getAllChannels().map((c) => ({ id: c.id, name: c.name })),
|
|
580
576
|
users: this.getAllUsers().map((u) => ({
|
|
@@ -676,7 +672,6 @@ export class SlackMessagingBot {
|
|
|
676
672
|
}
|
|
677
673
|
enqueueTaskRun(child) {
|
|
678
674
|
const { channel, thread_ts: root, sessionKey } = child;
|
|
679
|
-
this.taskQueueKeys.add(sessionKey);
|
|
680
675
|
const enqueued = this.getQueue(sessionKey).enqueue(async () => {
|
|
681
676
|
try {
|
|
682
677
|
await this.handler.handleEvent({
|
|
@@ -703,53 +698,44 @@ export class SlackMessagingBot {
|
|
|
703
698
|
if (!enqueued)
|
|
704
699
|
throw new Error("Task queue is closed.");
|
|
705
700
|
}
|
|
706
|
-
async
|
|
707
|
-
|
|
708
|
-
let resumed = 0;
|
|
701
|
+
async continueInterruptedRuns() {
|
|
702
|
+
let continued = 0;
|
|
709
703
|
for (const channelId of this.channels.keys()) {
|
|
710
704
|
if (this.stopped)
|
|
711
705
|
return;
|
|
712
|
-
if (this.channelKindFor(channelId) !== "im")
|
|
713
|
-
continue;
|
|
714
706
|
const office = this.office(channelId);
|
|
715
|
-
const
|
|
716
|
-
|
|
717
|
-
return ref.kind === "thread" && Number(ref.threadTs) * 1000 >= since
|
|
718
|
-
? [[task.sessionKey, ref.threadTs]]
|
|
719
|
-
: [];
|
|
720
|
-
}));
|
|
721
|
-
if (keys.size === 0)
|
|
722
|
-
continue;
|
|
723
|
-
const interrupted = await SessionStore.interruptedSince(office, [...keys.keys()], since);
|
|
724
|
-
if (interrupted.length === 0)
|
|
707
|
+
const sessionKeys = await SessionStore.continueInterrupted(office);
|
|
708
|
+
if (sessionKeys.length === 0)
|
|
725
709
|
continue;
|
|
726
|
-
const
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
const
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
await this.postInThread(channelId, root, formatResumingTask(this));
|
|
738
|
-
this.enqueueTaskRun({
|
|
739
|
-
type: "dm",
|
|
740
|
-
conversationKind: "direct",
|
|
710
|
+
const entries = readOfficeLog(office);
|
|
711
|
+
for (const sessionKey of sessionKeys) {
|
|
712
|
+
const ref = parseSlackSessionKey(sessionKey);
|
|
713
|
+
const threadTs = ref.kind === "thread" ? ref.threadTs : undefined;
|
|
714
|
+
const user = entries.findLast((entry) => !entry.isMessagingBot && entry.user && entry.sessionKey === sessionKey)?.user ??
|
|
715
|
+
entries.findLast((entry) => !entry.isMessagingBot && entry.user)?.user ??
|
|
716
|
+
"";
|
|
717
|
+
const direct = this.channelKindFor(channelId) === "im";
|
|
718
|
+
this.enqueueContinuation({
|
|
719
|
+
type: direct ? "dm" : "mention",
|
|
720
|
+
conversationKind: direct ? "direct" : "shared",
|
|
741
721
|
address: createOfficeAddress("slack", channelId),
|
|
742
722
|
channel: channelId,
|
|
743
|
-
user
|
|
744
|
-
ts:
|
|
745
|
-
thread_ts:
|
|
723
|
+
user,
|
|
724
|
+
ts: continuedRunId(sessionKey),
|
|
725
|
+
thread_ts: threadTs,
|
|
746
726
|
sessionKey,
|
|
747
|
-
text:
|
|
727
|
+
text: formatContinuingRun(this),
|
|
748
728
|
});
|
|
749
|
-
|
|
729
|
+
continued += 1;
|
|
750
730
|
}
|
|
751
731
|
}
|
|
752
|
-
log.logInfo(`
|
|
732
|
+
log.logInfo(`Continued ${continued} interrupted runs`);
|
|
733
|
+
}
|
|
734
|
+
enqueueContinuation(event) {
|
|
735
|
+
void (event.thread_ts
|
|
736
|
+
? this.postInThread(event.channel, event.thread_ts, event.text)
|
|
737
|
+
: this.postMessage(event.channel, event.text)).catch((error) => log.logWarning("Could not post the continuation notice", errorMessage(error)));
|
|
738
|
+
this.getQueue(event.sessionKey).enqueue(() => this.handler.handleEvent({ ...event, attachments: undefined }, this, this.createContext(event)));
|
|
753
739
|
}
|
|
754
740
|
isTaskThread(channel, root) {
|
|
755
741
|
return SessionStore.isTask(this.office(channel), resolveSlackSessionKey(channel, root));
|