dsh-task-ledger 0.0.125 → 0.0.127
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/dist/client.js +21192 -11429
- package/dist/client.js.map +1 -1
- package/dist/host/errors.d.ts +9 -3
- package/dist/host/errors.js +10 -0
- package/dist/host/repositories/cache.d.ts +2 -2
- package/dist/host/repositories/dirs.repository.d.ts +37 -0
- package/dist/host/repositories/dirs.repository.js +97 -0
- package/dist/host/repositories/history.repository.d.ts +20 -0
- package/dist/host/repositories/history.repository.js +63 -0
- package/dist/host/repositories/identity.repository.d.ts +53 -3
- package/dist/host/repositories/identity.repository.js +105 -10
- package/dist/host/repositories/ledger.repository.d.ts +0 -8
- package/dist/host/repositories/ledger.repository.js +3 -20
- package/dist/host/repositories/runner.d.ts +29 -0
- package/dist/host/repositories/runner.js +66 -4
- package/dist/host/repositories/stats.repository.js +2 -2
- package/dist/host/repositories/task.repository.d.ts +12 -0
- package/dist/host/repositories/task.repository.js +63 -0
- package/dist/host/repositories/trend.repository.d.ts +15 -5
- package/dist/host/repositories/trend.repository.js +38 -11
- package/dist/host/routes.d.ts +13 -1
- package/dist/host/routes.js +379 -12
- package/dist/host/services/continue.service.d.ts +126 -0
- package/dist/host/services/continue.service.js +138 -0
- package/dist/host/services/dirs.service.d.ts +34 -0
- package/dist/host/services/dirs.service.js +66 -0
- package/dist/host/services/history.service.d.ts +14 -0
- package/dist/host/services/history.service.js +172 -0
- package/dist/host/services/identity.service.d.ts +53 -0
- package/dist/host/services/identity.service.js +89 -0
- package/dist/host/services/stats.service.d.ts +2 -2
- package/dist/host/services/stats.service.js +23 -6
- package/dist/host/services/task.service.d.ts +15 -0
- package/dist/host/services/task.service.js +15 -0
- package/dist/host/services/trend.service.d.ts +2 -2
- package/dist/host/services/trend.service.js +5 -5
- package/dist/host/services/workspaces.service.d.ts +10 -0
- package/dist/host/services/workspaces.service.js +28 -0
- package/dist/host/types.d.ts +108 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.js +31 -3
- package/package.json +2 -2
- package/skill/SKILL.md +13 -13
- package/skill/package.json +1 -1
- package/skill/references/init-identity.md +1 -1
- package/skill/references/troubleshooting.md +1 -1
- package/skill/scripts/bin/ledger-darwin-arm64 +0 -0
- package/skill/scripts/bin/ledger-linux-amd64 +0 -0
- package/skill/scripts/bin/ledger-windows-amd64.exe +0 -0
- package/dist/host/workspace.d.ts +0 -20
- package/dist/host/workspace.js +0 -17
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { IdentityMissingError } from "../errors.js";
|
|
3
4
|
/**
|
|
4
5
|
* 内嵌 skill 入口的默认路径:dist/host/repositories/runner.js → 包根 skill/scripts/progress
|
|
5
6
|
* (比原 host/script.js 深一层 ⇒ 相对路径多一级 `../`)。
|
|
@@ -11,6 +12,32 @@ import { fileURLToPath } from "node:url";
|
|
|
11
12
|
const DEFAULT_SCRIPT_PATH = fileURLToPath(new URL("../../../skill/scripts/progress", import.meta.url));
|
|
12
13
|
/** 单次脚本调用超时上限(ms)。实测单仓 5 万行全量 1.2s,10s 是宽松上限。 */
|
|
13
14
|
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
15
|
+
/** 脚本绝对路径(界面上要写给用户复制的命令用;别在别处再拼一份)。 */
|
|
16
|
+
export function scriptPath() {
|
|
17
|
+
return DEFAULT_SCRIPT_PATH;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 脚本失败的统一出口:**没身份单独成类**(→ `LEDGER_IDENTITY_MISSING`),其余照旧是普通 Error。
|
|
21
|
+
* 各处别自己 `new Error(result.error)` —— 那样「没身份」就淹进「台账坏了」里,界面分不出来。
|
|
22
|
+
*/
|
|
23
|
+
export function failureOf(result, prefix = "", workspaceId = null) {
|
|
24
|
+
const message = `${prefix}${result.error}`;
|
|
25
|
+
return result.identityMissing === true
|
|
26
|
+
? new IdentityMissingError(message, workspaceId)
|
|
27
|
+
: new Error(message);
|
|
28
|
+
}
|
|
29
|
+
/** skill 侧 `ExitIdentityMissing`(`packages/skill/src/internal/shell/runner.go`)。 */
|
|
30
|
+
const IDENTITY_MISSING_EXIT = 100;
|
|
31
|
+
/** skill 过程标记的行前缀(`shell/render.go` 的 stepf)。 */
|
|
32
|
+
const STEP_PREFIX = "#step ";
|
|
33
|
+
/** 去掉 stderr 里的过程标记行:报错文案只留人话,别把 `#step` 漏到界面上。 */
|
|
34
|
+
function withoutSteps(stderr) {
|
|
35
|
+
return stderr
|
|
36
|
+
.split("\n")
|
|
37
|
+
.filter((line) => !line.startsWith(STEP_PREFIX))
|
|
38
|
+
.join("\n")
|
|
39
|
+
.trim();
|
|
40
|
+
}
|
|
14
41
|
/**
|
|
15
42
|
* 起一次台账程序、收 stdout / stderr。出错一律归一成人话(起不了程序 / 超时 / 非零退出)。
|
|
16
43
|
* 解析留给调用方:读命令要 JSON,写命令要原文。
|
|
@@ -18,12 +45,18 @@ const DEFAULT_TIMEOUT_MS = 10_000;
|
|
|
18
45
|
function exec(sub, args, opts) {
|
|
19
46
|
const scriptPath = opts?.scriptPath ?? DEFAULT_SCRIPT_PATH;
|
|
20
47
|
const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
48
|
+
const onStep = opts?.onStep;
|
|
21
49
|
return new Promise((resolve) => {
|
|
22
50
|
const child = spawn(scriptPath, [sub, ...args], {
|
|
23
51
|
stdio: ["ignore", "pipe", "pipe"],
|
|
52
|
+
env: onStep === undefined
|
|
53
|
+
? process.env
|
|
54
|
+
: { ...process.env, TASK_LEDGER_STEPS: "1" },
|
|
24
55
|
});
|
|
25
56
|
let stdout = "";
|
|
26
57
|
let stderr = "";
|
|
58
|
+
/** 未收完的一行(stderr 是流,标记可能被切在两个 chunk 里)。 */
|
|
59
|
+
let stderrRest = "";
|
|
27
60
|
let settled = false;
|
|
28
61
|
const timer = setTimeout(() => {
|
|
29
62
|
child.kill();
|
|
@@ -43,7 +76,17 @@ function exec(sub, args, opts) {
|
|
|
43
76
|
stdout += chunk.toString();
|
|
44
77
|
});
|
|
45
78
|
child.stderr.on("data", (chunk) => {
|
|
46
|
-
|
|
79
|
+
const text = chunk.toString();
|
|
80
|
+
stderr += text;
|
|
81
|
+
if (onStep === undefined)
|
|
82
|
+
return;
|
|
83
|
+
stderrRest += text;
|
|
84
|
+
const lines = stderrRest.split("\n");
|
|
85
|
+
stderrRest = lines.pop() ?? "";
|
|
86
|
+
for (const line of lines) {
|
|
87
|
+
if (line.startsWith(STEP_PREFIX))
|
|
88
|
+
onStep(line.slice(STEP_PREFIX.length));
|
|
89
|
+
}
|
|
47
90
|
});
|
|
48
91
|
child.on("error", (error) => {
|
|
49
92
|
settle({
|
|
@@ -52,14 +95,16 @@ function exec(sub, args, opts) {
|
|
|
52
95
|
});
|
|
53
96
|
});
|
|
54
97
|
child.on("close", (code) => {
|
|
98
|
+
const message = withoutSteps(stderr);
|
|
55
99
|
if (code !== 0) {
|
|
56
100
|
settle({
|
|
57
101
|
ok: false,
|
|
58
|
-
error:
|
|
102
|
+
error: message || `台账程序退出码 ${String(code)}`,
|
|
103
|
+
exitCode: code ?? undefined,
|
|
59
104
|
});
|
|
60
105
|
return;
|
|
61
106
|
}
|
|
62
|
-
settle({ ok: true, stdout, stderr:
|
|
107
|
+
settle({ ok: true, stdout, stderr: message });
|
|
63
108
|
});
|
|
64
109
|
});
|
|
65
110
|
}
|
|
@@ -73,9 +118,26 @@ function exec(sub, args, opts) {
|
|
|
73
118
|
* @param opts.timeoutMs - 覆盖超时
|
|
74
119
|
*/
|
|
75
120
|
export async function runLedgerScript(sub, args, opts) {
|
|
121
|
+
return parseScriptResult(await exec(sub, args, opts));
|
|
122
|
+
}
|
|
123
|
+
/** 写命令:认领 / 释放 / 结案这类改台账的动作走它(读命令走 `runLedgerScript`)。 */
|
|
124
|
+
export async function runLedgerCommand(sub, args, opts) {
|
|
76
125
|
const result = await exec(sub, args, opts);
|
|
77
126
|
if (!result.ok)
|
|
78
|
-
return
|
|
127
|
+
return {
|
|
128
|
+
ok: false,
|
|
129
|
+
error: result.error,
|
|
130
|
+
identityMissing: result.exitCode === IDENTITY_MISSING_EXIT,
|
|
131
|
+
};
|
|
132
|
+
return { ok: true, output: result.stdout.trim() };
|
|
133
|
+
}
|
|
134
|
+
function parseScriptResult(result) {
|
|
135
|
+
if (!result.ok)
|
|
136
|
+
return {
|
|
137
|
+
ok: false,
|
|
138
|
+
error: result.error,
|
|
139
|
+
identityMissing: result.exitCode === IDENTITY_MISSING_EXIT,
|
|
140
|
+
};
|
|
79
141
|
try {
|
|
80
142
|
return { ok: true, data: JSON.parse(result.stdout) };
|
|
81
143
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { LedgerDataError } from "../errors.js";
|
|
12
12
|
import { cached, cacheKey } from "./cache.js";
|
|
13
|
-
import { runLedgerScript } from "./runner.js";
|
|
13
|
+
import { failureOf, runLedgerScript } from "./runner.js";
|
|
14
14
|
function isPlainObject(value) {
|
|
15
15
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
16
16
|
}
|
|
@@ -29,7 +29,7 @@ export async function readStats(workspace) {
|
|
|
29
29
|
"--json",
|
|
30
30
|
]);
|
|
31
31
|
if (!result.ok)
|
|
32
|
-
throw
|
|
32
|
+
throw failureOf(result, `${workspace.title}: `, workspace.id);
|
|
33
33
|
return parseStats(result.data, workspace.title);
|
|
34
34
|
});
|
|
35
35
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** 界面行内按钮对应的动作:认领 / 释放 / 取消归档 / 正常结案。 */
|
|
2
|
+
export type TaskAction = "claim" | "release" | "cancel" | "close";
|
|
3
|
+
/** 写命令的阶段 key(与 skill `runner.go` 里的 `stepf(...)` 一一对应)。 */
|
|
4
|
+
export type TaskActionStep = "check" | "sync" | "write" | "commit" | "push";
|
|
5
|
+
/**
|
|
6
|
+
* 跑一条任务写命令。
|
|
7
|
+
*
|
|
8
|
+
* @param summary - 「取消」与「结案」都用:一句话理由 / 结案摘要,写进历史行与执行记录。
|
|
9
|
+
* 留空就不传 `--summary`(skill 允许取消不带摘要;正常结案由界面强制填)。
|
|
10
|
+
* @param onStep - 过程步骤回调(逐条转发给界面做进度翻牌),不传就不让 skill 打标记。
|
|
11
|
+
*/
|
|
12
|
+
export declare function runTaskAction(repo: string, id: string, action: TaskAction, summary?: string, onStep?: (step: TaskActionStep) => void): Promise<void>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { failureOf, runLedgerCommand, } from "./runner.js";
|
|
2
|
+
/**
|
|
3
|
+
* 任务写动作(认领 / 释放 / 取消归档)—— 一律走 skill,插件不碰台账文件。
|
|
4
|
+
*
|
|
5
|
+
* 写命令只回人话(`shell/render.go` 的 RenderResult),**不认 --json** ⇒ 走 `runLedgerCommand`
|
|
6
|
+
* 而不是 `runLedgerScript`。每条写命令内部都是「取最新 → 改 → 提交 → 推送」,
|
|
7
|
+
* 默认 10s 会被判超时(脚本被 kill 时可能改到一半)⇒ 与 rename / forget 同档给足时间。
|
|
8
|
+
*/
|
|
9
|
+
const WRITE_TIMEOUT_MS = 120_000;
|
|
10
|
+
const ACTION_NAME = {
|
|
11
|
+
claim: "认领",
|
|
12
|
+
release: "释放",
|
|
13
|
+
cancel: "取消",
|
|
14
|
+
close: "结案",
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* 跑一条任务写命令。
|
|
18
|
+
*
|
|
19
|
+
* @param summary - 「取消」与「结案」都用:一句话理由 / 结案摘要,写进历史行与执行记录。
|
|
20
|
+
* 留空就不传 `--summary`(skill 允许取消不带摘要;正常结案由界面强制填)。
|
|
21
|
+
* @param onStep - 过程步骤回调(逐条转发给界面做进度翻牌),不传就不让 skill 打标记。
|
|
22
|
+
*/
|
|
23
|
+
export async function runTaskAction(repo, id, action, summary = "", onStep) {
|
|
24
|
+
const opts = {
|
|
25
|
+
timeoutMs: WRITE_TIMEOUT_MS,
|
|
26
|
+
...(onStep === undefined
|
|
27
|
+
? {}
|
|
28
|
+
: {
|
|
29
|
+
// skill 侧 key 是字符串,这里收窄成阶段联合类型(多一个 key 也不该让整条命令失败)
|
|
30
|
+
onStep: (step) => onStep(step),
|
|
31
|
+
}),
|
|
32
|
+
};
|
|
33
|
+
let result;
|
|
34
|
+
switch (action) {
|
|
35
|
+
case "claim":
|
|
36
|
+
result = await runLedgerCommand("claim", ["--id", id, "--repo", repo], opts);
|
|
37
|
+
break;
|
|
38
|
+
case "release":
|
|
39
|
+
result = await runLedgerCommand("set", ["--id", id, "--release", "--repo", repo], opts);
|
|
40
|
+
break;
|
|
41
|
+
case "close":
|
|
42
|
+
result = await runLedgerCommand("close", [
|
|
43
|
+
"--id",
|
|
44
|
+
id,
|
|
45
|
+
...(summary === "" ? [] : ["--summary", summary]),
|
|
46
|
+
"--repo",
|
|
47
|
+
repo,
|
|
48
|
+
], opts);
|
|
49
|
+
break;
|
|
50
|
+
case "cancel":
|
|
51
|
+
result = await runLedgerCommand("close", [
|
|
52
|
+
"--id",
|
|
53
|
+
id,
|
|
54
|
+
"--cancel",
|
|
55
|
+
...(summary === "" ? [] : ["--summary", summary]),
|
|
56
|
+
"--repo",
|
|
57
|
+
repo,
|
|
58
|
+
], opts);
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
if (!result.ok)
|
|
62
|
+
throw failureOf(result, `${ACTION_NAME[action]}失败:`);
|
|
63
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import type { LedgerWorkspace } from "../types.js";
|
|
2
|
-
/**
|
|
3
|
-
|
|
1
|
+
import type { BoardTrendGran, LedgerWorkspace } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* 趋势图的窗口(周数):近半年。
|
|
4
|
+
* 2026-10-30 由 8 周放宽 —— 卡片按宽度能放几周就放几周(宽屏 12~14 周),
|
|
5
|
+
* 8 周不够铺满,也没得翻页;26 周 ≈ 4 屏,左右箭头一次翻 4 周。
|
|
6
|
+
*/
|
|
7
|
+
export declare const TREND_WEEKS = 26;
|
|
4
8
|
/** 一个人在一个周桶里的三个数(skill 口径:新增按 creator、完成 / 未结按 owner)。 */
|
|
5
9
|
export interface OwnerCounts {
|
|
6
10
|
readonly added: number;
|
|
@@ -30,7 +34,13 @@ export interface WorkspaceTrend {
|
|
|
30
34
|
readonly coverageFrom: string;
|
|
31
35
|
readonly coverageTo: string;
|
|
32
36
|
}
|
|
33
|
-
/** 单工作区趋势(skill `stats --trend
|
|
34
|
-
export declare function
|
|
37
|
+
/** 单工作区趋势(skill `stats --trend <gran> --last <N> --by-owner`;过 1.5s 读缓存)。 */
|
|
38
|
+
export declare function readBoardTrend(workspace: LedgerWorkspace, gran: BoardTrendGran): Promise<WorkspaceTrend>;
|
|
39
|
+
/**
|
|
40
|
+
* 历史页趋势的取数:`stats --trend <gran> --since --until`(明确窗口 ⇒ 不受
|
|
41
|
+
* day 粒度 365 桶上限的 --last 换算影响)。桶的切分 / 新增口径 / 补空桶全在 skill
|
|
42
|
+
* (用户 2026-10-30 定:聚合算法不自己写,host 只做跨工作区求和)。
|
|
43
|
+
*/
|
|
44
|
+
export declare function readTrendGran(workspace: LedgerWorkspace, gran: "day" | "week" | "month", since: string, until: string): Promise<WorkspaceTrend>;
|
|
35
45
|
/** `stats --trend` → {@link WorkspaceTrend}(容器级严格:缺字段即坏,不当 0)。 */
|
|
36
46
|
export declare function parseTrend(raw: unknown, where: string): WorkspaceTrend;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 趋势面取数:近
|
|
2
|
+
* 趋势面取数:近 26 周的「完成 / 未结 / 新增」,**整段桶序列一次拿回**(skill `stats --trend`)。
|
|
3
3
|
*
|
|
4
4
|
* 为什么不再拼现有方法:`history` 只给明细、且按**结案时间**过滤(新增取不到);
|
|
5
5
|
* 插件侧拉全量明细再聚合已被实测否决(20 万条 3s+、30MB 过进程边界)。
|
|
@@ -10,10 +10,21 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { LedgerDataError } from "../errors.js";
|
|
12
12
|
import { cached, cacheKey } from "./cache.js";
|
|
13
|
-
import { runLedgerScript } from "./runner.js";
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
import { failureOf, runLedgerScript } from "./runner.js";
|
|
14
|
+
/**
|
|
15
|
+
* 趋势图的窗口(周数):近半年。
|
|
16
|
+
* 2026-10-30 由 8 周放宽 —— 卡片按宽度能放几周就放几周(宽屏 12~14 周),
|
|
17
|
+
* 8 周不够铺满,也没得翻页;26 周 ≈ 4 屏,左右箭头一次翻 4 周。
|
|
18
|
+
*/
|
|
19
|
+
export const TREND_WEEKS = 26;
|
|
20
|
+
/**
|
|
21
|
+
* 首页趋势图按粒度的一次取数窗口:周 26 周、日 182 天(同一段时间 ⇒ 切档不换可翻范围)。
|
|
22
|
+
* skill 的 day 粒度上限是 365 桶(见 `TrendMaxDayBuckets`),182 天在线内。
|
|
23
|
+
*/
|
|
24
|
+
const TREND_LAST = {
|
|
25
|
+
day: `${String(TREND_WEEKS * 7)}d`,
|
|
26
|
+
week: `${String(TREND_WEEKS)}w`,
|
|
27
|
+
};
|
|
17
28
|
function isPlainObject(value) {
|
|
18
29
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
19
30
|
}
|
|
@@ -48,18 +59,34 @@ function parseOwners(raw, where) {
|
|
|
48
59
|
}
|
|
49
60
|
return out;
|
|
50
61
|
}
|
|
51
|
-
/** 单工作区趋势(skill `stats --trend
|
|
52
|
-
export async function
|
|
62
|
+
/** 单工作区趋势(skill `stats --trend <gran> --last <N> --by-owner`;过 1.5s 读缓存)。 */
|
|
63
|
+
export async function readBoardTrend(workspace, gran) {
|
|
64
|
+
const last = TREND_LAST[gran];
|
|
53
65
|
// 缓存 op 仍记 "stats"(脚本子命令就是 stats),detail 里写清是哪个窗口的趋势
|
|
54
|
-
return await cached(cacheKey(workspace.id, "stats", `trend:${
|
|
66
|
+
return await cached(cacheKey(workspace.id, "stats", `trend:${gran}:${last}`), async () => {
|
|
55
67
|
// 趋势自带 JSON 输出,**不能**再传 --json(skill 那边是用法错)
|
|
56
68
|
const result = await runLedgerScript("stats",
|
|
57
69
|
// --by-owner:一次就把「全部」与「按人」两套数都拿回来 ⇒ 勾「只看我的」零请求
|
|
58
|
-
["--repo", workspace.path, "--trend",
|
|
59
|
-
//
|
|
70
|
+
["--repo", workspace.path, "--trend", gran, "--last", last, "--by-owner"],
|
|
71
|
+
// 半年窗口最坏要读 7 个历史文件(skill 有月度缓存),比单月读重:给到 20s 再判超时
|
|
72
|
+
{ timeoutMs: 20_000 });
|
|
73
|
+
if (!result.ok)
|
|
74
|
+
throw failureOf(result, `${workspace.title}: `, workspace.id);
|
|
75
|
+
return parseTrend(result.data, workspace.title);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* 历史页趋势的取数:`stats --trend <gran> --since --until`(明确窗口 ⇒ 不受
|
|
80
|
+
* day 粒度 365 桶上限的 --last 换算影响)。桶的切分 / 新增口径 / 补空桶全在 skill
|
|
81
|
+
* (用户 2026-10-30 定:聚合算法不自己写,host 只做跨工作区求和)。
|
|
82
|
+
*/
|
|
83
|
+
export async function readTrendGran(workspace, gran, since, until) {
|
|
84
|
+
return await cached(cacheKey(workspace.id, "stats", `trend:${gran}:${since}:${until}`), async () => {
|
|
85
|
+
const result = await runLedgerScript("stats", ["--repo", workspace.path, "--trend", gran, "--since", since, "--until", until],
|
|
86
|
+
// 与周趋势同档:整年窗口最坏要读十几个历史文件
|
|
60
87
|
{ timeoutMs: 20_000 });
|
|
61
88
|
if (!result.ok)
|
|
62
|
-
throw
|
|
89
|
+
throw failureOf(result, `${workspace.title}: `, workspace.id);
|
|
63
90
|
return parseTrend(result.data, workspace.title);
|
|
64
91
|
});
|
|
65
92
|
}
|
package/dist/host/routes.d.ts
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* 详情 / 历史 / 筛选项 / 趋势 / 写动作的端点与实现已删除(要接回按 skill 方法重写,不复用旧直读逻辑)。
|
|
9
9
|
*/
|
|
10
10
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
11
|
-
import { type
|
|
11
|
+
import { type AgentDefaultModelLike, type AgentPresetsLike, type AgentsLike, type SessionTitleLike } from "./services/continue.service.js";
|
|
12
|
+
import type { RegistryWorkspace } from "./types.js";
|
|
12
13
|
/** 宿主 webServer.register 的最小面(WebRoute 形状见 external/host-webserver.md)。 */
|
|
13
14
|
export interface WebServerLike {
|
|
14
15
|
register(route: {
|
|
@@ -23,5 +24,16 @@ export interface WorkspaceRegistryLike {
|
|
|
23
24
|
}
|
|
24
25
|
export interface RouteDeps {
|
|
25
26
|
readonly registry: WorkspaceRegistryLike;
|
|
27
|
+
/**
|
|
28
|
+
* 「继续」要用的宿主面:**按需现取**(服务可能晚于路由就位)。
|
|
29
|
+
* 取不到就返回 undefined,由 service 报人话 —— 不写进上面那个 inject 依赖表,
|
|
30
|
+
* 否则任一服务缺席都会让整块数据面永远 pending(入口注释里的那条老坑)。
|
|
31
|
+
*/
|
|
32
|
+
readonly agents?: () => AgentsLike | undefined;
|
|
33
|
+
readonly presets?: () => AgentPresetsLike | undefined;
|
|
34
|
+
readonly defaultModel?: () => AgentDefaultModelLike | undefined;
|
|
35
|
+
readonly sessionTitle?: () => SessionTitleLike | undefined;
|
|
26
36
|
}
|
|
37
|
+
/** 核心 explorer 的只读文件路由(`serveFsRoute` 挂这里,client 的 `connectFs` 用同一个值)。 */
|
|
38
|
+
export declare const FS_ROUTE = "/api/task-ledger/fs";
|
|
27
39
|
export declare function registerRoutes(webServer: WebServerLike, deps: RouteDeps): void;
|