@siming-org/opencode-plugin 0.1.15 → 0.1.16
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 +36 -2
- package/dist/fetch-assets.d.ts +26 -0
- package/dist/fetch-assets.d.ts.map +1 -1
- package/dist/fetch-assets.js +54 -0
- package/dist/fetch-assets.js.map +1 -1
- package/dist/host-api.d.ts +12 -1
- package/dist/host-api.d.ts.map +1 -1
- package/dist/host-api.js.map +1 -1
- package/dist/register/skills.d.ts +6 -4
- package/dist/register/skills.d.ts.map +1 -1
- package/dist/register/skills.js +7 -2
- package/dist/register/skills.js.map +1 -1
- package/dist/register/todo-suite.d.ts +28 -0
- package/dist/register/todo-suite.d.ts.map +1 -0
- package/dist/register/todo-suite.js +133 -0
- package/dist/register/todo-suite.js.map +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +44 -3
- package/dist/server/index.js.map +1 -1
- package/dist/todo/config.d.ts +21 -0
- package/dist/todo/config.d.ts.map +1 -0
- package/dist/todo/config.js +272 -0
- package/dist/todo/config.js.map +1 -0
- package/dist/todo/counter.d.ts +14 -0
- package/dist/todo/counter.d.ts.map +1 -0
- package/dist/todo/counter.js +19 -0
- package/dist/todo/counter.js.map +1 -0
- package/dist/todo/nudge-log.d.ts +5 -0
- package/dist/todo/nudge-log.d.ts.map +1 -0
- package/dist/todo/nudge-log.js +45 -0
- package/dist/todo/nudge-log.js.map +1 -0
- package/dist/todo/prompt.d.ts +9 -0
- package/dist/todo/prompt.d.ts.map +1 -0
- package/dist/todo/prompt.js +18 -0
- package/dist/todo/prompt.js.map +1 -0
- package/dist/todo/rate-limit.d.ts +7 -0
- package/dist/todo/rate-limit.d.ts.map +1 -0
- package/dist/todo/rate-limit.js +20 -0
- package/dist/todo/rate-limit.js.map +1 -0
- package/dist/todo/task-planning-skill.d.ts +9 -0
- package/dist/todo/task-planning-skill.d.ts.map +1 -0
- package/dist/todo/task-planning-skill.js +58 -0
- package/dist/todo/task-planning-skill.js.map +1 -0
- package/package.json +2 -2
package/dist/server/index.js
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* 1. 宿主版本检测(< v2.0.26 console.error 提示,不中断);
|
|
6
6
|
* 2. CLI 定位:cliJs 解析失败=安装损坏 → setup 抛结构化错误(plugin remove + add 重装指引);
|
|
7
7
|
* 解释器缺失=预期降级(MCP/siming_cli 跳过,其余照常——固定项基准 5→3);
|
|
8
|
-
* 3. 注册固定面(五样 +
|
|
8
|
+
* 3. 注册固定面(五样 + 任务纪律注入 + todo 三件套;降级面按解释器轴与宿主 session 域/todo 门控裁定)
|
|
9
|
+
* + reload 通道注入 + 任务创建观测;
|
|
9
10
|
* 4. 初始化拉取:同步阻塞有界 10s,失败/超时空集注册不中断激活(迟到成功仍写入 store);
|
|
10
11
|
* 5. 激活自检:list() 回查固定项与动态项,区分「拉取失败(预期降级)」与「拉取成功但注册缺项」,
|
|
11
12
|
* 仅激活时刻执行一次(此后动态增减由三触发点承接,正确性归 §6 刷新链单测)。
|
|
@@ -20,6 +21,8 @@ import { SIMING_REFRESH_TOOL_NAME, registerRefreshTool } from '../register/refre
|
|
|
20
21
|
import { registerTaskDiscipline } from '../register/task-discipline.js';
|
|
21
22
|
import { registerSkills } from '../register/skills.js';
|
|
22
23
|
import { registerAgents } from '../register/agents.js';
|
|
24
|
+
import { registerTodoSuite } from '../register/todo-suite.js';
|
|
25
|
+
import { createTodoNudgeConfig } from '../todo/config.js';
|
|
23
26
|
import { GUIDE_SKILL_NAME } from '../guide-skill.js';
|
|
24
27
|
import { listEntryNames } from '../host-api.js';
|
|
25
28
|
/** 激活自检(§4.G:固定项按双轴基准;动态项区分拉取失败与注册缺项;异常 console.error) */
|
|
@@ -56,6 +59,12 @@ async function selfCheck(ctx, store, revalidator, opts) {
|
|
|
56
59
|
if (typeof ctx.session?.hook !== 'function' || typeof ctx.session?.get !== 'function') {
|
|
57
60
|
problems.push('任务纪律注入 session 域不可用(context hook 或 session.get 缺失)——本宿主不注入任务纪律提示词');
|
|
58
61
|
}
|
|
62
|
+
// todo 三件套(T202610260002):active 时 task-planning 技能必须在册(系统提示词/提醒注入不走注册表)
|
|
63
|
+
if (opts.todo !== null && opts.todo.status === 'active' && opts.todo.skillInfo !== null) {
|
|
64
|
+
if (!skillNames.has(opts.todo.skillInfo.name)) {
|
|
65
|
+
problems.push(`技能 ${opts.todo.skillInfo.name} 已内置于插件但未出现在 skill 域注册表`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
59
68
|
// 动态项:拉取成功但注册缺项(拉取失败时 store 为空、此处自然无比对项=预期降级不告警)
|
|
60
69
|
const snapshot = store.getSnapshot();
|
|
61
70
|
for (const skill of snapshot.skills) {
|
|
@@ -84,9 +93,30 @@ async function selfCheck(ctx, store, revalidator, opts) {
|
|
|
84
93
|
: target.projectSource === 'workspace'
|
|
85
94
|
? ',项目已绑定(工作区 defaultProject)'
|
|
86
95
|
: ',项目已绑定(实例默认项目)';
|
|
96
|
+
// todo 三件套状态段(T202610260002 §4.6):active 顺带开关现值与 watcher 健康度
|
|
97
|
+
let todoLabel = '';
|
|
98
|
+
if (opts.todo === null) {
|
|
99
|
+
todoLabel = ';todo 提醒:本宿主不支持(session 域缺失)';
|
|
100
|
+
}
|
|
101
|
+
else if (opts.todo.status === 'error') {
|
|
102
|
+
todoLabel = `;todo 提醒:未激活(初始化异常${opts.todo.reason === undefined ? '' : `:${opts.todo.reason}`},重启宿主后重试)`;
|
|
103
|
+
}
|
|
104
|
+
else if (opts.todo.status === 'gated-off') {
|
|
105
|
+
todoLabel = ';todo 提醒:未激活(宿主未开启 experimental.todo,开启并重启后生效)';
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
const snap = opts.todoConfig.snapshot();
|
|
109
|
+
todoLabel =
|
|
110
|
+
snap === null
|
|
111
|
+
? ';todo 提醒:激活,配置损坏按关闭处理'
|
|
112
|
+
: `;todo 提醒:${snap.enabled ? '开' : '关'}(每 ${String(snap.every)} 次)`;
|
|
113
|
+
if (!opts.todoConfig.healthy())
|
|
114
|
+
todoLabel += ',配置热重载不可用(变更需重启生效)';
|
|
115
|
+
}
|
|
87
116
|
console.log(`[siming-plugin] 激活完成:固定 ${opts.interpreterOk ? '5' : '3'} 项(解释器${opts.interpreterOk ? '正常' : '缺失降级'})` +
|
|
88
117
|
` + 技能 ${String(skillCount)} + 子代理 ${String(agentCount)}` +
|
|
89
118
|
`${target !== null ? `(server:${target.serverUrl}${bindLabel})` : ''}` +
|
|
119
|
+
`${todoLabel}` +
|
|
90
120
|
`${skillCount === 0 && agentCount === 0 ? '——资产拉取未成功(空集注册,首次建任务/手动刷新时自动重试)' : ''}`);
|
|
91
121
|
}
|
|
92
122
|
const plugin = {
|
|
@@ -112,10 +142,17 @@ const plugin = {
|
|
|
112
142
|
const store = createAssetsStore();
|
|
113
143
|
const revalidator = createRevalidator(store, directory, referencesRoot);
|
|
114
144
|
// 注册面(解释器轴降级:MCP 与 siming_cli 跳过,其余照常;任务纪律注入不在此轴,仅依赖宿主 session 域)
|
|
145
|
+
// todo 三件套(T202610260002 §4.6):config 实例在此创建,同一实例贯穿注入判定/计数复位/selfCheck;
|
|
146
|
+
// 双层兜底(suite 内部 + 此处调用位)确保 todo 任何初始化异常不阻断其余注册面(§6 契约)
|
|
147
|
+
const todoNudgeConfig = createTodoNudgeConfig(directory);
|
|
148
|
+
let todoSuite = await registerTodoSuite(ctx, directory, referencesRoot, todoNudgeConfig).catch((err) => {
|
|
149
|
+
console.error(`[siming-plugin] ${directory}:todo 三件套注册异常(${String(err)})——todo 不生效,其余注册面不受影响`);
|
|
150
|
+
return { skillInfo: null, status: 'error', reason: String(err) };
|
|
151
|
+
});
|
|
115
152
|
if (nodeBin !== null)
|
|
116
153
|
registerMcp(ctx, { nodeBin, cliJs });
|
|
117
154
|
registerRefreshTool(ctx, revalidator, store);
|
|
118
|
-
registerSkills(ctx, store, referencesRoot);
|
|
155
|
+
registerSkills(ctx, store, referencesRoot, todoSuite.skillInfo === null ? [] : [todoSuite.skillInfo]);
|
|
119
156
|
registerAgents(ctx, store);
|
|
120
157
|
if (nodeBin !== null)
|
|
121
158
|
registerSimingCli(ctx, { nodeBin, cliJs }, directory);
|
|
@@ -127,7 +164,11 @@ const plugin = {
|
|
|
127
164
|
// 初始化拉取(setup 期会话未建立 → 构造时 location directory 基准,§4.C3-3)
|
|
128
165
|
await revalidator.initFetch();
|
|
129
166
|
// 激活自检(仅此刻一次)
|
|
130
|
-
await selfCheck(ctx, store, revalidator, {
|
|
167
|
+
await selfCheck(ctx, store, revalidator, {
|
|
168
|
+
interpreterOk: nodeBin !== null,
|
|
169
|
+
todo: todoSuite,
|
|
170
|
+
todoConfig: todoNudgeConfig,
|
|
171
|
+
});
|
|
131
172
|
},
|
|
132
173
|
};
|
|
133
174
|
export default plugin;
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface TodoNudgeConfig {
|
|
2
|
+
enabled: boolean;
|
|
3
|
+
every: number;
|
|
4
|
+
text: string;
|
|
5
|
+
}
|
|
6
|
+
export interface TodoNudgeConfigWatch {
|
|
7
|
+
/** null = corrupt 态(调用方视为 enabled=false) */
|
|
8
|
+
readonly snapshot: () => TodoNudgeConfig | null;
|
|
9
|
+
/** watcher 是否存活(selfCheck/降级声明用) */
|
|
10
|
+
readonly healthy: () => boolean;
|
|
11
|
+
/** 生效快照变化回调(计数复位接线用;corrupt↔恢复也触发) */
|
|
12
|
+
readonly onChange: (cb: (next: TodoNudgeConfig | null) => void) => void;
|
|
13
|
+
/** 仅为测试与完整性提供(宿主 location 存活期即插件存活期,无 dispose 时机) */
|
|
14
|
+
readonly dispose: () => void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 创建配置实例:同步完成首次读取(启动即建快照)与监听挂载;失败不抛——
|
|
18
|
+
* corrupt 态/降级态在返回对象内表达(§6 契约表)。
|
|
19
|
+
*/
|
|
20
|
+
export declare function createTodoNudgeConfig(directory: string): TodoNudgeConfigWatch;
|
|
21
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/todo/config.ts"],"names":[],"mappings":"AA2BA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,eAAe,GAAG,IAAI,CAAC;IAChD,oCAAoC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC;IAChC,sCAAsC;IACtC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC;IACxE,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAqGD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,oBAAoB,CA+J7E"}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* todoNudge 配置模型与热生效(技术方案 §4.1/§4.2,T202610260002)。
|
|
3
|
+
*
|
|
4
|
+
* 配置键:工作区 <ws>/.siming/config.json(严格 JSON)与全局 ~/.siming/config.json(jsonc 宽容)
|
|
5
|
+
* 新增可选键 `todoNudge: { enabled, every, text }`;既有键(serverUrl/defaultProject)互不影响。
|
|
6
|
+
*
|
|
7
|
+
* 语义要点(PRD 规则 4/17,F-1 读取路径约束):
|
|
8
|
+
* - 合并按字段级「最具体提供层」:工作区(就近命中的那份文件)→ 全局 → 内置默认;
|
|
9
|
+
* 某层提供了该字段但值非法 → 取内置默认并告警(不继承下一层——错误不跨层传染);
|
|
10
|
+
* - 读取不得复用 readWorkspaceConfig/tryLoadJsonc(两者把「损坏」折叠成 null=缺席):
|
|
11
|
+
* 本模块自建读取路径 existsSync → 读取 → 解析,解析失败即 corrupt;
|
|
12
|
+
* - corrupt:任一层文件存在但不可读/解析失败 → snapshot()=null(enabled 视同 false),
|
|
13
|
+
* 不回退其他层也不回退默认;下一次配置变更事件重读成功即恢复;
|
|
14
|
+
* - 热生效:fs.watch 监听集合由定位算法驱动(walkTodoConfigPath),150ms 防抖重读,
|
|
15
|
+
* 重读即重新定位;watcher 失败降级为冻结快照 + healthy()=false(变更需重启生效)。
|
|
16
|
+
*
|
|
17
|
+
* per-location 实例(T202610220003):每次 createTodoNudgeConfig 各自持有快照与 watcher,
|
|
18
|
+
* 无模块级状态;多 location 重复监听全局层为已接受的代价(§4.8)。
|
|
19
|
+
*/
|
|
20
|
+
import { existsSync, readFileSync, watch } from 'node:fs';
|
|
21
|
+
import { homedir } from 'node:os';
|
|
22
|
+
import { join } from 'node:path';
|
|
23
|
+
import { parse as parseJsonc } from 'jsonc-parser';
|
|
24
|
+
import { walkTodoConfigPath } from '../fetch-assets.js';
|
|
25
|
+
import { DEFAULT_NUDGE_TEXT } from './prompt.js';
|
|
26
|
+
import { createRateLimiter } from './rate-limit.js';
|
|
27
|
+
/** 内置默认(PRD 规则 2/8.3 逐字) */
|
|
28
|
+
const DEFAULTS = { enabled: true, every: 6, text: DEFAULT_NUDGE_TEXT };
|
|
29
|
+
const DEBOUNCE_MS = 150;
|
|
30
|
+
/** 工作区层读取:严格 JSON(对齐 CLI 工作区配置读取惯例);不可读/解析失败/非对象即 corrupt
|
|
31
|
+
* (与全局层同口径:文件存在但不是可用配置对象 = 损坏,不是「未提供」) */
|
|
32
|
+
function readWorkspaceLayer(file) {
|
|
33
|
+
try {
|
|
34
|
+
const parsed = JSON.parse(readFileSync(file, 'utf8'));
|
|
35
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
36
|
+
return { values: null, corrupt: true };
|
|
37
|
+
}
|
|
38
|
+
return { values: parsed, corrupt: false };
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return { values: null, corrupt: true };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** 全局层读取:jsonc 宽容(注释/尾逗号容忍);解析结果非对象、或扫描器报 error 即 corrupt。
|
|
45
|
+
* F-CFG-01:jsonc-parser parse 是容错扫描器——内容损坏(如 `{ not-json`)不抛错而是返回
|
|
46
|
+
* 折叠结果(undefined/{}/残留对象),仅判返回值会把「损坏」视同合法空配置。必须收集 errors
|
|
47
|
+
* 并以「errors 非空」为损坏信号(PRD 规则 17/验收 7:损坏按关闭)。
|
|
48
|
+
* allowTrailingComma 必须显式 true:ParseOptions.DEFAULT.allowTrailingComma=false,尾逗号
|
|
49
|
+
* 默认产生 error——不开启会把合法尾逗号样本误判 corrupt(注释保持默认宽容:
|
|
50
|
+
* disallowComments 默认 false,不写 error)。 */
|
|
51
|
+
function readGlobalLayer(file) {
|
|
52
|
+
try {
|
|
53
|
+
const errors = [];
|
|
54
|
+
const parsed = parseJsonc(readFileSync(file, 'utf8'), errors, { allowTrailingComma: true });
|
|
55
|
+
if (errors.length > 0 || typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
56
|
+
return { values: null, corrupt: true };
|
|
57
|
+
}
|
|
58
|
+
return { values: parsed, corrupt: false };
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return { values: null, corrupt: true };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function todoNudgeOf(values, file, allowAlert) {
|
|
65
|
+
if (values === null)
|
|
66
|
+
return { values: null, file };
|
|
67
|
+
const raw = values['todoNudge'];
|
|
68
|
+
if (raw === undefined)
|
|
69
|
+
return { values: null, file };
|
|
70
|
+
if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
|
|
71
|
+
if (allowAlert(`todoNudge-shape:${file}`)) {
|
|
72
|
+
console.error(`[siming-plugin] ${file} 的 todoNudge 不是对象(忽略该层的 todoNudge,其余键不受影响)`);
|
|
73
|
+
}
|
|
74
|
+
return { values: null, file };
|
|
75
|
+
}
|
|
76
|
+
return { values: raw, file };
|
|
77
|
+
}
|
|
78
|
+
/** 字段级合并:最具体提供层优先;值非法取内置默认并告警(不继承下一层,PRD 规则 17) */
|
|
79
|
+
function mergeLayers(workspace, global, allowAlert) {
|
|
80
|
+
const pick = (field, isValid, fallback) => {
|
|
81
|
+
for (const layer of [workspace, global]) {
|
|
82
|
+
const raw = layer.values?.[field];
|
|
83
|
+
if (raw === undefined)
|
|
84
|
+
continue;
|
|
85
|
+
if (isValid(raw))
|
|
86
|
+
return raw;
|
|
87
|
+
if (allowAlert(`field:${layer.file}:${field}`)) {
|
|
88
|
+
console.error(`[siming-plugin] ${layer.file} 的 todoNudge.${field} 非法(${JSON.stringify(raw)}),该字段回退内置默认`);
|
|
89
|
+
}
|
|
90
|
+
return fallback;
|
|
91
|
+
}
|
|
92
|
+
return fallback;
|
|
93
|
+
};
|
|
94
|
+
const enabled = pick('enabled', (v) => typeof v === 'boolean', DEFAULTS.enabled);
|
|
95
|
+
const every = pick('every', (v) => typeof v === 'number' && Number.isInteger(v) && v >= 1, DEFAULTS.every);
|
|
96
|
+
const text = pick('text', (v) => typeof v === 'string', DEFAULTS.text);
|
|
97
|
+
// text 合法但空/纯白 → 默认文案(合法配置,不告警,PRD 规则 6)
|
|
98
|
+
const effectiveText = text.trim().length > 0 ? text : DEFAULTS.text;
|
|
99
|
+
return { enabled, every, text: effectiveText };
|
|
100
|
+
}
|
|
101
|
+
function describeSnapshot(snap) {
|
|
102
|
+
return snap === null ? '<corrupt 按关闭>' : JSON.stringify(snap);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* 创建配置实例:同步完成首次读取(启动即建快照)与监听挂载;失败不抛——
|
|
106
|
+
* corrupt 态/降级态在返回对象内表达(§6 契约表)。
|
|
107
|
+
*/
|
|
108
|
+
export function createTodoNudgeConfig(directory) {
|
|
109
|
+
const allowAlert = createRateLimiter(60_000);
|
|
110
|
+
// 全局层路径在实例创建时冻结:homedir() 读的是进程环境(HOME 可被中途改写——测试 fixture、
|
|
111
|
+
// 宿主环境异常),每次重读现取会把「别的时刻的家目录」读进本实例,跨实例互相污染快照,
|
|
112
|
+
// 违反 per-location 隔离(T202610220003:本文件头注声明各实例独立持有快照与监听)。
|
|
113
|
+
// 冻结后各实例全局层恒定指向创建时刻的家目录;生产 HOME 恒定,行为不变。
|
|
114
|
+
// 已知残留:工作区层遍历(walkTodoConfigPath/isHomeDir 的「遇 $HOME 即止」边界)仍每次现取
|
|
115
|
+
// homedir()——生产 HOME 恒定等价无影响;如需全链冻结,后续把 home 边界作为参数传入。
|
|
116
|
+
const homeDirAtCreate = homedir();
|
|
117
|
+
const globalSimingDir = join(homeDirAtCreate, '.siming');
|
|
118
|
+
const globalConfigFile = join(globalSimingDir, 'config.json');
|
|
119
|
+
let snapshot = null;
|
|
120
|
+
let watchers = [];
|
|
121
|
+
let watchTargetsKey = '';
|
|
122
|
+
let healthy = true;
|
|
123
|
+
let disposed = false;
|
|
124
|
+
let timer = null;
|
|
125
|
+
const changeCallbacks = [];
|
|
126
|
+
let booted = false; // 初读建快照为静默路径(不日志、不通知)——null 初始值不构成「变更」
|
|
127
|
+
const degrade = (reason) => {
|
|
128
|
+
if (!healthy)
|
|
129
|
+
return;
|
|
130
|
+
healthy = false;
|
|
131
|
+
for (const w of watchers) {
|
|
132
|
+
try {
|
|
133
|
+
w.close();
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// 关闭失败即弃——watcher 随进程回收
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
watchers = [];
|
|
140
|
+
if (timer !== null) {
|
|
141
|
+
clearTimeout(timer);
|
|
142
|
+
timer = null;
|
|
143
|
+
}
|
|
144
|
+
console.error(`[siming-plugin] todoNudge 配置热重载不可用(${reason})——变更需重启宿主生效(当前快照冻结)`);
|
|
145
|
+
};
|
|
146
|
+
/** 防抖:末次事件后 150ms 合并重读(编辑器原子替换连发 rename/change) */
|
|
147
|
+
const scheduleReread = () => {
|
|
148
|
+
if (!healthy || disposed)
|
|
149
|
+
return;
|
|
150
|
+
if (timer !== null)
|
|
151
|
+
clearTimeout(timer);
|
|
152
|
+
timer = setTimeout(() => {
|
|
153
|
+
timer = null;
|
|
154
|
+
if (healthy && !disposed)
|
|
155
|
+
reread();
|
|
156
|
+
}, DEBOUNCE_MS);
|
|
157
|
+
};
|
|
158
|
+
const attach = (dir, onlySiming) => {
|
|
159
|
+
let w;
|
|
160
|
+
try {
|
|
161
|
+
w = watch(dir, { recursive: false }, (_eventType, filename) => {
|
|
162
|
+
// 缺口目录/家目录监听只关心 `.siming` 的出现(否则目录内高频活动会反复触发重读)
|
|
163
|
+
if (onlySiming && filename !== '.siming')
|
|
164
|
+
return;
|
|
165
|
+
scheduleReread();
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
degrade(String(err));
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
w.on('error', (err) => degrade(String(err)));
|
|
173
|
+
watchers.push(w);
|
|
174
|
+
};
|
|
175
|
+
/** 监听集合随定位结果重建(§4.2:集合①全部 .siming 目录 + 集合②缺口目录 + 全局层) */
|
|
176
|
+
const rebuildWatchers = (simingDirs, gapDir) => {
|
|
177
|
+
if (!healthy || disposed)
|
|
178
|
+
return;
|
|
179
|
+
const targets = [
|
|
180
|
+
...simingDirs.map((dir) => ({ dir, onlySiming: false })),
|
|
181
|
+
...(gapDir !== null ? [{ dir: gapDir, onlySiming: true }] : []),
|
|
182
|
+
// 全局层:~/.siming 存在直接监听;不存在监听家目录等 .siming 出现(出现即重读升级)
|
|
183
|
+
existsSync(globalSimingDir)
|
|
184
|
+
? { dir: globalSimingDir, onlySiming: false }
|
|
185
|
+
: { dir: homeDirAtCreate, onlySiming: true },
|
|
186
|
+
];
|
|
187
|
+
const key = targets.map((t) => `${t.onlySiming ? '!' : '='}${t.dir}`).sort().join('|');
|
|
188
|
+
if (key === watchTargetsKey)
|
|
189
|
+
return; // 集合未变不重建(避免每次配置编辑重建 watcher)
|
|
190
|
+
for (const w of watchers) {
|
|
191
|
+
try {
|
|
192
|
+
w.close();
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// 同上
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
watchers = [];
|
|
199
|
+
watchTargetsKey = key;
|
|
200
|
+
for (const t of targets) {
|
|
201
|
+
if (!healthy)
|
|
202
|
+
return; // attach 失败已走 degrade
|
|
203
|
+
attach(t.dir, t.onlySiming);
|
|
204
|
+
}
|
|
205
|
+
// 补读:watcher 建立后 macOS FSEvents 存在激活窗口,窗口内的文件变更不产生事件——
|
|
206
|
+
// 补一次防抖重读兜底(启动/拓扑变化后紧跟的配置编辑不丢;稳态无事件则读后无变化,零副作用)
|
|
207
|
+
scheduleReread();
|
|
208
|
+
};
|
|
209
|
+
const reread = () => {
|
|
210
|
+
// corrupt 判定与字段级合并(读取顺序无关,两层独立)
|
|
211
|
+
const walk = walkTodoConfigPath(directory);
|
|
212
|
+
const wsLayer = walk.hit === null ? { values: null, corrupt: false } : readWorkspaceLayer(walk.hit.path);
|
|
213
|
+
const glLayer = existsSync(globalConfigFile) ? readGlobalLayer(globalConfigFile) : { values: null, corrupt: false };
|
|
214
|
+
let next;
|
|
215
|
+
if (wsLayer.corrupt || glLayer.corrupt) {
|
|
216
|
+
const which = [wsLayer.corrupt ? walk.hit?.path : null, glLayer.corrupt ? globalConfigFile : null]
|
|
217
|
+
.filter((p) => p !== null && p !== undefined)
|
|
218
|
+
.join('、');
|
|
219
|
+
if (allowAlert(`corrupt:${which}`)) {
|
|
220
|
+
console.error(`[siming-plugin] todoNudge 配置文件损坏(${which})——提醒按关闭处理,不回退其他层;修复后自动恢复`);
|
|
221
|
+
}
|
|
222
|
+
next = null;
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
next = mergeLayers(todoNudgeOf(wsLayer.values, walk.hit?.path ?? '<无工作区层>', allowAlert), todoNudgeOf(glLayer.values, globalConfigFile, allowAlert), allowAlert);
|
|
226
|
+
}
|
|
227
|
+
if (!booted) {
|
|
228
|
+
// 初读建快照:静默(此前 null → 首个快照被误判为变更,会在启动时打一行假「配置已更新」并触发空通知)
|
|
229
|
+
snapshot = next;
|
|
230
|
+
booted = true;
|
|
231
|
+
}
|
|
232
|
+
else if (describeSnapshot(next) !== describeSnapshot(snapshot)) {
|
|
233
|
+
// 生效值变化一行日志(前→后,配置变更排障用,非提醒日志)
|
|
234
|
+
console.log(`[siming-plugin] todoNudge 配置已更新:${describeSnapshot(snapshot)} → ${describeSnapshot(next)}`);
|
|
235
|
+
snapshot = next;
|
|
236
|
+
for (const cb of changeCallbacks) {
|
|
237
|
+
try {
|
|
238
|
+
cb(next);
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
console.error(`[siming-plugin] todoNudge onChange 回调异常(忽略):${String(err)}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
rebuildWatchers(walk.simingDirs, walk.gapDir);
|
|
246
|
+
};
|
|
247
|
+
reread(); // 启动首次读取(静默建立初始快照,不触发 onChange)
|
|
248
|
+
return {
|
|
249
|
+
snapshot: () => snapshot,
|
|
250
|
+
healthy: () => healthy,
|
|
251
|
+
onChange(cb) {
|
|
252
|
+
changeCallbacks.push(cb);
|
|
253
|
+
},
|
|
254
|
+
dispose() {
|
|
255
|
+
disposed = true;
|
|
256
|
+
if (timer !== null) {
|
|
257
|
+
clearTimeout(timer);
|
|
258
|
+
timer = null;
|
|
259
|
+
}
|
|
260
|
+
for (const w of watchers) {
|
|
261
|
+
try {
|
|
262
|
+
w.close();
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
// 同上
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
watchers = [];
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/todo/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* todo 提醒计数器(技术方案 §4.4):
|
|
3
|
+
* - per-session 自增计数(1-based),命中判定 n % every === 0(由调用方执行);
|
|
4
|
+
* - 跨轮累计不重置;enabled=false 期间调用方不调用 next(关闭不计数);
|
|
5
|
+
* - 重开从 0:配置快照 disabled/corrupt→enabled 跃迁时调用方调 resetAll() 清空全部会话计数;
|
|
6
|
+
* - 防膨胀:新会话键数超 4096(异常量级的长寿进程)整体清空 + 一行日志(计数归零,语义同重启)。
|
|
7
|
+
* Map 实例态随 location 工厂创建,无模块级状态(T202610220003)。
|
|
8
|
+
*/
|
|
9
|
+
export interface NudgeCounter {
|
|
10
|
+
next(sessionID: string): number;
|
|
11
|
+
resetAll(): void;
|
|
12
|
+
}
|
|
13
|
+
export declare function createNudgeCounter(): NudgeCounter;
|
|
14
|
+
//# sourceMappingURL=counter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"counter.d.ts","sourceRoot":"","sources":["../../src/todo/counter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,QAAQ,IAAI,IAAI,CAAC;CAClB;AAID,wBAAgB,kBAAkB,IAAI,YAAY,CAgBjD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const SESSION_CAP = 4096;
|
|
2
|
+
export function createNudgeCounter() {
|
|
3
|
+
const counts = new Map();
|
|
4
|
+
return {
|
|
5
|
+
next(sessionID) {
|
|
6
|
+
if (!counts.has(sessionID) && counts.size >= SESSION_CAP) {
|
|
7
|
+
counts.clear();
|
|
8
|
+
console.error(`[siming-plugin] todo 提醒计数会话数超 ${String(SESSION_CAP)},计数整体重置(语义同重启)`);
|
|
9
|
+
}
|
|
10
|
+
const n = (counts.get(sessionID) ?? 0) + 1;
|
|
11
|
+
counts.set(sessionID, n);
|
|
12
|
+
return n;
|
|
13
|
+
},
|
|
14
|
+
resetAll() {
|
|
15
|
+
counts.clear();
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=counter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"counter.js","sourceRoot":"","sources":["../../src/todo/counter.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,GAAG,IAAI,CAAC;AAEzB,MAAM,UAAU,kBAAkB;IAChC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,OAAO;QACL,IAAI,CAAC,SAAiB;YACpB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC;gBACzD,MAAM,CAAC,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,iCAAiC,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;YACtF,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YAC3C,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;YACzB,OAAO,CAAC,CAAC;QACX,CAAC;QACD,QAAQ;YACN,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nudge-log.d.ts","sourceRoot":"","sources":["../../src/todo/nudge-log.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAClF;AAID,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW,CA6BrE"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* todo 提醒命中日志(技术方案 §4.5):
|
|
3
|
+
* - 文件 <referencesRoot>/todo-nudge.log,行格式 `<ISO> hit session=<sid> count=<n>/<N> messages=<len>`
|
|
4
|
+
* (PRD 规则 10 四要素:时间/会话标识/累计次数/消息数);
|
|
5
|
+
* - 性质:运行日志而非技能/子代理资产——不属于「资产不落盘」承诺范围,可手删;
|
|
6
|
+
* 技能缓存对账只清理 referencesRoot/skills/ 子目录,不会误删根级日志;
|
|
7
|
+
* - 只在命中时写(未命中/关闭不写);轮转 1MB → .1 保留一代(写入前 statSync 判定);
|
|
8
|
+
* - 写失败(磁盘满/根不可写)console.error 限频(同类 60s 一条),不影响注入。
|
|
9
|
+
* referencesRoot 由 setup 定格传入(referencesRootOf 语义:工作区 .siming/temp/ 或 tmpdir 兜底),
|
|
10
|
+
* 可能尚未被 references 物化创建——写入前防御性 mkdir。
|
|
11
|
+
*/
|
|
12
|
+
import { appendFileSync, existsSync, mkdirSync, renameSync, statSync } from 'node:fs';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
import { createRateLimiter } from './rate-limit.js';
|
|
15
|
+
const ROTATE_BYTES = 1_048_576; // 1MB
|
|
16
|
+
export function createNudgeLogger(referencesRoot) {
|
|
17
|
+
const file = join(referencesRoot, 'todo-nudge.log');
|
|
18
|
+
const allowLog = createRateLimiter(60_000);
|
|
19
|
+
return {
|
|
20
|
+
hit(sessionID, count, every, messageCount) {
|
|
21
|
+
try {
|
|
22
|
+
mkdirSync(referencesRoot, { recursive: true });
|
|
23
|
+
// 轮转:超 1MB → .1(rename 覆盖旧 .1,保留一代)
|
|
24
|
+
if (existsSync(file)) {
|
|
25
|
+
try {
|
|
26
|
+
if (statSync(file).size > ROTATE_BYTES)
|
|
27
|
+
renameSync(file, `${file}.1`);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
if (allowLog(`rotate:${String(err)}`)) {
|
|
31
|
+
console.error(`[siming-plugin] todo 提醒日志轮转失败(忽略,继续写入):${String(err)}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
appendFileSync(file, `${new Date().toISOString()} hit session=${sessionID} count=${String(count)}/${String(every)} messages=${String(messageCount)}\n`, 'utf8');
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
if (allowLog(String(err))) {
|
|
39
|
+
console.error(`[siming-plugin] todo 提醒日志写入失败(不影响注入):${String(err)}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=nudge-log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nudge-log.js","sourceRoot":"","sources":["../../src/todo/nudge-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACtF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAMpD,MAAM,YAAY,GAAG,SAAS,CAAC,CAAC,MAAM;AAEtC,MAAM,UAAU,iBAAiB,CAAC,cAAsB;IACtD,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC3C,OAAO;QACL,GAAG,CAAC,SAAiB,EAAE,KAAa,EAAE,KAAa,EAAE,YAAoB;YACvE,IAAI,CAAC;gBACH,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/C,oCAAoC;gBACpC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrB,IAAI,CAAC;wBACH,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,YAAY;4BAAE,UAAU,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC;oBACxE,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,IAAI,QAAQ,CAAC,UAAU,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;4BACtC,OAAO,CAAC,KAAK,CAAC,0CAA0C,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;wBACzE,CAAC;oBACH,CAAC;gBACH,CAAC;gBACD,cAAc,CACZ,IAAI,EACJ,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,gBAAgB,SAAS,UAAU,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,aAAa,MAAM,CAAC,YAAY,CAAC,IAAI,EACjI,MAAM,CACP,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;oBAC1B,OAAO,CAAC,KAAK,CAAC,wCAAwC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* todo 三件套内置常量(技术方案 §4.7):
|
|
3
|
+
* - TODO_SYSTEM_PROMPT:注入主会话 system 的常驻短规则(PRD §8.1 逐字,含标题行);
|
|
4
|
+
* - DEFAULT_NUDGE_TEXT:尾部注入的默认提醒文案(PRD §8.3 逐字,含「非用户输入」标识)。
|
|
5
|
+
* 常量只承载 todo 规则本身,不提及 todoNudge 配置(PRD 规则 14 尾款)。
|
|
6
|
+
*/
|
|
7
|
+
export declare const TODO_SYSTEM_PROMPT = "## \u4EFB\u52A1\u6E05\u5355\uFF08todos\uFF09\n\n\u76F8\u5BF9\u590D\u6742\u7684\u4EFB\u52A1\uFF08\u9884\u8BA1 3 \u6B65\u4EE5\u4E0A\u3001\u6D89\u53CA\u591A\u4E2A\u6587\u4EF6\u6216\u547D\u4EE4\u3001\u6709\u5148\u540E\u4F9D\u8D56\uFF09\u5FC5\u987B\u5148\u7528 todowrite \u5EFA\u6E05\u5355\uFF1B\u5355\u6B65\u4EFB\u52A1\u3001\u7EAF\u95EE\u7B54\u4E0D\u5EFA\u3002\n\n- \u62C6\u5206\uFF1A\u600E\u4E48\u62C6\u7531\u4F60\u6309\u4EFB\u52A1\u5B9E\u9645\u5185\u5BB9\u51B3\u5B9A\uFF1B\u4E00\u6761\u5BF9\u5E94\u4E00\u4E2A\u80FD\u72EC\u7ACB\u63A8\u8FDB\u3001\u80FD\u770B\u51FA\u662F\u5426\u5B8C\u6210\u7684\u6B65\u9AA4\u3002\u7C92\u5EA6\u8981\u5408\u9002\uFF0C\u4E0D\u80FD\u7C97\u5230\u300C\u6574\u4E2A\u529F\u80FD\u300D\u6216\u300C\u6574\u4E2A DAG \u8282\u70B9\u300D\u4E00\u6761\u3002\n- siming \u6D41\u7A0B\u4EFB\u52A1\uFF1A\u53EA\u62C6\u5F53\u524D DAG \u8282\u70B9\u5185\u90E8\u7684\u6B65\u9AA4\uFF0C\u6700\u5C11 3 \u9879\u3001\u4E0D\u8BBE\u4E0A\u9650\uFF08\u6309\u8282\u70B9\u5B9E\u9645\u590D\u6742\u5EA6\u8BC4\u4F30\uFF0C\u8BE5\u591A\u5C11\u5C31\u591A\u5C11\uFF09\uFF1B\u4E0D\u8981\u628A\u591A\u4E2A\u8282\u70B9\u5408\u5E76\u8FDB\u540C\u4E00\u5F20\u6E05\u5355\u3002\n- \u72B6\u6001\uFF1A\u5F00\u59CB\u505A\u65F6\u6807 in_progress\uFF0C\u9636\u6BB5\u6027\u5B8C\u6210\u540E\u6807 completed\uFF1B\u66F4\u65B0\u4FDD\u6301\u76F8\u5BF9\u53CA\u65F6\u3002\n- \u63A8\u8FDB\uFF1A\u4E32\u884C\u3001\u5E76\u884C\u3001\u8DF3\u7740\u505A\u90FD\u7531\u4F60\u51B3\u5B9A\uFF0C\u4E0D\u8981\u6C42\u6309\u6E05\u5355\u987A\u5E8F\u63A8\u8FDB\uFF1B\u540C\u65F6\u5728\u8FDB\u884C\u7684\u6761\u76EE\u6570\u91CF\u4E0D\u505A\u9650\u5236\u3002\n- \u7EF4\u62A4\uFF1A\u53D1\u73B0\u65B0\u6B65\u9AA4\u968F\u65F6\u8FFD\u52A0\uFF1B\u653E\u5F03\u7684\u9879\u6807 cancelled \u5E76\u5199\u539F\u56E0\uFF1B\u65E7\u6E05\u5355\u5B8C\u6210\u3001\u5207\u6362\u4EFB\u52A1\u6216\u5207\u6362\u8282\u70B9\u65F6\u6574\u5F20\u66FF\u6362\uFF0C\u4E0D\u590D\u7528\u65E7\u6761\u76EE\u3002\n- \u6536\u5C3E\uFF1A\u7ED9\u6700\u7EC8\u7B54\u590D\u524D\u987A\u624B\u6838\u5BF9\u6E05\u5355\uFF0C\u72B6\u6001\u4E0E\u5B9E\u9645\u8FDB\u5EA6\u4E00\u81F4\u5373\u53EF\uFF0C\u4E0D\u5FC5\u4E3A\u4E86\u6E05\u96F6\u800C\u6539\u72B6\u6001\u3002";
|
|
8
|
+
export declare const DEFAULT_NUDGE_TEXT = "[todo-nudge \u81EA\u52A8\u63D0\u9192\uFF0C\u975E\u7528\u6237\u8F93\u5165] \u590D\u6742\u4EFB\u52A1\u5EFA\u8BAE\u7528 todos \u8DDF\u8E2A\uFF1B\u5B50\u9879\u5B8C\u6210\u540E\u987A\u624B\u66F4\u65B0\u72B6\u6001\u3002";
|
|
9
|
+
//# sourceMappingURL=prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/todo/prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,kBAAkB,wnEASW,CAAC;AAE3C,eAAO,MAAM,kBAAkB,0NAA0D,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* todo 三件套内置常量(技术方案 §4.7):
|
|
3
|
+
* - TODO_SYSTEM_PROMPT:注入主会话 system 的常驻短规则(PRD §8.1 逐字,含标题行);
|
|
4
|
+
* - DEFAULT_NUDGE_TEXT:尾部注入的默认提醒文案(PRD §8.3 逐字,含「非用户输入」标识)。
|
|
5
|
+
* 常量只承载 todo 规则本身,不提及 todoNudge 配置(PRD 规则 14 尾款)。
|
|
6
|
+
*/
|
|
7
|
+
export const TODO_SYSTEM_PROMPT = `## 任务清单(todos)
|
|
8
|
+
|
|
9
|
+
相对复杂的任务(预计 3 步以上、涉及多个文件或命令、有先后依赖)必须先用 todowrite 建清单;单步任务、纯问答不建。
|
|
10
|
+
|
|
11
|
+
- 拆分:怎么拆由你按任务实际内容决定;一条对应一个能独立推进、能看出是否完成的步骤。粒度要合适,不能粗到「整个功能」或「整个 DAG 节点」一条。
|
|
12
|
+
- siming 流程任务:只拆当前 DAG 节点内部的步骤,最少 3 项、不设上限(按节点实际复杂度评估,该多少就多少);不要把多个节点合并进同一张清单。
|
|
13
|
+
- 状态:开始做时标 in_progress,阶段性完成后标 completed;更新保持相对及时。
|
|
14
|
+
- 推进:串行、并行、跳着做都由你决定,不要求按清单顺序推进;同时在进行的条目数量不做限制。
|
|
15
|
+
- 维护:发现新步骤随时追加;放弃的项标 cancelled 并写原因;旧清单完成、切换任务或切换节点时整张替换,不复用旧条目。
|
|
16
|
+
- 收尾:给最终答复前顺手核对清单,状态与实际进度一致即可,不必为了清零而改状态。`;
|
|
17
|
+
export const DEFAULT_NUDGE_TEXT = '[todo-nudge 自动提醒,非用户输入] 复杂任务建议用 todos 跟踪;子项完成后顺手更新状态。';
|
|
18
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/todo/prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;0CASQ,CAAC;AAE3C,MAAM,CAAC,MAAM,kBAAkB,GAAG,uDAAuD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/todo/rate-limit.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAW9E"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 同类事件限频闸(todo 套件内部共用):
|
|
3
|
+
* 配置告警、handler 异常、日志写失败均要求「同类 60s 一条」(技术方案 §4.1/§4.3/§4.5),
|
|
4
|
+
* 避免每请求级错误刷屏宿主日志。返回 true = 本次应输出。
|
|
5
|
+
*/
|
|
6
|
+
export function createRateLimiter(intervalMs) {
|
|
7
|
+
const lastAt = new Map();
|
|
8
|
+
return (key) => {
|
|
9
|
+
const now = Date.now();
|
|
10
|
+
const prev = lastAt.get(key);
|
|
11
|
+
if (prev !== undefined && now - prev < intervalMs)
|
|
12
|
+
return false;
|
|
13
|
+
// 防膨胀:键数异常量级时整体重置(限频窗口短,重置代价可忽略)
|
|
14
|
+
if (lastAt.size >= 256)
|
|
15
|
+
lastAt.clear();
|
|
16
|
+
lastAt.set(key, now);
|
|
17
|
+
return true;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=rate-limit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/todo/rate-limit.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAClD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,OAAO,CAAC,GAAW,EAAW,EAAE;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,IAAI,KAAK,SAAS,IAAI,GAAG,GAAG,IAAI,GAAG,UAAU;YAAE,OAAO,KAAK,CAAC;QAChE,iCAAiC;QACjC,IAAI,MAAM,CAAC,IAAI,IAAI,GAAG;YAAE,MAAM,CAAC,KAAK,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC"}
|