dsh-client-auto-continue 0.7.5 → 0.8.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/README.md +6 -14
- package/README.zh.md +6 -14
- package/lib/client.js +201 -1193
- package/lib/client.js.map +4 -4
- package/lib/index.js +989 -30
- package/lib/types/client/bridge.d.ts +39 -0
- package/lib/types/client/engine.d.ts +5 -250
- package/lib/types/client/index.d.ts +11 -14
- package/lib/types/client/locales.d.ts +0 -4
- package/lib/types/client/settings-card.d.ts +0 -2
- package/lib/types/host/engine.d.ts +118 -0
- package/lib/types/index.d.ts +11 -13
- package/lib/types/shared/core.d.ts +234 -0
- package/package.json +4 -3
- package/src/client/bridge.ts +202 -0
- package/src/client/engine.ts +17 -1639
- package/src/client/index.ts +19 -29
- package/src/client/locales.ts +0 -8
- package/src/client/settings-card.tsx +9 -30
- package/src/host/engine.ts +837 -0
- package/src/index.ts +98 -9
- package/src/shared/core.ts +459 -0
- package/tsconfig.json +2 -1
package/src/client/index.ts
CHANGED
|
@@ -1,37 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Auto-continue plugin, browser half.
|
|
2
|
+
* Auto-continue plugin, browser half (thin shell).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Since 0.8.0 the auto-continue ENGINE runs inside the host process (single
|
|
5
|
+
* instance — see src/host/engine.ts), so this half only:
|
|
6
|
+
* - registers the `auto-continue` settings card (`settings.plugin.item`),
|
|
7
|
+
* - subscribes to the host status bridge (SSE) and shows browser
|
|
8
|
+
* notifications with action buttons (Resume now / Pause 1h) via the bridge
|
|
9
|
+
* action endpoint,
|
|
10
|
+
* - feeds the card's stats / paused-sessions panels from the bridge state.
|
|
8
11
|
*/
|
|
9
12
|
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
|
|
10
|
-
import type { ConnectionHandle } from '@deepseek-ai/dsh-client-connection/client';
|
|
11
13
|
// Type-only: pulls the locale plugin's Context merge (ctx.locale).
|
|
12
14
|
import type {} from '@deepseek-ai/dsh-client-locale/client';
|
|
13
15
|
// Type-only: pulls the settings-surface SlotMap merge and ctx.settingsScope.
|
|
14
16
|
import type {} from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
15
17
|
// Type-only: pulls the `settings.plugin.item` SlotMap merge.
|
|
16
18
|
import type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client';
|
|
17
|
-
import {
|
|
19
|
+
import { type AutoContinueSettings } from './engine.ts';
|
|
18
20
|
import { en, zh, type SettingsCardKey } from './locales.ts';
|
|
19
21
|
import {
|
|
20
22
|
AutoContinueSettingsCard,
|
|
21
23
|
AutoContinueSettingsCardController,
|
|
22
24
|
} from './settings-card.tsx';
|
|
23
|
-
|
|
24
|
-
/** 客户端根上下文的 connection 服务(由 dsh-client-connection 挂载)。 */
|
|
25
|
-
declare module '@deepseek-ai/cordis' {
|
|
26
|
-
interface Context {
|
|
27
|
-
connection: ConnectionHandle;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
25
|
+
import { startBridge } from './bridge.ts';
|
|
30
26
|
|
|
31
27
|
/** Dictionary namespace owned by this plugin. */
|
|
32
28
|
const NS = 'auto-continue';
|
|
33
29
|
|
|
34
|
-
/** Settings namespace the
|
|
30
|
+
/** Settings namespace the settings card edits (the host engine reads it). */
|
|
35
31
|
const SETTINGS_NS = 'auto-continue';
|
|
36
32
|
|
|
37
33
|
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
@@ -42,39 +38,33 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
|
42
38
|
}
|
|
43
39
|
|
|
44
40
|
/** Services required by this plugin. */
|
|
45
|
-
export const inject = ['slots', 'locale', '
|
|
41
|
+
export const inject = ['slots', 'locale', 'settingsScope'];
|
|
46
42
|
|
|
47
|
-
// 浏览器侧辅助(
|
|
43
|
+
// 浏览器侧辅助(设置卡片用): 桥状态读取与暂停解除。
|
|
48
44
|
export {
|
|
49
|
-
fillTemplate,
|
|
50
|
-
pauseSession,
|
|
51
45
|
pausedSessions,
|
|
52
46
|
readTodayStats,
|
|
53
47
|
resetTodayStats,
|
|
54
|
-
sessionPauseUntil,
|
|
55
48
|
unpauseSession,
|
|
56
|
-
} from './
|
|
57
|
-
|
|
58
|
-
/** 当前 runner(HMR 重载时先销毁旧的再建新的)。 */
|
|
59
|
-
let current: AutoContinueRunner | null = null;
|
|
49
|
+
} from './bridge.ts';
|
|
60
50
|
|
|
61
51
|
/**
|
|
62
|
-
* Plugin body:
|
|
52
|
+
* Plugin body: settings card + host status bridge (notifications, stats,
|
|
53
|
+
* paused sessions).
|
|
63
54
|
* @param ctx - client root context.
|
|
64
55
|
*/
|
|
65
56
|
export function apply(ctx: ClientContext): void {
|
|
66
57
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'auto-continue: dictionaries');
|
|
67
58
|
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
current?.dispose();
|
|
71
|
-
current = new AutoContinueRunner(ctx.connection.api, () => resolveConfig(scope.getSnapshot().value));
|
|
59
|
+
// 状态桥: 订阅 host 的通知与运行时状态, 弹浏览器通知并驱动卡片面板。
|
|
60
|
+
ctx.effect(() => startBridge(), 'auto-continue: host bridge');
|
|
72
61
|
|
|
73
62
|
// Plugin configuration card: one staged form over the `auto-continue`
|
|
74
63
|
// settings namespace, contributed to the plugin-configuration section
|
|
75
64
|
// (Settings → Plugins). Since DSH 0.1.0-rc.7 `settings.plugin.item` is a
|
|
76
65
|
// keyed slot dispatched by the settings namespace it edits, so the entry
|
|
77
66
|
// registers with `key` (the namespace), like the official cards.
|
|
67
|
+
const scope = ctx.settingsScope.bind<AutoContinueSettings>({ namespace: SETTINGS_NS });
|
|
78
68
|
const controller = new AutoContinueSettingsCardController(scope);
|
|
79
69
|
ctx.slots.inject('settings.plugin.item', () =>
|
|
80
70
|
ctx.slots.register(
|
package/src/client/locales.ts
CHANGED
|
@@ -32,10 +32,6 @@ export const zh = {
|
|
|
32
32
|
'field.scanLimitHint': '最多检查多少个最近更新的会话(不含运行中与子代理会话)。',
|
|
33
33
|
'field.freshMs': '扫描时间窗 (ms)',
|
|
34
34
|
'field.freshMsHint': '扫描只处理该时间窗内的中断。',
|
|
35
|
-
'field.reconnectScanDelayMs': '重连扫描延迟 (ms)',
|
|
36
|
-
'field.reconnectScanDelayMsHint': '重连后等待宿主完成恢复再扫描。',
|
|
37
|
-
'field.reconnectBackoffMs': '重连退避 (ms)',
|
|
38
|
-
'field.reconnectBackoffMsHint': '事件流断开后的重连间隔。',
|
|
39
35
|
'field.verbose': '详细日志',
|
|
40
36
|
'field.verboseHint': '在浏览器控制台输出 [auto-continue] 日志。',
|
|
41
37
|
'field.classify': '错误分类',
|
|
@@ -122,10 +118,6 @@ export const en: Record<SettingsCardKey, string> = {
|
|
|
122
118
|
'field.scanLimitHint': 'How many most-recently-updated sessions to check (running / subagent sessions excluded).',
|
|
123
119
|
'field.freshMs': 'Scan window (ms)',
|
|
124
120
|
'field.freshMsHint': 'Only interruptions inside this window are considered.',
|
|
125
|
-
'field.reconnectScanDelayMs': 'Reconnect scan delay (ms)',
|
|
126
|
-
'field.reconnectScanDelayMsHint': 'Wait for the host to finish recovering before scanning after a reconnect.',
|
|
127
|
-
'field.reconnectBackoffMs': 'Reconnect backoff (ms)',
|
|
128
|
-
'field.reconnectBackoffMsHint': 'Interval between event-stream reconnect attempts.',
|
|
129
121
|
'field.verbose': 'Verbose logs',
|
|
130
122
|
'field.verboseHint': 'Log [auto-continue] lines to the browser console.',
|
|
131
123
|
'field.classify': 'Classify errors',
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
import { useEffect, useState, type ReactNode } from 'react';
|
|
11
11
|
import { createSnapshotStore, type SettingsScope, type SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client';
|
|
12
12
|
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
13
|
+
import { DEFAULT_CONFIG, type AutoContinueSettings } from './engine.ts';
|
|
13
14
|
import {
|
|
14
|
-
DEFAULT_CONFIG,
|
|
15
15
|
pausedSessions,
|
|
16
16
|
readTodayStats,
|
|
17
17
|
resetTodayStats,
|
|
18
|
+
subscribeBridge,
|
|
18
19
|
unpauseSession,
|
|
19
|
-
|
|
20
|
-
} from './engine.ts';
|
|
20
|
+
} from './bridge.ts';
|
|
21
21
|
import type { SettingsCardKey } from './locales.ts';
|
|
22
22
|
import {
|
|
23
23
|
booleanField,
|
|
@@ -48,8 +48,6 @@ export interface AutoContinueSettingsCardState extends CardShell {
|
|
|
48
48
|
scanOnBoot: CardFieldState;
|
|
49
49
|
scanLimit: CardFieldState;
|
|
50
50
|
freshMs: CardFieldState;
|
|
51
|
-
reconnectScanDelayMs: CardFieldState;
|
|
52
|
-
reconnectBackoffMs: CardFieldState;
|
|
53
51
|
verbose: CardFieldState;
|
|
54
52
|
classify: CardFieldState;
|
|
55
53
|
backoffFactor: CardFieldState;
|
|
@@ -94,8 +92,6 @@ export class AutoContinueSettingsCardController {
|
|
|
94
92
|
booleanField('scanOnBoot'),
|
|
95
93
|
numberField('scanLimit', 1),
|
|
96
94
|
numberField('freshMs', 0),
|
|
97
|
-
numberField('reconnectScanDelayMs', 0),
|
|
98
|
-
numberField('reconnectBackoffMs', 0),
|
|
99
95
|
booleanField('verbose'),
|
|
100
96
|
booleanField('classify'),
|
|
101
97
|
numberField('backoffFactor', 1),
|
|
@@ -127,8 +123,6 @@ export class AutoContinueSettingsCardController {
|
|
|
127
123
|
scanOnBoot: this.form.field('scanOnBoot'),
|
|
128
124
|
scanLimit: this.form.field('scanLimit'),
|
|
129
125
|
freshMs: this.form.field('freshMs'),
|
|
130
|
-
reconnectScanDelayMs: this.form.field('reconnectScanDelayMs'),
|
|
131
|
-
reconnectBackoffMs: this.form.field('reconnectBackoffMs'),
|
|
132
126
|
verbose: this.form.field('verbose'),
|
|
133
127
|
classify: this.form.field('classify'),
|
|
134
128
|
backoffFactor: this.form.field('backoffFactor'),
|
|
@@ -304,8 +298,13 @@ function LivePanels(props: { t: (key: SettingsCardKey) => string }) {
|
|
|
304
298
|
const { t } = props;
|
|
305
299
|
const [, refresh] = useState(0);
|
|
306
300
|
useEffect(() => {
|
|
301
|
+
// host 状态桥推送时刷新; 5 秒轮询兜底(桥短暂断线时)
|
|
302
|
+
const unsubscribe = subscribeBridge(() => refresh((value) => value + 1));
|
|
307
303
|
const timer = setInterval(() => refresh((value) => value + 1), 5000);
|
|
308
|
-
return () =>
|
|
304
|
+
return () => {
|
|
305
|
+
unsubscribe();
|
|
306
|
+
clearInterval(timer);
|
|
307
|
+
};
|
|
309
308
|
}, []);
|
|
310
309
|
const stats = readTodayStats();
|
|
311
310
|
const hasStats = stats.sent + stats.skipped + stats.recovered + stats.failed + stats.gaveUp + stats.looped > 0;
|
|
@@ -537,26 +536,6 @@ export function AutoContinueSettingsCard(props: AutoContinueSettingsCardProps) {
|
|
|
537
536
|
onEdit={(text) => props.edit('freshMs', text)}
|
|
538
537
|
onReset={() => props.resetField('freshMs')}
|
|
539
538
|
/>
|
|
540
|
-
<ValueField
|
|
541
|
-
id="auto-continue-reconnect-scan-delay"
|
|
542
|
-
label={t('field.reconnectScanDelayMs')}
|
|
543
|
-
hint={t('field.reconnectScanDelayMsHint')}
|
|
544
|
-
numeric
|
|
545
|
-
{...shared}
|
|
546
|
-
{...state.reconnectScanDelayMs}
|
|
547
|
-
onEdit={(text) => props.edit('reconnectScanDelayMs', text)}
|
|
548
|
-
onReset={() => props.resetField('reconnectScanDelayMs')}
|
|
549
|
-
/>
|
|
550
|
-
<ValueField
|
|
551
|
-
id="auto-continue-reconnect-backoff"
|
|
552
|
-
label={t('field.reconnectBackoffMs')}
|
|
553
|
-
hint={t('field.reconnectBackoffMsHint')}
|
|
554
|
-
numeric
|
|
555
|
-
{...shared}
|
|
556
|
-
{...state.reconnectBackoffMs}
|
|
557
|
-
onEdit={(text) => props.edit('reconnectBackoffMs', text)}
|
|
558
|
-
onReset={() => props.resetField('reconnectBackoffMs')}
|
|
559
|
-
/>
|
|
560
539
|
<BooleanField
|
|
561
540
|
id="auto-continue-verbose"
|
|
562
541
|
label={t('field.verbose')}
|