dsh-connect 0.6.7 → 0.7.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/lib/binding.d.ts +2 -0
- package/lib/binding.d.ts.map +1 -1
- package/lib/binding.js +1 -1
- package/lib/binding.js.map +1 -1
- package/lib/commands.d.ts +10 -1
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +18 -6
- package/lib/commands.js.map +1 -1
- package/lib/dedup.d.ts +31 -0
- package/lib/dedup.d.ts.map +1 -0
- package/lib/dedup.js +52 -0
- package/lib/dedup.js.map +1 -0
- package/lib/i18n.d.ts +17 -1
- package/lib/i18n.d.ts.map +1 -1
- package/lib/i18n.js +34 -2
- package/lib/i18n.js.map +1 -1
- package/lib/index.d.ts +7 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -0
- package/lib/index.js.map +1 -1
- package/lib/mirror-lock.d.ts +51 -0
- package/lib/mirror-lock.d.ts.map +1 -0
- package/lib/mirror-lock.js +56 -0
- package/lib/mirror-lock.js.map +1 -0
- package/lib/retry.d.ts +35 -0
- package/lib/retry.d.ts.map +1 -0
- package/lib/retry.js +41 -0
- package/lib/retry.js.map +1 -0
- package/lib/runner.d.ts +42 -6
- package/lib/runner.d.ts.map +1 -1
- package/lib/runner.js +214 -106
- package/lib/runner.js.map +1 -1
- package/lib/scheduler.d.ts +46 -0
- package/lib/scheduler.d.ts.map +1 -0
- package/lib/scheduler.js +162 -0
- package/lib/scheduler.js.map +1 -0
- package/lib/service.d.ts +27 -0
- package/lib/service.d.ts.map +1 -1
- package/lib/service.js +106 -3
- package/lib/service.js.map +1 -1
- package/lib/types.d.ts +8 -0
- package/lib/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure lock-state machine for the Feishu ↔ Web mirror mutual exclusion.
|
|
3
|
+
*
|
|
4
|
+
* A mirrored chat has two writers: the Feishu runner (chat side) and the Web
|
|
5
|
+
* GUI (which reads/writes the shared DSH session directly). The `lockOwner`
|
|
6
|
+
* field on a binding records which channel currently owns write access so the
|
|
7
|
+
* two sides do not drive the same session concurrently. This module contains
|
|
8
|
+
* every transition as a pure function over a `LockState`-shaped object — no
|
|
9
|
+
* I/O, no adapter calls — so the state machine is unit-testable in isolation.
|
|
10
|
+
* @module dsh-connect/mirror-lock
|
|
11
|
+
*/
|
|
12
|
+
/** Default lock timeout (5 minutes) when a binding has no explicit timeout. */
|
|
13
|
+
export declare const DEFAULT_LOCK_TIMEOUT_MS: number;
|
|
14
|
+
/** One message parked in `queuedMessages` while the session lock is held. */
|
|
15
|
+
export interface QueuedMessage {
|
|
16
|
+
text: string;
|
|
17
|
+
senderKey: string;
|
|
18
|
+
timestamp: number;
|
|
19
|
+
replyRef?: string;
|
|
20
|
+
images?: readonly string[];
|
|
21
|
+
files?: readonly string[];
|
|
22
|
+
/** Channel the message originated on; used when replaying after lock release. */
|
|
23
|
+
channel?: string;
|
|
24
|
+
}
|
|
25
|
+
/** The lock-related slice of a `ChatBinding` (structural; keeps this module decoupled). */
|
|
26
|
+
export interface LockState {
|
|
27
|
+
lockOwner?: "feishu" | "web";
|
|
28
|
+
lockAcquiredAt?: number;
|
|
29
|
+
lockTimeoutMs?: number;
|
|
30
|
+
queuedMessages?: QueuedMessage[];
|
|
31
|
+
}
|
|
32
|
+
/** True when a lock exists and its acquisition timestamp is older than its timeout. */
|
|
33
|
+
export declare function isLockTimedOut(state: LockState, now?: number): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Whether `channel` may write to the session. A timed-out lock counts as
|
|
36
|
+
* free (the caller normally releases it and notifies the user).
|
|
37
|
+
*/
|
|
38
|
+
export declare function canWrite(state: LockState, channel: "feishu" | "web", now?: number): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Acquire (or renew) the lock for `channel`. Returns the next state when the
|
|
41
|
+
* lock is free, timed out, or already owned by `channel`; `undefined` when a
|
|
42
|
+
* different channel currently holds a live lock. Generic over the full state
|
|
43
|
+
* object so callers keep their complete binding type.
|
|
44
|
+
*/
|
|
45
|
+
export declare function acquire<S extends LockState>(state: S, channel: "feishu" | "web", now?: number): S | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Release the lock, preserving every other field (including the parked queue —
|
|
48
|
+
* the caller drains `queuedMessages` before or after releasing).
|
|
49
|
+
*/
|
|
50
|
+
export declare function release<S extends LockState>(state: S): S;
|
|
51
|
+
//# sourceMappingURL=mirror-lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mirror-lock.d.ts","sourceRoot":"","sources":["../src/mirror-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,+EAA+E;AAC/E,eAAO,MAAM,uBAAuB,QAAgB,CAAC;AAErD,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,2FAA2F;AAC3F,MAAM,WAAW,SAAS;IACxB,SAAS,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;CAClC;AAED,uFAAuF;AACvF,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,SAAa,GAAG,OAAO,CAI1E;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,GAAG,KAAK,EAAE,GAAG,SAAa,GAAG,OAAO,CAI/F;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,GAAG,KAAK,EAAE,GAAG,SAAa,GAAG,CAAC,GAAG,SAAS,CAUjH;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAExD"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure lock-state machine for the Feishu ↔ Web mirror mutual exclusion.
|
|
3
|
+
*
|
|
4
|
+
* A mirrored chat has two writers: the Feishu runner (chat side) and the Web
|
|
5
|
+
* GUI (which reads/writes the shared DSH session directly). The `lockOwner`
|
|
6
|
+
* field on a binding records which channel currently owns write access so the
|
|
7
|
+
* two sides do not drive the same session concurrently. This module contains
|
|
8
|
+
* every transition as a pure function over a `LockState`-shaped object — no
|
|
9
|
+
* I/O, no adapter calls — so the state machine is unit-testable in isolation.
|
|
10
|
+
* @module dsh-connect/mirror-lock
|
|
11
|
+
*/
|
|
12
|
+
/** Default lock timeout (5 minutes) when a binding has no explicit timeout. */
|
|
13
|
+
export const DEFAULT_LOCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
14
|
+
/** True when a lock exists and its acquisition timestamp is older than its timeout. */
|
|
15
|
+
export function isLockTimedOut(state, now = Date.now()) {
|
|
16
|
+
if (state.lockOwner === undefined || state.lockAcquiredAt === undefined)
|
|
17
|
+
return false;
|
|
18
|
+
const timeoutMs = state.lockTimeoutMs ?? DEFAULT_LOCK_TIMEOUT_MS;
|
|
19
|
+
return now - state.lockAcquiredAt > timeoutMs;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Whether `channel` may write to the session. A timed-out lock counts as
|
|
23
|
+
* free (the caller normally releases it and notifies the user).
|
|
24
|
+
*/
|
|
25
|
+
export function canWrite(state, channel, now = Date.now()) {
|
|
26
|
+
if (state.lockOwner === undefined)
|
|
27
|
+
return true;
|
|
28
|
+
if (isLockTimedOut(state, now))
|
|
29
|
+
return true;
|
|
30
|
+
return state.lockOwner === channel;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Acquire (or renew) the lock for `channel`. Returns the next state when the
|
|
34
|
+
* lock is free, timed out, or already owned by `channel`; `undefined` when a
|
|
35
|
+
* different channel currently holds a live lock. Generic over the full state
|
|
36
|
+
* object so callers keep their complete binding type.
|
|
37
|
+
*/
|
|
38
|
+
export function acquire(state, channel, now = Date.now()) {
|
|
39
|
+
if (state.lockOwner !== undefined && !isLockTimedOut(state, now) && state.lockOwner !== channel) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
...state,
|
|
44
|
+
lockOwner: channel,
|
|
45
|
+
lockAcquiredAt: now,
|
|
46
|
+
lockTimeoutMs: state.lockTimeoutMs ?? DEFAULT_LOCK_TIMEOUT_MS,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Release the lock, preserving every other field (including the parked queue —
|
|
51
|
+
* the caller drains `queuedMessages` before or after releasing).
|
|
52
|
+
*/
|
|
53
|
+
export function release(state) {
|
|
54
|
+
return { ...state, lockOwner: undefined, lockAcquiredAt: undefined };
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=mirror-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mirror-lock.js","sourceRoot":"","sources":["../src/mirror-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAsBrD,uFAAuF;AACvF,MAAM,UAAU,cAAc,CAAC,KAAgB,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAC/D,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,cAAc,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACtF,MAAM,SAAS,GAAG,KAAK,CAAC,aAAa,IAAI,uBAAuB,CAAC;IACjE,OAAO,GAAG,GAAG,KAAK,CAAC,cAAc,GAAG,SAAS,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAgB,EAAE,OAAyB,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IACpF,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC/C,IAAI,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5C,OAAO,KAAK,CAAC,SAAS,KAAK,OAAO,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAsB,KAAQ,EAAE,OAAyB,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAChG,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,KAAK,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC;QAChG,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO;QACL,GAAG,KAAK;QACR,SAAS,EAAE,OAAO;QAClB,cAAc,EAAE,GAAG;QACnB,aAAa,EAAE,KAAK,CAAC,aAAa,IAAI,uBAAuB;KAC9D,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAsB,KAAQ;IACnD,OAAO,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC;AACvE,CAAC"}
|
package/lib/retry.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded outbound retry for channel deliveries.
|
|
3
|
+
*
|
|
4
|
+
* The core wraps every registered adapter's delivery methods (sendText /
|
|
5
|
+
* sendCard / promptChoice / closeMenu) so a transient channel failure —
|
|
6
|
+
* network blip, 429, 5xx — retries a few times with jittered exponential
|
|
7
|
+
* backoff instead of silently dropping a user-visible message. streamText is
|
|
8
|
+
* deliberately NOT retried: a partially-streamed reply cannot be resumed, and
|
|
9
|
+
* restarting it would duplicate the streaming card.
|
|
10
|
+
* @module dsh-connect/retry
|
|
11
|
+
*/
|
|
12
|
+
import type { ChannelAdapter } from "./types.js";
|
|
13
|
+
export interface RetryOptions {
|
|
14
|
+
/** Total attempts including the first call (default 3). */
|
|
15
|
+
attempts?: number;
|
|
16
|
+
/** Base delay between attempts in ms (default 250). */
|
|
17
|
+
baseDelayMs?: number;
|
|
18
|
+
/** Cap for a single delay in ms (default 2000). */
|
|
19
|
+
maxDelayMs?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Decide whether an error is worth retrying. Defaults to retrying every
|
|
22
|
+
* error — bounded attempts keep permanent failures cheap (a few extra
|
|
23
|
+
* channel calls), while transient ones actually recover.
|
|
24
|
+
*/
|
|
25
|
+
isTransient?: (error: unknown) => boolean;
|
|
26
|
+
}
|
|
27
|
+
/** Run `fn` with bounded, jittered exponential backoff on failure. */
|
|
28
|
+
export declare function retry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
29
|
+
/**
|
|
30
|
+
* Wrap an adapter so its delivery methods retry transient failures.
|
|
31
|
+
* Non-delivery faces (start/stop/onInbound) and streamText pass through
|
|
32
|
+
* untouched.
|
|
33
|
+
*/
|
|
34
|
+
export declare function withOutboundRetry(adapter: ChannelAdapter, options?: RetryOptions): ChannelAdapter;
|
|
35
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,YAAY;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CAC3C;AAED,sEAAsE;AACtE,wBAAsB,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,CAAC,CAAC,CAkB3F;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,GAAE,YAAiB,GAAG,cAAc,CAYrG"}
|
package/lib/retry.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Run `fn` with bounded, jittered exponential backoff on failure. */
|
|
2
|
+
export async function retry(fn, options = {}) {
|
|
3
|
+
const attempts = Math.max(1, options.attempts ?? 3);
|
|
4
|
+
const baseDelayMs = Math.max(0, options.baseDelayMs ?? 250);
|
|
5
|
+
const maxDelayMs = Math.max(1, options.maxDelayMs ?? 2000);
|
|
6
|
+
const isTransient = options.isTransient ?? (() => true);
|
|
7
|
+
let lastError;
|
|
8
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
9
|
+
try {
|
|
10
|
+
return await fn();
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
lastError = error;
|
|
14
|
+
if (attempt >= attempts || !isTransient(error))
|
|
15
|
+
throw error;
|
|
16
|
+
const backoff = Math.min(maxDelayMs, baseDelayMs * 2 ** (attempt - 1));
|
|
17
|
+
const jitter = backoff * 0.25 * Math.random();
|
|
18
|
+
await new Promise((resolve) => setTimeout(resolve, Math.round(backoff + jitter)));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
throw lastError;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Wrap an adapter so its delivery methods retry transient failures.
|
|
25
|
+
* Non-delivery faces (start/stop/onInbound) and streamText pass through
|
|
26
|
+
* untouched.
|
|
27
|
+
*/
|
|
28
|
+
export function withOutboundRetry(adapter, options = {}) {
|
|
29
|
+
return {
|
|
30
|
+
id: adapter.id,
|
|
31
|
+
start: () => adapter.start(),
|
|
32
|
+
stop: () => adapter.stop(),
|
|
33
|
+
onInbound: (handler) => adapter.onInbound(handler),
|
|
34
|
+
sendText: (target, text) => retry(() => adapter.sendText(target, text), options),
|
|
35
|
+
sendCard: (target, card) => retry(() => adapter.sendCard(target, card), options),
|
|
36
|
+
promptChoice: (target, prompt, updateMessageId) => retry(() => adapter.promptChoice(target, prompt, updateMessageId), options),
|
|
37
|
+
closeMenu: (messageId, summary) => retry(() => adapter.closeMenu(messageId, summary), options),
|
|
38
|
+
streamText: (target, chunks) => adapter.streamText(target, chunks),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=retry.js.map
|
package/lib/retry.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AA4BA,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,KAAK,CAAI,EAAoB,EAAE,UAAwB,EAAE;IAC7E,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;IACpD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,WAAW,IAAI,GAAG,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACxD,IAAI,SAAkB,CAAC;IACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC;QACrD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,CAAC;YAClB,IAAI,OAAO,IAAI,QAAQ,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAC;YAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,WAAW,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;YACvE,MAAM,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YAC9C,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;IACD,MAAM,SAAS,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAuB,EAAE,UAAwB,EAAE;IACnF,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE;QAC5B,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE;QAC1B,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC;QAClD,QAAQ,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAChF,QAAQ,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAChF,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,OAAO,CAAC;QAC9H,SAAS,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAC9F,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC;KACnE,CAAC;AACJ,CAAC"}
|
package/lib/runner.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { type Session, type SessionEvent } from "@deepseek-ai/dsh-session";
|
|
|
3
3
|
import type { ChannelAdapter, InboundMessage, TurnOutcome } from "./types.js";
|
|
4
4
|
import type { BindingStore } from "./binding.js";
|
|
5
5
|
import { type Language } from "./i18n.js";
|
|
6
|
+
import { type ReminderStore } from "./scheduler.js";
|
|
6
7
|
export interface ConnectConfig {
|
|
7
8
|
/** Agent preset id composed into each session; `undefined` = roster default. */
|
|
8
9
|
agentPreset?: string;
|
|
@@ -105,6 +106,14 @@ export declare class AgentRunner {
|
|
|
105
106
|
private readonly adapter;
|
|
106
107
|
private readonly bindings;
|
|
107
108
|
private readonly adapters?;
|
|
109
|
+
/**
|
|
110
|
+
* Route a replayed queued message back into the runner of its own channel
|
|
111
|
+
* (wired by ConnectService). Without it, replayed messages would run in
|
|
112
|
+
* whichever runner happened to release the lock.
|
|
113
|
+
*/
|
|
114
|
+
private readonly requeue?;
|
|
115
|
+
/** Persistent chat-level reminders (`/remind`), wired by ConnectService. */
|
|
116
|
+
private readonly reminders?;
|
|
108
117
|
private readonly queue;
|
|
109
118
|
private running;
|
|
110
119
|
private agent?;
|
|
@@ -115,7 +124,15 @@ export declare class AgentRunner {
|
|
|
115
124
|
private notifyLevel;
|
|
116
125
|
private progressTimeoutMs;
|
|
117
126
|
private t;
|
|
118
|
-
constructor(ctx: Context, config: ResolvedConnectConfig, channel: string, chatKey: string, chatType: "p2p" | "group", adapter: ChannelAdapter, bindings: BindingStore, adapters?: Map<string, ChannelAdapter> | undefined
|
|
127
|
+
constructor(ctx: Context, config: ResolvedConnectConfig, channel: string, chatKey: string, chatType: "p2p" | "group", adapter: ChannelAdapter, bindings: BindingStore, adapters?: Map<string, ChannelAdapter> | undefined,
|
|
128
|
+
/**
|
|
129
|
+
* Route a replayed queued message back into the runner of its own channel
|
|
130
|
+
* (wired by ConnectService). Without it, replayed messages would run in
|
|
131
|
+
* whichever runner happened to release the lock.
|
|
132
|
+
*/
|
|
133
|
+
requeue?: ((msg: InboundMessage) => void) | undefined,
|
|
134
|
+
/** Persistent chat-level reminders (`/remind`), wired by ConnectService. */
|
|
135
|
+
reminders?: ReminderStore | undefined);
|
|
119
136
|
private menuTitle;
|
|
120
137
|
private rootMenuSections;
|
|
121
138
|
private reasonLabel;
|
|
@@ -220,6 +237,21 @@ export declare class AgentRunner {
|
|
|
220
237
|
* steers the in-flight task), and an idle driver starts a new turn with it.
|
|
221
238
|
*/
|
|
222
239
|
private handleAppend;
|
|
240
|
+
/**
|
|
241
|
+
* `/remind <time> <text>` — persist a chat-level reminder that fires
|
|
242
|
+
* without waking the agent (see src/scheduler.ts).
|
|
243
|
+
*/
|
|
244
|
+
private handleRemind;
|
|
245
|
+
/**
|
|
246
|
+
* `/send <path>` — deliver a file from the workspace through the channel's
|
|
247
|
+
* `sendFile` capability; falls back to sending the path as text.
|
|
248
|
+
*/
|
|
249
|
+
private handleSend;
|
|
250
|
+
/**
|
|
251
|
+
* `/broadcast <text>` — admins push a message to every bound chat.
|
|
252
|
+
* Admin gating lives in the connect service (allowUsers).
|
|
253
|
+
*/
|
|
254
|
+
private handleBroadcast;
|
|
223
255
|
private recordSession;
|
|
224
256
|
/**
|
|
225
257
|
* Automatically create a Web mirror for the session.
|
|
@@ -283,7 +315,8 @@ export declare class AgentRunner {
|
|
|
283
315
|
*/
|
|
284
316
|
private handleRenewLock;
|
|
285
317
|
/**
|
|
286
|
-
* Export conversation history
|
|
318
|
+
* Export conversation history as Markdown (a future PDF pipeline can be
|
|
319
|
+
* added here; `/export pdf` currently falls back to Markdown).
|
|
287
320
|
*/
|
|
288
321
|
private handleExport;
|
|
289
322
|
/**
|
|
@@ -310,11 +343,14 @@ export declare class AgentRunner {
|
|
|
310
343
|
* Re-enqueues them into the runner's message queue for actual execution.
|
|
311
344
|
*/
|
|
312
345
|
private processQueuedMessages;
|
|
313
|
-
/**
|
|
346
|
+
/**
|
|
347
|
+
* Release session lock. Awaits the queued-message drain, then clears the
|
|
348
|
+
* lock from a FRESH read: the drain's queue-clearing put must not be
|
|
349
|
+
* overwritten by a stale binding object (which would resurrect the queue
|
|
350
|
+
* and cause duplicate processing on the next release).
|
|
351
|
+
*/
|
|
314
352
|
private releaseLock;
|
|
315
|
-
/** Check
|
|
316
|
-
private isLockTimedOut;
|
|
317
|
-
/** Check and release timed-out locks. */
|
|
353
|
+
/** Check and release timed-out locks (delegates to the pure lock module). */
|
|
318
354
|
private checkAndReleaseTimeoutLock;
|
|
319
355
|
/** Release a timed-out lock and notify. */
|
|
320
356
|
private releaseTimeoutLock;
|
package/lib/runner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAA2B,KAAK,OAAO,EAAE,KAAK,YAAY,EAAiB,MAAM,0BAA0B,CAAC;AAGnH,OAAO,KAAK,EAAE,cAAc,EAAgB,cAAc,EAA+B,WAAW,EAAc,MAAM,YAAY,CAAC;AAGrI,OAAO,KAAK,EAAE,YAAY,EAAkC,MAAM,cAAc,CAAC;AACjF,OAAO,EAAY,KAAK,QAAQ,EAAiB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
|