@linxin666/dsh-client-ui-task-board 0.2.4 → 0.2.5
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.i18n.yaml +2 -2
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/lib/index.js +17 -15
- package/lib/types/host-runner.d.ts +10 -1
- package/lib/types/host-service.d.ts +2 -1
- package/lib/types/index.d.ts +1 -1
- package/package.json +5 -1
- package/src/host-runner.ts +22 -8
- package/src/host-service.ts +8 -3
- package/src/index.ts +13 -3
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# node scripts/verify-docs.mjs --write <dir>
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 359b35160b1cf7a8c697152b4e3fc60193ed3599
|
|
6
|
+
README.zh.md: 535ac2b5c8b4c6fdbff61c08b9cadae3b5679cc7
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ A hot-pluggable DeepSeek Harness (DSH) Web GUI plugin with a Host-authoritative
|
|
|
18
18
|
- **Deterministic recovery**: a running execution with a recorded session is observed after restart; an interrupted start without a session id is cancelled and is not resent.
|
|
19
19
|
- **Live synchronization**: mutations return a full revisioned snapshot; SSE announces revision, scheduler, and power changes, while reconnect and page visibility recovery fetch a full snapshot.
|
|
20
20
|
- **Optional idle-sleep protection**: off by default; when enabled it covers every running DSH session, enabled non-archived task-board schedules, and unknown session state.
|
|
21
|
-
- **System-prompt injection**: the Host registers a `plugin:task-board` section (order 200) through `SystemPrompt.section`, and the task-board settings can disable the announcement without disabling the board.
|
|
21
|
+
- **System-prompt injection**: the Host registers a `plugin:task-board` section (order 200) through `SystemPrompt.section`, and the task-board settings can disable the announcement without disabling the board. The guidance also reminds agents to close any visible `todo_write` plan before the final answer.
|
|
22
22
|
|
|
23
23
|
## Architecture and protocol
|
|
24
24
|
|
package/README.zh.md
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
- **确定性恢复**:已有 session id 的 running execution 在重启后继续观察;没有 session id 的启动中断会取消且不会重发。
|
|
19
19
|
- **实时同步**:变更返回完整 revision snapshot;SSE 只提示 revision、scheduler 与 power 变化,重连和页面恢复可见时重新拉完整 snapshot。
|
|
20
20
|
- **可选空闲睡眠保护**:默认关闭;开启后覆盖全部运行中的 DSH 会话、已启用且未归档的任务计划和未知会话状态。
|
|
21
|
-
- **系统提示词注入**:Host 通过 `SystemPrompt.section` 注册 order 200 的 `plugin:task-board`
|
|
21
|
+
- **系统提示词注入**:Host 通过 `SystemPrompt.section` 注册 order 200 的 `plugin:task-board` 段;任务看板设置可单独关闭声明而不关闭看板。该提示也会提醒 agent 在最终回复前收尾可见的 `todo_write` 计划列表。
|
|
22
22
|
|
|
23
23
|
## 架构与协议
|
|
24
24
|
|
package/lib/index.js
CHANGED
|
@@ -1361,8 +1361,10 @@ function isErrorTurnEnd(data) {
|
|
|
1361
1361
|
}
|
|
1362
1362
|
var HostExecutionRunner = class {
|
|
1363
1363
|
api;
|
|
1364
|
-
|
|
1364
|
+
commands;
|
|
1365
|
+
constructor(api, commands) {
|
|
1365
1366
|
this.api = api;
|
|
1367
|
+
this.commands = commands;
|
|
1366
1368
|
}
|
|
1367
1369
|
async launch(task) {
|
|
1368
1370
|
if (task.workspaceId !== void 0) {
|
|
@@ -1390,16 +1392,10 @@ var HostExecutionRunner = class {
|
|
|
1390
1392
|
}));
|
|
1391
1393
|
if (!renamed.result.ok) throw failure(renamed.result.error);
|
|
1392
1394
|
if (task.permission !== void 0) {
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
type: "text",
|
|
1398
|
-
text: `/permission ${task.permission}`
|
|
1399
|
-
}]
|
|
1400
|
-
}));
|
|
1401
|
-
if (!command.result.ok) throw failure(command.result.error);
|
|
1402
|
-
if (command.result.value.command?.kind !== "success") throw new Error("permission command was not acknowledged");
|
|
1395
|
+
if (this.commands === void 0) throw new Error("permission command dispatcher is unavailable");
|
|
1396
|
+
const command = await this.commands.execute(sessionId, `/permission ${task.permission}`, AbortSignal.timeout(3e4));
|
|
1397
|
+
if (command === void 0) throw new Error("permission command was not acknowledged");
|
|
1398
|
+
if (command.kind !== "success") throw new Error(command.text ?? "permission command failed");
|
|
1403
1399
|
}
|
|
1404
1400
|
const prompt = await this.api.sessions.prompt(request({
|
|
1405
1401
|
sessionId,
|
|
@@ -1805,7 +1801,7 @@ var TaskBoardHostService = class {
|
|
|
1805
1801
|
now;
|
|
1806
1802
|
constructor(api, options = {}) {
|
|
1807
1803
|
this.ledger = options.ledger ?? new HostTaskLedger();
|
|
1808
|
-
this.runner = new HostExecutionRunner(api);
|
|
1804
|
+
this.runner = new HostExecutionRunner(api, options.commandDispatcher);
|
|
1809
1805
|
this.power = options.power ?? new PowerInhibitor();
|
|
1810
1806
|
this.now = options.now ?? Date.now;
|
|
1811
1807
|
this.ledger.subscribe(() => {
|
|
@@ -2277,10 +2273,12 @@ const DEFAULT_PROXY_TOKEN_ENV = "DSH_TASK_BOARD_PROXY_TOKEN";
|
|
|
2277
2273
|
const inject = [
|
|
2278
2274
|
"systemPrompt",
|
|
2279
2275
|
"apiProxy",
|
|
2280
|
-
"webServer"
|
|
2276
|
+
"webServer",
|
|
2277
|
+
"agents",
|
|
2278
|
+
"commands"
|
|
2281
2279
|
];
|
|
2282
2280
|
/** Model-facing announcement: plugin presence, capabilities, and limits. */
|
|
2283
|
-
const TASK_BOARD_GUIDANCE = "本机已安装 dsh-task-board 插件(DSH Web GUI 的任务看板):侧边栏「任务看板」入口;在 dsh-web-ui 插件全家桶仓库(packages/dsh-task-board)统一维护,经聚合包 web-ui-all 一键安装。能力:多列看板管理任务;Host 权威账本;关闭浏览器后仍由 Host 执行和结算;任务可钉住工作区、agent 预设和权限;支持 Host 本地时区的 5 段 cron,错过的触发点不补跑;可选且默认关闭的空闲系统睡眠保护允许屏幕熄灭,但不承诺拦截合盖、手动睡眠、休眠、关机或唤醒已睡眠机器。执行消耗 API 额度。用户提到「任务看板 / 看板 /
|
|
2281
|
+
const TASK_BOARD_GUIDANCE = "本机已安装 dsh-task-board 插件(DSH Web GUI 的任务看板):侧边栏「任务看板」入口;在 dsh-web-ui 插件全家桶仓库(packages/dsh-task-board)统一维护,经聚合包 web-ui-all 一键安装。能力:多列看板管理任务;Host 权威账本;关闭浏览器后仍由 Host 执行和结算;任务可钉住工作区、agent 预设和权限;支持 Host 本地时区的 5 段 cron,错过的触发点不补跑;可选且默认关闭的空闲系统睡眠保护允许屏幕熄灭,但不承诺拦截合盖、手动睡眠、休眠、关机或唤醒已睡眠机器。执行消耗 API 额度。用户提到「任务看板 / 看板 / 定时任务」时即指本插件,请据此协作。若你同时用 todo_write 维护会话顶部的可见计划列表,最终回复前必须再次调用 todo_write 收尾:没有剩余工作时不要保留 in_progress,已完成的最后一步要标为 completed。";
|
|
2284
2282
|
/**
|
|
2285
2283
|
* Settings namespace of the board's announcement capability — the section the
|
|
2286
2284
|
* web settings surface edits. Spelled here rather than imported: the browser
|
|
@@ -2319,7 +2317,11 @@ const DEFAULT_ANNOUNCE = true;
|
|
|
2319
2317
|
*/
|
|
2320
2318
|
const apply = mountOnce("@linxin666/dsh-client-ui-task-board", applyImpl);
|
|
2321
2319
|
function applyImpl(ctx, config) {
|
|
2322
|
-
const host = new TaskBoardHostService(ctx.apiProxy)
|
|
2320
|
+
const host = new TaskBoardHostService(ctx.apiProxy, { commandDispatcher: { async execute(sessionId, line, signal) {
|
|
2321
|
+
const agent = ctx.agents.get(sessionId);
|
|
2322
|
+
if (agent === void 0) throw new Error(`execution session ${sessionId} is not available`);
|
|
2323
|
+
return (await ctx.commands.execute(agent, line, [], signal))?.result;
|
|
2324
|
+
} } });
|
|
2323
2325
|
host.setConfiguration(config?.enabled ?? true, config?.preventIdleSleep ?? false);
|
|
2324
2326
|
host.start();
|
|
2325
2327
|
ctx.effect(() => {
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import type { ApiProxy } from '@deepseek-ai/dsh-host-apiproxy';
|
|
2
|
+
import type { CommandResult } from '@deepseek-ai/dsh-commands/types';
|
|
2
3
|
import type { TaskRecord } from './core/tasks.ts';
|
|
3
4
|
/** One session-list row, extracted from the sessions.list RPC result. */
|
|
4
5
|
export type SessionSummary = Extract<Awaited<ReturnType<ApiProxy['sessions']['list']>>['result'], {
|
|
5
6
|
ok: true;
|
|
6
7
|
}>['value']['items'][number];
|
|
8
|
+
type ExecutionSessionId = Extract<Awaited<ReturnType<ApiProxy['sessions']['create']>>['result'], {
|
|
9
|
+
ok: true;
|
|
10
|
+
}>['value']['sessionId'];
|
|
11
|
+
export interface SessionCommandDispatcher {
|
|
12
|
+
execute(sessionId: ExecutionSessionId, line: string, signal: AbortSignal): Promise<CommandResult | undefined>;
|
|
13
|
+
}
|
|
7
14
|
export type ExecutionInspection = {
|
|
8
15
|
outcome: 'pending';
|
|
9
16
|
} | {
|
|
@@ -22,7 +29,8 @@ export declare class SessionLaunchError extends Error {
|
|
|
22
29
|
}
|
|
23
30
|
export declare class HostExecutionRunner {
|
|
24
31
|
private readonly api;
|
|
25
|
-
|
|
32
|
+
private readonly commands?;
|
|
33
|
+
constructor(api: ApiProxy, commands?: SessionCommandDispatcher | undefined);
|
|
26
34
|
launch(task: TaskRecord): Promise<string>;
|
|
27
35
|
listRunning(): Promise<{
|
|
28
36
|
known: true;
|
|
@@ -39,3 +47,4 @@ export declare class HostExecutionRunner {
|
|
|
39
47
|
*/
|
|
40
48
|
inspect(sessionId: string, startedAt?: number, sessions?: readonly SessionSummary[]): Promise<ExecutionInspection>;
|
|
41
49
|
}
|
|
50
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ApiProxy } from '@deepseek-ai/dsh-host-apiproxy';
|
|
2
2
|
import { HostTaskLedger } from './host-ledger.ts';
|
|
3
|
-
import { HostExecutionRunner } from './host-runner.ts';
|
|
3
|
+
import { HostExecutionRunner, type SessionCommandDispatcher } from './host-runner.ts';
|
|
4
4
|
import { PowerInhibitor } from './power-inhibitor.ts';
|
|
5
5
|
import type { TaskBoardAction, TaskBoardEventPayload, TaskBoardSnapshot } from './protocol.ts';
|
|
6
6
|
export declare class TaskBoardHostService {
|
|
@@ -21,6 +21,7 @@ export declare class TaskBoardHostService {
|
|
|
21
21
|
ledger?: HostTaskLedger;
|
|
22
22
|
power?: PowerInhibitor;
|
|
23
23
|
now?: () => number;
|
|
24
|
+
commandDispatcher?: SessionCommandDispatcher;
|
|
24
25
|
});
|
|
25
26
|
start(): void;
|
|
26
27
|
setConfiguration(active: boolean, preventIdleSleep: boolean): void;
|
package/lib/types/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import z from 'schemastery';
|
|
|
11
11
|
export declare const DEFAULT_PROXY_TOKEN_ENV = "DSH_TASK_BOARD_PROXY_TOKEN";
|
|
12
12
|
export declare const inject: string[];
|
|
13
13
|
/** Model-facing announcement: plugin presence, capabilities, and limits. */
|
|
14
|
-
export declare const TASK_BOARD_GUIDANCE = "\u672C\u673A\u5DF2\u5B89\u88C5 dsh-task-board \u63D2\u4EF6\uFF08DSH Web GUI \u7684\u4EFB\u52A1\u770B\u677F\uFF09\uFF1A\u4FA7\u8FB9\u680F\u300C\u4EFB\u52A1\u770B\u677F\u300D\u5165\u53E3\uFF1B\u5728 dsh-web-ui \u63D2\u4EF6\u5168\u5BB6\u6876\u4ED3\u5E93\uFF08packages/dsh-task-board\uFF09\u7EDF\u4E00\u7EF4\u62A4\uFF0C\u7ECF\u805A\u5408\u5305 web-ui-all \u4E00\u952E\u5B89\u88C5\u3002\u80FD\u529B\uFF1A\u591A\u5217\u770B\u677F\u7BA1\u7406\u4EFB\u52A1\uFF1BHost \u6743\u5A01\u8D26\u672C\uFF1B\u5173\u95ED\u6D4F\u89C8\u5668\u540E\u4ECD\u7531 Host \u6267\u884C\u548C\u7ED3\u7B97\uFF1B\u4EFB\u52A1\u53EF\u9489\u4F4F\u5DE5\u4F5C\u533A\u3001agent \u9884\u8BBE\u548C\u6743\u9650\uFF1B\u652F\u6301 Host \u672C\u5730\u65F6\u533A\u7684 5 \u6BB5 cron\uFF0C\u9519\u8FC7\u7684\u89E6\u53D1\u70B9\u4E0D\u8865\u8DD1\uFF1B\u53EF\u9009\u4E14\u9ED8\u8BA4\u5173\u95ED\u7684\u7A7A\u95F2\u7CFB\u7EDF\u7761\u7720\u4FDD\u62A4\u5141\u8BB8\u5C4F\u5E55\u7184\u706D\uFF0C\u4F46\u4E0D\u627F\u8BFA\u62E6\u622A\u5408\u76D6\u3001\u624B\u52A8\u7761\u7720\u3001\u4F11\u7720\u3001\u5173\u673A\u6216\u5524\u9192\u5DF2\u7761\u7720\u673A\u5668\u3002\u6267\u884C\u6D88\u8017 API \u989D\u5EA6\u3002\u7528\u6237\u63D0\u5230\u300C\u4EFB\u52A1\u770B\u677F / \u770B\u677F / \u5B9A\u65F6\u4EFB\u52A1\u300D\u65F6\u5373\u6307\u672C\u63D2\u4EF6\uFF0C\u8BF7\u636E\u6B64\u534F\u4F5C\u3002";
|
|
14
|
+
export declare const TASK_BOARD_GUIDANCE = "\u672C\u673A\u5DF2\u5B89\u88C5 dsh-task-board \u63D2\u4EF6\uFF08DSH Web GUI \u7684\u4EFB\u52A1\u770B\u677F\uFF09\uFF1A\u4FA7\u8FB9\u680F\u300C\u4EFB\u52A1\u770B\u677F\u300D\u5165\u53E3\uFF1B\u5728 dsh-web-ui \u63D2\u4EF6\u5168\u5BB6\u6876\u4ED3\u5E93\uFF08packages/dsh-task-board\uFF09\u7EDF\u4E00\u7EF4\u62A4\uFF0C\u7ECF\u805A\u5408\u5305 web-ui-all \u4E00\u952E\u5B89\u88C5\u3002\u80FD\u529B\uFF1A\u591A\u5217\u770B\u677F\u7BA1\u7406\u4EFB\u52A1\uFF1BHost \u6743\u5A01\u8D26\u672C\uFF1B\u5173\u95ED\u6D4F\u89C8\u5668\u540E\u4ECD\u7531 Host \u6267\u884C\u548C\u7ED3\u7B97\uFF1B\u4EFB\u52A1\u53EF\u9489\u4F4F\u5DE5\u4F5C\u533A\u3001agent \u9884\u8BBE\u548C\u6743\u9650\uFF1B\u652F\u6301 Host \u672C\u5730\u65F6\u533A\u7684 5 \u6BB5 cron\uFF0C\u9519\u8FC7\u7684\u89E6\u53D1\u70B9\u4E0D\u8865\u8DD1\uFF1B\u53EF\u9009\u4E14\u9ED8\u8BA4\u5173\u95ED\u7684\u7A7A\u95F2\u7CFB\u7EDF\u7761\u7720\u4FDD\u62A4\u5141\u8BB8\u5C4F\u5E55\u7184\u706D\uFF0C\u4F46\u4E0D\u627F\u8BFA\u62E6\u622A\u5408\u76D6\u3001\u624B\u52A8\u7761\u7720\u3001\u4F11\u7720\u3001\u5173\u673A\u6216\u5524\u9192\u5DF2\u7761\u7720\u673A\u5668\u3002\u6267\u884C\u6D88\u8017 API \u989D\u5EA6\u3002\u7528\u6237\u63D0\u5230\u300C\u4EFB\u52A1\u770B\u677F / \u770B\u677F / \u5B9A\u65F6\u4EFB\u52A1\u300D\u65F6\u5373\u6307\u672C\u63D2\u4EF6\uFF0C\u8BF7\u636E\u6B64\u534F\u4F5C\u3002\u82E5\u4F60\u540C\u65F6\u7528 todo_write \u7EF4\u62A4\u4F1A\u8BDD\u9876\u90E8\u7684\u53EF\u89C1\u8BA1\u5212\u5217\u8868\uFF0C\u6700\u7EC8\u56DE\u590D\u524D\u5FC5\u987B\u518D\u6B21\u8C03\u7528 todo_write \u6536\u5C3E\uFF1A\u6CA1\u6709\u5269\u4F59\u5DE5\u4F5C\u65F6\u4E0D\u8981\u4FDD\u7559 in_progress\uFF0C\u5DF2\u5B8C\u6210\u7684\u6700\u540E\u4E00\u6B65\u8981\u6807\u4E3A completed\u3002";
|
|
15
15
|
/**
|
|
16
16
|
* Settings namespace of the board's announcement capability — the section the
|
|
17
17
|
* web settings surface edits. Spelled here rather than imported: the browser
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linxin666/dsh-client-ui-task-board",
|
|
3
3
|
"description": "Host-authoritative task board for the DSH Web GUI with real session execution, Host cron scheduling, and optional cross-platform idle-sleep protection; mounted without DSH source changes.",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.5",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/types/index.d.ts",
|
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
+
"@deepseek-ai/dsh-agent": "^0.1.0-rc.8",
|
|
39
|
+
"@deepseek-ai/dsh-commands": "^0.1.0-rc.8",
|
|
38
40
|
"react": "^18.2.0"
|
|
39
41
|
},
|
|
40
42
|
"dependencies": {
|
|
@@ -42,11 +44,13 @@
|
|
|
42
44
|
},
|
|
43
45
|
"devDependencies": {
|
|
44
46
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
47
|
+
"@deepseek-ai/dsh-agent": "^0.1.0-rc.8",
|
|
45
48
|
"@deepseek-ai/dsh-client-connection": "^0.1.0-rc.8",
|
|
46
49
|
"@deepseek-ai/dsh-client-locale": "^0.1.0-rc.8",
|
|
47
50
|
"@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.8",
|
|
48
51
|
"@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.8",
|
|
49
52
|
"@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.8",
|
|
53
|
+
"@deepseek-ai/dsh-commands": "^0.1.0-rc.8",
|
|
50
54
|
"@deepseek-ai/dsh-host-apiproxy": "^0.1.0-rc.8",
|
|
51
55
|
"@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.8",
|
|
52
56
|
"@deepseek-ai/dsh-settings": "^0.1.0-rc.8",
|
package/src/host-runner.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ApiProxy, RpcId } from '@deepseek-ai/dsh-host-apiproxy'
|
|
2
|
+
import type { CommandResult } from '@deepseek-ai/dsh-commands/types'
|
|
2
3
|
import type { TaskRecord } from './core/tasks.ts'
|
|
3
4
|
|
|
4
5
|
function request<T>(payload: T) {
|
|
@@ -15,6 +16,19 @@ export type SessionSummary = Extract<
|
|
|
15
16
|
{ ok: true }
|
|
16
17
|
>['value']['items'][number]
|
|
17
18
|
|
|
19
|
+
type ExecutionSessionId = Extract<
|
|
20
|
+
Awaited<ReturnType<ApiProxy['sessions']['create']>>['result'],
|
|
21
|
+
{ ok: true }
|
|
22
|
+
>['value']['sessionId']
|
|
23
|
+
|
|
24
|
+
export interface SessionCommandDispatcher {
|
|
25
|
+
execute(
|
|
26
|
+
sessionId: ExecutionSessionId,
|
|
27
|
+
line: string,
|
|
28
|
+
signal: AbortSignal,
|
|
29
|
+
): Promise<CommandResult | undefined>
|
|
30
|
+
}
|
|
31
|
+
|
|
18
32
|
export type ExecutionInspection =
|
|
19
33
|
| { outcome: 'pending' }
|
|
20
34
|
| { outcome: 'succeeded' }
|
|
@@ -36,7 +50,10 @@ function isErrorTurnEnd(data: unknown): boolean {
|
|
|
36
50
|
}
|
|
37
51
|
|
|
38
52
|
export class HostExecutionRunner {
|
|
39
|
-
constructor(
|
|
53
|
+
constructor(
|
|
54
|
+
private readonly api: ApiProxy,
|
|
55
|
+
private readonly commands?: SessionCommandDispatcher,
|
|
56
|
+
) {}
|
|
40
57
|
|
|
41
58
|
async launch(task: TaskRecord): Promise<string> {
|
|
42
59
|
if (task.workspaceId !== undefined) {
|
|
@@ -63,13 +80,10 @@ export class HostExecutionRunner {
|
|
|
63
80
|
const renamed = await this.api.sessions.rename(request({ sessionId, title: task.title }))
|
|
64
81
|
if (!renamed.result.ok) throw failure(renamed.result.error)
|
|
65
82
|
if (task.permission !== undefined) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}))
|
|
71
|
-
if (!command.result.ok) throw failure(command.result.error)
|
|
72
|
-
if (command.result.value.command?.kind !== 'success') throw new Error('permission command was not acknowledged')
|
|
83
|
+
if (this.commands === undefined) throw new Error('permission command dispatcher is unavailable')
|
|
84
|
+
const command = await this.commands.execute(sessionId, `/permission ${task.permission}`, AbortSignal.timeout(30_000))
|
|
85
|
+
if (command === undefined) throw new Error('permission command was not acknowledged')
|
|
86
|
+
if (command.kind !== 'success') throw new Error(command.text ?? 'permission command failed')
|
|
73
87
|
}
|
|
74
88
|
const prompt = await this.api.sessions.prompt(request({
|
|
75
89
|
sessionId,
|
package/src/host-service.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { ApiProxy } from '@deepseek-ai/dsh-host-apiproxy'
|
|
|
2
2
|
import { nextRunAtMs } from './core/schedule.ts'
|
|
3
3
|
import type { TaskRecord } from './core/tasks.ts'
|
|
4
4
|
import { HostTaskLedger, type OpenedRun } from './host-ledger.ts'
|
|
5
|
-
import { HostExecutionRunner, SessionLaunchError, type SessionSummary } from './host-runner.ts'
|
|
5
|
+
import { HostExecutionRunner, SessionLaunchError, type SessionCommandDispatcher, type SessionSummary } from './host-runner.ts'
|
|
6
6
|
import { PowerInhibitor } from './power-inhibitor.ts'
|
|
7
7
|
import type { TaskBoardAction, TaskBoardEventPayload, TaskBoardSnapshot } from './protocol.ts'
|
|
8
8
|
|
|
@@ -25,9 +25,14 @@ export class TaskBoardHostService {
|
|
|
25
25
|
private lastPowerJson = ''
|
|
26
26
|
private readonly now: () => number
|
|
27
27
|
|
|
28
|
-
constructor(api: ApiProxy, options: {
|
|
28
|
+
constructor(api: ApiProxy, options: {
|
|
29
|
+
ledger?: HostTaskLedger
|
|
30
|
+
power?: PowerInhibitor
|
|
31
|
+
now?: () => number
|
|
32
|
+
commandDispatcher?: SessionCommandDispatcher
|
|
33
|
+
} = {}) {
|
|
29
34
|
this.ledger = options.ledger ?? new HostTaskLedger()
|
|
30
|
-
this.runner = new HostExecutionRunner(api)
|
|
35
|
+
this.runner = new HostExecutionRunner(api, options.commandDispatcher)
|
|
31
36
|
this.power = options.power ?? new PowerInhibitor()
|
|
32
37
|
this.now = options.now ?? Date.now
|
|
33
38
|
this.ledger.subscribe(() => {
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { Context } from '@deepseek-ai/cordis'
|
|
10
|
+
import type {} from '@deepseek-ai/dsh-agent'
|
|
11
|
+
import type {} from '@deepseek-ai/dsh-commands'
|
|
10
12
|
import { installSettingsSection, settingsNamespace } from '@deepseek-ai/dsh-settings'
|
|
11
13
|
import z from 'schemastery'
|
|
12
14
|
import type {} from '@deepseek-ai/dsh-system-prompt'
|
|
@@ -22,10 +24,10 @@ const SECTION_ORDER = 200
|
|
|
22
24
|
/** Default environment variable holding the authenticated proxy token. */
|
|
23
25
|
export const DEFAULT_PROXY_TOKEN_ENV = 'DSH_TASK_BOARD_PROXY_TOKEN'
|
|
24
26
|
|
|
25
|
-
export const inject = ['systemPrompt', 'apiProxy', 'webServer']
|
|
27
|
+
export const inject = ['systemPrompt', 'apiProxy', 'webServer', 'agents', 'commands']
|
|
26
28
|
|
|
27
29
|
/** Model-facing announcement: plugin presence, capabilities, and limits. */
|
|
28
|
-
export const TASK_BOARD_GUIDANCE = '本机已安装 dsh-task-board 插件(DSH Web GUI 的任务看板):侧边栏「任务看板」入口;在 dsh-web-ui 插件全家桶仓库(packages/dsh-task-board)统一维护,经聚合包 web-ui-all 一键安装。能力:多列看板管理任务;Host 权威账本;关闭浏览器后仍由 Host 执行和结算;任务可钉住工作区、agent 预设和权限;支持 Host 本地时区的 5 段 cron,错过的触发点不补跑;可选且默认关闭的空闲系统睡眠保护允许屏幕熄灭,但不承诺拦截合盖、手动睡眠、休眠、关机或唤醒已睡眠机器。执行消耗 API 额度。用户提到「任务看板 / 看板 /
|
|
30
|
+
export const TASK_BOARD_GUIDANCE = '本机已安装 dsh-task-board 插件(DSH Web GUI 的任务看板):侧边栏「任务看板」入口;在 dsh-web-ui 插件全家桶仓库(packages/dsh-task-board)统一维护,经聚合包 web-ui-all 一键安装。能力:多列看板管理任务;Host 权威账本;关闭浏览器后仍由 Host 执行和结算;任务可钉住工作区、agent 预设和权限;支持 Host 本地时区的 5 段 cron,错过的触发点不补跑;可选且默认关闭的空闲系统睡眠保护允许屏幕熄灭,但不承诺拦截合盖、手动睡眠、休眠、关机或唤醒已睡眠机器。执行消耗 API 额度。用户提到「任务看板 / 看板 / 定时任务」时即指本插件,请据此协作。若你同时用 todo_write 维护会话顶部的可见计划列表,最终回复前必须再次调用 todo_write 收尾:没有剩余工作时不要保留 in_progress,已完成的最后一步要标为 completed。'
|
|
29
31
|
|
|
30
32
|
/**
|
|
31
33
|
* Settings namespace of the board's announcement capability — the section the
|
|
@@ -87,7 +89,15 @@ const DEFAULT_ANNOUNCE = true
|
|
|
87
89
|
export const apply = mountOnce('@linxin666/dsh-client-ui-task-board', applyImpl)
|
|
88
90
|
|
|
89
91
|
function applyImpl(ctx: Context, config?: Config): void {
|
|
90
|
-
const host = new TaskBoardHostService(ctx.apiProxy
|
|
92
|
+
const host = new TaskBoardHostService(ctx.apiProxy, {
|
|
93
|
+
commandDispatcher: {
|
|
94
|
+
async execute(sessionId, line, signal) {
|
|
95
|
+
const agent = ctx.agents.get(sessionId)
|
|
96
|
+
if (agent === undefined) throw new Error(`execution session ${sessionId} is not available`)
|
|
97
|
+
return (await ctx.commands.execute(agent, line, [], signal))?.result
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
})
|
|
91
101
|
host.setConfiguration(config?.enabled ?? true, config?.preventIdleSleep ?? false)
|
|
92
102
|
host.start()
|
|
93
103
|
ctx.effect(() => {
|