dsh-client-auto-continue 0.5.2 → 0.5.3
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/package.json +7 -3
- package/src/client/engine.ts +1116 -0
- package/src/client/index.ts +91 -0
- package/src/client/locales.ts +140 -0
- package/src/client/settings-card.tsx +547 -0
- package/src/client/settings-form.ts +293 -0
- package/src/client/styles.ts +172 -0
- package/src/index.ts +62 -0
- package/tsconfig.build.json +11 -0
- package/tsconfig.json +29 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-continue plugin, browser half.
|
|
3
|
+
*
|
|
4
|
+
* - Runs the auto-continue engine over the live mux + host event streams.
|
|
5
|
+
* - Registers the `auto-continue` settings card into the plugin-configuration
|
|
6
|
+
* section (`settings.plugin.item`), editing the same namespace the engine
|
|
7
|
+
* reads — every behavior knob is configurable from the GUI.
|
|
8
|
+
*/
|
|
9
|
+
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
|
|
10
|
+
import type { ConnectionHandle } from '@deepseek-ai/dsh-client-connection/client';
|
|
11
|
+
// Type-only: pulls the locale plugin's Context merge (ctx.locale).
|
|
12
|
+
import type {} from '@deepseek-ai/dsh-client-locale/client';
|
|
13
|
+
// Type-only: pulls the settings-surface SlotMap merge and ctx.settingsScope.
|
|
14
|
+
import type {} from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
15
|
+
// Type-only: pulls the `settings.plugin.item` SlotMap merge.
|
|
16
|
+
import type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client';
|
|
17
|
+
import { AutoContinueRunner, resolveConfig, type AutoContinueSettings } from './engine.ts';
|
|
18
|
+
import { en, zh, type SettingsCardKey } from './locales.ts';
|
|
19
|
+
import {
|
|
20
|
+
AutoContinueSettingsCard,
|
|
21
|
+
AutoContinueSettingsCardController,
|
|
22
|
+
} from './settings-card.tsx';
|
|
23
|
+
|
|
24
|
+
/** 客户端根上下文的 connection 服务(由 dsh-client-connection 挂载)。 */
|
|
25
|
+
declare module '@deepseek-ai/cordis' {
|
|
26
|
+
interface Context {
|
|
27
|
+
connection: ConnectionHandle;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Dictionary namespace owned by this plugin. */
|
|
32
|
+
const NS = 'auto-continue';
|
|
33
|
+
|
|
34
|
+
/** Settings namespace the engine reads and the settings card edits. */
|
|
35
|
+
const SETTINGS_NS = 'auto-continue';
|
|
36
|
+
|
|
37
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
38
|
+
interface LocaleNamespaceMap {
|
|
39
|
+
/** auto-continue settings-card copy. */
|
|
40
|
+
'auto-continue': SettingsCardKey;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Services required by this plugin. */
|
|
45
|
+
export const inject = ['slots', 'locale', 'connection', 'settingsScope'];
|
|
46
|
+
|
|
47
|
+
// 浏览器侧辅助(设置卡片与模拟测试共用): 暂停控制与统计读取。
|
|
48
|
+
export {
|
|
49
|
+
fillTemplate,
|
|
50
|
+
pauseSession,
|
|
51
|
+
pausedSessions,
|
|
52
|
+
readTodayStats,
|
|
53
|
+
resetTodayStats,
|
|
54
|
+
sessionPauseUntil,
|
|
55
|
+
unpauseSession,
|
|
56
|
+
} from './engine.ts';
|
|
57
|
+
|
|
58
|
+
/** 当前 runner(HMR 重载时先销毁旧的再建新的)。 */
|
|
59
|
+
let current: AutoContinueRunner | null = null;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Plugin body: mount the engine and the settings card.
|
|
63
|
+
* @param ctx - client root context.
|
|
64
|
+
*/
|
|
65
|
+
export function apply(ctx: ClientContext): void {
|
|
66
|
+
ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'auto-continue: dictionaries');
|
|
67
|
+
|
|
68
|
+
// Engine: reads the settings scope live, so GUI changes apply immediately.
|
|
69
|
+
const scope = ctx.settingsScope.bind<AutoContinueSettings>({ namespace: SETTINGS_NS });
|
|
70
|
+
current?.dispose();
|
|
71
|
+
current = new AutoContinueRunner(ctx.connection.api, () => resolveConfig(scope.getSnapshot().value));
|
|
72
|
+
|
|
73
|
+
// Plugin configuration card: one staged form over the `auto-continue`
|
|
74
|
+
// settings namespace, contributed to the plugin-configuration section
|
|
75
|
+
// (Settings → Plugins). Registered through the public `settings.plugin.item`
|
|
76
|
+
// slot — no hardcoded section order, label or path anywhere — so the card
|
|
77
|
+
// shows up in the plugin list like any other plugin's config card.
|
|
78
|
+
const controller = new AutoContinueSettingsCardController(scope);
|
|
79
|
+
ctx.slots.inject('settings.plugin.item', () =>
|
|
80
|
+
ctx.slots.register(
|
|
81
|
+
{
|
|
82
|
+
name: 'settings.plugin.item',
|
|
83
|
+
id: 'auto-continue',
|
|
84
|
+
order: 90,
|
|
85
|
+
locale: NS,
|
|
86
|
+
inject: () => controller.inject(),
|
|
87
|
+
},
|
|
88
|
+
AutoContinueSettingsCard,
|
|
89
|
+
),
|
|
90
|
+
);
|
|
91
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `auto-continue` namespace dictionaries: copy for the plugin settings card
|
|
3
|
+
* registered into the `settings.plugin.item` seat of the plugin-configuration
|
|
4
|
+
* section. Includes the card-chrome keys the card component reads.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** 简体中文词典(键集的事实来源)。 */
|
|
8
|
+
export const zh = {
|
|
9
|
+
'card.title': '自动继续',
|
|
10
|
+
'card.description': '请求因网络等原因(非人为)中断后, 自动发送「继续」续跑。',
|
|
11
|
+
'field.paused': '暂停自动继续',
|
|
12
|
+
'field.pausedHint': '全局暂停: 实时与扫描都不会再自动发送, 已排队的待发送也会取消。',
|
|
13
|
+
'field.continueText': '继续文本',
|
|
14
|
+
'field.continueTextHint': '中断后自动发送的消息内容。',
|
|
15
|
+
'field.continueTextMaxTokens': '超限时的继续文本',
|
|
16
|
+
'field.continueTextMaxTokensHint': '达到输出 token 上限时自动发送的文本, 支持与继续文本相同的占位符。',
|
|
17
|
+
'field.graceMs': '宽限期 (ms)',
|
|
18
|
+
'field.graceMsHint': '检测到中断后等待的时长; 期间宿主自行恢复则取消。',
|
|
19
|
+
'field.cooldownMs': '冷却时间 (ms)',
|
|
20
|
+
'field.cooldownMsHint': '同一会话两次自动「继续」的最小间隔, 失败尝试也计入。',
|
|
21
|
+
'field.maxConsecutive': '最大连续次数',
|
|
22
|
+
'field.maxConsecutiveHint': '同一会话连续自动「继续」的上限; 超过后停止, 直到用户手动介入或出现成功回合。',
|
|
23
|
+
'field.scanOnBoot': '启动/重连扫描',
|
|
24
|
+
'field.scanOnBootHint': '页面启动或重连时扫描最近中断的会话并自动续跑(如浏览器关闭期间宿主崩溃)。',
|
|
25
|
+
'field.scanLimit': '扫描会话数',
|
|
26
|
+
'field.scanLimitHint': '最多检查多少个最近更新的会话(不含运行中与子代理会话)。',
|
|
27
|
+
'field.freshMs': '扫描时间窗 (ms)',
|
|
28
|
+
'field.freshMsHint': '扫描只处理该时间窗内的中断。',
|
|
29
|
+
'field.reconnectScanDelayMs': '重连扫描延迟 (ms)',
|
|
30
|
+
'field.reconnectScanDelayMsHint': '重连后等待宿主完成恢复再扫描。',
|
|
31
|
+
'field.reconnectBackoffMs': '重连退避 (ms)',
|
|
32
|
+
'field.reconnectBackoffMsHint': '事件流断开后的重连间隔。',
|
|
33
|
+
'field.verbose': '详细日志',
|
|
34
|
+
'field.verboseHint': '在浏览器控制台输出 [auto-continue] 日志。',
|
|
35
|
+
'field.classify': '错误分类',
|
|
36
|
+
'field.classifyHint': '仅自动恢复临时性错误(网络/超时/5xx 等); 认证/余额/模型不存在等永久性错误跳过并通知。',
|
|
37
|
+
'field.backoffFactor': '退避系数',
|
|
38
|
+
'field.backoffFactorHint': '连续失败时冷却间隔的倍率(如 2 表示 20s→40s→80s 递增)。',
|
|
39
|
+
'field.backoffMaxMs': '最大退避间隔 (ms)',
|
|
40
|
+
'field.backoffMaxMsHint': '自适应退避的上限, 防止等待过久。',
|
|
41
|
+
'field.notify': '浏览器通知',
|
|
42
|
+
'field.notifyHint': '自动继续成功/放弃/遇到永久性错误时弹出浏览器通知, 通知带「立即续跑」与「暂停该会话 1 小时」按钮。',
|
|
43
|
+
'stats.title': '今日统计',
|
|
44
|
+
'stats.sent': '自动继续',
|
|
45
|
+
'stats.skipped': '跳过(永久错误)',
|
|
46
|
+
'stats.recovered': '恢复成功',
|
|
47
|
+
'stats.failed': '继续后仍失败',
|
|
48
|
+
'stats.gaveUp': '停止(达上限)',
|
|
49
|
+
'stats.byCode': '错误码分布',
|
|
50
|
+
'stats.empty': '今天还没有自动继续记录。',
|
|
51
|
+
'stats.reset': '清零',
|
|
52
|
+
'pause.title': '已暂停会话',
|
|
53
|
+
'pause.none': '没有暂停中的会话。',
|
|
54
|
+
'pause.clearAll': '全部解除',
|
|
55
|
+
'pause.unpause': '解除',
|
|
56
|
+
'pause.minutes': '分钟',
|
|
57
|
+
'chrome.collapse': '收起设置',
|
|
58
|
+
'chrome.expand': '展开设置',
|
|
59
|
+
'chrome.unsaved': '未保存',
|
|
60
|
+
'chrome.readOnly': '当前部署的设置只读。',
|
|
61
|
+
'chrome.saveFailed': '部署未接受这些值, 已保留供你修改。',
|
|
62
|
+
'chrome.discard': '放弃',
|
|
63
|
+
'chrome.saving': '保存中…',
|
|
64
|
+
'chrome.save': '保存',
|
|
65
|
+
'chrome.overridden': '已覆盖',
|
|
66
|
+
'chrome.reset': '恢复默认',
|
|
67
|
+
'chrome.invalidNumber': '请输入数字, 留空则使用默认值。',
|
|
68
|
+
'chrome.inherit': '继承',
|
|
69
|
+
'chrome.on': '开',
|
|
70
|
+
'chrome.off': '关',
|
|
71
|
+
} satisfies Record<string, string>;
|
|
72
|
+
|
|
73
|
+
/** 本插件的键联合。 */
|
|
74
|
+
export type SettingsCardKey = keyof typeof zh;
|
|
75
|
+
|
|
76
|
+
/** English dictionary, checked complete against the zh key set. */
|
|
77
|
+
export const en: Record<SettingsCardKey, string> = {
|
|
78
|
+
'card.title': 'Auto continue',
|
|
79
|
+
'card.description': 'When a request is interrupted by a non-human cause, automatically send 「继续」 to resume.',
|
|
80
|
+
'field.paused': 'Pause auto-continue',
|
|
81
|
+
'field.pausedHint': 'Globally pause: no live or scan auto-send fires, and queued pending sends are cancelled.',
|
|
82
|
+
'field.continueText': 'Continue text',
|
|
83
|
+
'field.continueTextHint': 'Message automatically sent after an interruption.',
|
|
84
|
+
'field.continueTextMaxTokens': 'Continue text (max tokens)',
|
|
85
|
+
'field.continueTextMaxTokensHint': 'Text sent when the output token ceiling is reached; same placeholders as the continue text.',
|
|
86
|
+
'field.graceMs': 'Grace period (ms)',
|
|
87
|
+
'field.graceMsHint': 'Wait after an interruption; cancelled if the host recovers on its own.',
|
|
88
|
+
'field.cooldownMs': 'Cooldown (ms)',
|
|
89
|
+
'field.cooldownMsHint': 'Minimum interval between auto-continues per session; failed attempts count too.',
|
|
90
|
+
'field.maxConsecutive': 'Max consecutive',
|
|
91
|
+
'field.maxConsecutiveHint': 'Max consecutive auto-continues per session; stops until a user intervenes or a turn completes.',
|
|
92
|
+
'field.scanOnBoot': 'Scan on load / reconnect',
|
|
93
|
+
'field.scanOnBootHint': 'Scan recently interrupted sessions on page load or reconnect (e.g. the host crashed while the browser was closed).',
|
|
94
|
+
'field.scanLimit': 'Scan limit',
|
|
95
|
+
'field.scanLimitHint': 'How many most-recently-updated sessions to check (running / subagent sessions excluded).',
|
|
96
|
+
'field.freshMs': 'Scan window (ms)',
|
|
97
|
+
'field.freshMsHint': 'Only interruptions inside this window are considered.',
|
|
98
|
+
'field.reconnectScanDelayMs': 'Reconnect scan delay (ms)',
|
|
99
|
+
'field.reconnectScanDelayMsHint': 'Wait for the host to finish recovering before scanning after a reconnect.',
|
|
100
|
+
'field.reconnectBackoffMs': 'Reconnect backoff (ms)',
|
|
101
|
+
'field.reconnectBackoffMsHint': 'Interval between event-stream reconnect attempts.',
|
|
102
|
+
'field.verbose': 'Verbose logs',
|
|
103
|
+
'field.verboseHint': 'Log [auto-continue] lines to the browser console.',
|
|
104
|
+
'field.classify': 'Classify errors',
|
|
105
|
+
'field.classifyHint': 'Auto-resume transient failures only (network/timeout/5xx…); auth, balance and model errors are skipped and notified.',
|
|
106
|
+
'field.backoffFactor': 'Backoff factor',
|
|
107
|
+
'field.backoffFactorHint': 'Cooldown multiplier per consecutive failure (2 = 20s→40s→80s…).',
|
|
108
|
+
'field.backoffMaxMs': 'Max backoff (ms)',
|
|
109
|
+
'field.backoffMaxMsHint': 'Cap on the adaptive backoff interval.',
|
|
110
|
+
'field.notify': 'Browser notifications',
|
|
111
|
+
'field.notifyHint': 'Notify when auto-continue fires, gives up, or hits a permanent error; notifications carry "Resume now" and "Pause this session 1h" buttons.',
|
|
112
|
+
'stats.title': "Today's stats",
|
|
113
|
+
'stats.sent': 'Auto-continued',
|
|
114
|
+
'stats.skipped': 'Skipped (permanent)',
|
|
115
|
+
'stats.recovered': 'Recovered',
|
|
116
|
+
'stats.failed': 'Failed after',
|
|
117
|
+
'stats.gaveUp': 'Gave up (cap)',
|
|
118
|
+
'stats.byCode': 'By error code',
|
|
119
|
+
'stats.empty': 'No auto-continue activity today.',
|
|
120
|
+
'stats.reset': 'Reset',
|
|
121
|
+
'pause.title': 'Paused sessions',
|
|
122
|
+
'pause.none': 'No sessions paused.',
|
|
123
|
+
'pause.clearAll': 'Clear all',
|
|
124
|
+
'pause.unpause': 'Resume',
|
|
125
|
+
'pause.minutes': 'min',
|
|
126
|
+
'chrome.collapse': 'Hide settings',
|
|
127
|
+
'chrome.expand': 'Show settings',
|
|
128
|
+
'chrome.unsaved': 'Unsaved',
|
|
129
|
+
'chrome.readOnly': 'This deployment stores settings read-only.',
|
|
130
|
+
'chrome.saveFailed': 'The deployment did not accept these values; they were left for you to correct.',
|
|
131
|
+
'chrome.discard': 'Discard',
|
|
132
|
+
'chrome.saving': 'Saving…',
|
|
133
|
+
'chrome.save': 'Save',
|
|
134
|
+
'chrome.overridden': 'Overridden',
|
|
135
|
+
'chrome.reset': 'Reset to default',
|
|
136
|
+
'chrome.invalidNumber': 'Enter a number, or leave blank to use the default.',
|
|
137
|
+
'chrome.inherit': 'Inherit',
|
|
138
|
+
'chrome.on': 'On',
|
|
139
|
+
'chrome.off': 'Off',
|
|
140
|
+
};
|